如何使用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 $(for f in *.mp4 ; do echo -n "

以上是关于如何使用FFmpeg连接两个MP4文件? concat视频过滤器concat demuxer concat协议的主要内容,如果未能解决你的问题,请参考以下文章

使用 FFMPEG 连接某些 mp4 文件时听不到音频 [重复]

FFmpeg连接视频

使用halfninja ffmpeg在Android中连接mp4文件

如何使用 ffmpeg 将 MP4 转换为 WMV 以获得更好的质量?

使用ffmpeg合并两个文件时获取异常

如何使用 Node.js 通过 ffmpeg 流式传输 MP4 文件?