如何使用FFmpeg连接两个MP4文件? concat视频过滤器concat demuxer concat协议
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用FFmpeg连接两个MP4文件? concat视频过滤器concat demuxer concat协议相关的知识,希望对你有一定的参考价值。
我正在尝试使用ffmpeg连接两个mp4文件。我需要这是一个自动过程因此我选择ffmpeg。我正在将这两个文件转换为.ts文件,然后将它们连接起来,然后尝试对该连接的.ts文件进行编码。文件是h264和aac编码,我希望保持质量相同或尽可能接近原始。
ffmpeg -i part1.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part1.ts
ffmpeg -i part2.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part2.ts
cat part1.ts part2.ts > parts.ts
ffmpeg -y -i parts.ts -acodec copy -ar 44100 -ab 96k -coder ac -vbsf h264_mp4toannexb parts.mp4
不幸的是我在编码过程中收到来自ffmpeg的以下错误消息:
[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[NULL @ 0x101d600]error, non monotone timestamps 13779431 >= 13779431kbits/s
av_interleaved_write_frame(): Error while opening file
这种情况发生在编码的一半左右,这让我觉得你不能将两个.ts文件连在一起并让它工作。
FFmpeg有三种串联方法。
1. concat video filter
ffmpeg -i opening.mkv -i episode.mkv -i ending.mkv \
-filter_complex "[0:v] [0:a] [1:v] [1:a] [2:v] [2:a] concat=n=3:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" output.mkv
请注意,此方法执行重新编码。
2. concat demuxer
$ cat mylist.txt
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'
$ ffmpeg -f concat -i mylist.txt -c copy output.mp4
对于Windows:
(echo file 'first file.mp4' & echo file 'second file.mp4' )>list.txt
ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4
3. concat protocol
ffmpeg -i "concat:input1|input2" -codec copy output.mkv
由于这些格式的性质以及通过此方法执行的简单连接,此方法不适用于许多格式,包括MP4。
哪一个使用
- concat过滤器:如果您的输入没有相同的参数(宽度,高度等),或者不是相同的格式/编解码器,或者您想要执行任何过滤,请使用此选项。 (您可以仅重新编码不匹配的输入,以便它们共享相同的编解码器和其他参数,然后使用concat解复用器来避免重新编码其他输入)。
- concat demuxer:当您想要避免重新编码时使用,并且您的格式不支持文件级别连接(一般用户使用的大多数文件不支持文件级别连接)。
- concat协议:与支持文件级联接的格式(MPEG-1,MPEG-2 PS,DV)一起使用。不要与MP4一起使用。
如果有疑问,请尝试使用concat demuxer。
Also see
这对我有用(在Windows上)
ffmpeg -i "concat:input1|input2" -codec copy output
一个例子...
ffmpeg -i "concat:01.mp4|02.mp4" -codec copy output.mp4
蟒蛇
使用一些python代码与尽可能多的mp4一起使用在一个文件夹中(从python.org安装python,复制并粘贴并将此代码保存到一个名为mp4.py的文件中,然后从python文件夹中打开的cmd运行它) mp4.py和文件夹中的所有mp4将被连接)
import glob
import os
stringa = ""
for f in glob.glob("*.mp4"):
stringa += f + "|"
os.system("ffmpeg -i \"concat:" + stringa + "\" -codec copy output.mp4")
Version 2 with Python
取自我的post on my blog,这是我在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()
这是我用几个GoPro mp4连接到720p mp4的脚本。希望它有所帮助。
#!/bin/sh
cmd="( "
for i; do
cmd="${cmd}ffmpeg -i $i -ab 256000 -vb 10000000 -mbd rd -trellis 2 -cmp 2 -subcmp 2 -g 100 -f mpeg -; "
done
cmd="${cmd} ) | ffmpeg -i - -vb 10000000 -ab 256000 -s 1280x720 -y out-`date +%F-%H%M.%S`.mp4"
echo "${cmd}"
eval ${cmd}
从这里的文档:https://trac.ffmpeg.org/wiki/Concatenate
如果您有MP4文件,可以通过首先将它们转码为MPEG-2传输流来无损地连接这些文件。使用H.264视频和AAC音频,可以使用以下内容:
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
这种方法适用于所有平台。
我需要能够将其封装在跨平台脚本中,因此我使用了fluent-ffmpeg
并提出了以下解决方案:
const unlink = path =>
new Promise((resolve, reject) =>
fs.unlink(path, err => (err ? reject(err) : resolve()))
)
const createIntermediate = file =>
new Promise((resolve, reject) => {
const out = `${Math.random()
.toString(13)
.slice(2)}.ts`
ffmpeg(file)
.outputOptions('-c', 'copy', '-bsf:v', 'h264_mp4toannexb', '-f', 'mpegts')
.output(out)
.on('end', () => resolve(out))
.on('error', reject)
.run()
})
const concat = async (files, output) => {
const names = await Promise.all(files.map(createIntermediate))
const namesString = names.join('|')
await new Promise((resolve, reject) =>
ffmpeg(`concat:${namesString}`)
.outputOptions('-c', 'copy', '-bsf:a', 'aac_adtstoasc')
.output(output)
.on('end', resolve)
.on('error', reject)
.run()
)
names.map(unlink)
}
concat(['file1.mp4', 'file2.mp4', 'file3.mp4'], 'output.mp4').then(() =>
console.log('done!')
)
对于.mp4
文件,我发现使用opensource命令行工具更好,更快:mp4box
。然后你可以这样使用它:
mp4box.exe -add video1.mp4 -cat video2.mp4 destvideo.mp4
在大多数平台上下载:https://gpac.wp.imt.fr/mp4box/
ffmpeg \
-i input_1.mp4 \
-i input_2.mp4 \
-filter_complex '[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid]' \
-map [vid] \
-c:v libx264 \
-crf 23 \
-preset veryfast \
output.mp4
合并当前目录中的所有mp4文件
我个人不喜欢创建我之后必须删除的外部文件,所以我的解决方案是包含文件编号列表(如qazxsw poi,...)
file_1_name, file_2_name, file_10_name, file_20_name, file_100_name
经过各种尝试下面的脚本在Windows 10 PowerShell上为我工作。
#!/bin/bash
filesList=""
for file in $(ls -1v *.mp4);do #lists even numbered file
filesList="${filesList}${file}|"
done
filesList=${filesList%?} # removes trailing pipe
ffmpeg -i "concat:$filesList" -c copy $(date +%Y%m%d_%H%M%S)_merged.mp4
这里前两行创建一个文本文件temp.txt,其中包含以下内容
$files=Get-ChildItem -path e:\ -Filter *.mp4
$files| ForEach-Object {"file '$($_.FullName)'"}| Out-File -FilePath e:\temp.txt -Encoding ASCII
if (-not (test-path "e:\ffmpeg\bin\ffmpeg.exe")) {throw "e:\ffmpeg\bin\ffmpeg.exe needed"}
E:\ffmpeg\bin\ffmpeg.exe -safe 0 -f concat -i "e:\temp.txt" -c copy -bsf:v hevc_mp4toannexb -an e:\joined.mp4
# Conversion Cleanup
Remove-Item e:\temp.txt
第3行,第4行检查ffmpeg是否在路径中可用并创建“joined.mp4”
与其他答案的主要区别如下
file 'e:\first.mp4'
file 'e:\second.mp4'
对于我上面的mp4文件,您可能需要使用其他替代方案,具体取决于您的视频编码。
usage of -bsf:v hevc_mp4toannexb -an
所有这些可能的比特流过滤器都可以在h264_mp4toannexb
找到
这是我使用命令替换加入一个充满MP4文件的目录的方法和concat视频过滤器(这将重新编码) - 想到其他人会从这个单行中获得一些用处,特别是如果你有很多文件(我只是一举加入17个文件):
https://ffmpeg.org/ffmpeg-bitstream-filters.html
注:这个命令按照命名的顺序加入你的文件(即如果你运行 以上是关于如何使用FFmpeg连接两个MP4文件? concat视频过滤器concat demuxer concat协议的主要内容,如果未能解决你的问题,请参考以下文章 使用 FFMPEG 连接某些 mp4 文件时听不到音频 [重复] 使用halfninja ffmpeg在Android中连接mp4文件ffmpeg $(for f in *.mp4 ; do echo -n "