首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >四倍以内声音在,四倍以上只留关键帧

四倍以内声音在,四倍以上只留关键帧

原创
作者头像
用户1290566
发布于 2026-11-12 18:17:29
发布于 2026-11-12 18:17:29
190
举报

用户手里的倍速是一条档位滑杆,引擎里接住的却不是一档参数:四倍是一条线,线两边各有一套跑法。四倍以内每帧都解,音频变速不变调,画面靠丢帧追节奏;四倍以上解码已经追不上播放速度,整条链换成 I 帧模式——非关键帧在进包处就丢掉,音频整条退出,进度条换判据。这篇讲两边的跑法,以及从一边切到另一边时撞上的时序问题。

倍速在四倍分成两套跑法:四倍以内全量解码、音频变速不变调,四倍以上只解关键帧、音频整条退出。这篇讲分界从哪来、I 帧模式在进包处与渲染端各做什么,以及穿越四倍时那一下怎么接。

分水岭画在四倍,出处是解码吞吐

四倍以内,视频照常解码,显示时长按倍速缩放,落后了丢帧追赶;音频照常出声,只是时间轴被压缩。这一半的机制——变速在交给设备之前完成、时钟怎么走——音频渲染与音画同步两篇写过,这里不展开。

四倍这条线不是拍出来的。解码是这条链上最重的一段,全负荷跑也就实时四倍上下:两倍到四倍之间,解码线程连时间片都不让出,能解就立刻解下一包;再往上把每帧都解出来已经追不上,只能不解非关键帧。代码里那句注释写的就是这件事:超过四倍后只解码 I 帧,相反可以慢下来了。所以分界两侧是两条策略——一侧全速解、靠渲染端丢帧控节奏,另一侧干脆不解,把解码压力降下来。

丢弃的落点也只留一处:解码侧那段丢帧的分支在代码里是注释掉的,实际丢弃全发生在进包处。两处都丢,等于两个地方各扣各的,节奏反而乱。

恰好四倍仍按全量处理,丢弃只对超过四倍生效。

四倍以上:丢弃发生在进包处

开了只解 I 帧的开关、倍速又超过四倍,这两个条件合成一个真值,三处共用:进包处、渲染节奏、音频解码线程的超时豁免。共用是刻意的——音频解码线程在 I 帧模式期间要持续重置超时,因为音频包被丢掉、无包可解是预期;要是那边的判据单独写成「倍速大于四」,开关关掉、音频包正常流动时,豁免还在生效,真实的解码故障就被吞掉了。

四倍以上的 I 帧模式:丢弃、放行与直通各在哪一段
四倍以上的 I 帧模式:丢弃、放行与直通各在哪一段

进包处丢两类:视频的非关键帧直接丢,音频包也直接丢。配置帧照常放行——降回四倍以内时,新解码器要靠它立刻接上。录制不受影响:录制拿的是完整原始流,丢帧只是播放策略。

音频为什么是整条丢,而不是静音?静音的话音频管线还在按原速消费,包队列很快堆满,入队阻塞之后解封装就喂不进视频包,视频的 I 帧管线反而被饿死;反过来消费更快时,解封装又会狂读,进度条乱闪。在进包处丢掉,解封装只被视频 I 帧管线按倍速自节流,音频侧不需要任何节流参数。代价是同步也没了对象——四倍以上音频不渲染,音画同步一并关掉,降回来再恢复。

I 帧模式的渲染节奏与进度

I 帧模式下,每一帧只显示「自己的时长除以倍速」这么久:两秒一个关键帧的片源,八倍速就是每帧两百五十毫秒。普通模式的三件事在这里都要改:关键帧之间本来就隔得远,不把长间隔判成时间戳跳变;帧本来就少,不做丢帧;没有音频时钟可追,渲染节奏只按自己的缩放时长走。

进度条也换了判据,取渲染到哪,不取读到哪。四倍以上磁盘或网络会超前读,视频队列里能缓存上百个关键帧,相当于几十秒到几分钟的内容,拿读取位置当进度,进度条会说谎。

源侧也有一种 I 帧模式

上面都是播放侧的策略。还有一类流本身就是纯关键帧:一些切片、监看类的流,服务端只发 I 帧。这种流不用倍速就会撞上,引擎在源侧自动识别——连续收到时间戳不同的关键帧就进入 I 帧模式,收到 P、B 帧自动退出。另一条是预判:只有真有倍速语义的源(服务端能按倍速切流的)才在倍速下预判进入;对包流不随倍速变化的本地与点播源,预判只会白静音、打乱时钟。

穿过分水岭,按一次 seek 来接

两个方向切换,坑都在切换那一下,而且对称。

升速排干积压,降速重对位置,都按渲染时间重定位
升速排干积压,降速重对位置,都按渲染时间重定位

升速(四倍以内进到四倍以上):门闸只拦新包,包队列里已经积压的几十秒 P、B 旧包要靠解码排干才能真进入 I 帧模式,这个排干是秒级到几十秒——点了八倍速,画面还在慢慢放一阵,然后突然开始跳。修法是把它当成一次 seek:可重新定位的源,直接重定位到当前渲染位置,冲掉旧包,重启后的包全部经过已经打开的丢弃。四倍以上内部调速(八倍调六倍)本来没有积压,不走这条路。

降速(回到四倍以内)是另一个方向:四倍以上音频包被丢、解封装又超前读,音频恢复的位置和视频渲染位置对不上,进度条跟着音频时钟前后跳。修法一样,重定位到渲染位置;这一半音画同步那篇讲过。不可重定位的源(纯直播)没有这两条路,误差只能靠缓冲和后续同步慢慢收敛。

还有一处不起眼的滞后:变速插件的播放态一旦标定,回到一倍速并不立刻复位。半倍、两倍期间攒下的音视频解码轴发散要等队列排空才收敛,在那之前对齐看门狗会把这段发散误报成异常,所以这个闩一直留到换片或关闭才解。

体验上这道线很好认:四倍以上声音本来就不渲染,穿过去是「有声音和没声音」的区别,不是音量变小;变调只发生在四倍以内、且变速插件缺席的降级路径上。

引擎 avox 在 GitHub 开源,仓库 xxxzhou/avox。

系列《从零做一个全平台播放器》按施工顺序发,本篇是 6.2;已发各篇收在这里:https://cloud.tencent.com/developer/column/109457

上一篇:6.1 seek 先挑入口,要准就多解一段 https://cloud.tencent.com/developer/article/2781763

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 分水岭画在四倍,出处是解码吞吐
  • 四倍以上:丢弃发生在进包处
  • I 帧模式的渲染节奏与进度
  • 源侧也有一种 I 帧模式
  • 穿过分水岭,按一次 seek 来接
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档