使用FFmpeg检索专辑封面 [英] Retrieve album art using FFmpeg

查看:559
本文介绍了使用FFmpeg检索专辑封面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一种依赖于FFmpeg来检索音频元数据的Android应用程序。我知道可以使用FFMpeg以编程方式检索专辑封面。然而,一旦你解码了艺术(MP3中的一个视频帧),怎么生成一个应用程序中使用的图像文件(PNG)呢?我搜索全部,但似乎找不到一个工作的例子。

I'm developing an Android application that relies on FFmpeg to retrieve audio metadata. I know it's possible to retrieve album art programmatically using FFMpeg. However, once you have decoded the art (a video frame within an MP3) how do generate an image file (a PNG) for use within an application? I've search all over but can't seem to find a working example.

编辑,这里是解决方案:

Edit, here is the solution:

#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;
}


推荐答案

要以编程方式使用ffmpeg,认为您必须在libavformat中调用 read_apic () ffmpeg的一部分)。

To use ffmpeg programmatically, I think you would have to call read_apic() in libavformat (which is part of ffmpeg).

从命令行可以看出:

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

命令行行为意味着封面艺术图像被视为只是另一个视频流(仅包含一帧),因此以通常的方式使用libavformat,您将要解析流的视频部分应该产生该图像。

The commandline behaviour implies that the cover art image is seen as just another video stream (containing just one frame), so using libavformat in the usual way you would to demux the video part of a stream should produce that image.

解职示例代码: ffmpeg / docs / examples / demuxing.c 将从MP3中解码视频流获得的第一个(且仅)AVPacket将包含JPEG文件(仍然编码为JPEG,未解码)。

Sample code for demuxing: ffmpeg/docs/examples/demuxing.c The first (and only) AVPacket that would be obtained from demuxing the video stream in an mp3 would contain the JPEG file (still encoded as JPEG, not decoded).

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);

如果有多个图像,我认为它们将被视为单独的视频流,而不是单独的数据包在同一个流中。第一个流将是最大分辨率的流。

If there are multiple images, I think they would be seen as separate video streams, rather than as separate packets in the same stream. The first stream would be the one with the largest resolution.

所有这些都可能在内部使用read_apic()方法实现。

All this is probably implemented internally in terms of read_apic().

ID3v2规范允许任何图像格式,但建议使用JPEG或PNG。实际上,ID3中的所有图像都是JPEG。

The ID3v2 spec allows for any image format, but recommends JPEG or PNG. In practice all images in ID3 are JPEG.

编辑:将一些不太有用的位移动到后记:

EDIT: Moved some of the less useful bits to postscript:

PS ffmpeg -i input.mp3 -f ffmetadata metadata.txt 将产生一个包含元数据的类似于ini的文件,但图像甚至不在其中引用,所以不是一个有用的方法。

P.S. ffmpeg -i input.mp3 -f ffmetadata metadata.txt will produce an ini-like file containing the metadata, but the image is not even referred to in there, so that is not a useful approach.

PS ID3v2标签中可能会有多个图片。当有多张图像或多于一种类型的图像时,您可能需要处理这种情况。

P.S. There may be multiple images in an ID3v2 tag. You may have to handle the case when there is more than one image or more than one type of image present.

P.S。 ffmpeg可能不是最好的软件。使用 id3lib TagLib ,或其他 ID3的实施之一。这些可以用作库(可以从您选择的语言调用)或作为命令行实用程序使用。这里有TagLib的示例C ++代码:如何使用TagLib以不同的音频格式读/写coverart?,对于id3lib,请执行以下操作:如何使用id3lib从音频文件获取专辑封面

P.S. ffmpeg is probably not the best software for this. Use id3lib, TagLib, or one of the other implementations of ID3. These can be used either as libraries (callable from the language of your choice) or as commandline utilities. There is sample C++ code for TagLib here: How do I use TagLib to read/write coverart in different audio formats? and for id3lib here: How to get album art from audio files using id3lib.

这篇关于使用FFmpeg检索专辑封面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆