[ffmpeg] 时间基总结
三个常见 time base
tbc → time base (codec)
Codec 层的时间基数
在 FFmpeg 里是 AVCodecContext->time_base
表示「编码器/解码器理解的时间单位」
常见:
视频:1/framerate(例如 1/30)
音频:1/samplerate(例如 1/48000)
tbn → time base (stream)
Stream 层的时间基数
在 FFmpeg 里是 AVStream->time_base
表示「容器 / 协议使用的时间戳单位」
常见:
MP4/MKV → {1,1000} 毫秒
TS/RTP → {1,90000}(90 kHz 时钟)
RTMP → {1,1000} 毫秒
音频轨 → 通常 {1,sample_rate}
tbr → time base (rate)(准确说是 frame rate guess)
avg_frame_rate / r_frame_rate
ffmpeg 根据 PTS 统计出来的平均帧率
不是时基,只是给人看的帧率估算
为什么有了 tbc 还需要有 tbn
音视频的 tbc 本来就不一样。
视频:1/30 → 每个 PTS 单位 = 0.0333 秒
音频:1/48000 → 每个 PTS 单位 = 0.0000208 秒
如果直接把它们丢进容器,播放器根本没法对齐(一个用 0.0333s 计时,一个用 0.0000208s 计时)。
所以,容器层引入 统一的 time base(tbn):
所有流的时间戳都要 rescale 成 同一种“货币单位”,比如毫秒或 90kHz。
这样容器里的音视频轨才能对齐,播放器才能同步解码和播放。
什么时候需要转换时间基
一帧视频的渲染时间为 pts*时间基;
当刚开始 pts 的时间基是以 tbc 为单位保存的,在录制和发送前需要将 pts 和 dts 转换成对应协议的时间基下的 pts 和 dts。
btn 的时间基是怎么来的,可以改变吗?
btn 的时间基是每种协议根据自身场景,定义出来的,不能随意改变。
- MPEG-TS / RTP(H.264) → 90 kHz
来自广播电视标准(MPEG-2 Systems),定义了 PCR/PTS/DTS 的时钟基准是 90 kHz。
90 kHz 刚好是 27 MHz 时钟(硬件常用)除以 300,方便整数除法。
所以 TS、RTP 推流几乎都用 90 kHz time base。 - MP4/MOV → 通常 1/1000 或者其他 timescale(trak 级别可变)
ISO BMFF 规范里,timescale 是一个整数,表示“一秒有多少时间单位”。
写文件时 muxer 通常选 1000(毫秒)或者 600/48000(和音频采样率对齐),便于人类可读或和音频同步。 - MKV/WebM → 1/1000 秒
Matroska 规定了默认 timecode scale 是 1ms,所以大部分 MKV 就是 {1,1000}。 - AVI → 多数情况下 1/帧率
AVI 比较古老,直接用 dwScale/dwRate 定义帧率关系。
RTMP → 毫秒
Adobe RTMP 协议规定时间戳就是毫秒。