ffmpeg join two mp4 files with ffmpeg on command line

29

7

I can successfully join multiple files using the following command:

ffmpeg -f concat -i input.txt -codec copy output.mp4

The only problem with this command is that you need to read the filepaths from the text file called input.txt with the following content:

file 'C:\Users\fabio\Downloads\Super\Sharks\01.mp4'
file 'C:\Users\fabio\Downloads\Super\Sharks\02.mp4'
file 'C:\Users\fabio\Downloads\Super\Sharks\03.mp4'

Is there a way to achieve the same goal without having to read the filepaths from a file? I have tried the following with no luck:

ffmpeg -f concat -i file "C:\a\b\01.mp4" file "C:\a\b\02.mp4" -codec copy output.mp4
ffmpeg -f concat -i "C:\a\b\01.mp4" "C:\a\b\02.mp4" -codec copy output.mp4

Do I have to use a different command?

Fabio Delarias

Posted 2016-03-30T16:05:06.550

Reputation: 393

1

related: https://stackoverflow.com/questions/7333232/concatenate-two-mp4-files-using-ffmpeg

– Ciro Santilli 新疆改造中心法轮功六四事件 – 2018-05-13T23:55:35.240

Answers

37

2019 Update:

As mentioned in the comments, Stack Overflow has a great description of the available options for concatenation, as well as a discussion of which method to use depending on the types of files you're using:

How to concatenate two MP4 files using FFmpeg?

Original 2016 Answer:

You should be able to use the concat protocol method to combine the files:

ffmpeg -i "concat:input1.mp4|input2.mp4|input3.mp4" -c copy output.mp4

In addition, the FFmpeg manual discusses a method specifically for MP4 files, in order to losslessly concatenate them, but requires that you create temporary files (or named pipes):

ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4

Carson Darling

Posted 2016-03-30T16:05:06.550

Reputation: 531

Sweet!... Thank you! The first method didn't work for me but the second did the trick. I don't have a problem creating intermediate files as long as I don't have to read inputs ( filepaths) from a file. This is crucial for the project I am working on... thanks again – Fabio Delarias – 2016-03-30T17:32:31.510

Oh and the FFmpeg manual you are referring to is it the website FFmpeg.org or is it in a PDF or book version? – Fabio Delarias – 2016-03-30T17:35:22.447

I was just referring to FFmpeg.org, specifically the concat protocol section (https://trac.ffmpeg.org/wiki/Concatenate#protocol). Their documentation can be a little hard to read through, but it does cover a ton of use cases.

– Carson Darling – 2016-03-30T18:07:19.640

1First command worked for me like a butter..it took 2 to 3 seconds to concat my 6 mp4 files into output file (239 MB approx). – Sachin – 2016-12-16T10:39:46.867

22The first command didn't work for me. It just copied the first file. – Luis A. Florit – 2017-06-11T01:32:01.630

The same here: the first command just copied the first file; the second command does the trick... but the output file has no audio! – smartmouse – 2017-12-24T13:17:28.707

At what version was this feature introduced? Debian 9 (with version 3.3.7) simply says "concat:.....mp4: No such file or directory" and quits. – Liam – 2018-05-16T17:20:17.540

I guess the first command only works depending on the source MP4. The named pipes method worked without issues, audio came ok. SO's q&a is more complete regarding the various concat techniques: How to concatenate two MP4 files using FFmpeg?

– brasofilo – 2018-11-09T21:34:26.623

3This doesn't work, it just copied the first file to output.mp4. – crmpicco – 2018-11-14T14:01:39.890

@crmpicco, the same problem, regardless the file have the same codec, same framerate and created by the same program. Found an alternative solution. – Qwertiy – 2019-02-21T07:54:30.140

2File-level concatenation does not work for MP4, so the concat protocol is not recommended for this format and will generally not work. – llogan – 2019-02-21T18:23:36.440

1@brasofilo Thank you for the link. This is long overdue, but I updated the answer to point people in that direction. – Carson Darling – 2019-02-22T16:11:30.073

5

You may replace file with list by outputting list to stdout and reading the list from stdin by ffmpeg:

(echo file 'a.mp4' & echo file 'b.mp4') | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -vcodec copy -acodec copy "result.mp4"

Qwertiy

Posted 2016-03-30T16:05:06.550

Reputation: 206

Using ffmpeg version 2.4.3-tessus on Mac OS 10.12.6, this just throws an error: "Unrecognized option 'protocol_whitelist'". Without the protocol_whitelist option, it seems to just make a copy of the second MP4 file. – James – 2019-06-20T18:53:46.097

2

No, there appears to be no way to use the ffmpeg concat demuxer on a single command line without some hack. You need to create the input text file with the list of files. I thought this strange myself, maybe someone will add this to FFMpeg at a later date.

The accepted answer to this question uses the concat protocol, not the concat demuxer which is what the OP asked.

georgiecasey

Posted 2016-03-30T16:05:06.550

Reputation: 160

1Actually there is. stdin. – Qwertiy – 2019-02-21T09:11:01.107

concat protocol shouldn't be used with MP4 or any other format the requires a global header. – llogan – 2019-09-18T19:00:05.113

1

You could still do it in a script without changing the command. Something like:

echo "file fname1" >$$.tmp    #single redirect creates or truncates file
echo "file fname2" >>$$.tmp   # double redirect appends
echo "file fname3" >>$$.tmp   # do as many as you want.

ffmpeg -f concat -i $$.tmp -codec copy output.mp4

rm $$.tmp  # just to clean up the temp file. 
           # For debugging, I usually leave this out.

The $$ expands to the pid of the shell running the command, so the file name will be different every time you run it. so you could use $$.txt if you prefer. Or something else...

Also, you can use here files to add a bunch of data to the file:

cat <<EOF >$$.tmp
file fname1
file fname2
file fname3
EOF

bash Variable substitution works, so you can programatically determine the content of the file, it doesn't have to be fixed. I embed this sort of stuff in for loops all the time. Finally, the redirect works the same as above, so >$$.tmp truncates then writes, >>$$.tmp appends.

Richard Betel

Posted 2016-03-30T16:05:06.550

Reputation: 41

2The question asks, "is there a way to achieve the same goal without having to read the filepaths from a file?"  All you have done is provide a way to write the filepaths to a file (prior to reading the filepaths from the file).  This does not answer the question. – Scott – 2017-02-13T00:01:25.050