使用ffmpeg复制编解码器将* .ts文件合并为单个mp4


47

我有一堆由单个index.m3u8文件描述的ts片段:

index.m3u8        
segment1_0_av.ts  
segment2_0_av.ts  
segment3_0_av.ts  
segment4_0_av.ts  
segment5_0_av.ts

我知道它们都以相同的方式编码。ffprobe给了我以下内容:

Input #0, mpegts, from 'segment1_0_av.ts':
  Duration: 00:00:10.00, start: 0.100511, bitrate: 1251 kb/s
  Program 1 
    Stream #0:0[0x100]: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p, 960x540 [SAR 1:1 DAR 16:9], 12.50 fps, 25 tbr, 90k tbn, 25 tbc
    Stream #0:1[0x101]: Audio: aac ([15][0][0][0] / 0x000F), 44100 Hz, stereo, fltp, 105 kb/s
    Stream #0:2[0x102]: Unknown: none ([21][0][0][0] / 0x0015)

我想将它们合并到一个mp4容器中。但是当我尝试如下命令时:

ffmpeg -f concat -i filelist.txt -c copy output.mp4

从index.m3u8文件生成filelist.txt的地方,它抱怨无法读取各种文件。但是转换ts文件本身似乎可以正常工作。我认为我没有正确使用ffmpeg。

如何使用ffmpeg使用复制编解码器将index.m3u8描述的ts文件组合到单个mp4容器中?

Answers:


58

我不确定ffmpeg为什么会给您一个错误。但是,ts是可以简单地串联的少数格式之一。然后,一旦您拥有一个ts,则将其复用到mp4。

在Windows下:

copy /b segment1_0_av.ts+segment2_0_av.ts+segment3_0_av.ts all.ts
ffmpeg -i all.ts -acodec copy -vcodec copy all.mp4

在GNU / Linux下,使用bash:

cat segment1_0_av.ts segment2_0_av.ts segment3_0_av.ts > all.ts
ffmpeg -i all.ts -acodec copy -vcodec copy all.mp4

12
您可能还需要-bsf:a aac_adtstoasc
卡米洛·马丁

1
有趣的是,该命令不是NOT ffmpeg copy ...,它是copy ...(在Windows下)
Ron Royston,

25

使用copy或cat组合文件(例如szatmary当前的最佳答案)可能会导致您播放的文件超出限制,并且无法找到播放问题。

相反,要正确组合这些文件,请按照https://trac.ffmpeg.org/wiki/Concatenate中的说明使用ffmpeg 。(如果尚未安装ffmpeg,请在此处安装https://github.com/adaptlearning/adapt_authoring/wiki/Installing-FFmpeg。)

如果您懒于阅读我的第一个链接,则基本上必须在您要保存的文件夹中创建一个.txt文件,列出要合并的所有文件,这样(我的第一个链接提供了有关如何轻松完成操作的说明)重新进行串联:

file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

这是我第一个链接的复制粘贴,以一种方式创建文本文件(例如,如果您在命令行中使用Windows),但是显然您可以手动创建文件,也可以根据需要:

(for %i in (*.ts) do @echo file '%i') > mylist.txt

请仔细检查您的.txt文件,确保其外观良好且格式正确!

之后,在命令行上运行:

ffmpeg -f concat -i mylist.txt -c copy all.ts

其中“ mylist.txt”是您刚创建的.txt文件。

检查生成的文件是否正确播放视频。在这里,您可以像往常一样将多路复用器转换为mp4:

ffmpeg -i all.ts -acodec copy -vcodec copy all.mp4

for %i in (*.ts) do对于i> = 10,这不能正确排序。除此之外,一切正常,谢谢。确实,级联文件存在问题,更不用说使用您的方法制作的文件小了16%(我有1400个部分乘以400kb)。
用户

@user输入数字,以便可以循环访问数字,例如for i in {1..10}; do echo file \'$i.ts\' >> list.txt ; done
qwr

8

2017年答案

但是当我尝试类似的命令时...,它抱怨无法读取各种文件。

当我ffmpeg -i some.ts -c copy some.mp4在某个视频上执行时,出现以下错误消息:

Malformed AAC bitstream detected: use the audio bitstream filter 
'aac_adtstoasc' to fix it ('-bsf:a aac_adtstoasc' option with ffmpeg)

av_interleaved_write_frame(): Operation not permitted

毫不奇怪,执行ffmpeg -i some.ts -c copy -bsf:a aac_adtstoasc some.mp4修复它。


3
获取足够的新资源ffmpeg,它将立即自动执行此操作。
llogan

7

放在一起

使用Juan Aquino的答案(并纠正第一个与Bash兼容的命令并使用文件的自然顺序),再加上7vujy0f0hy的答案,一个适用于Linux Bash shell的简单工作脚本是:

#!/bin/bash
for i in `ls *.ts | sort -V`; do echo "file $i"; done >> mylist.txt
ffmpeg -f concat -i mylist.txt -c copy -bsf:a aac_adtstoasc video.mp4

4

从m3u8播放列表连接多个视频文件的正确方法是

ffmpeg -i "index.m3u8" -codec copy output.mp4


  • m3u8播放列表可以在网络上或本地目录中
    • 它包含相对于播放列表的文件路径列表
  • -codec copy 避免编码
  • 容器类型很重要:
    • *.mp4 很好,但是从网络上获取播放列表时,混音似乎有点慢
    • *.mkv*.ts最适合我

2

您可以像使用bash这样简单地进行串联:

for f in ./{0..<number>}.ts; do cat $f >> out.ts; done

替换<number>为最高编号(显然)。ffmpeg的变体无法正常工作。输出的视频文件会奇怪地结结巴巴。

我使用for循环来确保文件的正确顺序。也许您不需要它。甚至有可能将输出通过管道传输到ffmpeg并即时将其转换为mp4。


0

在运行ffmpeg之前误导读者连接TS文件的所有常见问题解答都是不正确的。为确保在mp4流的组装过程中音频和视频不会出现不同步,应使用ffmpeg的文献记载不充分但很重要的“ -f concat”功能。

    delimiterBeforeFileNumber="-"
    ls |egrep '[.]ts$' \
        |sort "-t$delimiterBeforeFileNumber" -k2,2n \
        |sed -r "s/(.*)/file '\1'/" >ts.files.txt

    ffmpeg -f concat -i ts.files.txt -c copy tsw.014.ts.mp4

两条准备代码行仅创建一个文件,其中包含以下行格式的TS文件列表:

    file 'seg-37-a.ts'

实际上,当我尝试这样做时,最终视频中的各个片段之间有些“停顿”。因此,至少在这种情况下,它有助于首先串联TS文件。
Sphinxxx

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.