96SEO 2026-02-20 09:58 18
我们的播放器现在能够同时视频和音频了但还不够你会发现视频画面和音频会对不上这是因为我们没有做音画同步。

在现有的代码中我们每隔
去播放一帧画面而音频则是由系统的音频线程来负责驱动调用。
这等于说视频和音频各播各的画面与声音失去了同步。
因此本章将讨论如何进行音画同步。
rambodrahmani/ffmpeg-video-player
ffmpeg_video_player_tutorial-my_tutorial05_01_clock.cpp。
帧关键帧也被称为内插帧。
每一帧都是独立的图像也就是说它不依赖于其他任何帧的图像信息。
I帧类似于完整的图像编解码器只需要本帧数据就可以完成解码。
在视频播放时I帧也是快进、快退、拖动的定位点通常情况下视频中的第一帧就是I帧。
帧预测帧P帧的数据包含与前一个I帧或P帧的差别在编码时仅考虑了前向预测也就是只与前一帧比较来找出两帧之间的区别然后只记录下这个差别。
P帧依赖于前面的I帧或P帧。
帧双向预测帧B帧记录的是该帧与前后帧的差别即考虑了双向的预测可以理解为B帧被插在I、P帧之间通过前后帧进行预测、记录、解压。
B帧依赖于前后的I帧或P帧。
需要所有这些帧的主要原因是为了压缩视频。
I帧需要的数据量最多但是不可能所有帧都为I帧这样压缩率就很低所以P帧和B帧诞生了P帧和B帧只记录和参考帧的差异信息所以数据量小压缩率高缺点是如果参考帧丢失那么将导致无法解压出真实图像。
总的来说所有这些帧的组合能够使视频数据得以有效的压缩同时保持视频质量。
这种编码模式下视频帧的解码过程较为简单播放顺序和解码顺序是一样的因为这种情况下没有B帧存在P帧只依赖前面的I帧或P帧。
首先解码第一帧I帧I帧是关键帧可以独立解码不依赖任何其他帧。
然后解码第二帧P帧此P帧只依赖于前一帧前一帧是I帧已经解码。
接着解码第三帧P帧此P帧也只依赖于前一帧前一帧是P帧已经解码。
最后解码第四帧P帧此P帧只依赖于前一帧前一帧是P帧已经解码。
这种编码模式下视频帧的解码顺序和播放顺序也是不一样的。
B帧依赖前面和后面的帧因此需要等待后一个参考帧I或P帧解析完成后才能开始
首先解码第一帧I帧I帧是关键帧可以独立解码不依赖任何其他帧。
然后解码第四帧P帧P帧只依赖于之前的I帧或P帧这一步可以顺利进行。
解码完第四帧P帧后才能开始解码第二帧和第三帧B帧。
B帧需要依赖前一帧和后一帧也就是需要依赖第一帧I帧和第四帧P帧。
因此类似的在包含B帧的情况下解码顺序和播放顺序是有所不同的这也是为什么在视频解码过程中需要对帧进行重新排序的原因。
Stamp解码时间戳来表示解码的顺序PTSPresentation
都是时间戳那么时间的单位是什么是秒s还是毫秒ms呢其实都不是DTS
是以时间基(timebase)为单位的时间基是由编码格式决定的通常它是一个如1/90000这样的分数。
呢引入timebase主要是为了提供更为灵活和精细的时间表示方法。
虽然可以选择只用秒或毫秒作为单位但这可能会在一些特殊的情况下引入不必要的误差或者损失精度。
在多媒体处理中每种编码格式或者媒体流可能有其特定的帧率或者时钟频率用一个固定的时间单位如秒或毫秒可能难以精确地表示这些特定的时间点或时长。
比如有些视频可能是24帧/秒有的可能是30帧/秒有的可能是29.97帧/秒等。
而timebase是一个分数形式的时间单位它的分子和分母都可以根据具体的编码格式或者媒体流来自由设定可以精确适配不同的帧率和时钟频率使得时间表示既可以非常精细也可以非常灵活。
例如对于一个帧率为29.97fps的视频我们可以设置timebase为1/30000这样就能够非常精确地表示每一帧的时间。
所以引入timebase主要是为了在多媒体处理中提供一个既灵活又精确的时间表示方法。
不如常见的秒或者毫秒那样直观。
对于绝大多数人来说1/30000秒涉及到的分数运算可能会比较难以理解相比之下33.33毫秒可能会更直观一些。
但是在多媒体编程中由于需要处理各种不同的编码格式和媒体流每种可能有其特定的帧率或者时钟频率这就需要一个更灵活和精细的时间表示方法来适应这些差异这就是引入timebase的原因。
对于程序来说处理timebase只不过是一些简单的乘法和除法运算而对于熟悉多媒体编程的开发者来说他们也已经习惯了timebase这样的时间表示方法。
在FFmpeg中timebase是一个分数表示的是时间单位用于进行时间戳与实际时间的转换。
它由一个分子和一个分母构成。
分子通常为1分母通常等于媒体的帧率或者时钟频率。
分子(numerator)通常为1在方程中根据需要设定分母(denominator)通常将帧率或者时钟频率设定为分母
以数字视频为例如果一个视频的帧率是每秒30帧那么它的timebase就是1/30这个值表示的是每帧的时间长度。
换算成秒就是约0.0333秒。
如果你有一个时间戳值例如100那么这个时间戳对应的实际时间就是100
再举一个数字音频的例子如果音频的采样率是44100Hz表示每秒钟有44100个音频样本那么它的timebase就是1/44100。
如果你有一个时间戳值例如22050那么这个时间戳对应的实际时间就是22050
需要注意的是不同的流可能有不同的time_base。
例如一个包含视频和音频的媒体文件它的视频流的time_base可能是1/30对应30fps的帧率而音频流的time_base可能是1/44100对应44100Hz的采样率。
所以在计算时间戳对应的实际时间时需要使用正确的time_base。
或者换一种理解在FFmpeg中timebase以一个分数形式存在分母表示将1秒拆分成的份额而分子表示每一帧或采样或其他计数单位占用的份额。
例如如果一个时间基准timebase是7/30那么这意味着1秒被拆分成了30份每一帧占用了7份。
所以每一帧对应的时间就是7
在大多数的实际应用中timebase的分子通常为1这是因为在大多数媒体格式中每一帧或其他的计数单位通常都对应于一个单位的时间。
这样的话如1/24、1/30、1/60这样的timebase也就表示了每帧的时间直接是1/24秒、1/30秒、1/60秒。
在FFmpeg中AV_TIME_BASE是一个宏定义其值为1000000。
这是作为FFmpeg内部处理时间戳时的一个共同参考用于统一不同的时间基准。
这个宏定义的原理是以微秒作为基础时间单位。
这样你可以用这个AV_TIME_BASE来将时间戳从微秒转换到FFmpeg内部使用的时间单位反之亦然。
例如如果你有一个以秒为单位的时间量你可以乘以AV_TIME_BASE将其转换为基于FFmpeg的时间单位。
AV_TIME_BASE。
多了解这一点可以帮助你更好地理解FFmpeg在处理时间戳时的一些机制和单位转换等问题。
需要注意的是虽然FFmpeg内部用AV_TIME_BASE作为统一的时间处理标准但是不同的流还是可能有各自的时间基准这需要我们在处理时对时间戳进行相应的转换。
假设我们有一个视频流帧率是30fps所以视频流的timebase是1/30我们还有一个音频流样本率是44100Hz所以音频流的timebase是1/44100。
假设我们现在有一个视频帧和一个音频样本它们的PTS显示时间戳分别是v_pts和a_pts。
首先我们需要把v_pts和a_pts转换到以AV_TIME_BASE为单位的时间戳也就是以微秒为单位的时间戳
AV_TIME_BASE然后我们就可以直接比较v_pts_us和a_pts_us这样就能知道音频和视频哪个应该先播放。
v_pts_us那么这个音频样本应该先播放。
这样就实现了音画同步。
当然这是一个简化的示例在真实的应用中可能还需要更复杂的逻辑来处理AV同步例如处理拖动播放条引起的seek操作处理音频和视频的解码延迟等。
结构体表示时间基数的分数结构体来重新缩放时间戳。
你可以像下面这样使用它
AV_TIME_BASE_QAV_TIME_BASE的时间基数值为1/1000000。
同样的你可以用这个函数转换音频时间戳
就目前的程序而言视频和音频正在愉快地运行根本不需要同步。
如果一切正常我们就不必担心这个问题。
但你的电脑并不完美很多视频文件也不完美。
因此我们有三种选择将音频同步到视频、将视频同步到音频或者将两者同步到外部时钟如电脑。
现在我们介绍的是将视频同步到音频。
我们首先要解决的第一个问题是如何精确的纪录当前视频/音频流的时间。
只有拿到了精确的时间我们才能知道视频与音频之间的快慢关系。
ffmpeg_video_player_tutorial-my_tutorial05_01_clock.cpp
ptspre_frame_delay上次帧的延迟。
在某些情况我们将使用这个变量作为当前帧的延迟。
|--------------------|--------------------|--------------------|
|----------|---------------------------------------------|-----|
...play_ctx-setClock(play_ctx-audio_clock_t,frame-pts
av_q2d(audio_stream-time_base));//
本文主要讲解如何将视频同步到音频因此在音频线程中我们只需更新音频时钟而无需进行任何同步操作。
所有的音频视频同步操作都会在视频播放线程中进行。
毫秒刷新一帧的视频为例。
如果视频播放速度超过了音频我们可以适当地延长下一帧的刷新时间使视频播放速度慢一些给音频一些“追赶”的时间比如延长到
毫秒刷新一帧。
相反如果音频的播放速度快于视频我们可以缩短下一帧的刷新时间使视频播放快一些以便能跟得上音频的速度。
av_q2d(decode_ctx-video_stream-time_base);auto
video_timebase_d;setClock(video_clock_t,
video_clock_t.pre_pts;printf(PTS
video_clock_t.pre_frame_delay;}printf(Corrected
pts;video_clock_t.pre_frame_delay
};上述代码片段是一个函数用于视频同步。
用于使用音频时钟作为参考来调整视频帧的展示时间从而实现音画同步。
pts。
影片序数pts是一个表示时间基数的特殊单位表示在给定的时间标度time
decode_ctx-video_stream-time_base
pts_delay它表示当前帧和上一帧之间的延迟。
如果这被认为是无效的即小于等于0或大于等于1.0则会使用先前的帧延迟。
这些信息存储起来供下一次使用。
第三部分获取音频时钟
video_clock并计算出二者之间的差值diff这表示音频和视频帧之间的延迟。
第四部分计算出调整阈值
pts_delay音频和视频同步。
若差值音频和视频延时过大则根据其正负使视频速度加快或放慢实现音视频同步。
最后返回
的值以毫秒为单位这个返回值将被用作等待时间来决定何时展示下一帧。
是如何描述时间的然后我们详细的描述了音画同步实施的具体要点包括如何精确的纪录不同流的当前时间在什么时间节点来更新时钟以及音画同步的具体算法。
ffmpeg_video_player_tutorial-my_tutorial05_01_clock.cpp。
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback