I can successfully join multiple files using the following command:
ffmpeg -f concat -i input.txt -codec copy output.mp4The 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.mp4Do I have to use a different command?
17 Answers
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.mp4In 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 15 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" 6 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.
2Without external text file, one line command to merge all MP4 files in a folder:
in CMD (the Command Prompt):
(FOR /R %A IN (*.mp4) DO @ECHO file '%A') | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -vcodec copy -acodec copy "Videos_Merged.mp4"in a BATch file:
(FOR /R %%A IN (*.mp4) DO @ECHO file '%%A') | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -vcodec copy -acodec copy "Videos_Merged.mp4"P.S.: CHCP 65001 command need if the directory contains unicode characaters.
(This code based Qwertiy's one-line command. I'm again grateful to Qwertiy for the informations in his reply. So I fixed the code.
3You 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
EOFbash 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.
1I also liked Qwertiy's answer best. Here is a script (works for an arbitrary number of files, also for .mov; tested on macOS):
#!/bin/bash
if [ $# -lt 1 ]; then echo "Usage: `basename $0` input_1.mp4 input_2.mp4 ... output.mp4" exit 0
fi
ARGS=("$@") # determine all arguments
output=${ARGS[${#ARGS[@]}-1]} # get the last argument (output file)
unset ARGS[${#ARGS[@]}-1] # drop it from the array
(for f in "${ARGS[@]}"; do echo "file '$f'"; done) | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -vcodec copy -acodec copy $output GoPro 'chapters' are footage around 4 GB - The camera starts a new file every ~ 10 minutes. If you have media files with exactly the same codec and codec parameters you can concatenate them quite easily. Fastest way, that I found, is use ffmpeg with concating function:
ffmpeg -f concat -safe 0 -i <(for f in *.MP4; do echo "file '$PWD/$f'"; done) -c copy output.mp4