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

MP3的ID3信息简介及其如何解析

        解析MP3文件的ID3信息是一个非常常见的任务。ID3标签是MP3文件中用来存储元数据(如歌名、歌手、专辑、年份等)的标准。

        目前主要有两个大版本广泛使用:ID3v1 和 ID3v2。ID3v2功能更强大,但解析也更复杂。下面详细解释如何解析这两个版本。

■ 1. ID3v1 / ID3v1.1

        ID3v1非常简单,它固定地放在MP3文件的最后128个字节。如果MP3文件中有APE格式信息,则在APE信息之后。

结构(128字节):

        *   前3字节 (0-2): 标签头,必须是 `TAG`,用于识别这是一个ID3v1标签。

        *   后续30字节 (3-32): 歌曲标题 (Title)

        *   后续30字节 (33-62): 艺术家 (Artist)

        *   后续30字节 (63-92): 专辑 (Album)

        *   后续4字节 (93-96): 年份 (Year)

        *   后续30字节 (97-126): 注释 (Comment)

        *   第128字节 (127): 流派 (Genre),用一个0-255的数字表示,对应一个预定义的流派列表。

ID3v1.1 的改进:

        在注释字段上做了小改动:

        *   注释改为28字节 (97-124)

        *   第125字节 (124): 保留,为 `0`。

        *   第126字节 (125): 音轨号 (Track Number)。

解析步骤:

        1.  以二进制模式打开MP3文件。

        2.  将文件指针移动到末尾向前128字节的位置(`file.seek(-128, 2)`)。

        3.  读取这128个字节。

        4.  检查前3个字节是否是 `TAG`。

        5.  如果是,按照上面的固定结构,按顺序和固定长度解析出各个字段。这些字段通常用ISO-8859-1编码填充,并以空字符(`0x00`)终止,所以解析后需要去除多余的空白和终止符。

        优点: 简单易解析。

        缺点: 信息容量固定且小,不支持国际化(如中文),信息有限。

-------------------------------------------------------------------------------------------------------------------------------

■ 2. ID3v2

        ID3v2标签位于MP3文件的最开头,功能非常强大。它由一个标签头和多个帧(Frame) 组成。

▲ ID3v2 标签头

        标签头固定为 10个字节,结构如下:

        *   前3字节 (0-2): 标识,必须是 `ID3`。

        *   第4-5字节 (3-4): 版本号。例如,`03 00` 表示 ID3v2.3.0;`04 00` 表示 ID3v2.4.0。

     *   第6字节 (5): 标志(Flags)。这是一个8位的位图,包含一些辅助信息(如是否 Unsynchronisation,是否有扩展头等)。

        *   第7-10字节 (6-9): 标签大小。这4个字节的解析是重点和难点!

            *   它是一个32位的同步安全整数(synchsafe integer)。

            *   每个字节的最高位(第7位)恒为0,有效数据只有低7位。

             计算公式:`Size = (byte0 & 0x7F) * 0x200000 + (byte1 & 0x7F) * 0x400 + (byte2 & 0x7F) * 0x80 + (byte3 & 0x7F)`

            *   简单理解:它避免了数据与MP3音频帧的同步字冲突。

▲ ID3v2 帧(Frame)

        在标签头之后,就是一系列的帧,每个帧存储一种特定的信息(如 `TIT2` 是标题,`TPE1` 是艺术家)。

        每个帧也由一个帧头和帧数据组成。

帧头(Frame Header):

        *   对于 v2.3: 帧头是 10字节。

            *   前4字节: 帧ID(例如 `TALB`, `TRCK`, `TXXX`)。必须是字母和数字。

            *   中间4字节: 帧数据部分的大小(以字节为单位)。这是一个普通的32位整数,不是同步安全整数。

            *   后2字节: 标志(Flags)。

        *   对于 v2.4: 帧头也是10字节,但帧大小编码可能使用同步安全整数,标志位定义也不同,解析时需注意版本差异。

常见帧ID:

*   `TIT2`: 标题 (Title)

*   `TPE1`: 艺术家 (Artist/Performer)

*   `TALB`: 专辑 (Album)

*   `TRCK`: 音轨号 (Track)

*   `TYER`: 年份 (Year) - v2.3

*   `TDRC`: 录制时间 (Recording Time) - v2.4,兼容性更好

*   `TCON`: 流派 (Genre)

*   `APIC`: 附加图片 (Attached Picture),用于存储专辑封面

*   `TXXX`: 用户自定义文本帧

...

        帧数据的编码:

        文本帧的数据部分第一个字节是文本编码描述符,指明后面内容的编码方式。

                *   `0x00`: ISO-8859-1

                *   `0x01`: UTF-16 (带BOM)

                *   `0x02`: UTF-16BE (无BOM) - v2.4+

                *   `0x03`: UTF-8 - v2.4+

解析步骤:

        1.  以二进制模式打开MP3文件。

        2.  读取文件开头的10个字节。

        3.  检查前3个字节是否是 `ID3`。如果不是,说明没有ID3v2标签。

        4.  解析版本号和标志。

        5.  解析标签大小(需要按同步安全整数解析),得到整个ID3v2标签(包括10字节头)的总长度 `size_total`。

        6.  读取从第11字节开始的 `size_total - 10` 字节数据,这就是所有帧的数据区。

        7.  在这个数据区内循环解析各个帧:

            *   读取帧ID(4字节)。如果ID是空或填充符(`0x00`),说明后面没有有效帧了,解析结束。

            *   根据版本(从标签头获知)读取帧大小(4字节)。v2.3是普通整数,v2.4可能是同步安全整数。

            *   读取帧标志(2字节)。

            *   根据读取到的“帧大小”,读取相应长度的帧数据。

            *   根据帧ID和编码描述符来解析帧数据。例如,如果是 `TIT2`,就先读一个字节看编码,然后用对应的编码去解码剩下的数据。

-------------------------------------------------------------------------------------------------------------------------------

■ 实践建议和工具

        手动解析虽然有助于理解,但在实际开发中,我们通常使用成熟的库。

        ▲ 使用现成的库(推荐)

*   Python: 使用 `mutagen` 库,它非常强大且易用。

    python代码如下:

    from mutagen.mp3 import MP3

    from mutagen.id3 import ID3, TIT2, TPE1, TALB, APIC

    audio = MP3('song.mp3', ID3=ID3)

    # 获取基本信息

    print(audio['TIT2']) # 标题

    print(audio['TPE1']) # 艺术家

    print(audio.info.length) # 时长

    # 获取并保存专辑封面

    if ‘APIC’ in audio.tags:

        with open('cover.jpg', 'wb') as img:

            img.write(audio.tags[‘APIC’].data)

*   JavaScript (Node.js): 使用 `jsmediatags` 或 `musicmetadata` 库。

    npm install jsmediatags

    javascript代码:

    const jsmediatags = require("jsmediatags");

    jsmediatags.read("song.mp3", {

      onSuccess: function(tag) {

        console.log(tag.tags.title);

        console.log(tag.tags.artist);

        console.log(tag.tags.picture); // 专辑封面数据

      },

      onError: function(error) {

        console.log('Error', error);

      }

    });

*   Java: 使用 `jaudiotagger` 库。

▲ 手动分析和调试工具

        *   Hex Editor (十六进制编辑器): 如 010 Editor (Windows/macOS) 或 Bless (Linux)。用它直接打开MP3文件,可以清晰地看到文件开头的 `ID3` 标记和各个帧的结构。

        *   MP3Diags: 一个专门用于查看和修复MP3标签的工具,可以直观地展示所有ID3信息。

        *   ffprobe (FFmpeg 工具集的一部分): 命令行工具,可以查看媒体信息。

                    ffprobe -show_format -show_streams song.mp3

    

■ 总结

| 特性 | ID3v1 / ID3v1.1 | ID3v2 (v2.3 / v2.4) |

| 位置 | 文件末尾 | 文件开头 |

| 大小 | 固定128字节 | 可变,最大可达数MB |

| 结构 | 简单,固定字段 | 复杂,由标签头和多个帧组成 |

| 信息量 | 很少 | 非常丰富(支持歌词、多封面、多字段等) |

| 编码 | 仅支持ISO-8859-1 | 支持多种编码(UTF-8, UTF-16等),支持国际化 |

| 解析难度 | 非常简单 | 复杂,需要注意版本差异和编码 |

        对于现代应用,ID3v2 是绝对的主流,但ID3v2.4版本由于解析更为复杂,而且ID3v2.3版本储存的信息基本能够满足绝大多数的应用,所以大多数的MP3使用的是ID3v2.3版本。除非有特殊需求(如学习或处理非常古老的文件),否则都应该优先解析ID3v2标签,并使用现成的库来避免重复造轮子和处理各种兼容性细节。


文章转载自:

http://sDvIrYua.tnthd.cn
http://3Hsw0zkm.tnthd.cn
http://54LcEeEd.tnthd.cn
http://60lglZh2.tnthd.cn
http://QU7UlqvZ.tnthd.cn
http://roBhYubf.tnthd.cn
http://5njKJZyP.tnthd.cn
http://BlipvdKg.tnthd.cn
http://Gd78K7ES.tnthd.cn
http://BR4EQdec.tnthd.cn
http://cPPMrShD.tnthd.cn
http://nQRY5o6n.tnthd.cn
http://MNuA0m9t.tnthd.cn
http://xeDLOKUx.tnthd.cn
http://ZdxxOO6B.tnthd.cn
http://EATLUpHB.tnthd.cn
http://eWlKroQi.tnthd.cn
http://mtIwGLzu.tnthd.cn
http://lViuUywZ.tnthd.cn
http://QUlppJMT.tnthd.cn
http://ZcFKr5Cy.tnthd.cn
http://RRBMF6wb.tnthd.cn
http://tw2SVT4U.tnthd.cn
http://12nc6zud.tnthd.cn
http://CQmvork7.tnthd.cn
http://dNlGNMy3.tnthd.cn
http://7n50OAUK.tnthd.cn
http://Uu9d7s1z.tnthd.cn
http://ELVk3dDd.tnthd.cn
http://KxWhcJuP.tnthd.cn
http://www.dtcms.com/a/385458.html

相关文章:

  • MyBatis-Plus 扩展全局方法
  • java中的泛型
  • 使用 AWS Comprehend 综合指南
  • 使用秩和比拟解决非独立同分布情况下的投毒攻击
  • 七、vue3后台项目系列——包装scss、全句变量scss与导入
  • 煤矿山井下绝绝缘监测故障定位
  • 海外分部人员OA请假申请时长为0
  • MySQL --JDBC
  • python使用pyodbc通过不同认证方式连接sqlserver数据源
  • java通过线程池加CompletableFuture实现批量异步处理
  • Coze源码分析-资源库-创建知识库-后端源码-详细流程梳理
  • 极简版 Nginx 反向代理实验步骤
  • python-86-基于Graphviz或Mermaid绘制流程图
  • 智能农机无人驾驶作业套圈路径规划
  • Rayon Rust中的数据并行库入门教程
  • NumPy数组与Python列表的赋值行为解析
  • 基于 AI 的大前端智能家居控制应用开发
  • RAGFlow集成SGLang部署的大模型:实现OpenAI API兼容的自定义LLM调用
  • sqlsever 内存配置错误无法连接,后面恢复连接
  • 51c大模型~合集182
  • 2025.9.15总结
  • 深入理解 Roo Code 的 Code Actions 功能
  • Java---线程池讲解
  • PEFT QLora Deepspeed Zero Stage 3 Offload Trainning
  • 线程概念,控制
  • 扫描仪常见样式:平板与馈纸的特性与适用场景
  • Python进程和线程——多线程
  • 2025年AIOCR审核革命!七大智能费控报销系统终结手工录入
  • 从循环到矩阵运算:矢量化加速机器学习的秘诀
  • R 语言入门实战|第七章 程序:从“老虎机”项目学透流程控制与代码优化