开发文章

FFMPEG转码音视频不同步情况总结

使用FFMPEG转码一年半的时间,遇到了各种情况的音视频不同步,下面我们就来根据问题出现的原因,对所遇到的音视频不同步做一个分类。

1. 源本身音视频不同步且无法播放

这种情况极为罕见,在A客户东方卫视频道转码时遇到过。

表现为输出的音视频严重不匹配,录制下来的视频源无法播放,要么只有声音没有图像,要么只有图像没有声音,且图像播放卡顿。

解决方案:转码器无法修复这种异常源,需要反馈给源提供方修复。

2. 源本身的时间戳问题,但源可正常播放

这种情况较少见,在M客户湖南卫视直播源时出现过。

表现为转码出来的视频图像播放正常,但是没有声音。录制下来的视频源能正常播放。

分析方法:打印出输入AVPacket包的时间戳,发现音频包的PTS正常,而DTS长时间不变。

解决方法:读出音频数据包后,如果判断DTS != PTS,则强制将DTS设为PTS的值。

3. 一段时间内,只丢失一个流的数据

在M客户的中国气象频道转码过程中遇到。

表现:输入源有数据持续输入的情况下,转码有一段时间没有输出,且恢复输出后播放没有声音。

分析方法:录制出问题时间段的视频源,分析其中的音视频数据包及时间戳。分析发现在一段时间之内,大概几秒到十几秒,输入的音频流丢失而视频流正常,导致在输出交织时一直等不到音频流而不断地buffer数据,直到音频流恢复后,或者等待超时后才有数据输出,而输入音频流恢复后,由于FFMPEG中执行了如下代码调整了原本正常的音频时间戳,使得音频时间戳错乱,导致播放时只有画面而没有声音。

播放时只有画面而没有声音.png

解决方法:本段代码在已知场景中用处不大,可以注销掉;也可以将dts_delta_threshold阈值调至一个较大值(默认为10秒,可以调至100秒等等),使之不满足阈值而不做时间戳调整。另外,为了防止长时间缺失一个流时没有输出,以及防止buffer溢出,参数max_interleave_delta值不能设置过大。

4.  源的部分视频帧未设置时间戳

在一些客户的直播转码过程中,输入输出帧率相同的情况下,会遇到log中大量打印“Past duration XXX too large”且伴有frame drop相关信息的打印。

分析方法:将输入视频包的时间戳信息打印出来,发现一些视频帧未设置DTS/PTS,这些视频帧携带的时间戳都是默认值为AV_NOPTS_VALUE,代码中对该值的定义如下:

#define AV_NOPTS_VALUE         ((int64_t)UINT64_C(0x8000000000000000))

而这些帧在编码输出之前会被Drop掉,为了满足设定的帧率,后面的有效时间戳的帧会提前输出,导致视频提前而音频滞后。

解决方法:由于我们为这些未设置时间戳的输入帧填充有效时间戳不是一件很容易的事(需要结合输入视频是否采用B帧等),因此在输入输出帧率相同时,我们可以将这些携带无效时间戳的帧正常送至编码器编码并输出,而不是丢弃。

5. "dts < pcr"

在线CBR转码时常遇到"dts < pcr, TS is invalid"的打印,时间久了也可能引起输出码流的音视频失步。

首先我们先看看代码中PCR的计算,

PCR的计算.png

可见PCR的值与muxrate和写入到AVIOContext中的数据量有关系。

在保证封装码率稳定的前提下,我们需要关注写入到AVIOContext中的音视频数据的速度。一般音频编码的速率较为稳定,而视频编码速度受B帧策略的影响较大,当视频编码使用较多的B帧时,由于是双向预测,导致编码速度慢于时间戳相近的音频帧,而当视频帧编码完成并输出时,AVIOContext中已经填充了较多的音频帧,使得PCR值超过了当前输出的视频帧的DTS,即出现了“dts < pcr”的打印。

解决方法: 在线转码时,在对视频质量没有特别要求的前提下,优先保证编码速度,就x264编码器来说,可以使用zerolatency策略,禁掉B帧的使用并尽量降低编码延迟。

6. 循环源与非单调时间戳

在M客户电竞直播与H客户云转码项目中都遇到了这种循环源与非单调时间戳问题。

FFMPEG默认只支持单调时间戳,一旦遇到非单调时间戳,FFMPEG会强制修改输出时间戳,代码如下,

FFMPEG会强制修改输出时间戳.png

但修改后的时间戳是不正常的,导致输出视频播放异常。具体表现为,若为音视频透传,则输出的音视频均异常;若转码,输出的视频正常,而音频异常,这是因为视频编码器会根据帧率和输出的帧数重新计算时间戳,而音频时间戳则是继承了输入时间戳,从而输出的视频时间戳为单调递增的正常值,而音频时间戳为FFMPEG强制修改后的值,导致播放没有声音。

解决方法:

包括三个方面,

1.  将以上截图部分对时间戳的修改注销;

2. 取消由于非单调时间戳导致的转码退出:

时间戳导致的转码.png

3. 需要转码时,由于视频转码输出时间戳为单调递增,为了使音频时间戳与视频时间戳同步,需要将音频时间戳按照单调递增的顺序来说出,算法设计时需要考虑时间戳跳变、丢帧等各种情况的处理。

7.长时间转码后出现轻微音视频不同步

这种音视频不同步暂时没有找到根本原因,多见于网络不稳定时,对音视频丢帧数量统计不精确导致网络恢复后时间戳出现轻微不对齐,且随着转码时间的延长或者网络波动情况的增多,不同步程度会加重。由于暂时无法确定具体原因,且一般在转码几天之后才出现,因此针对该情况的处理方案是,设计一套音视频不同步检测算法来评估音视频不同步的程度,当达到一定的阈值后,通知前端重启转码器以达到重新同步。

感谢 DeliaPu 支持 磐实编程网 原文地址:
blog.csdn.net/deliapu/article/details/75667661

文章信息

发布时间:2017-07-27

作者:DeliaPu

发布者:aquwcw

浏览次数: