I\'m trying to concatenate two mp4 files using ffmpeg. I need this to be an automatic process hence why I chose ffmpeg. I\'m converting the two files into .ts files and th
based on rogerdpack's and Ed999's responses, I've created my .sh version
#!/bin/bash
[ -e list.txt ] && rm list.txt
for f in *.mp4
do
echo "file $f" >> list.txt
done
ffmpeg -f concat -i list.txt -c copy joined-out.mp4 && rm list.txt
it joins all the *.mp4
files in current folder into joined-out.mp4
tested on mac.
resulting filesize is exact sum of my 60 tested files. Should not be any loss. Just what I needed
I found the pipe operator did not work for me when using option 3 to concat several MP4s on a Mac in the accepted answer.
The following one-liner works on a Mac (High Sierra) to concatenate mp4s, with no intermediary file creation required.
ffmpeg -f concat -safe 0 -i <(for f in ./*.mp4; do echo "file '$PWD/$f'"; done) -c copy output.mp4
If they are not exactly same (100% same codec, same resolution, same type) MP4 files, then you have to trans-code them into intermediate streams at first:
ffmpeg -i myfile1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp1.ts
ffmpeg -i myfile2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp2.ts
// now join
ffmpeg -i "concat:temp1.ts|temp2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
NOTE!: Output will be like first file ( and not a second one)
The accepted answer in the form of reusable PowerShell script
Param(
[string]$WildcardFilePath,
[string]$OutFilePath
)
try
{
$tempFile = [System.IO.Path]::GetTempFileName()
Get-ChildItem -path $wildcardFilePath | foreach { "file '$_'" } | Out-File -FilePath $tempFile -Encoding ascii
ffmpeg.exe -safe 0 -f concat -i $tempFile -c copy $outFilePath
}
finally
{
Remove-Item $tempFile
}
Here's my method for joining a directory full of MP4 files using command substitution and the concat video filter (this will re-encode) - figured someone else will get some use out of this one-liner, especially if you have many files (I just joined 17 files in one fell swoop):
ffmpeg $(for f in *.mp4 ; do echo -n "-i $f "; done) -filter_complex \
"$(i=0 ; for f in *.mp4 ; do echo -n "[$i:v] [$i:a] " ; i=$((i+1)) ; done \
&& echo "concat=n=$i:v=1:a=1 [v] [a]")" -map "[v]" -map "[a]" output.mp4
N.B. this command joins your files in the order in which they're named (i.e. the same order as they're presented if you run ls *.mp4
) - in my case, they each had a track number, so it worked great.
this worked for me (on windows)
ffmpeg -i "concat:input1|input2" -codec copy output
an example...
ffmpeg -i "concat:01.mp4|02.mp4" -codec copy output.mp4
Using some python code to do it with as many mp4 there are in a folder (install python from python.org, copy and paste and save this code into a file called mp4.py and run it from the cmd opened in the folder with python mp4.py and all the mp4 in the folder will be concatenated)
import glob
import os
stringa = ""
for f in glob.glob("*.mp4"):
stringa += f + "|"
os.system("ffmpeg -i \"concat:" + stringa + "\" -codec copy output.mp4")
Taken from my post on my blog, this is how I do it in python:
import os
import glob
def concatenate():
stringa = "ffmpeg -i \"concat:"
elenco_video = glob.glob("*.mp4")
elenco_file_temp = []
for f in elenco_video:
file = "temp" + str(elenco_video.index(f) + 1) + ".ts"
os.system("ffmpeg -i " + f + " -c copy -bsf:v h264_mp4toannexb -f mpegts " + file)
elenco_file_temp.append(file)
print(elenco_file_temp)
for f in elenco_file_temp:
stringa += f
if elenco_file_temp.index(f) != len(elenco_file_temp)-1:
stringa += "|"
else:
stringa += "\" -c copy -bsf:a aac_adtstoasc output.mp4"
print(stringa)
os.system(stringa)
concatenate()