You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用Go或C++转码fmp4分段AVCC/AnexB流并保留PTS/DTS?

问题解答

导出的.h264文件合法性说明

你看到的重复SPS/PPS是gohlslib生成fmp4分片时的正常行为——为了保证每个分片能独立被解码器解析,库会在分片头部插入参数集(即便分段内已有)。这种带重复SPS/PPS的.h264文件完全合法,H.264解码器会自动忽略重复的参数集,不影响后续处理。

Go语言实现转码并保留PTS/DTS

Go本身无原生H.264转码库,通常借助FFmpeg工具或其绑定库实现:

  • 直接调用FFmpeg命令行:通过os/exec执行命令,核心参数-copyts用于强制保留原流的PTS/DTS:
    package main
    
    import "os/exec"
    
    func main() {
        cmd := exec.Command(
            "ffmpeg",
            "-i", "input.h264",
            "-c:v", "libx264",
            "-preset", "fast",
            "-copyts",
            "-crf", "23",
            "output.h264",
        )
        if err := cmd.Run(); err != nil {
            // 处理错误逻辑
        }
    }
    
  • 使用FFmpeg绑定库:比如github.com/u2takey/ffmpeg-go,封装了FFmpeg API,核心逻辑和命令行一致,只需配置时间戳保留参数即可。

C++语言实现转码并保留PTS/DTS

基于FFmpeg的libav系列库(libavformat、libavcodec、libswscale)可实现精细化控制,核心步骤如下:

  1. 初始化输入上下文,打开.h264文件并找到视频流,初始化解码器。
  2. 循环读取AVPacket并解码为AVFrame,记录原帧的pts、dts和时间基。
  3. 初始化输出编码器,根据目标码率/分辨率配置参数,注意时间基的转换对齐。
  4. 将解码后的AVFrame转换为编码器时间基下的时间戳,编码后写入输出文件。

关键代码片段示例:

// 解码得到AVFrame后,转换时间戳到编码器时间基
frame->pts = av_rescale_q(pkt->pts, in_stream->time_base, out_codec_ctx->time_base);
frame->dts = av_rescale_q(pkt->dts, in_stream->time_base, out_codec_ctx->time_base);
frame->duration = av_rescale_q(pkt->duration, in_stream->time_base, out_codec_ctx->time_base);

// 发送带时间戳的帧到编码器
int ret = avcodec_send_frame(out_codec_ctx, frame);
// 处理编码后的AVPacket并写入输出

该逻辑可确保转码后帧的时间戳与原分片完全对应,不破坏原有分段的时间结构。

注意事项

  • 转码时需确保输入.h264文件完整包含所有NALU(包括重复的SPS/PPS),解码器会自动处理冗余参数集。
  • 若生成ABR多码率流,仅需调整编码器的码率、分辨率参数,时间戳保留逻辑保持一致。

内容的提问来源于stack exchange,提问作者bot.top.pop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 16:35:11