c++ - 正确读取被 ID3 标签打乱的 MP3 文件

标签 c++ parsing ffmpeg mp3 id3

我的学期项目将于本周四到期,我在读取 MP3 文件方面遇到了重大问题(该项目是关于声音分析的,不要问我到底是关于什么的以及为什么我这么晚才做)。

首先,我读取了前 10 个字节以检查 ID3 标签。如果它们存在,我将直接跳到第一个 MP3 标题 - 或者至少这是个好主意。以下是我计算 ID3 标签大小的方法:

if (inbuf[0] == 'I' && inbuf[1] == 'D' && inbuf[2] == '3') //inbuf contains first 10 bytes from file
{
    int size = inbuf[3] * 2097152 + inbuf[4] * 16384 + inbuf[5] * 128 + inbuf[6]; //Will change to binary shifts later
    //Do something else with it - skip rest of ID3 tags etc
}

对于没有 ID3 标签的文件和一些带有 ID3 标签的文件,它工作正常,但对于其他一些文件,ffmpeg(我用于解码)返回“无 header ”错误,这意味着它没有正确捕获 MP3 header 。我知道,因为如果我从该 .mp3 文件中删除 ID3(例如使用 Winamp),则不会发生任何错误。结论是大小计数算法并不总是有效。

所以问题是:我如何知道 .mp3 文件的整个 ID3 部分到底有多大(所有可能的标签、专辑图片等等)?我到处都在寻找它,但我一直在寻找我在上面发布的算法。有时我还需要考虑大约 10 个字节的页脚,但它似乎经常需要超过 10 个字节才能最终捕获正确的 MP3 帧。

最佳答案

ID3v1 标签的大小始终固定为 128 字节。

我会找到下面的描述

If you one sum the the size of all these fields we see that 30+30+30+4+30+1 equals 125 bytes and not 128 bytes. The missing three bytes can be found at the very beginning of the tag, before the song title. These three bytes are always "TAG" and is the identification that this is indeed a ID3 tag. The easiest way to find a ID3v1/1.1 tag is to look for the word "TAG" 128 bytes from the end of a file.

来源:http://id3.org/ID3v1

还有一个版本,叫做ID3v2:

One of the design goals were that the ID3v2 should be very flexible and expandable... Since each frame can be 16MB and the entire tag can be 256MB you'll probably never again be in the same situation as when you tried to write a useful comment in the old ID3 being limited to 30 characters.

此 ID3v2 始终从音频文件的开头开始,您可以在此处阅读:http://id3.org/ID3v2Easy

ID3v2/file identifier   "ID3"
ID3v2 version           $03 00
ID3v2 flags             %abc00000
ID3v2 size              4 * %0xxxxxxx

ID3v2 标签大小用四个字节编码,其中每个字节的最高有效位(第 7 位)设置为零,总共 28 位。归零位将被忽略,因此 257 字节长的标签表示为 $00 00 02 01。

关于c++ - 正确读取被 ID3 标签打乱的 MP3 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37777610/

相关文章:

c++ - vector in struct 耗时吗?使用指针更好吗?

c++ - UTF-8 请求的 cURL。当它应该是 çabe 时,它​​总是像 �abe

c++ - 限制(放大器)功能的默认参数

c# - 如何将字符串中包含的 XML 解析为 IList<BusinessObject>?

php - 您必须安装 FFMPEG 才能使用此功能

c++ - ffmpeg和代码生成的碎片化mp4文件的区别

c++ - C 和 C++ 标准的数学精度要求

read_csv() 解析错误信息,如何解释?

swift - 如何仅解析出文件的实际名称而不是完整路径?

android - ffmpeg 使用单个图像和音频文件,但输出视频不可搜索(即使提前搜索也只能从 0 :00, 恢复)