How can I merge two mp4 files without losing quality?
I usually use VirtualDub to merge my files, but it doesn't seem to support mp4. So what alternatives are there?
Avidemux. It's just like VirtualDub, only with more formats supported and built-in codecs and filters. I always use it in preference; it joins AVC+AAC.MP4 files (without recoding) fine for me.
To join them in AviDemux:
- File -> Open -> Select File
- File -> Append -> Select File
- Set all to Copy
- File -> Save -> FileName
- Wait..
According to AViDemux forums, this join process is lossless (http://www.avidemux.org/smf/index.php?topic=9467.0)
You can do this with ffmpeg:
mkfifo temp0 temp1
ffmpeg -i input0.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts -y temp0 2> /dev/null & \
ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts -y temp1 2> /dev/null & \
ffmpeg -f mpegts -i "concat:temp0|temp1" -c copy -absf aac_adtstoasc output.mp4
This doesn't re-encode anything, it places them in a new transport stream container, which makes them more easy to concatenate, and then concatenates them back into an MP4. If output.mp4 already exists, the command will fail. The version above uses named pipes, if you're on a system that doesn't support those you'd have to use intermediate files (like windows):
ffmpeg -i input0.mp4 -c copy -bsf:v h264_mp4toannexb temp0.ts
ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb temp1.ts
ffmpeg -i "concat:temp0.ts|temp1.ts" -c copy -bsf:a aac_adtstoasc output.mp4
Concat demuxer
The concat demuxer was added to ffmpeg 1.1. If your version of ffmpeg is to old, get the newest static binary from here: http://www.ffmpeg.org/download.html
Instructions
Create a file mylist.txt
with all the files you want to have concatenated in the following form (Lines starting with a dash are ignored):
# this is a comment
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'
Note that these can be either relative or absolute paths. Then you can encode your files with:
ffmpeg -f concat -i mylist.txt -c copy output
It is possible to generate this list file with a bash for loop, or using printf. Either one of the following would generate a list file containing every *.wav in the working directory:
for f in ./*.wav; do echo "file '$f'" >> mylist.txt; done
printf "file '%s'\n" ./*.wav > mylist.txt
Source: ffmpeg wiki