FFmpeg时间基相关函数大杂烩

目录

一、核心时间基概念速记

二、时间基转换「主函数表」(最重要)

[三、AVRational 工具函数表](#三、AVRational 工具函数表)

[四、FFmpeg 内置时间基常量](#四、FFmpeg 内置时间基常量)

五、不同场景「怎么选函数」对照表

[1️. Packet PTS → 毫秒(最常用)](#1️. Packet PTS → 毫秒(最常用))

[2️. Frame PTS → 秒(double)](#2️. Frame PTS → 秒(double))

[3️. 音频 frame → 下一帧 pts(防抖动)](#3️. 音频 frame → 下一帧 pts(防抖动))

[4️. Seek 时间戳(必须 round)](#4️. Seek 时间戳(必须 round))

[5️. 音视频同步(master clock = audio clock)](#5️. 音视频同步(master clock = audio clock))

[六、av_rescale_q_rnd 的 rounding 参数详解](#六、av_rescale_q_rnd 的 rounding 参数详解)

[七、Stream / Codec / Frame 时间基到底用哪个?](#七、Stream / Codec / Frame 时间基到底用哪个?)

八、完整"黄金模板"

九、时间基"血泪坑"速查表

十、一句话总结


觉得有用,就请您帮忙点赞转发收藏吧,您的鼓励是我创作的动力,多谢看官。

由于能力水平有限,文中的错误或不严谨的地方在所难免,还请批评指正。

FFmpeg 在处理视频和音频时,经常需要与时间基(time base)相关联的操作。时间基是视频和音频处理中的一个核心概念,它定义了帧之间的时间间隔。FFmpeg 提供了一系列的函数和工具来帮助开发者处理与时间基相关的问题。


一、核心时间基概念速记

名字 类型 含义
AVRational {int num, den} 时间单位:1 / den
time_base AVRational 一单位 pts 等于多少秒
pts / dts int64_t 时间戳(单位是 time_base)
AV_TIME_BASE 1000000 ffmpeg 内部时间:微秒

公式一句话:

复制代码
真实时间(s) = pts × num / den

二、时间基转换「主函数表」(最重要)

函数 原型 / 参数 用途 常见场景
**av_rescale_q()**​ (a, src_tb, dst_tb) pts 从 A 时间基 → B 时间基 99% 用这个
**av_rescale_q_rnd()**​ (a, src, dst, enum AVRounding) 同上 + 四舍五入 / ceil 音频 / 精确对齐
av_rescale() (a, b, c) a*b/c防止溢出 自己算 ratio
av_rescale_rnd() (a, b, c, rnd) 带 round 的整数 rescale 底层封装
av_mul_q() (AVRational a, AVRational b) rational 乘法 推导 time_base
av_div_q() (a, b) rational 除法 fps ↔ duration
av_add_q()/ av_sub_q() (a,b) rational 加减 偏移时间

记住一句话:FFmpeg 里永远用 av_rescale_q()做 pts 转换


三、AVRational 工具函数表

函数 作用 示例
av_make_q(num, den) 构造 AVRational AVRational tb = av_make_q(1, 1000);
av_d2q(d, max) double → AVRational tb = av_d2q(1.0/44100, 100000);
av_q2d(tb) tb → double 秒 sec = pkt->pts * av_q2d(tb);
av_inv_q(tb) 倒数 fps → 每帧秒数
av_reduce() 约分 rational 内部用

四、FFmpeg 内置时间基常量

常量 / API 含义
AV_TIME_BASE 1000000(微秒)
AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE}
av_get_time_base_q() 返回 AV_TIME_BASE_Q

音视频同步常用目标:

复制代码
dst_tb = AV_TIME_BASE_Q;   // 微秒
dst_tb = av_make_q(1,1000); // 毫秒

五、不同场景「怎么选函数」对照表

1️. Packet PTS → 毫秒(最常用)

复制代码
int64_t ms = av_rescale_q(pkt->pts,
                          stream->time_base,
                          av_make_q(1, 1000));

av_rescale_q


2️. Frame PTS → 秒(double)

复制代码
double sec = pkt->pts * av_q2d(stream->time_base);

av_q2d(只读不写)


3️. 音频 frame → 下一帧 pts(防抖动)

复制代码
AVRational tb = codec_ctx->pkt_timebase;
int64_t next_pts = av_rescale_q(
    frame->nb_samples,
    av_make_q(1, frame->sample_rate),
    tb
);

推导音频时钟


4️. Seek 时间戳(必须 round)

复制代码
int64_t seek_ts = av_rescale_q_rnd(
    target_ms,
    av_make_q(1, 1000),
    stream->time_base,
    AV_ROUND_DOWN   // 或 AV_ROUND_NEAR_INF
);

avformat_seek_file(fmt_ctx, audio_idx, INT64_MIN, seek_ts, INT64_MAX, 0);

seek 必须用 _rnd


5️. 音视频同步(master clock = audio clock)

复制代码
double vid_clk = vid_pkt->pts * av_q2d(vid_tb);
double aud_clk = aud_pkt->pts * av_q2d(aud_tb);
double diff = aud_clk - vid_clk;

六、av_rescale_q_rnd 的 rounding 参数详解

行为 用途
AV_ROUND_ZERO 向 0 取整 不推荐
AV_ROUND_INF 远离 0 很少用
AV_ROUND_DOWN 向下 ✅ seek(避免越界)
AV_ROUND_UP 向上 buffer size
AV_ROUND_NEAR_INF 四舍五入 ✅ 显示时间 / 音频对齐
AV_ROUND_PASS_MINMAX 保留 INT64_MIN/MAX 内部用

推荐记忆:

复制代码
seek   → AV_ROUND_DOWN
ui ms → AV_ROUND_NEAR_INF

七、Stream / Codec / Frame 时间基到底用哪个?

这是新手地狱,直接给结论表:

对象 pts 所在 timebase 怎么转
AVPacket AVStream::time_base av_rescale_q(pkt->pts, st->time_base, dst)
AVFrame(video) AVCodecContext::pkt_timebasest->time_base 解码后一般继承 stream
AVFrame(audio) 解码后建议转成 1/sample_rate 自己算
avformat_seek_file() AVStream::time_base 别用 AV_TIME_BASE

经典错误:

复制代码
avformat_seek_file(fmt_ctx, idx, ..., ms, ..., 0); // ❌ ms 直接塞

八、完整"黄金模板"

复制代码
static int64_t pts_ms(AVPacket *pkt, AVStream *st)
{
    return av_rescale_q_rnd(
        pkt->pts,
        st->time_base,
        av_make_q(1, 1000),
        AV_ROUND_NEAR_INF
    );
}

static int64_t pts_us(AVFrame *frm, AVStream *st)
{
    return av_rescale_q(frm->pts,
                        st->time_base,
                        AV_TIME_BASE_Q);
}

九、时间基"血泪坑"速查表

结果
pkt pts 当秒用 快进 1000 倍
seek 用微秒直接塞 seek 到天边
audio frame 用 video timebase 声音飞走
rescale 不 rnd 帧跳
pkt/dts 混用 B 帧倒放

十、一句话总结

**FFmpeg 时间基只有三条铁律:**​

1️.pts 永远是 int64_t,单位是 AVRational

2️.转换只用 av_rescale_q()/ av_rescale_q_rnd()

3️.seek / 显示 / 同步各选一个主时钟,统一 rescale 再比

相关推荐
程序员老陆1 天前
FFmpeg libswresample 模块的关键函数swr_convert 到底在干嘛?
ffmpeg·音视频·格式转换·音频重采样
海兰1 天前
ffmpeg-wasm 完整安装指南(Ubuntu 24.04)
ubuntu·ffmpeg·wasm
≮傷£≯√2 天前
QT配置FFmpeg
开发语言·qt·ffmpeg
Everbrilliant892 天前
Android FFmpeg 实战:从基础到播放器的完整技术解析
android·ffmpeg·ffmepg实战·音视频同步实现·ffmpegpractices·ffmpegpractice·opengl 视频渲染
苏灿烤鱼3 天前
从微信公众号内容到视频号视频:自动化视频生成的技术实现
人工智能·python·ffmpeg
桐桐桐3 天前
视频画面裁剪与尺寸压缩实战:ffmpeg crop/scale 用法与在线替代
ffmpeg·音视频·视频
程序员老陆3 天前
音频为什么不编码成“声卡格式”(例如S16)?因为声卡只负责响,编码器只负责省
ffmpeg·音视频
程序员老陆4 天前
FFmpeg -tune参数全景解析:zerolatency、film、animation 到底在调什么?
ffmpeg·音视频·编码
cpp_learner4 天前
FFmpeg 硬件解码全流程解析
ffmpeg