How to combine multiple files with FFmpeg
To create a large video file from multiple video files, one does not simply cat into Mordor, because of different header information or stream mappings in the files. But one can use ffmpeg to do that job.
Let’s say you have authored a DVD with one video stream, eight subtitles and two audio streams and you want to create a single vob file with video, the first two subtitles and both audio streams for further transcoding. To concatenate the files, enter the keyword concat before the first input file and then separate the files by a pipe.
$ ffmpeg -i concat:"vts_01_1.vob|vts_01_2.vob|vts_01_3.vob|vts_01_4.vob"
ffmpeg will now analyse the files and tell you which streams have which index. To make a copy of the input files without transcoding, use the -c copy option. This tells ffmpeg to pass through all streams. You can copy multiple streams into the output file with the -map x:y option, where x is the input file index and y the stream index in that file, both starting at 0. The video stream will most likely have the index 0. Let’s say you found out with the first command that the subtitle streams you want are index 1 and 2 and the audio streams are 9 and 10. The command to enter is
$ ffmpeg -i concat:"vts_01_1.vob|vts_01_2.vob|vts_01_3.vob|vts_01_4.vob" -c copy -map 0:0 -map 0:1 -map 0:2 -map 0:9 -map 0:10 concat.vob
Some file formats like mp4 cannot be joined using the concat protocol. In that case you can use the concat demuxer. To use it, you have to list the files you want to concatenate in a text file like such:
The ffmpeg command then looks as follows:
$ ffmpeg -f concat -i filestoconcatenate.txt -c copy concatenated.mp4
If you have the video and audio streams in different files and want to create a single video file containing both streams, ffmpeg is also the tool of your choice. For this example, let’s assume the file videoWithAudio1.mp4 contains a video and an audio stream, while the files audio2.m4a and audio3.m4a only contain a single audio stream. Again we use the -c copy option for passing through the streams and the -map x:y option for stream selection.
$ ffmpeg -i videoWithAudio1.mp4 -i audio2.m4a -i audio3.m4a -c copy -map 0:0 -map 0:1 -map 1:0 -map 2:0 muxed.mp4
As you can see, the file videoWithAudio1.mp4 has index 0, audio2.m4a index 1 and audio3.m4a index 2, so the mapping is very straight forward.