音视频同步

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了音视频同步相关的知识,希望对你有一定的参考价值。

参考技术A 上两篇文章单独写了FFmpeg解码视频与播放《 FFmpeg音频解码播放 》《 FFmpeg视频解码播放 》在项目中不可能直接使用一个线程来做视频的解码播放,通常视频流与音频流的解码播放都是存在单独的线程。线程随机抢占cpu来执行任务,解码过程中各帧数据解码的复杂度不一,导致执行任务速度上存在差异的,就会存在声音与画面不同步,严重的影响观看体验。
要做音视频的同步就要引入帧的缓冲对列,来缓存视频解码的帧数据,通过调节音频播放线程或画面渲染线程控制播放的速度来达到声音与画面同步,也可以解决因为解码复杂度的不一导致解码的抖动导致的视频播放卡顿,影响到视频播放。
机器是并不能像我们人一样去感知声音与画面是否在同一时间上播放。因此在视频录制过程中都会给每帧数据标记一个时间戳,以方便来确定什么时刻去播放。这样就能严格的将声音与画面对应起来。
通常视频画面帧率25帧每秒,声音的采样率44100HZ,每秒都会抽取44100个采样点,理论上来说每生产一帧数据都会有一个固定的时长,实际中还是会存在略微偏差。包括声音和画面都是分开采集的时间上也会存在略微偏差,但在一定的阈值之内人是感觉不到音画的差异。声音与画面的同步就是控制好在同一时刻播放器该去渲染帧画面,播放那帧音频数据。

1.以声音为播放基准,调控画面渲染的速度
2.以画面渲染为基准,调控声音播放速度快慢
3.参考一个外部时钟,将声音与画面同步至此时间
通常我们都采用第一种方式,以声音为基准去调控画面的播放速度,一般画面的播放速度要比声音播放要快,人耳对声音的快慢感知度是比较强的,能够快速的感知声音的不正常(快或者是慢),对于画面的渲染其实就是一张张的图片刷新,反而人眼的感知度却没有那么强。

具体看看怎么实现画面同步到音频的先来了解一下FFmpeg 中一些时间相关概念

每帧数据都有标识DTS(解码时间戳)和PTS(显示时间戳),音频的PTS和DTS是一致的,而某些视频中因为有B帧的存在DTS和PTS不一至,DTS与PTS用来确定该帧数据的解码时刻与显示时刻。

对于视频流与音频流的time_base不一定是相同的,因此在做同步的时候要取对应流中的时间基作为计算标准来计算当前的时间。time_base简单的理解就是一个时间的度量单位,通过当前帧的PTS*time_base就可以获取到当前的实际播放的时间。

画面同步声音,在音频播放线程不断的去计算当前播放的音频帧的实际时间,在画面渲染线程获取当前画面的播放实际时间,两个时间做比较,如果画面当前时间大于音频播放时间,计算出画面应该延时的时间。将画面渲染线程进入休眠等待音频追上画面播放再去播放。如果画面当前时间小于音频时间(这种情况比较少出现,一般画面的速度都是快与声音的播放速度),当时间差大于一点的阈值这时候我们可以不进行该帧的渲染(跳帧丢帧去追上音频的播放)

与 ffmpeg 的音视频同步

【中文标题】与 ffmpeg 的音视频同步【英文标题】:Audio Video Sync With ffmpeg 【发布时间】:2012-12-16 14:59:52 【问题描述】:

我有一个非常奇怪的视频文件。 它有音频/视频同步问题。视频很快,音频很好。 视频有奇怪的帧速率:26.07 fps。

如何使用 ffmpeg 修复视频流。在视频开始时,同步正常,但在视频流结束时,还剩下大约 5 分钟的音频,并且正在黑屏播放。

这是 ffmpeg -i video.avi 的输出

ffmpeg version git-2011-10-15-1d0afec, Copyright (c) 2000-2011 the FFmpeg developers
  built on Oct 15 2011 14:27:57 with gcc 4.4.5
  configuration: --enable-gpl --enable-libfaac --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libtheora --enable-libvorbis --enable-libx264 --enable-nonfree --enable-postproc --enable-version3 --enable-x11grab --enable-libxvid
  libavutil    51. 21. 0 / 51. 21. 0
  libavcodec   53. 20. 1 / 53. 20. 1
  libavformat  53. 16. 0 / 53. 16. 0
  libavdevice  53.  4. 0 / 53.  4. 0
  libavfilter   2. 43. 6 /  2. 43. 6
  libswscale    2.  1. 0 /  2.  1. 0
  libpostproc  51.  2. 0 / 51.  2. 0
[mpeg4 @ 0xa585420] Invalid and inefficient vfw-avi packed B frames detected
Input #0, matroska,webm, from 'video.avi':
  Duration: 02:03:46.01, start: 0.000000, bitrate: 103 kb/s
    Stream #0:0: Video: mpeg4 (Advanced Simple Profile) (XVID / 0x44495658), yuv420p, 704x288 [SAR 1:1 DAR 22:9], 26.07 fps, 25 tbr, 1k tbn, 25 tbc (default)
    Stream #0:1(pol): Audio: ac3, 48000 Hz, 5.1(side), s16, 448 kb/s (default)

【问题讨论】:

【参考方案1】:

首先您可能需要分离音频:

 ffmpeg -i input.avi -vn -ac 2 -ar 48000 -ab 448k -f mp3 audio.mp3

然后您需要将视频文件的整个长度(以秒为单位)除以视频流的实际长度(视频停止并且您可以听到音频的时间)。你应该得到一个略高于 1 的数字(1.12 或类似的数字)。你取这个商,然后:

 ffmpeg -i input.avi -vf "setpts=quotient*PTS" -an output.avi

然后你将视频和音频结合起来。

【讨论】:

以上是关于音视频同步的主要内容,如果未能解决你的问题,请参考以下文章

谈一谈:音视频同步原理及实现

使用rtcp实现音视频同步

关于音视频同步

即时通讯——详解音视频同步技术

与 ffmpeg 的音视频同步

音视频同步