【问题标题】:how to use libavcodec/ffmpeg to find duration of video file如何使用 libavcodec/ffmpeg 查找视频文件的持续时间
【发布时间】:2011-09-21 01:30:59
【问题描述】:

我需要一个库来执行视频文件的长度、大小等基本功能(我是通过元数据或标签来猜测的),所以我选择了 ffmpeg。有效的视频格式主要是电影文件中流行的格式,即。 wmv、wmvhd、avi、mpeg、mpeg-4 等。如果可以,请帮助我了解视频文件的持续时间。我在 Linux 平台上。

【问题讨论】:

    标签: c++ ffmpeg


    【解决方案1】:

    libavcodec 很难编程,也很难找到文档,所以我感受到了你的痛苦。 This tutorial 是一个好的开始。 Here 是主要的 API 文档。

    查询视频文件的主要数据结构是AVFormatContext。在本教程中,它是您打开的第一件事,使用 av_open_input_file - 文档说它已被弃用,您应该改用 avformat_open_input。

    从那里,您可以从 AVFormatContext 中读取属性:duration 在几分之一秒内(请参阅文档)、file_size(以字节为单位)、bit_rate 等。

    所以放在一起应该是这样的:

    AVFormatContext* pFormatCtx = avformat_alloc_context();
    avformat_open_input(&pFormatCtx, filename, NULL, NULL);
    int64_t duration = pFormatCtx->duration;
    // etc
    avformat_close_input(&pFormatCtx);
    avformat_free_context(pFormatCtx);
    

    如果您的文件格式没有标头,例如 MPEG,您可能需要在 avformat_open_input 之后添加此行以从数据包中读取信息(这可能会更慢):

    avformat_find_stream_info(pFormatCtx, NULL);
    

    编辑:

    • 在代码示例中添加了 pFormatCtx 的分配和取消分配。
    • 添加了 avformat_find_stream_info(pFormatCtx, NULL) 以处理没有标头的视频类型,例如 MPEG

    【讨论】:

    • 在我看来 pFormatCtx 应该初始化为 NULL 吗?否则,avformat_open_input 假定调用者已经分配了上下文。
    • @jpa 很好的发现。我的错。我决定将代码更改为显式分配和取消分配,而不是简单地将其初始化为 NULL 并让 avformat_open_input 分配它(这种方式更清楚您也需要取消分配)。
    • 为了使用 avformat_open_input,您将 libav 的哪个部分链接到程序?我从 git 安装了最新的 libav 库版本,并将它们全部链接到我的代码。我仍然收到错误 undefined reference to avformat_open_input... 所以这个函数在库中不知何故不存在。我做错什么了吗?
    • @mmoment 它仍然对我有用(使用 apt get,libavformat 0.7.2)。我正在与-lavformat -lavcodec 链接。您需要确保您的 C 文件出现在命令行上的链接器文件之前 -- this recently changed and I was bitten by it。如果这不起作用,请使用 objdump 找出函数是否真的在库中:objdump -T /usr/lib/libavformat.so | grep avformat_open_input.
    • @mgiuca 我知道发生了什么。显然,安装程序将库和头文件到处乱扔。这就是为什么我不得不面对诸如不匹配标头等问题的原因。感谢您的努力,objdump 真的帮助我实现了这一点!
    【解决方案2】:

    我必须添加一个呼叫

    avformat_find_stream_info(pFormatCtx,NULL)
    

    在avformat_open_input 之后得到 mgiuca 的答案。 (无法评论)

    #include <libavformat/avformat.h>
    ...
    av_register_all();
    AVFormatContext* pFormatCtx = avformat_alloc_context();
    avformat_open_input(&pFormatCtx, filename, NULL, NULL);
    avformat_find_stream_info(pFormatCtx,NULL)
    int64_t duration = pFormatCtx->duration;
    // etc
    avformat_close_input(&pFormatCtx);
    avformat_free_context(pFormatCtx);
    

    持续时间以 uSeconds 为单位,除以 AV_TIME_BASE 得到秒数。

    【讨论】:

    • 谢谢!你的补充对我很有用。如果没有这个调用,它不会返回持续时间。
    • "持续时间以 uSeconds 为单位,除以 AV_TIME_BASE 得到秒数。" 当我除以错误的视频持续时间时。 @seeseac
    【解决方案3】:

    使用这个功能它的工作:

    extern "C"
    JNIEXPORT jint JNICALL
    Java_com_ffmpegjni_videoprocessinglibrary_VideoProcessing_getDuration(JNIEnv *env,
                                                                          jobject instance,
                                                                          jstring input_) {
        av_register_all();
        AVFormatContext *pFormatCtx = NULL;
        if (avformat_open_input(&pFormatCtx, jStr2str(env, input_), NULL, NULL) < 0) {
            throwException(env, "Could not open input file");
            return 0;
        }
    
    
        if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
            throwException(env, "Failed to retrieve input stream information");
            return 0;
        }
    
        int64_t duration = pFormatCtx->duration;
    
        avformat_close_input(&pFormatCtx);
        avformat_free_context(pFormatCtx);
        return (jint) (duration / AV_TIME_BASE);
    }
    

    当我使用 (jint) (duration / AV_TIME_BASE) 时,此视频持续时间出现了错误。

    【讨论】:

      【解决方案4】:
      AVFormatContext* pFormatCtx = avformat_alloc_context();
      

      会导致内存泄漏。

      应该是AVFormatContext* pFormatCtx = NULL

      【讨论】:

      • "指向用户提供的 AVFormatContext 的指针(由 avformat_alloc_context 分配)。可能是指向 NULL 的指针,在这种情况下,AVFormatContext 由此函数并写入 ps。请注意,用户提供的 AVFormatContext 将在失败时被释放。 ffmpeg 文档
      猜你喜欢
      • 2016-12-17
      • 2018-02-10
      • 2020-12-11
      • 2014-08-07
      • 2014-02-26
      • 2016-06-08
      • 2015-06-14
      • 2019-02-23
      • 2010-11-11
      相关资源
      最近更新 更多