FFmpeg拼接文件常见问题

Posted Jack_Chai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FFmpeg拼接文件常见问题相关的知识,希望对你有一定的参考价值。

本文出处:http://blog.csdn.net/chaijunkun/article/details/117674932,转载请注明。由于本人不定期会整理相关博文,会对相应内容作出完善。因此强烈建议在原始出处查看此文。

拼接文件并不简单

将多个视频文件拼接在一起,看似是个很简单的需求,但事实上由于音视频编码的复杂性,原始素材编码的稍稍不同,有可能就会影响拼接的顺利进行。在之前的文章中,笔者介绍了音视频精准拼接的算法原理,以及音视频流顺序不一致导致的拼接问题,本篇文章,将继续介绍一些在拼接场景中的常见问题。

拼接清单文件

文件编码

清单文件中如果包含中文,需要使用UTF-8编码格式进行存储,并且不要带BOM。

文件名字符

在清单文件中指定的文件名,优先推荐使用不带目录的相对文件名,例如像上面的清单文件。这是因为在默认情况下,该种视频合并算法中对文件名进行了安全校验。详细的代码可以在libavformat/concatdec.c文件的safe_filename方法中看到。允许出现的字符为:A-Za-z0-9_-

当使用绝对文件名,尤其是在Windows环境中(有d:\\这样的盘符),检查会无法通过,需要加上-safe 0进行规避校验。另外,绝对文件名中的路径分隔符,无论在Windows下还是Linux下,均无需特别处理,直接使用“\\”或者“/”即可。

更多参考资料,可查阅官方文档:Concatenate Wiki

相对路径问题

笔者发现,在Windows和Linux中,FFmpeg对于concat清单文件中的路径解析方式不太一样。

Windows环境

清单文件有下列内容:

file 'D:\\res\\seg_01.mp4'
file 'template\\copyright.mp4'

目录结构:

D:
	\\res
		\\seg_01.mp4
	\\template
		\\copyright.mp4

FFmpeg工作目录:D:\\

Linux环境

清单文件有下列内容:

file '/data/res/seg_01.mp4'
file 'template/copyright.mp4'

目录结构:

/data
	/res
		/seg_01.mp4
	/template
		/copyright.mp4

FFmpeg工作目录:/data

分别运行

根据描述可知,除系统因素外,相对目录结构是一致的,在Windows中,FFmpeg可以正常识别相对目录的写法;在Linux中,FFmpeg在拼接时显示了警告信息:

[concat @ 0x5c57480] Impossible to open 'res/template/copyright.mp4' 5kbits/s speed= 919x
res/manifest.txt: No such file or directory

虽然命令退出代码是0,但输出的内容并不完整(如果强制在命令中指定了-xerror,则退出代码不为0)。

通过警告信息,发现尝试打开的文件路径并不正确,被强制在前追加了清单文件所在目录。而在Windows中,上述命令可成功执行。

总之归纳为,Windows系统下,查找相对文件名的完整文件名是基于工作目录的,而Linux系统下是基于清单文件所在目录的。

因此,为了保证各平台一致性,要么全部使用相对路径,并将资源放在一起;要么全部使用绝对路径

拼接素材编码参数

有时拼接多个素材时,某些可以正常执行,有些会在控制台显示出如下警告信息:

[mov,mp4,m4a,3gp,3g2,mj2 @ 000001d22ce17a40] Auto-inserting h264_mp4toannexb bitstream filter
[mov,mp4,m4a,3gp,3g2,mj2 @ 000001d22d7ff280] Auto-inserting h264_mp4toannexb bitstream filter
[mov,mp4,m4a,3gp,3g2,mj2 @ 000001d22ce1d440] Auto-inserting h264_mp4toannexb bitstream filter
[mp4 @ 000001d22d2f0740] Non-monotonous DTS in output stream 0:0; previous: 8505397, current: 8504899; changing to 8505398. This may result in incorrect timestamps in the output file.

前两条是正常拼接的输出,在第三条素材将要进行拼接时,提示stream 0:0出了问题。可能导致不正确的时间戳输出。

通过流编号以及查询原始素材,得知该问题出在视频流上。那么具体是什么问题呢?

在fftools/ffmpeg.c文件(write_packet方法)中,找到了相关的判断条件,该问题出现在视频流、音频流、字幕流的拼接时(当然还有一些例外情况,感兴趣的朋友可以自行查阅源代码),如果当前准备拼接的文件中,数据包dts(decode timestamp)小于之前所有的最大值,则触发该异常。

看来是原始素材的问题,这里需要一款跨平台的媒体分析工具:mediainfo。该工具可以很方便地查看媒体文件的编码信息,从而帮助我们更为方便地定位问题。先看下正常文件的编码信息(为方便,笔者使用的命令行版mediainfo,官方也提供了GUI版):

mediainfo source.mp4

得到以下输出,由于之前排查出问题来源于视频流,因此我做了节选:

Video
ID                                       : 1
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : Baseline@L4
...
Encoding settings                        : cabac=0 / ref=1 / deblock=0:0:0 / analyse=0:0 / me=dia ...

然后查看出现问题的文件:

mediainfo copyright.mp4

输出信息:

Video
ID                                       : 1
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : High@L4
...
Encoding settings                        : cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex ...

可以看到,两个文件的编码器设置参数不同,这主要是由于前者先采用了较低版本的Profile,而后面的文件使用了较高版本的Profile造成的。假设将两者顺序调换,先使用较高版本Profile的文件,再使用较低版本Profile的文件,是可以正常拼接的。由此可见,高版本可以兼容低版本,而低版本无法兼容高版本。这里顺便也列举一下,不同profile的特性:

Profile特性
Baseline支持I/P 帧,只支持无交错(Progressive)和CAVLC,一般用于低阶或需要额外容错的应用,比如视频通话、手机视频等;
Main支持I/P/B 帧,无交错(Progressive)和交错(Interlaced),CAVLC 和CABAC。用于主流消费类电子产品规格如低解码(相对而言)的mp4、便携的视频播放器、PSP和Ipod等;
High在Main的基础上增加了8x8 内部预测、自定义量化、无损视频编码和更多的YUV 格式(如4:4:4)。用于广播及视频碟片存储(蓝光影片),高清电视的应用。

因此,若拼接顺序无法改变,则必须将高版本的Profile降下来才可以正常拼接

ffmpeg -i copyright.mp4 -profile:v baseline -level:v 4 -c:a copy copyright_baseline.mp4

此时再进行拼接,恢复正常

[mov,mp4,m4a,3gp,3g2,mj2 @ 000002252880d580] Auto-inserting h264_mp4toannexb bitstream filter
[mp4 @ 0000022528a504c0] Starting second pass: moving the moov atom to the beginning of the file
frame=  429 fps=0.0 q=-1.0 Lsize=    3248kB time=00:00:17.17 bitrate=1549.4kbits/s speed= 740x
video:3153kB audio:82kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.373567%

参考文献:
[1]微岩.H264 Profile对比分析
[EB/OL].https://blog.csdn.net/matrix_laboratory/article/details/72764621,2017-05-26.

以上是关于FFmpeg拼接文件常见问题的主要内容,如果未能解决你的问题,请参考以下文章

FFmpeg拼接文件常见问题

FFmpeg拼接文件常见问题

FFmpeg拼接文件常见问题

ffmpeg拼接视频

ffmpeg_拼接并提取flv视频文件中的音频生成mp3文件

FFmpeg音视频拼接命令