认识 AVAsset
AV Foundation 中最重要的类就是 AVAsset
,它定义了 AV Foundation 的时基媒体模型,是 AV Foundation 设计的核心,其是一个抽象类和不可变类,定义了媒体资源混合呈现的方式,将媒体资源的静态属于模块化一个整体,比如标题、时长和元数据等。
AVAsset
不需要考虑媒体资源所具有的两个重要范畴:
-
媒体格式
AVAsset
提供了对基本媒体格式的层抽象,意味着无论是处理什么格式的媒体,面对的都只有资源这个概念,不需要考虑多种编解码器和容器格式因为细节不同而带来的困扰。 资源路径
苹果使用类簇设计AVAsset
,用其具体的子类 AVURLAsset
和 NSURL
实例化,这个地址可能是本地的 URL,也可能是远程服务器的 URL。
下图来源于AVFoundation Programming Guide -Representation of Assets,描述了 AVAsset
及其子类:
AVAsset
还可以插入到AVMutableCompositions
中,通过多个AVAsset
组装成一个音视频。
AVAssetTrack (轨道)
AVAsset
本身并不是媒体资源,作为时基媒体的容器,AVAsset
包含旨在一起呈现或处理的轨道(track)集合,轨道由AVAssetTrack
的实例表示,AVAsset
可以通过 tracks
属性进行访问轨道的集合,其集合中每个轨道都具有统一的媒体类型,包括(但不限于)音频、视频、文本、隐藏式字幕,而 AVAsset
对象提供有关整个资源的信息,例如持续时间或标题。如下图所示,在一个典型的简单情况下,一个轨道代表音频分量,另一个轨道代表视频分量;在复杂的合成中,可能存在多个重叠的音频和视频轨道。
创建 AVAsset
由于 AVAsset
是一个抽象类,意味着它不能直接被实例化,可以通过 URL 来对它进行初始化来实现。
NSURL *url = <#标识视听资产的 URL,例如电影文件#>;
AVAsset *sset = [AVAsset assetWithURL:url];
当它使用 assetWithURL:
方法创建实例时,实际上是创建了它 AVURLAsset
子类的一个实例,我们可以直接使用 AVURLAsset
进行创建,AVURLAsset
提供了通过传递字典参数选项调整资源的创建方式,字典中可配置选项如下:
-
AVURLAssetAllowsCellularAccessKey
一个布尔值,指示系统是否允许蜂窝网络请求资源,最低使用版本 iOS 10.0
-
AVURLAssetAllowsConstrainedNetworkAccessKey
一个布尔值,指示系统是否允许受约束(开启低数据模式时生效,用户可设置)的网络请求资源,最低使用版本 iOS 13.0
-
AVURLAssetAllowsExpensiveNetworkAccessKey
一个布尔值,指示系统是否允许昂贵的网络(连接蜂窝数据、个人热点或低数据模式时生效,系统自动判断)请求资源,比如蜂窝网络、受约束的网络,最低使用版本 iOS 13.0
AVURLAssetPreferPreciseDurationAndTimingKey
一个布尔值,指示资产是否应按时间提供准确的持续时间访问。
AVURLAssetHTTPCookiesKey
随 HTTP 请求一起发送的 HTTP cookie,最低使用版本 iOS 8.0
-
AVURLAssetReferenceRestrictionsKey
一个
AVAssetReferenceRestrictions
枚举值,表示在解析对外部媒体数据的引用时资产使用的限制 -
AVURLAssetURLRequestAttributionKey
一个
NSURLRequestAttribution
值,用于指定此资产请求的 URL 的属性,最低使用版本 iOS 15.0
例如,希望获取更准确的时长信息可以使用 AVURLAssetPreferPreciseDurationAndTimingKey
:
NSURL *url = <#标识视听资产的 URL,例如电影文件#>;
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:@{AVURLAssetPreferPreciseDurationAndTimingKey:@true}];
异步加载
AVAsset
具有多种有用的方法和属性,可以提供有关资源的信息。在创建时,资源就是对基础媒体文件的处理。 AVAsset
使用一种高效的设计方法,即延长载入资源的属性,直到请求时才载入 ,这样就可以快速地创建资源。AVAsset
和 AVAssetTrack
都遵守了 AVAsynchronousKeyValueLoading
协议:
@protocol AVAsynchronousKeyValueLoading
- (AVKeyValueStatus)statusOfValueForKey:(NSString *)key error:(NSError * _Nullable * _Nullable)outError;
- (void)loadValuesAsynchronouslyForKeys:(NSArray<NSString *> *)keys completionHandler:(nullable void (^)(void))handler;
@end
开发者可以在调用资产的方法之前先查询给定属性的状态AVKeyValueStatus
,如果状态不是AVKeyValueStatusLoaded
,则需要先异步加载属性值。例如,下面的代码显示了如何使用此方法 loadValuesAsynchronouslyForKeys:completionHandler:duration
加载资产的属性:
NSURL *url = <#A URL that identifies an audiovisual asset such as a movie file#>;
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
NSArray *keys = @[@"duration"];
[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^() {
NSError *error = nil;
AVKeyValueStatus tracksStatus = [asset statusOfValueForKey:@"duration" error:&error];
switch (tracksStatus) {
case AVKeyValueStatusLoaded:
[self updateUserInterfaceForDuration];
break;
case AVKeyValueStatusFailed:
[self reportError:error forAsset:asset];
break;
case AVKeyValueStatusCancelled:
// Do whatever is appropriate for cancelation.
break;
}
}];
由于
loadValuesAsynchronouslyForKeys:completionHandler:duration
可能会因为某种原因失败、或者被取消,因此,在回调中需要检查当前状态。
一次加载多个属性可以使 AV Foundation 通过批量加载请求来优化性能。