Skip to content

Instantly share code, notes, and snippets.

@cohnt
Last active May 12, 2026 03:02
Show Gist options
  • Select an option

  • Save cohnt/bc09fb8520e62e8361bd75f04871c665 to your computer and use it in GitHub Desktop.

Select an option

Save cohnt/bc09fb8520e62e8361bd75f04871c665 to your computer and use it in GitHub Desktop.
Steam Clip Conversion Script
#!/bin/bash
# Configuration
mkdir -p processed
mkdir -p to_delete
PROCESSED_ROOT=$(realpath processed)
TO_DELETE_ROOT=$(realpath to_delete)
# Iterate through each clip folder
for clip_dir in clips/*/; do
[ -e "$clip_dir" ] || continue
dir_name=$(basename "$clip_dir")
# Locate the folder containing the actual .m4s segments
# Steam puts these in a nested 'video/bg_...' subfolder
segment_dir=$(find "$clip_dir" -name "init-stream0.m4s" -exec dirname {} \;)
if [[ -z "$segment_dir" ]]; then
echo "No segments found in $dir_name, skipping."
continue
fi
output_file="$PROCESSED_ROOT/${dir_name}.mp4"
echo "Processing: $dir_name"
pushd "$segment_dir" > /dev/null
# 1. Stitch Video Chunks (init + all chunks)
cat init-stream0.m4s chunk-stream0-*.m4s > temp_v.mp4
# 2. Stitch Audio Chunks (if they exist)
if [ -f "init-stream1.m4s" ]; then
cat init-stream1.m4s chunk-stream1-*.m4s > temp_a.m4a
# 3. Combine with +genpts to fix timestamp errors
ffmpeg -y -loglevel error -fflags +genpts -i temp_v.mp4 -i temp_a.m4a -c copy "$output_file"
rm temp_a.m4a
else
# Video only if no audio stream found
ffmpeg -y -loglevel error -fflags +genpts -i temp_v.mp4 -c copy "$output_file"
fi
status=$?
rm temp_v.mp4
popd > /dev/null
# Move source to 'to_delete' if successful
if [[ $status -eq 0 ]]; then
echo "Success. Moving to 'to_delete'."
mv "$(realpath "$clip_dir")" "$TO_DELETE_ROOT/"
else
echo "Error: FFmpeg failed for $dir_name."
fi
done
echo "Batch processing complete."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment