当前位置: 首页 > article >正文

获取metadata耗时对比(libtag/ffmpeg/gstreamer)

前言

        有个需求是获取metadata,我想试试几种框架的性能对比情况,

结论

  • libtag获取metadata确实比ffmpeg和gstreamer快

  • 但是libtag支持的格式不如后两者:

  • gstreamer支持的格式和ffmpeg相同,但是速度慢了不少

QT测试程序源码

pro文件:

  SOURCES += \
    main.cpp


LIBS += -ltag

# ffmpeg*************************************
LIBS += \
#    -lSDL2 \
    -lavcodec \
#    -lavdevice \
#    -lavfilter \
    -lavformat \
    -lavutil \
    -lswresample \
    -lswscale


# gstreamer**********************************

CONFIG += link_pkgconfig
PKGCONFIG += gstreamer-1.0 gstreamer-plugins-base-1.0  gstreamer-pbutils-1.0#gtk+-3.0
LIBS    += -lX11
LIBS    +=-lglib-2.0
LIBS    +=-lgobject-2.0
LIBS    +=-lgstreamer-1.0          # <gst/gst.h>
LIBS    +=-lgstvideo-1.0             # <gst/video/videooverlay.h>
LIBS    +=-L/usr/lib/x86_64-linux-gnu/gstreamer-1.0
LIBS    +=-lgstautodetect
LIBS    +=-lgstaudio-1.0
LIBS    +=-lgstapp-1.0

INCLUDEPATH += \
            /usr/include/glib-2.0 \
            /usr/lib/x86_64-linux-gnu/glib-2.0/include \
            /usr/include/gstreamer-1.0 \
            /usr/lib/x86_64-linux-gnu/gstreamer-1.0/include

main.cpp


#include <QCoreApplication>
#include <QDebug>
#include <QElapsedTimer>
#include <QUrl>

#include <taglib/fileref.h>
#include <taglib/tag.h>

extern "C" {
#include <libavformat/avformat.h>
#include <libavutil/dict.h>
}

#include <gst/gst.h>
#include <gst/tag/tag.h>
#include <gst/pbutils/pbutils.h>

void testTaglib(QString filePath){

    // 使用 TagLib 读取文件
    TagLib::FileRef file(filePath.toStdString().c_str());

    if (!file.isNull() && file.tag()) {
        // 获取元数据
        TagLib::Tag *tag = file.tag();
        QString title = QString::fromStdString(tag->title().to8Bit(true));
        QString artist = QString::fromStdString(tag->artist().to8Bit(true));
        QString album = QString::fromStdString(tag->album().to8Bit(true));
        uint year = tag->year();
        uint track = tag->track();

        // 打印元数据
        qDebug() << "Title:" << title;
        qDebug() << "Artist:" << artist;
        qDebug() << "Album:" << album;
        qDebug() << "Year:" << year;
        qDebug() << "Track:" << track;

        // 获取音频时长
        if (file.audioProperties()) {
            int length = file.audioProperties()->lengthInSeconds();
            qDebug() << "Duration:" << length << "seconds";
        }
    } else {
        qDebug() << "Failed to read file or metadata.";
    }

}

void testFFmpeg(QString filePath){
    // 打开文件
        AVFormatContext *formatContext = avformat_alloc_context();
        if (avformat_open_input(&formatContext, filePath.toStdString().c_str(), nullptr, nullptr) != 0) {
            qDebug() << "Could not open file";
            return ;
        }

        // 获取流信息
        if (avformat_find_stream_info(formatContext, nullptr) < 0) {
            qDebug() << "Could not find stream information";
            avformat_close_input(&formatContext);
            return ;
        }

        // 打印元数据
        AVDictionaryEntry *tag = nullptr;
        while ((tag = av_dict_get(formatContext->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
            qDebug() << tag->key << ":" << tag->value;
        }

        // 获取时长(以秒为单位)
        if (formatContext->duration != AV_NOPTS_VALUE) {
            int64_t duration = formatContext->duration / AV_TIME_BASE;
            qDebug() << "Duration:" << duration << "seconds";
        }

        // 释放资源
        avformat_close_input(&formatContext);
}


void print_metadata(const GstDiscovererInfo *info)
{
    if (!info) {
        qDebug() << "No metadata found.";
        return;
    }

    // 获取标签列表
    const GstTagList *tags = gst_discoverer_info_get_tags(info);
    if (tags) {
        // 定义一个辅助函数来获取标签值
        auto get_tag_string = [](const GstTagList *tags, const char *tag_name) -> QString {
            gchar *value = nullptr;
            gst_tag_list_get_string(tags, tag_name, &value);
            QString result = value ? QString::fromUtf8(value) : "N/A";
            g_free(value);
            return result;
        };

        // 提取并打印元数据
        qDebug() << "Title:" << get_tag_string(tags, GST_TAG_TITLE);
        qDebug() << "Artist:" << get_tag_string(tags, GST_TAG_ARTIST);
        qDebug() << "Album:" << get_tag_string(tags, GST_TAG_ALBUM);

        // 获取持续时间
        guint64 duration = gst_discoverer_info_get_duration(info);
        if (duration != GST_CLOCK_TIME_NONE) {
            qDebug() << "Duration:" << duration / GST_SECOND << "seconds";
        } else {
            qDebug() << "Duration: N/A";
        }
    } else {
        qDebug() << "No tags found.";
    }
}

void testGst(QString filePath)
{
    // 创建 GstDiscoverer 实例,设置超时时间为 5 秒
    GstDiscoverer *discoverer = gst_discoverer_new(5 * GST_SECOND, nullptr);
    if (!discoverer) {
        qDebug() << "Failed to create GstDiscoverer instance";
        return ;
    }

    // 同步获取元数据
    GError *error = nullptr;
    GstDiscovererInfo *info = gst_discoverer_discover_uri(discoverer, qPrintable(QUrl::fromLocalFile(filePath).toString()), &error);

    if (error) {
        qDebug() << "Error discovering media file:" << error->message;
        g_error_free(error);
    } else {
        // 打印元数据
        print_metadata(info);
    }

    // 清理资源
    if (info) {
        gst_discoverer_info_unref(info);
    }

    g_object_unref(discoverer);
}

int main(int argc, char *argv[])
{
    //QCoreApplication a(argc, argv);

    // 初始化 FFmpeg
    av_register_all();

    // 初始化 GStreamer
    gst_init(&argc, &argv);

    // 音频文件路径
    QString filePath = "/home/enpht/Music/test1.mp3";
    //QString filePath = "/home/enpht/Videos/9sub.mkv";

    // test Taglib:
    qDebug()<<"taglib:";
    QElapsedTimer timer1;
    qint64 elapsed1 = 0;
    timer1.start();
    testTaglib(filePath);
    elapsed1 = timer1.elapsed();
    qDebug()<<"tablib cost time: "<<elapsed1<<" milliseconds";

    // test ffmpeg
    qDebug()<<"\nffmpeg:";
    filePath = "/home/enpht/Music/test1.mp3";
    //filePath = "/home/enpht/Videos/9sub.mkv";
    QElapsedTimer timer2;
    qint64 elapsed2 = 0;
    timer2.start();
    testFFmpeg(filePath);
    elapsed2 = timer2.elapsed();
    qDebug()<<"ffmpeg cost time: "<<elapsed2<<" milliseconds";

    // test gst
    qDebug()<<"\ngst:";
    QElapsedTimer timer3;
    qint64 elapsed3 = 0;
    timer3.start();
    testGst(filePath);
    elapsed3 = timer3.elapsed();
    qDebug()<<"gst cost time: "<<elapsed3<<" milliseconds";

    //return a.exec();
    return 0;
}


http://www.kler.cn/a/523673.html

相关文章:

  • three.js用粒子使用canvas生成的中文字符位图材质
  • Vscode的AI插件 —— Cline
  • games101-作业2
  • 【漫话机器学习系列】064.梯度下降小口诀(Gradient Descent rule of thume)
  • 神经网络|(五)概率论基础知识-条件概率
  • decison tree 决策树
  • 第 5 章:声音与音乐系统
  • 一文大白话讲清楚webpack基本使用——17——Tree Shaking
  • [Dialog屏幕开发] 屏幕绘制(使用向导创建Tabstrip Control标签条控件)
  • Java 9模块开发:IntelliJ IDEA实战指南
  • Transformation,Animation and Viewing
  • 高通Yocto项目 - 全解析
  • 【MQ】探索 Kafka
  • 【Unity3D】Unity混淆工具Obfuscator使用
  • 51单片机入门_01_单片机(MCU)概述(使用STC89C52芯片;使用到的硬件及课程安排)
  • PAT甲级-1022 Digital Libiary
  • Python JSON:深入解析与高效应用
  • 21.Word:小赵-毕业论文排版❗【39】
  • PHP 7 新特性
  • JAVA实战开源项目:蜗牛兼职平台(Vue+SpringBoot) 附源码
  • 数论问题74
  • Linux C++
  • 「Unity3D」在Unity中使用C#控制显示Android的状态栏
  • 02数组+字符串+滑动窗口+前缀和与差分+双指针(D5_双指针)
  • Oracle PMON进程清洗功能
  • Unbutu虚拟机+eclipse+CDT编译调试环境搭建