我正在开发一个依赖于FFmpeg来检索音频元数据的
Android应用程序.我知道可以使用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; }
解决方法
要以编程方式使用ffmpeg,我认为你必须在libavformat(它是ffmpeg的一部分)中调用
read_apic().
从命令行,您显然可以这样做:
ffmpeg -i input.mp3 -an -vcodec copy cover.jpg
命令行的行为意味着封面艺术图像被视为另一个视频流(仅包含一个帧),因此以通常的方式使用libavformat来分解流的视频部分应该产生该图像.
解复用的示例代码:ffmpeg/docs/examples/demuxing.c将mp3中的视频流解复用而获得的第一个(也是唯一的)AVPacket将包含JPEG文件(仍编码为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,image_file); fclose(image_file);
如果有多个图像,我认为它们将被视为单独的视频流,而不是同一流中的单独数据包.第一个流将是具有最大分辨率的流.
所有这些可能都是在read_apic()方面内部实现的.
ID3v2规范允许任何图像格式,但建议使用JPEG或PNG.实际上,ID3中的所有图像都是JPEG.
编辑:将一些不太有用的位移到postscript:
附: ffmpeg -i input.mp3 -f ffMetadata Metadata.txt将生成一个包含元数据的类似ini的文件,但在那里甚至没有引用图像,因此这不是一种有用的方法.
附: ID3v2标签中可能有multiple images.当存在多个图像或多种图像时,您可能必须处理该情况.
附: ffmpeg可能不是最好的软件.使用id3lib,TagLib或其中一个implementations of ID3.这些可以用作库(可从您选择的语言调用)或命令行实用程序.这里有TagLib的示例C代码:How do I use TagLib to read/write coverart in different audio formats?和id3lib:How to get album art from audio files using id3lib.