FFMpeg 复制流而不转码

2023-12-04

我正在尝试将多个文件中的所有流复制到一个文件中,而不对流进行转码。你经常做的事情ffmpeg效用由ffmpeg -i “file_with_audio.mp4” -i “file_with_video.mp4” -c copy -shortest file_with_audio_and_video.mp4

这是代码:

int ffmpegOpenInputFile(const char* filename, AVFormatContext **ic) {

    int ret;
    unsigned int i;

    *ic = avformat_alloc_context();
    if (!(*ic))
        return -1; // Couldn't allocate input context

    if((ret = avformat_open_input(ic, filename, NULL, NULL)) < 0)
        return ret; // Couldn't open file

    // Get format info (retrieve stream information)
    if ((ret = avformat_find_stream_info(*ic, NULL)) < 0)
        return ret; // Couldn't find stream information

    for (int i = 0; i < (*ic)->nb_streams; i++) {
        AVStream *stream;
        AVCodecContext *codec_ctx;
        stream = (*ic)->streams[i];
        codec_ctx = stream->codec;
        /* Reencode video & audio and remux subtitles etc. */
        if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
            || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
            /* Open decoder */
            ret = avcodec_open2(codec_ctx,
                                avcodec_find_decoder(codec_ctx->codec_id), NULL);
            if (ret < 0) {
                av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);
                return ret;
            }
        }
    }

    // Dump information about file onto standard error
    av_dump_format(*ic, 0, filename, 0);

    return 0;
}



int main(int argc, char *argv[]) {

    const char *inputFilename1 = "/avfiles/video_input.mp4";
    const char *inputFilename2 = "/avfiles/audio_input.mp4";
    const char *filename = "/avfiles/out.mp4";

    int ret;

    av_register_all();

    AVFormatContext *ic1 = nullptr;
    AVFormatContext *ic2 = nullptr;
    AVFormatContext *oc = nullptr;

    if ((ret = ffmpegOpenInputFile(inputFilename1, &ic1)) < 0)
        return ret;  // and free resources and

    if ((ret = ffmpegOpenInputFile(inputFilename2, &ic2)) < 0)
        return ret;  // and free resources and

    AVOutputFormat *outfmt = av_guess_format(NULL, filename, NULL);
    if (outfmt == NULL)
        return -1;  // Could not guess output format

    avformat_alloc_output_context2(&oc, outfmt, NULL, filename);
    if (!oc)
        return AVERROR_UNKNOWN;  // Could not create output context

    // populate input streams from all input files
    AVStream **input_streams = NULL;
    int nb_input_streams = 0;
    for (int i = 0; i < ic1->nb_streams; i++) {
        input_streams = (AVStream **) grow_array(input_streams, sizeof(*input_streams), &nb_input_streams,
                                                 nb_input_streams + 1);
        input_streams[nb_input_streams - 1] = ic1->streams[i];
    }
    for (int i = 0; i < ic2->nb_streams; i++) {
        input_streams = (AVStream **) grow_array(input_streams, sizeof(*input_streams), &nb_input_streams,
                                                 nb_input_streams + 1);
        input_streams[nb_input_streams - 1] = ic2->streams[i];
    }

    for (int i = 0; i < nb_input_streams; i++) {
        AVStream *ist = input_streams[i];  // could be named 'm_in_vid_strm'

        // if output context has video codec support and current input stream is video
        if (/*oc->video_codec_id*/ oc->oformat->video_codec != AV_CODEC_ID_NONE && ist != NULL
                                   && ist->codec->codec_type == AVMEDIA_TYPE_VIDEO) {

            AVCodec *out_vid_codec = avcodec_find_encoder(oc->oformat->video_codec);
            if (NULL == out_vid_codec)
                return -1;  // Couldn't find video encoder

            AVStream *m_out_vid_strm = avformat_new_stream(oc, out_vid_codec);
            if (NULL == m_out_vid_strm)
                return -1;  // Couldn't output video stream

            m_out_vid_strm->id = 0;  // XXX:

            ret = avcodec_copy_context(m_out_vid_strm->codec, ist->codec);
            if (ret < 0)
                return ret;  // Failed to copy context

        }

        // if output context has audio codec support and current input stream is audio
        if (/*oc->audio_codec_id*/ oc->oformat->audio_codec != AV_CODEC_ID_NONE && ist != NULL
                                   && ist->codec->codec_type == AVMEDIA_TYPE_AUDIO) {

            AVCodec *out_aud_codec = avcodec_find_encoder(oc->oformat->audio_codec);
            if (nullptr == out_aud_codec)
                return -1;  // couldn't find audio codec

            AVStream *m_out_aud_strm = avformat_new_stream(oc, out_aud_codec);
            if (nullptr == m_out_aud_strm)
                return -1;  // couldn't allocate audio out stream

            ret = avcodec_copy_context(m_out_aud_strm->codec, ist->codec);
            if (ret < 0)
                return ret;  // couldn't copy context

        }
    }

    // finally output header
    if (!(oc->flags & AVFMT_NOFILE)) {

        ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE);
        if (ret < 0)
            return ret;  // Could not open output file

        av_dump_format(oc, 0, filename, 1);

        ret = avformat_write_header(oc, NULL);
        if (ret < 0)
            return ret; // Error occurred when opening output file

    }

    return 0;

}

avformat_write_header(oc, NULL);总是返回错误,我看到以下消息:

[mp4 @ 0x7f84ec900a00] Using AVStream.codec.time_base as a timebase hint to the muxer is deprecated. Set AVStream.time_base instead.
[mp4 @ 0x7f84ec900a00] Tag avc1/0x31637661 incompatible with output codec id '28' ([33][0][0][0])

但输入和输出流匹配:

Input streams from 2 files:
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 2834 kb/s, 23.98 fps, 23.98 tbr, 90k tbn, 47.95 tbc (default)
Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)

Output #0, mp4, to '/Users/alex/Workspace/_qt/tubisto/avfiles/out.mp4':
    Stream #0:0: Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 2834 kb/s, 47.95 tbc
    Stream #0:1: Audio: aac (libvo_aacenc) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s

为什么会出现输出编解码器不兼容的错误? 我的代码有什么问题以及如何使其能够将所有输入文件中的所有流复制到输出文件?


原因是你没有设置编码器codec_tag正确。

你应该设置正确的codec_tag,或设置codec_tag为 0 并让复用器为您处理。

以下是如何执行的示例代码。

AVFormatContext *ofmt_ctx; // todo
AVCodec *oc; // todo

AVStream *stream = avformat_new_stream(ofmt_ctx, oc);

if (stream != NULL) {
    // ...
    unsigned int tag = 0;
    // for ffmpeg new api 3.x
    AVCodecParameters *parameters = stream->codecpar;
    if (av_codec_get_tag2(ofmt_ctx->oformat->codec_tag, oc->id, &tag) == 0) {
        av_log(NULL, AV_LOG_ERROR, "could not find codec tag for codec id %d, default to 0.\n", oc->id);
    }
    parameters->codec_tag = tag;
    stream->codec = avcodec_alloc_context3(oc);
    // more setting for stream->codec
    avcodec_parameters_to_context(stream->codec, parameters);

    // for old ffmpeg version
    stream->codec->codec_tag = tag;
    // ...
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FFMpeg 复制流而不转码 的相关文章

随机推荐

  • openCV 中的结果比较Hist

    我正在尝试比较我存储为数组的两个直方图 我是 C 接口 cv Mat 和 OpenCV 中计算直方图的新手 My code int testArr1 4 12 10 11 11 int testArr2 4 12 0 11 0 cv Mat
  • 在 C# 中使用 POST/httpwebrequest 上传 zip 文件

    我正在尝试代码http www paraesthesia com archive 2009 12 16 posting multipartform data using net webrequest aspx通过 httpwebreques
  • 如何在超级账本结构中获取资产修改历史记录

    我在用IBM Bluemix 区块链服务为我的资产共享演示尝试一些智能合约逻辑 无论如何 是否可以查询超级账本结构网络中的资产修改历史记录 我检查了 Fabric 0 6 和 1 0 版本的文档 但我只能找到stub pushState k
  • 是否可以从 bdist 中排除数据文件源和中间文件?

    我正在使用 setuptools 构建许多数据文件 编译的翻译 图标调整大小并转换为不同的格式等 我想将这些数据文件的来源包含在sdist和构建结果 但不是它们的源和中间文件bdist wheel 当我使用package data源文件 中
  • 在值/键上加入 AngularFire 路径不起作用(将用户配置文件合并到记录中)

    我正在使用 Firebase 1 0 和 Angular 1 4 开发一个应用程序 我遇到的问题是确保视图中的数据与 Firebase 同步 同时从 Firebase 中的两个表获取非规范化数据 图书表如下所示 books JyDpkQrU
  • 检索由shiny::reactive()推断的反应性依赖关系

    考虑一下这个推介会Joe Cheng 解释了他和他的同事如何在闪亮中实现响应式框架 其灵感来自于Meteor 实际问题 有人可以向我解释一下我将如何找到一个反应式对象的依赖关系 即列出它们的名称和环境 实际访问它们等 这些是由shiny r
  • 在 while 循环内部设置的 Shell 变量在其外部不可见

    我试图找到其中字符最多的路径名 可能有更好的方法来做到这一点 但我想知道为什么会出现这个问题 LONGEST CNT 0 find samples while read line do line length echo line wc m
  • 禁用 Asp.Net WebAPI 中的默认验证

    我想完全禁用 WebAPI 控制器的模型验证 我尝试了几种方法来为 MVC 做到这一点 但似乎 WebAPI 没有得到这些方法 就我而言 自定义格式化程序创建并填充对象 默认验证发生 对象传递给控制器 我的代码开始工作 我正在尝试完全删除第
  • 有没有办法只接受 JTextField 中的数字值?

    有没有办法只接受 a 中的数字值JTextField 有什么特殊的方法吗 由于这个问题经常出现 所以我在这个答案上投入了比平时更多的努力 我的投票投给了JFormattedTextField IMO 每个 Swing 开发人员都应该在他 她
  • R:具有重复数据框的扩展函数

    我有一个需要旋转的数据框 但该数据框有重复的标识符 所以spread函数给出错误Error Duplicate identifiers for rows 5 6 Dimension c A A B B A A Date c Mon Tue
  • 无法在我的 Mac Mountain Lion 上运行 Composer - openssl 扩展

    我安装了几个需要 Composer 的 CMS 两天以来我遇到了错误 无法继续 RuntimeException You must enable the openssl extension to download files via htt
  • Powershell 中的管道

    我正在阅读有关 PowerShell 中管道如何工作的信息 about 管道 并了解管道一次传送一个对象 So this Get Service Format Table Property Name DependentServices 与此
  • 将外键关系限制为相关子类型的行

    概述 我试图表示数据库中的几种类型的实体 这些实体具有许多共同的基本字段 然后每个实体都有一些不与其他类型的实体共享的附加字段 工作流程经常涉及将实体列出在一起 因此我决定使用一个包含其公共字段的表 然后每个实体将拥有自己的包含附加字段的表
  • 查找单击按钮的类

    我知道我已经问过这个问题很多次了 但我仍然没有找到正确的答案 num 只需要显示在单击按钮的类中
  • C#程序中TCP Socket没有停止接收数据

    Android 2 2 手机中的 Java Android 应用程序正在将字符串数据发送到 C 程序 C 程序接收数据并正确显示仅限第一次 然后它就不会停止接收数据 但由于没有数据 所以显示为0作为接收到的数据 在调试时并没有接收到Java
  • Swift 3 - 在视图控制器之间传递数据,然后传递到另一个视图控制器

    我正在尝试执行一个segue 但它不起作用 我想做的是发送我的视图控制器 主 中文本字段中的数据 之后我想将其发送到名为 OperationsController 的 ViewController 然后将其发送到另一个视图 CreateCo
  • 用向量 R 中的每个其他值减去向量中的每个值

    假设我有一个矩阵 data lt matrix seq 1 6 ncol 2 nrow 3 byrow TRUE A B 1 1 2 2 3 4 3 5 6 从 A 列开始 我想创建 A 中每个数字与 A 中每个其他数字之间的成对差异向量
  • 使 Windows Mobile 设备模拟蓝牙 HID 设备

    我正在寻找一种通过蓝牙将 Windows Mobile 设备连接到 PC 并使其作为 HID 设备 即键盘或鼠标 显示在 PC 上的方法 我想这主要是修改 Windows Mobile 设备上可用的蓝牙配置文件的问题 以便它公开蓝牙 HID
  • C# 中检测系统从睡眠状态唤醒的事件

    我需要检测系统电源状态模式 准确地说 我需要一个当 Windows 7 从睡眠状态唤醒时触发的事件 我已经在使用 SystemEvents PowerModeChanged SystemEvents PowerModeChanged 但此事
  • FFMpeg 复制流而不转码

    我正在尝试将多个文件中的所有流复制到一个文件中 而不对流进行转码 你经常做的事情ffmpeg效用由ffmpeg i file with audio mp4 i file with video mp4 c copy shortest file