基于FFmpeg官方转码示例开发H.265转换器,可采用什么进度展示单位(如百分比)
适配transcoding_8c示例的H.265转码进度实现方案
可采集的量化计算维度
所有维度都可以直接嵌入示例代码现有逻辑,不需要额外引入第三方依赖:
- 进度计算的基准分母:输入流总时长
在open_input_file流程中,直接从输入格式上下文的duration字段读取,单位为微秒,作为百分比计算的总参照值。如果遇到流元信息缺失(比如裸H.265流、损坏的MP4),则切换为粗粒度计算模式:用输入文件总大小当分母,已读取的输入文件字节数当临时参照。 - 进度计算的分子:已完成写入的输出流时间戳
示例代码本身有逐包写入输出文件的write_frame逻辑,每成功写入一个H.265编码后的视频包,就提取该包的dts时间戳,换算为微秒值,始终保留历史处理的最大dts值作为分子,不要逐包累加时间差,避免B帧重排序、时间戳偏移带来的进度倒退问题。 - 可选校准维度
- 如果输入容器元信息里记录了视频流总帧数,就累计逐帧解码的帧数量,用「已解码帧数/总帧数」和时间戳计算结果做加权平均,把进度误差控制在1%以内
- 按固定时间窗口(比如每500ms)统计一次实际转码速度(单位:微秒/秒),可以搭配百分比进度同步显示预估剩余转码时间
落地嵌入步骤
完全匹配transcoding_8c的原有执行流程,不需要重构核心转码逻辑:
- 初始化阶段:完成输入流打开后,立刻校验输入总时长的合法性——如果总时长值小于等于1秒(基本可以判定元信息读取异常),直接切到字节数统计的粗进度模式,不要硬算时间进度
- 转码循环阶段:在原有逐包读入、解码、编码的主循环里,每执行完一次成功的输出包写入操作,就实时计算当前进度值:
当前进度 = 钳位(已写入最大dts微秒值 / 输入总时长微秒值 * 100, 0, 100)
这里的钳位逻辑是为了避免时间戳误差导致进度出现负数、或者超过100%的异常展示 - 收尾阶段:当主循环读到输入流EOF,且把编码器内部残留的所有缓冲帧全部冲刷写入输出文件后,直接强制将进度值置为100%,避免因为H.265编码器参考帧队列较长,出现进度长时间卡在99%的问题
常见踩坑提醒
- 不要用已读取的输入包数量算进度:输入包里混杂音频包、无效的跳过帧,包数量和实际转码进度没有线性对应关系
- 不要在帧刚解码出来的时候就更新进度:H.265编码器的缓冲队列比H.264长很多,必须等帧完成编码、真正写入到输出文件之后再更新进度值,否则会出现进度虚高、最后长时间卡在90%以上等编码缓冲排空的问题
- 遇到时间戳跳变、丢帧的场景,不要直接累加时间差算进度,所有分子值只保留历史最大值,绝对避免进度数值倒退
内容的提问来源于stack exchange,提问作者BloodyFerret
相关产品推荐
相关产品推荐

