26

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?

35

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
  • 1
    First 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 Dec 16 '16 at 10:39
  • 21
    The first command didn't work for me. It just copied the first file. – Luis A. Florit Jun 11 '17 at 1:32
  • 2
    This doesn't work, it just copied the first file to output.mp4. – crmpicco Nov 14 '18 at 14:01
  • 2
    File-level concatenation does not work for MP4, so the concat protocol is not recommended for this format and will generally not work. – llogan Feb 21 at 18:23
  • 1
    @brasofilo Thank you for the link. This is long overdue, but I updated the answer to point people in that direction. – Carson Darling Feb 22 at 16:11
4

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"
  • 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 Jun 20 at 18:53
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.

  • 1
    Actually there is. stdin. – Qwertiy Feb 21 at 9:11
  • concat protocol shouldn't be used with MP4 or any other format the requires a global header. – llogan Sep 18 at 19:00
0

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.

  • 2
    The 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 Feb 13 '17 at 0:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.