使用FFmpeg的检索专辑封面(Retrieve album art using FFmpeg)

2019-07-04 04:51发布

我开发一个Android应用程序,它依赖于FFmpeg的检索音频的元数据。 我知道这是可能检索编程方式使用FFmpeg的专辑封面。 但是,一旦你(的MP3内的视频帧)解码的艺术如何生成使用的图像文件(PNG)的应用程序中? 我一直在寻找一切,但似乎无法找到工作的例子。

编辑,这里是解决方案:

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>

void retrieve_album_art(const char *path, const char *album_art_file) {
    int i, ret = 0;

    if (!path) {
        printf("Path is NULL\n");
        return;
    }

    AVFormatContext *pFormatCtx = avformat_alloc_context();

    printf("Opening %s\n", path);

    // open the specified path
    if (avformat_open_input(&pFormatCtx, path, NULL, NULL) != 0) {
        printf("avformat_open_input() failed");
        goto fail;
    }

    // read the format headers
    if (pFormatCtx->iformat->read_header(pFormatCtx) < 0) {
        printf("could not read the format header\n");
        goto fail;
    }

    // find the first attached picture, if available
    for (i = 0; i < pFormatCtx->nb_streams; i++)
        if (pFormatCtx->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) {
            AVPacket pkt = pFormatCtx->streams[i]->attached_pic;
            FILE* album_art = fopen(album_art_file, "wb");
            ret = fwrite(pkt.data, pkt.size, 1, album_art);
            fclose(album_art);
            av_free_packet(&pkt);
            break;
        }

    if (ret) {
        printf("Wrote album art to %s\n", album_art_file);
    }

    fail:
        av_free(pFormatCtx);
        // this line crashes for some reason...
        //avformat_free_context(pFormatCtx);
}

int main() {
    avformat_network_init();
    av_register_all();

    const char *path = "some url";
    const char *album_art_file = "some path";

    retrieve_album_art(path, album_art_file);

    return 0;
}

Answer 1:

以编程方式使用的ffmpeg,我想你将不得不调用read_apic ()在libavformat流(这是的ffmpeg的一部分)。

从命令行,你可以明显地做到这一点:

ffmpeg -i input.mp3 -an -vcodec copy cover.jpg

命令行行为意味着,封面图像被视为只是另一个视频流(只包含一帧),因此,使用了libavformat在你将通常的方式来解复用器一个流的视频部分应产生该图像。

对多路分解的示例代码: FFMPEG /文档/示例/ demuxing.c ,将来自多路分解在一个mp3将包含JPEG文件中的视频流中获得的第一个(只)AVPacket(仍然编码为JPEG,不进行解码)。

AVFormatContext* fmt_ctx;
// set up fmt_ctx to read first video stream
AVPacket pkt;
av_read_frame(fmt_ctx, &pkt);
FILE* image_file = fopen("image.jpg", "wb");
int result = fwrite(pkt.data, pkt.size, 1, image_file);
fclose(image_file);

如果有多个图片,我想他们会被看作是独立的视频流,而不是同一数据流中作为单独的数据包。 第一物流将是一个具有最大分辨率。

所有这一切都可能是read_apic方面的内部实现()。

该ID3v2的规范允许任何图像格式,但建议JPEG或PNG。 在实践中的ID3所有图像是JPEG。

编辑 :有些感动的那么有用位后记:

PS ffmpeg -i input.mp3 -f ffmetadata metadata.txt将产生包含元数据的一个ini状文件,但在那里图像不连称,所以这不是一个有用的方法。

PS可能有多个图像中的ID3v2标签。 您可能必须在有一个以上的图像或多于一个类型的图像目前的处理情况。

PS ffmpeg的可能不是这样做的最好的软件。 使用id3lib , 标签库 ,或其他的一个ID3的实现 。 这些可以被用来作为库(从您所选择的语言调用)或命令行实用程序。 有样品C ++代码标签库在这里: 如何使用标签库来读取不同的音频格式/写封面艺术? 和id3lib这里: 如何从音频文件使用id3lib拿到专辑封面 。



Answer 2:

作为加法上面的答案,我需要一种方法来调整输出图像以及因此我发现了下面的命令,而与当前答案命令试验:

ffmpeg -i input.mp3 -filter:v scale=-2:250 -an output.jpeg

因此,这基本上缩放输出图像到任何你想要的比例或价值。



文章来源: Retrieve album art using FFmpeg