本节主要讲解AVFoundation中关于资源的元数据信息的操做数组
上一节主要针对 AVFoundation
框架进行了总览概况,这是AVFoundation
框架详细讲解的第一节,此节主要讲解一些基本知识以及相关的操做,针对后续章节作铺垫做用。 在本章一下内容以前必须先明确一下几个问题session
什么是元数据?
元数据能够理解为就是资源的基本描述数据, 好比一个视频文件或者音频文件,它的时间,频率,声道等等信息;其也能够表示更加详细的音视频流数据以及字幕等信息数据结构
元数据都包括那些东西?
元数据我的理解能够分为两种:架构
基本元数据框架
基本元数据通常包括资源的时间,频率等基本信息
详细元数据异步
包括资源内部关于容器格式的一些更加详细的信息,好比字幕,以及填写在容器格式内容的一些其余数据
元数据如何来的以及其做用是什么?
元数据最简单的用途就是了解资源文件的基本信息,好比时长, 格式, 图标等信息, 其更加详细的格式内数据肯定编解码器以及资源版权等等信息编辑器
在进行具体的元数据操做以前,须要先明确AVFoundation 框架中关于元数据的两个类:ide
AVAsset 是AVFoundation
框架的核心类(此类是个抽象类,并不能进行实例化,其经过URL地址实例化的是它的子类AVURLAsset
对象), 其框架的全部操做都是围绕此类来展开的。其将媒体资源模块化,对资源文件的信息进行抽象化,因为资源文件存在多种格式以及多种不一样参数下的资源文件都存在很大差别,经过AVAsset
进行封装,将资源文件进行标准化,让整个框架操做更加简洁明确模块化
框架处理总体化学习
简洁化开发,用户不须要考虑多种编码器和容器格式的问题
隐藏文件的具体路径,经过URL进行初始化资源
AVAssetTrack 是更加详细的媒体元数据类,每个AVAsset资源中能够对应多个用于描述其更加细致的元数据的AVAssetTrack
对象 。AVAssetTrack 最多见的形态是音频和视频流,可是其也能够表示文本,副标题以及字幕等媒体类型
提供访问具体资源元数据,能够对存储在格式中的帧中元数据进行访问
因为AVFoundation 是一个通用框架,其在iOS平台和Mac OS平台均可以使用,因此在获取资源时,不一样的平台有不一样的获取方式
iOS Assets库资源
-(void)initAsset { //不过此框架在iOS 9 已通过时了,能够经过 PHPhotoLibrary 框架获取资源,将在后续的章节中能够会讲解 ALAssetsLibrary *library = [[ALAssetsLibrary alloc]init]; [library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) { //过滤出全部的视频资源 [group setAssetsFilter:[ALAssetsFilter allVideos]]; [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:0] options:0 usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { if (result) { id representation = [result defaultRepresentation]; NSURL *url = [representation URL]; AVAsset *asset = [AVAsset assetWithURL:url]; } }]; } failureBlock:^(NSError *error) { }]; }
注意: 以上方式虽然能实现资源的获取,可是其在iOS9 已通过期,新的系统将采用PHPhotoLibrary
来进行媒体文件的管理,这个框架在之后会进行单独的讲解
AVAsset 中基友多种有用的方法和属性,能够提供有关资源的信息。可是 AVAsset 采用的是一种高效的设计方法,属性采用的是异步延迟载入资源属性,直到请求时才载入 , 由于媒体资源的属性不少,这样能够加快建立资源的速度而不用加载不少几乎不会用到的资源属性; 虽然资源属性的回去采用的是异步的方式实现的,可是资源属性的访问倒是同步发生的(__就是开发者该真没访问就怎么访问,只是内部数据处理上采用的延迟载入的,形成的结果就是访问速度变慢, 程序会阻塞__)
异步加载实现
AVAsset 和 AVAssetTrack 都实现了异步键值获取协议AVAsynchronousKeyValueLoading
, 此协议中定义了两个方法
//方法一 - (AVKeyValueStatus)statusOfValueForKey:(NSString *)key error:(NSError * _Nullable *)outError; //方法二 - (void)loadValuesAsynchronouslyForKeys:(NSArray<NSString *> *)keys completionHandler:(void (^)(void))handler;
__说明:__ * 方法1会返回一个状态,标识当前属性所处的状态, 从状态名和定义上能够看出只有在是`AVKeyValueStatusLoaded`时才能够直接使用,不然都将形成延迟 * 方法二就是异步获取属性的定义方法,经过给定keys来获取对应的值
NSArray *keys = @[@"tracks"]; __weak __typeof(self) weakSelf = self; [self.asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{ NSError *error = nil; AVKeyValueStatus status = [weakSelf.asset statusOfValueForKey:@"tracks" error:&error]; switch (status) { case AVKeyValueStatusFailed: case AVKeyValueStatusUnknown: case AVKeyValueStatusCancelled: case AVKeyValueStatusLoading: NSLog(@"值获取异常或者尚未获取,此时操做将形成延迟"); break; case AVKeyValueStatusLoaded: NSLog(@"值已经获取完毕,能够直接使用"); break; default: break; } }];
说明:
* 注意其中的keys 数组,其中放的是`AVAsset`对象中属性名称,当获取多个属性时,须要针对每一个属性进行单独验证状态(block中的代码须要些多份) * block会在任意队列进行调用,若是要更新UI的话,必需要回到主队列上
这里有一个简洁的方式获取属性值,从开始处能够找到AVAsset是一个抽象类,其建立的是一个子类 AVURLAsset类,此类的初始化方法带有一个options属性,能够经过此种方式实现
NSDictionary *dic = @{ AVURLAssetPreferPreciseDurationAndTimingKey: @(YES), AVURLAssetReferenceRestrictionsKey:@(1) }; AVAsset *asset = [AVURLAsset URLAssetWithURL:nil options:dic];
元数据的格式存在多种多样的,可是在Apple环境下,通常存在如下4种:
QuickTime
是苹果本身的开发的媒体架构,跨平台,文件格式为 .mov
格式,采用的是atoms的数据结构组成
能够经过十六进制编辑器打开此种文件查看器内容,可使用官方程序Atom Inspector
来查看
若是想对这些数据更加细致的了解的,请查看苹果官方文档关于此内容的部分
MPEG-4 音视频 (这个是两种哦)
MPEG-4 video
MPEG-4 audio
此文件格式与 QuickTime 相相似,由于它基于QuickTime来的。 此种文件存在多种文件后缀m4v,m4a,m4p,m4b等格式
MP3
MP3使用的是音频编码的形式,不是使用容器格式。一些元数据位于文件的头部
注意: AVFoundation 支持数据的读,但不支持写操做(MP3版权问题)
在进行元数据获取时, 实现了更加精准的获取,对元数据进行了分类。当获取好比歌手,插图信息等资源时,能够经过commonMetadata
属性获取,可是当获取指定格式的元数据时能够经过metadataForformat
方法获取
NSArray *keys = @[@"availableMetadataFormats"]; __weak __typeof(self) weakSelf = self; [self.asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{ NSMutableArray *metadata = @[].mutableCopy; for (NSString *formate in weakSelf.asset.availableMetadataFormats) { //此处获取的是一个 AVMetadataItem 数组 [metadata addObjectsFromArray:[weakSelf.asset metadataForFormat:formate]]; } }];
经过以上方式获取全部的元数据
如下是我获取的一个MP3格式的歌曲的信息
虽然经过以上的方式获取到了元数据,如何查找到本身须要的元数据?
经过以上的查找能够肯定查找出来的元素都是AVMetadataItem
类型的对象,那么获取就在这个里边啦 ,查看头文件发现这个类也实现了AVAsynchronousKeyValueLoading
异步获取。哈哈 怪不得上图中看到有些属性的值为 null 呢
在AVMetadataItem
头文件中能够找到答案. Apple已经对经常使用的Languages以及ID 作了指定的方法,其余的就能够经过AVMetadataItemFilter
类的+ (NSArray<AVMetadataItem *> *)metadataItemsFromArray:(NSArray<AVMetadataItem *> *)metadataItems withKey:(nullable id)key keySpace:(nullable NSString *)keySpace;
方法能够实现, 可是 , 啊哈哈 其中的参数从哪里来的 ,好像没有说清楚(有哪位同仁知道的麻烦告知下,在这里先谢过了)。不过这里提示可使用+ (NSArray<AVMetadataItem *> *)metadataItemsFromArray:(NSArray<AVMetadataItem *> *)metadataItems filteredByIdentifier:(NSString *)identifier
方法
补充: 此处的参数能够在
AVMetadataFormat.h
头文件中找到
修改元数据使用AVMetadataItem
对应的一个可变类AVMutableMetadataItem
来实现
虽然经过以上的方式能够实现元数据的修改和查找,可是保存就比较特殊, 保存并非保存元数据,而是须要将整个 AVAsset
资源重置一份, 由于此类是一个不可变类,不能经过简单的方式实现, AVFoundation框架谓词提供了一个专门的类 AVAssetExportSession
用于从一个 AVAsset资源到另外一个 AVAsset资源的转变
AVAssetExportSession *session = [[AVAssetExportSession alloc]initWithAsset:self.asset presetName:AVAssetExportPresetPassthrough]; session.outputURL = @""; //输出地址 session.outputFileType = @""; //输出的类型 session.metadata = @[]; //metadata元数据数组 [session exportAsynchronouslyWithCompletionHandler:^{ AVAssetExportSessionStatus status = session.status; //导出状态 switch (status) { case AVAssetExportSessionStatusCompleted: NSLog(@"导出成功"); break; default: break; } }];
说明:
经过以上的方式能够实现AVAsset资源到另外一个 AVAsset资源的转变, 能够实现修改元数据, 转码等等操做 特别注意的是`presetName`参数的值,值不一样,可进行操做的权限就不一样,此处采用的值确实容许修改一些元数据,可是不能添加新的元数据(使用转码预设值来实现添加)
经过以上的学习,能够多 AVFoundation框架又一个大体的了解, 以上只是对资源对象的简单介绍,其各类不一样资源类型还有更多的详细内容和具体的表明含义,这个须要对不一样类型格式进行更加详细的学习,不在系列文章学习范围内,若是想学,能够本身查找对应格式的详细说明手册 。
再一个针对元数据的说明:
我的理解就是全部的和资源文件相关的好比时间,icon,发行商,版权等等信息均可以统称为元数据,元数据能够理解为是一个抽象概念,并非一个具体的概念,在此处元数据能够指AVAsset
对象中的部分属性以及AVAssetTrack
对象和AVMetadataItem
的数据
以上内容只是我的针对这块的一些拙见,若是有不对的地方,还请指出.
playtomandjerry@gmail.com