公司动态

FFmpeg时间基相关函数大杂烩

📅 2026/8/10 22:28:04
FFmpeg时间基相关函数大杂烩
目录一、核心时间基概念速记二、时间基转换「主函数表」最重要三、AVRational 工具函数表四、FFmpeg 内置时间基常量五、不同场景「怎么选函数」对照表1️. Packet PTS → 毫秒最常用2️. Frame PTS → 秒double3️. 音频 frame → 下一帧 pts防抖动4️. Seek 时间戳必须 round5️. 音视频同步master clock audio clock六、av_rescale_q_rnd 的 rounding 参数详解七、Stream / Codec / Frame 时间基到底用哪个八、完整“黄金模板”九、时间基“血泪坑”速查表十、一句话总结觉得有用就请您帮忙点赞转发收藏吧您的鼓励是我创作的动力多谢看官。由于能力水平有限文中的错误或不严谨的地方在所难免还请批评指正。FFmpeg 在处理视频和音频时经常需要与时间基time base相关联的操作。时间基是视频和音频处理中的一个核心概念它定义了帧之间的时间间隔。FFmpeg 提供了一系列的函数和工具来帮助开发者处理与时间基相关的问题。一、核心时间基概念速记名字类型含义AVRational{int num, den}时间单位1 / den秒time_baseAVRational一单位 pts 等于多少秒​pts / dtsint64_t时间戳单位是 time_baseAV_TIME_BASE1000000ffmpeg 内部时间微秒公式一句话真实时间(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防止溢出自己算 ratioav_rescale_rnd()(a, b, c, rnd)带 round 的整数 rescale底层封装av_mul_q()(AVRational a, AVRational b)rational 乘法推导 time_baseav_div_q()(a, b)rational 除法fps ↔ durationav_add_q()/av_sub_q()(a,b)rational 加减偏移时间记住一句话FFmpeg 里永远用av_rescale_q()做 pts 转换三、AVRational 工具函数表函数作用示例av_make_q(num, den)构造 AVRationalAVRational tb av_make_q(1, 1000);av_d2q(d, max)double → AVRationaltb 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_BASE1000000微秒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_q2️. Frame PTS → 秒doubledouble 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 时间戳必须 roundint64_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 必须用_rnd5️. 音视频同步master clock audio clockdouble 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 sizeAV_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怎么转AVPacketAVStream::time_baseav_rescale_q(pkt-pts, st-time_base, dst)AVFrame(video)AVCodecContext::pkt_timebase或st-time_base解码后一般继承 streamAVFrame(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单位是AVRational2️.转换只用av_rescale_q()/av_rescale_q_rnd()3️.seek / 显示 / 同步各选一个主时钟统一 rescale 再比