阶段 9 · 原生实践高级32 分钟
原生音画同步:时钟、队列与丢帧策略
Audio Clock、Video Clock、External Clock 与 Drift Correction
实现以音频为主时钟的视频调度,处理早到等待、轻微漂移校正、严重迟到丢帧与 Seek 后时钟重置。
LEARNING GOALS
先明确本课目标
1
从已播放样本估算 audio clock
2
按视频 PTS 计算展示延迟
3
设计漂移阈值和丢帧策略
MENTAL MODEL · 再建立心智模型
音频设备是匀速传送带,视频帧像带预约时间的包裹;调度器比较预约 PTS 与传送带时钟,决定等、送或丢。
MINIMAL EXAMPLE
视频比音频早 60ms 时应该做什么?
先把视频 PTS 和 audio clock 换算到同一秒数,diff=videoPTS-audioClock。正值表示视频早到,应延迟;负值表示视频迟到,超过阈值才考虑丢帧。
cppdouble diff = videoPtsSeconds - audioClockSeconds;
if (diff > syncThreshold) {
scheduleAfter(std::min(diff, maxDelay));
} else if (diff < -dropThreshold) {
dropFrame();
} else {
renderOnNextVsync();
}- 统一时间域求差 PTS 与设备时钟必须都换算为秒。
- 早到则有限等待 设置 maxDelay 防止异常时间戳导致长时间停顿。
- 严重迟到才丢帧 死区内正常展示,避免对微小抖动过度反应。
视频围绕连续音频时钟稳定展示,并能在解码落后时主动追赶。
OPTIONAL · 按需查阅完整术语表与概念边界遇到陌生术语时再展开,不打断主线实验。
展开⌄
音视频原理PTSPresentation Timestamp,表示解码后帧应在媒体时间轴上展示或播放的时间。音视频原理A/V Sync依据共同主时钟协调音频样本和视频帧在正确时间输出的机制。音视频原理Audio Clock根据音频设备实际已播放样本估算的媒体时钟,常作为播放器同步主时钟。音视频原理Master Clock播放器选择的同步基准时钟;音频、视频或外部时钟之一作为主时钟,其他输出据此等待、追赶或丢帧。音视频原理Video Clock依据视频帧 PTS 和实际呈现进度估算的播放时钟,用于与音频或外部主时钟比较。音视频原理Clock Drift两个独立硬件或软件时钟运行速率存在微小差异,时间越久累计偏差越大的现象。音视频原理Frame Drop当视频帧已经明显晚于主时钟时跳过该帧,以阻止延迟继续累积的同步策略。音视频原理Sync Threshold判断音视频时间差是否需要等待、立即显示或丢帧的容忍阈值;通常应结合帧时长和播放状态动态设置。音视频原理External Clock不直接由音频设备或视频帧推进的外部时间基准,例如系统单调时钟或直播同步时钟,可在特定播放器中作为主时钟。
LIVE EXPERIMENT · 先获得反馈
边改边运行
浏览器加载后会激活代码编辑器、独立运行环境与实时输出。
本课挑战
实现一个带时钟死区、最大校正幅度和连续丢帧保护的调度器。
回到原理,解释刚才发生了什么
先用结果建立反馈,再按运行流程、核心原理和知识关系逐层深入。
CORE IDEA
核心讲解
音频常作为主时钟
声卡连续消费样本,其播放位置可由已提交样本减缓冲剩余估算。视频较容易通过等待或丢帧调整。
不要追逐每个微小误差
调度需要死区和上限。小误差保持原帧时长,中等误差微调延迟,大误差才丢帧或重同步,避免画面抖动。
OPTIONAL · 迁移时查阅Web 与原生实现对照主线实验完成后,再用完整映射处理跨平台或跨 API 迁移。
展开⌄
HTMLMediaElement 把同步做成黑盒,原生播放器必须把误差和决策变成可观测指标。
WebGL
以设备播放进度估算 audio clock,视频刷新线程按 PTS 和 diff 调度。
WebGPU
浏览器内部协调 audio/video;自建 WebCodecs 播放器可用 AudioContext.currentTime 作为参考。
同步代码必须同时记录 master clock、frame PTS、diff 和最终决策,否则很难诊断。