`
确实比较男
  • 浏览: 115246 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

解析mp3文件,获得mp3中的专辑图片

阅读更多

与上一篇写的一样,参考的都是一样的资料

参考的资料:

http://duyouhua1214.iteye.com/blog/1326238

 

 

这仍然也是操作的是字节,所以其他语言都是适用的。

mp3文件的首尾都存有文件的信息,存在尾部的称为ID3V1,在首部的称为 ID3V2。专辑图片是存放在部的ID3V2。所以这里解析ID3v2

 

 

主要的知识点,都是资料中的:

ID3V2 到现在一共有 4 个版本,但流行的播放软件一般只支持第 3 版,既 ID3v2.3。由于 ID3V1 记录
在 MP3 文件的末尾,ID3V2 就只好记录在 MP3 文件的首部了(如果有一天发布 ID3V3,真不知道该记录在哪
里)。也正是由于这个原因,对 ID3V2 的操作比 ID3V1 要慢。而且 ID3V2 结构比 ID3V1 的结构要复杂得多,
但比前者全面且可以伸缩和扩展。
 下面就介绍一下 ID3V2.3。
 每个 ID3V2.3 的标签都一个标签头和若干个标签帧或一个扩展标签头组成。关于曲目的信息如标题、作者
等都存放在不同的标签帧中,扩展标签头和标签帧并不是必要的,但每个标签至少要有一个标签帧。标签
头和标签帧一起顺序存放在 MP3 文件的首部。
1、标签头
在文件的首部顺序记录 10 个字节的 ID3V2.3 的头部。数据结构如下:
 char Header[3];     /*必须为"ID3"否则认为标签不存在*/
 char Ver;     /*版本号 ID3V2.3 就记录 3*/
 char Revision;     /*副版本号此版本记录为 0*/
 char Flag;     /*存放标志的字节,这个版本只定义了三位,稍后详细解说*/
 char Size[4];     /*标签大小,包括标签头的 10 个字节和所有的标签帧的大小*/
 1).标志字节
 标志字节一般为 0,定义如下:
 abc00000
 a -- 表示是否使用 Unsynchronisation(这个单词不知道是什么意思,字典里也没有找到,一般不设置)
 b -- 表示是否有扩展头部,一般没有(至少 Winamp 没有记录),所以一般也不设置
 c -- 表示是否为测试标签(99.99%的标签都不是测试用的啦,所以一般也不设置)
 2).标签大小
 一共四个字节,但每个字节只用 7 位,最高位不使用恒为 0。所以格式如下
 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx
 计算大小时要将 0 去掉,得到一个 28 位的二进制数,就是标签大小(不懂为什么要这样做),计算公式如
下:
 int total_size;
 total_size =    (Size[0]&0x7F)*0x200000
   +(Size[1]&0x7F)*0x400
   +(Size[2]&0x7F)*0x80
   +(Size[3]&0x7F)
2、标签帧
每个标签帧都有一个 10 个字节的帧头和至少一个字节的不固定长度的内容组成。                    它们也是顺序存放在文件
中,和标签头和其他的标签帧也没有特殊的字符分隔。得到一个完整的帧的内容只有从帧头中的到内容大
小后才能读出,读取时要注意大小,不要将其他帧的内容或帧头读入。
帧头的定义如下:
 char FrameID[4];   /*用四个字符标识一个帧,说明其内容,稍后有常用的标识对照表*/
 char Size[4];    /*帧内容的大小,不包括帧头,不得小于 1*/
 char Flags[2];    /*存放标志,只定义了 6 位,稍后详细解说*/
 1).帧标识
 用四个字符标识一个帧,说明一个帧的内容含义,常用的对照如下:
 TIT2=标题 表示内容为这首歌的标题,下同
 TPE1=作者
 TALB=专集
 TRCK=音轨 格式:N/M        其中 N 为专集中的第 N 首,M 为专集中共 M 首,N 和 M 为 ASCII 码表示的数字
 TYER=年代 是用 ASCII 码表示的数字
 TCON=类型 直接用字符串表示
 COMM=备注 格式:"eng\0 备注内容",其中 eng 表示备注所使用的自然语言
 2).大小
 这个可没有标签头的算法那么麻烦,每个字节的 8 位全用,格式如下
 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
 算法如下:
 int FSize;
 FSize = Size[0]*0x100000000
 +Size[1]*0x10000
 +Size[2]*0x100
 +Size[3];
 3).标志
 只定义了 6 位,另外的 10 位为 0,但大部分的情况下 16 位都为 0 就可以了。格式如下:
 abc00000 ijk00000
 a -- 标签保护标志,设置时认为此帧作废
 b -- 文件保护标志,设置时认为此帧作废
 c -- 只读标志,设置时认为此帧不能修改(但我没有找到一个软件理会这个标志)
 i -- 压缩标志,设置时一个字节存放两个 BCD 码表示数字
 j -- 加密标志(没有见过哪个 MP3 文件的标签用了加密)
 k -- 组标志,设置时说明此帧和其他的某帧是一组
 值得一提的是 winamp 在保存和读取帧内容的时候会在内容前面加个'\0',并把这个字节计算在帧内容的
大小中。
 
    这个文件SoundPlayer是在播放音乐的时候得到专辑
 
 
package service
{
	//import省略

	public class SoundPlayer
	{	private var channel:SoundChannel;//声音通道
		private var sound:Sound;//声音
		private var fileUrl:String;
		private var loader:Loader = new Loader  ;
		private var bitmap:Bitmap;
		public function SoundPlayer(){}

		//播放音乐的方法
		public function play(url:String):void
		{
			this.fileUrl = url;
			sound = new Sound  ;
			sound.load(new URLRequest(url));
			channel = sound.play();

			sound.addEventListener(Event.COMPLETE,soundLoaderComplete);
		}
		//soundLoaderComplete 歌曲加载成功 得到专辑图片
		private function soundLoaderComplete(event:Event):void
		{
			(event.target as Sound).removeEventListener(Event.COMPLETE,soundLoaderComplete);
			var fileStream:FileStream = new FileStream  ;
			fileStream.open(new File(this.fileUrl),FileMode.READ);
			//设置文件读取的位置;
			var buffer:ByteArray = new ByteArray  ;
			fileStream.readBytes(buffer,0,10);
			var id3Header:ID3V2Header = new ID3V2Header(buffer);
			//去除标签头
			while (true)
			{	//读取帧头
				var frameHeaderBuffer:ByteArray = new ByteArray  ;
				fileStream.readBytes(frameHeaderBuffer,0,10);
				var id3FrameHeader:ID3V2Frameheader = new ID3V2Frameheader(frameHeaderBuffer);
				if (id3FrameHeader.getFrameSize() <= 0)
				{
					//没有专辑图片
					//删除原来的图片
					loader.unload();
					loader.load(new URLRequest("../images/app.png"));
					loader.contentLoaderInfo.addEventListener(Event.COMPLETE,imageLoaderComplete);
					break;
				}

				//读取帧体
				var frameBodyBuffer:ByteArray = new ByteArray  ;
				fileStream.readBytes(frameBodyBuffer,0,id3FrameHeader.getFrameSize());

				//符标识;
				var key:String = id3FrameHeader.getFrameId();
				//专辑图片的符标识是“APIC”
				if (key == "APIC")
				{
					//专辑图片
					var imageBytes:ByteArray = new ByteArray  ;
					//前14个字节无用   去除掉
					frameBodyBuffer.position = 14;
					frameBodyBuffer.readBytes(imageBytes,0,frameBodyBuffer.length - 14);
					//删除原来的图片;
					loader.unload();
					loader.loadBytes(imageBytes);
					loader.contentLoaderInfo.addEventListener(Event.COMPLETE,imageLoaderComplete);

					break;
				}
			}
			fileStream.close();
		}

		//专辑图片加载完成
		private function imageLoaderComplete(event:Event):void
		{
			loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,imageLoaderComplete);                                                                                     
			this.bitmap = loader.content as Bitmap;
		}


	}

}
 
 
 
 标签头
ID3V2Header.as
 
package service
{
	import flash.utils.ByteArray;

	public class ID3V2Header
	{

		private var identi:ByteArray = new ByteArray;// ID3标示 3
		private var major:ByteArray = new ByteArray;// 版本号 3 1
		private var revsion:ByteArray = new ByteArray;// 0 1
		private var flags:ByteArray = new ByteArray;// 1
		private var total_size:int;// 标签体大小 4


		public function ID3V2Header(data:ByteArray)
		{
			// constructor code
			data.readBytes(identi,0,3);
			data.readBytes(major,0,1);
			data.readBytes(revsion,0,1);
			data.readBytes(flags,0,1);

			total_size = (data.readByte() & 0x7F) * 0x200000 + (data.readByte() & 0x7F) * 0x400
						+ (data.readByte() & 0x7F) * 0x80 + (data.readByte() & 0x7F);
			
		}
		
		
		//返回整个标签体的大小
		public function getTotal_size():int{
			return total_size;
		}

	}

}
 
帧头   ID3V2Frameheader.as
 
package service
{
	import flash.utils.ByteArray;

	public class ID3V2Frameheader
	{

		private var frameId:ByteArray = new ByteArray;//数据帧标示       4
		private var frameSize:int;//数据帧体大小   4
		private var flags:ByteArray =  new ByteArray;//0        2
		
		public function ID3V2Frameheader(data:ByteArray)
		{
			// constructor code
			data.readBytes(frameId,0,4);
			frameSize = data.readByte()*0x1000000
			 +data.readByte()*0x10000
			 +data.readByte()*0x100
			 +data.readByte();
			data.readBytes(flags,0,2);
			
		}
		
		//返回数据帧表示
		public function getFrameId():String{
			return this.frameId.toString();
		}
		
		//返回这一帧的总共数据大小
		public function getFrameSize():int{
			return this.frameSize;
		}
		

	}

}
 
 
 

 

在这里简单说下mp3文件的首部,

1.首先是一个标签头(10个字节), 里面有一个重要的信息是可以通过计算得出标签体的大小

2.然后就是标签体,其中是出若干的帧组成,帧又是由帧头(10个字节),帧体组成(大小不定)

3.帧头中主要有帧标识(APIC,TIT2等等),帧体的大小(可计算大小)

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
分享到:
评论

相关推荐

    MP3文件格式解析

    ### MP3文件格式解析 #### 一、概述 MP3是一种广泛使用的音频文件格式,它的全称是MPEG-1 Audio Layer-3。MPEG(Moving Picture Experts Group)是活动图像专家小组制定的一系列视频和音频压缩标准。MP3属于MPEG-1...

    读取mp3文件的ID3信息

    与`read`接口类似,需要先通过FileReader API处理MP3文件以获得Uint8Array。 使用JavaScript-ID3-Reader的步骤大致如下: 1. 获取用户选择的MP3文件,可以通过HTML5的`&lt;input type="file"&gt;`元素实现。 2. 使用...

    MP3格式 分解图片

    4. 提取图片:将解析出的图片数据写入新的图像文件,即可得到MP3文件中的图片。这通常需要编程知识,可以使用各种编程语言(如Python、C++或Java)和库(如Python的`mutagen`库)来实现。 在提供的压缩包文件`mp3_1...

    获取MP3中的ID3V1、ID3V2信息.rar_MP3 ID3_id3_id3v2_mp3 tag_mp3 信息

    通过解析MP3文件的头部,可以定位到ID3V1或ID3V2标签的位置,然后读取其中的数据。在C程序"获取MP3中的ID3V1、ID3V2信息.c"中,可能包含了这样的实现,包括打开MP3文件、解析ID3标签、提取元数据信息并显示给用户的...

    AlbumArt-Grabber:立即为您的mp3文件获取专辑封面

    它通过解析MP3文件中的元数据,如ID3标签,来识别歌曲的专辑名和艺术家,然后利用这些信息在网络数据库中搜索匹配的专辑封面。 具体来说,该工具可能使用了诸如` eyed3 `或`mutagen`这样的Python库来读取和操作MP3...

    基于STM32单片机的MP3播放器.doc

    ### 基于STM32单片机的多功能MP3播放器关键技术解析 #### 一、引言 近年来,随着计算机技术、微电子技术及数字信号处理技术的飞速发展,消费电子产品的面貌发生了翻天覆地的变化。尤其是网络多媒体技术的广泛应用...

    c语言mp3播放器源码

    可以从键盘上得到输入的字符,然后比较自己定义的密码,登录后会有字符图片的上下移动,形成动画形式,动画结束之后实现按任意键进入播放界面;之后会进行初始化播放器信息,读取本地播放列表和音乐添加到创建相应的...

    360云网盘直连解析 v1.0

    功能: 1、把360云网盘下载链接转化为直连。 2、如果资源是多媒体,可直接...5、点击播放复制,如果是 .mp3或者.mp4或者.flv后缀的话,会直接显示播放测试,如果不是这几个后缀的话,会直接复制解析地址倒剪贴板。

    ww2ogg019音频工具文件

    7. 开始转换,等待完成,得到mp3文件。 这个过程不仅涉及音频格式的转换,还涉及到资源管理和文件处理的技能。理解这些工具的工作原理和使用方法,对于游戏开发人员、音频编辑者或是数字媒体爱好者来说,都是非常...

    flash文件拆解器

    2. 音频分离:Flash文件内嵌的MP3、WAV或其他音频文件,可以导出为独立的音频格式,便于在音频编辑软件中进一步处理。 3. ActionScript查看:拆解器可以解析ActionScript代码,这对于理解动画逻辑、调试或学习AS编程...

    binary-class-mp3:MP3 ID3v2 库

    例如,`read-id3v2`函数可以解析MP3文件中的ID3v2标签,返回一个表示标签信息的结构体。`write-id3v2`函数则可以将修改后的标签写回文件,更新元数据。同时,库还可能提供如`get-frame`和`set-frame`这样的方法,...

    主流数码相框方案解析及对比.pdf

    而文件标题中提到的“方案解析及对比”意味着文档将分析和比较不同的数码相框解决方案。 在描述中,并没有提供额外信息,因此我们可以直接进入内容的解析。 首先,文档提到了一些特定的芯片和组件品牌,例如ATMEL...

    山西旅游网 纯静态HTML 带flash mp3

    “Web”可能是网站的所有HTML、CSS、JavaScript、图片等资源的目录,通过解压可以得到完整的网站源代码和媒体文件。 综合以上信息,我们可以得出以下知识点: 1. **纯静态网站的优势**:包括更快的加载速度、更低...

    Flash(SWF文件)拆解.rar

    本压缩包"Flash(SWF文件)拆解.rar"提供了一个工具或方法,能够将SWF文件分解为它的组成部分,包括图片、文本和声音元素,这样可以方便用户对这些资源进行单独处理或分析。 1. SWF 文件结构:SWF 文件是基于二进制的...

    010 Editor Templates 全新010模板打包下载

    这个压缩包中可能包含了各种各样的模板,涵盖了网络协议、图片格式、音频视频文件、软件配置文件等多种类型。这些模板由专业人员或社区成员精心制作,确保了准确性和实用性。 在实际使用中,用户可以通过010 Editor...

    威盘音乐外链 1.8

    增加 bd.php 百度网盘MP3外链解析文件,只支持解析MP3外链,如需要全能解析请联系! 程序目前支持mp3、wma格式上传,其他格式上传不了,如需修改,请在ok.php内修改: if(($Type!="mp3")&&($Type!="wma")) 这个要...

    010Editor模板—更新

    CAP模板可能用于网络封包分析,AVI和MP3模板分别对应音频和视频文件,而AndroidManifest则是Android应用的重要配置文件,包含了应用的基本信息和权限设置。 在此次更新中,开发者修复了一些bug,这意味着模板的稳定...

    android bootanimation 原理详解

    这些图片通常存储在 `/system/framework/framework-res.apk` 文件中,具体位置为 `/frameworks/base/core/res/assets/images/`。 - **前景图片**:`android-logo-mask.png`,这是一张包含 Android 文字且文字部分...

    android 实现图片,音频,视频,展示,拍摄,预览。存储等功能

    - `GalaryFork` 或 ` chooser-dialog `:可以帮助用户从设备中选择图片、音频或视频文件。 9. 编码与解码: - `MediaCodec`:Android的编码解码框架,支持硬件加速,用于处理音频和视频编码/解码任务。 以上就是...

    Automatizacion_Directorios:该JAVA应用程序递归遍历给定基本目录的目录。 该目录中的目录被视为专辑,并从中获得诸如艺术家,专辑,流派等音频文件的基本信息,并将其插入数据库中。 它还按相册关联图像,并选择封面图像

    Automatizacion_Directorios能够识别与专辑相关的图像文件,这些文件通常与音频文件一同存在于专辑目录下,如JPEG或PNG格式的图片。程序会将这些图片与对应的专辑关联起来,同时,它还有一个智能算法来选择最佳的...

Global site tag (gtag.js) - Google Analytics