35

I am trying to Merge two video without re-encoding them.

Currently i use a approach which is too much time consuming and resource as well. I just want to merge without re-encoding them. Currently i am using

        exec ( "cpulimit -l 90 ffmpeg -i $filename1 -qscale 0  $intermediate1 &> stream1.log" );
        exec ( "cpulimit -l 90 ffmpeg -i $filename2 -qscale 0  $intermediate2 &> stream2.log" );
        $output = '/var/www/html/myserver/merg/'.uniqid().'_merge.'.$ext;
        exec ( "cpulimit -l 90 cat $intermediate1 $intermediate2 | ffmpeg -i - -qscale 0 $output &> stream3.log" );

Above takes a lot of time.. I want a quick way to do it.

Yogesh Agarwal
  • 481
  • 1
  • 5
  • 8
  • By merging 2 videos, do you mean (1) concat one after the other ? or (2) mux both of them so they can co-exist in a single file ? (but cannot play both at the same time) , different requirements will lead to different solutions. – Han Jul 15 '21 at 17:33

1 Answers1

68

Concatenation of files with same codecs:

There are two methods within ffmpeg that can be used to concatenate files of the same type: the concat demuxer & the concat protocol

The demuxer is more flexible – it requires the same codecs, but different container formats can be used; and it can be used with any container formats, while the concat protocol only works with a select few containers.

The concat demuxer instructions:

create a text file named vidlist.txt in the following format:

file '/path/to/clip1'
file '/path/to/clip2'
file '/path/to/clip3'

Note that these can be either relative or absolute paths.

Then issue the command:

ffmpeg -f concat -safe 0 -i vidlist.txt -c copy output

In case it's not abundantly clear, replace output with the video filename you wish to produce (whether that be output.mp4, output.mkv, output.avi) ffmpeg will utilize the container indicated by the extension.

The files will be stream copied in the order they appear in the vidlist.txt into the output container. the "copy codec" is blazing fast.

Edit: Note that although the docs say you don't need -safe 0 if the paths are relative, my testing indicates it's a requirement. It's possible that this may vary with your version of ffmpeg.

There are tips for auto generating the file available in the docs.

Note: All the clips must already exist or the command will fail because decoding won't start until the whole list is read.

The concat protocol instructions:

ffmpeg -i "concat:video1.ts|video2.ts|video3.ts" -c copy output.ts

Note: as mentioned above the concat protocol is severely limited in what streams and containers it supports so I never use it. The above is only included in an attempt to create a thorough answer. The concat demuxer is a far better choice for most projects.

An alternative suggestion: Personally I prefer using the Matroska container due to it's flexibility and low overhead and join videos with the same encoding using mkvmerge -o output.mkv input1.mkv + input2.mkv

Concatenation of files with different codecs:

If your clips don't use the same codecs for audio and video and/or have different rates, your stuck re-encoding to intermediate files prior to joining which as we all know is both time and resource consuming.

Note that special characters can break things so if you have these in your filenames you'll need to deal with them.

Sources: Experience

https://ffmpeg.org/ffmpeg-formats.html

Elder Geek
  • 1,017
  • 1
  • 11
  • 18
  • FYI, it'll explode if you have ' in your file name. I guess it doesn't realize 3 single quotes means one is in the filename. – Katastic Voyage Apr 26 '18 at 19:56
  • @KatasticVoyage odd characters in filenames aren't recommended. However hey can be [dealt with](https://stackoverflow.com/questions/15783701/which-characters-need-to-be-escaped-in-bash-how-do-we-know-it) – Elder Geek Apr 27 '18 at 00:45
  • I got `Unable to find a suitable output format for 'output' output: Invalid argument`. Appending a recognizable extension to `output` like `output.mp4` solved the problem. – Michał Lepczyński Mar 17 '20 at 02:05
  • @MichałLepczyński Thanks for sharing. – Elder Geek Mar 20 '20 at 16:21
  • 6
    `ffmpeg -f concat -i vidlist.txt -c copy out.mp4` works for me – Aryeh Beitz Apr 19 '20 at 21:19
  • 2
    How to issue that command without the text file ! I need to run it from command line or script directly . – Salem Jul 01 '20 at 19:11
  • @Salem Please see the Alternative solution part of the answer that refers to mkvmerge. Despite the name mkvmerge can also produce mp4 files. – Elder Geek Jul 30 '20 at 17:21
  • @ElderGeek I already tried both solution if I put more than 2 file they get corrupted . – Salem Jul 31 '20 at 13:22
  • I'm confused - if `mkvmerge` also requires files of the same encoding, what advantage does it have over the `concat` protocol? Or have I misread? – Hashim Aziz Mar 03 '21 at 01:26
  • 1
    @HashimAziz Ok, now I'm confused! I'm not sure how alternative became synonymous with advantageous. To be clear, I'm not saying that an alternative approach that works is in any way superior to any other approach that also works. At that point it's a matter of preference as the end result is reached regardless. Cheers! – Elder Geek Sep 02 '21 at 19:37
  • @Salem I know it's a while back, but... I just ran an `mkvmerge -o output.mkv file1.mp4 + file2.mp4 + file3.mp4 + file4.mp4`, and the resulting file was the concatenation of all four inputs. So, that **should** work unless there's some other issue. A good test would be to try `mkvmerge -o part1.mkv file1.mp4 + file2.mp4; mkvmerge -o part2.mkv file2.mp4 + file3.mp4; mkvmerge -o part3.mkv file3.mp4 + file4.mp4` — if any of those three "part" files comes out damaged, then that's where the problem is. – FeRD Nov 13 '21 at 14:36
  • Thank you, works like charm! – Daggie Blanqx - Douglas Mwangi May 28 '22 at 18:48