How to Handle Clips from Steam Game Recordings on Steam Deck
How Clips are Stored on Steam Deck
On the Steam Deck, game clips are stored in the directory: /home/deck/.steam/steam/Steam/userdata/$STEAM_USER_ID/gamerecordings/clips
. The folders are named in the format clip_$appID_$date_$time
, such as clip_1887840_20240703_213601. And video is stored in a subfolder named video in the m4s format, split into multiple sections. The m4s files are categorized into two types:
- Video files: filenames follow the pattern
*-stream0*.m4s
. - Audio files: filenames follow the pattern
*-stream1*.m4s
.
Converting m4s into a Single mp4
For clips longer than one minute, manual conversion to mp4 is required. The process involves merging the video files into one mp4 file, the audio files into another mp4 file, and then combining them into a single mp4 file with both video and audio using ffmpeg.
If we are in the directory /home/deck/.steam/steam/Steam/userdata/$STEAM_USER_ID/gamerecordings/clips/clip_1887840_20240703_213601
, we can use the find
command to list all m4s files and sort them by the numerical suffix indicating the timeline order. Then, use the cat
command to combine all stream files into one mp4.
find . -type f -name '*-stream0*.m4s' | sort -t '-' -k2 -V | xargs cat > tmp_video.mp4
find . -type f -name '*-stream1*.m4s' | sort -t '-' -k2 -V | xargs cat > tmp_audio.mp4
After that, use ffmpeg to merge them into the final result.
ffmpeg -i tmp_video.mp4 -i tmp_audio.mp4 -c copy final_result.mp4
Creating a Script to Sync Clips Back to a Local Device and Convert Them
Here is a shell script (for zsh) example for:
- Syncing all clips back to a local device.
- Converting each clip into a single mp4 file, naming it with
$app_name-$seconds.mp4
, and storing the final result in$output_dir
. - Removing temporary files and the clip folder.
local deck_address=deck@10.10.10.10
local local_path="/Users/MyName"
local game_recordings_path=/home/deck/.steam/steam/Steam/userdata/$STEAM_USER_ID/gamerecordings
normalizing_timestamp() {
local timestamp=$1
date -j -f "%Y%m%d_%H%M%S" "$timestamp" "+%s"
}
get_app_name() {
local app_id=$1
local api_url="https://store.steampowered.com/api/appdetails?l=tchinese&appids=$app_id"
local app_name
# Fetch API response and extract app name
app_name=$(curl -s "$api_url" | jq -r ".\"$app_id\".data.name")
# If app name is not found or null, use app ID instead
if [[ -z "$app_name" || "$app_name" == "null" ]]; then
echo "$app_id"
else
# Replace spaces with underscores for filename
echo "$app_name" | tr ' ' '_'
fi
}
rsync -avz $deck_address:$game_recordings_path/clips $local_path/
for folder in $local_path/clips/*; do
if [[ -d $folder ]]; then
echo "Processing folder: $folder"
# Extract folder name and app ID
folder_name=$(basename $folder)
app_id=$(echo $folder_name | cut -d'_' -f2)
timestamp=$(echo $folder_name | cut -d'_' -f3,4)
# Convert timestamp to unix time
seconds=$(normalizing_timestamp $timestamp)
# Get app name from Steam API
app_name=$(get_app_name $app_id)
# Create app-specific output directory
output_dir="$local_path/Videos/$app_name"
mkdir -p "$output_dir"
# Create output filename
output_file="$output_dir/$app_name-$seconds.mp4"
# Merge video streams
echo "Merging video streams..."
find "$folder" -type f -name '*-stream0*.m4s' | sort -t '-' -k2 -V | xargs cat > "$output_dir/tmp_video.mp4"
# Merge audio streams
echo "Merging audio streams..."
find "$folder" -type f -name '*-stream1*.m4s' | sort -t '-' -k2 -V | xargs cat > "$output_dir/tmp_audio.mp4"
# Combine video and audio
echo "Combining video and audio..."
ffmpeg -i "$output_dir/tmp_video.mp4" -i "$output_dir/tmp_audio.mp4" -c copy "$output_file"
# Clean up temporary files & remove clip folder
rm "$output_dir/tmp_video.mp4" "$output_dir/tmp_audio.mp4" && rm -rf $folder
echo "Finished processing: $output_file"
fi
done
You can create a function in your ~/.zshrc
or create an executable .sh
file to handle the sync and conversion process.