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

如何在FFmpeg C++代码中保留H.265视频的hvc1编码标签?

解决FFmpeg C++重封装时保留HEVC的hvc1编码标签问题

问题背景

我尝试复制带有HEVC视频的MP4文件,源文件的编码标签为hvc1:

Stream #0:0(und): Video: hevc (Main) (hvc1 / 0x31637668)

但复制后编码标签变为hev1:

Stream #0:0(und): Video: hevc (Main) (hev1 / 0x31766568)

已知FFmpeg命令行可通过-tag:v hvc1实现保留hvc1标签,但我在C++代码中尝试设置标签却无效,附上相关代码求解决方法。

问题分析

看你代码里的逻辑,你用av_codec_get_tag2去获取输出格式对应的编码器标签,但MP4容器对HEVC的默认标签是hev1,所以这个函数返回的就是hev1的数值,自然覆盖了你想要的hvc1。另外你后面多余的编码器上下文分配代码也没必要——重封装不需要编解码,只需要复制流参数就行,那部分代码反而可能干扰参数设置。

解决代码修改方案

直接针对HEVC视频流手动指定hvc1标签,替换你原来设置codec_tag的逻辑:

for (i = 0; i < (int)ifmt_ctx->nb_streams; i++) {
    AVStream *out_stream;
    AVStream *in_stream = ifmt_ctx->streams[i];
    AVCodecParameters *in_codecpar = in_stream->codecpar;

    if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO && in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO && in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
        stream_mapping[i] = -1;
        continue;
    }

    stream_mapping[i] = stream_index++;
    out_stream = avformat_new_stream(ofmt_ctx, NULL);
    if (!out_stream) {
        fprintf(stderr, "Failed allocating output stream\n");
        ret = AVERROR_UNKNOWN;
        goto end;
    }

    // 复制输入流的编码参数到输出流
    ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);
    if (ret < 0) {
        fprintf(stderr, "Failed to copy codec parameters\n");
        goto end;
    }

    // 单独处理HEVC视频流,强制设置hvc1标签
    if (in_codecpar->codec_id == AV_CODEC_ID_HEVC && in_codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        // MKTAG是FFmpeg宏,把字符转成对应32位标签值,hvc1对应0x31637668
        out_stream->codecpar->codec_tag = MKTAG('h','v','c','1');
    } else {
        // 其他流按原有逻辑获取默认标签
        unsigned int tag = 0;
        if (av_codec_get_tag2(ofmt_ctx->oformat->codec_tag, in_codecpar->codec_id, &tag) == 0) {
            av_log(NULL, AV_LOG_WARNING, "Could not find codec tag for codec id %d, using default 0.\n", in_codecpar->codec_id);
        }
        out_stream->codecpar->codec_tag = tag;
    }

    // 重封装不需要编码器上下文,删掉下面两行冗余代码
    // out_stream->codec = avcodec_alloc_context3(encoder);
    // avcodec_parameters_to_context(out_stream->codec, parameters);
}

补充说明

在MP4容器里,HEVC的两个标签区别在于:

  • hev1:只包含基础编码信息,不附带SPS/PPS等序列参数
  • hvc1:包含完整的SPS/PPS数据,兼容性更强(很多设备只认hvc1)

FFmpeg的MP4复用器默认用hev1,所以必须手动指定hvc1才能和源文件保持一致。

内容的提问来源于stack exchange,提问作者ppcat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:38:42