FFmpeg recipe
FFmpeg: Merge / Concatenate Two MP4 Videos
For videos with identical codec / resolution / fps, concat demuxer is lossless and instant. Otherwise use the concat filter to re-encode.
Command
# Step 1: build a list file
echo "file 'clip1.mp4'
file 'clip2.mp4'" > list.txt
# Step 2: concat (lossless)
ffmpeg -f concat -safe 0 -i list.txt -c copy -y output.mp4Prefer no terminal?
Use the Video Merger in your browser
What each flag does
| -i | Input file. Can be a video, audio, or image. Repeat for multiple inputs. |
|---|---|
| -c copy | Stream-copy: no re-encoding. Output is bit-identical between cut points. Fastest possible. |
| -y | Overwrite output file without confirmation. |
| -f concat | Use the concat demuxer (file-list-driven concatenation). |
| -safe 0 | Allow absolute paths in the list file. |
Notes & gotchas
- All inputs must share codec, resolution, frame rate, and audio settings for -c copy. Mismatch → garbled output.
- For mismatched inputs, use the concat filter: -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a]" with re-encoding.
Check it worked
ffprobe -v error -show_entries format=duration -of csv=p=0 output.mp4The sum of the input durations, give or take a frame.
What to change
| concat demuxer needs matching streams | Same codec, resolution, frame rate and audio layout. Mismatch is why the second clip turns to garbage rather than erroring. |
|---|---|
| Use the concat filter for mismatched files | It re-encodes and accepts anything, at the cost of time and one generation of quality. |
| -safe 0 for absolute paths | Without it the demuxer refuses paths outside the working directory, with an error that does not say so. |
If it fails
Unsafe file name, or the concat demuxer refuses to start.
Why: The list file contains absolute paths, which the demuxer rejects by default.
Fix: Add -safe 0, or use paths relative to the list file.
The second clip is garbled, or audio drops after the join.
Why: Concat with stream copy requires identical codecs, resolution, frame rate and audio parameters in every input.
Fix: Normalise the inputs first by re-encoding them to matching settings, or use the concat filter, which re-encodes and tolerates differences.