ffmpeg join two mp4 files with ffmpeg on command line

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?

1

7 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.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
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.

2

Without 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.

3

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.

1

I 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

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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

You Might Also Like