我想异步加载持续时间,时间(创建视频的时间戳)和资产的区域设置。
Apple显示的'loadValuesAsynchronouslyForKeys:keys'
使用的所有示例代码始终只显示一个键。即:
NSURL *url = aUrl;
AVAsset asset = [[AVURLAsset alloc] initWithURL:url options:nil];
NSArray *keys = [NSArray arrayWithObject:@"duration"];
[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^() {
NSError *error = nil;
AVKeyValueStatus durationStatus = [asset statusOfValueForKey:@"duration" error:&error];
switch (durationSatus) {
case AVKeyValueStatusLoaded:
// Read duration from asset
CMTime assetDurationInCMTime = [asset duration];
break;
case AVKeyValueStatusFailed:
// Report error
break;
case AVKeyValueStatusCancelled:
// Do whatever is appropriate for cancelation
}
}];
我可以假设如果一个项目的状态是'AVKeyValueStatusLoaded',那么在完成块中可以同时读取其他值吗?即:
[asset tracks]
[asset commonMetadata];
[asset duration]
答案 0 :(得分:6)
不,你不能这么认为。我的一种方法看了两个键,可玩和持续时间,我发现可玩性通常可用,而持续时间尚未。我因此将loadValuesAsynchronouslyForKeys:代码移动到一个单独的方法shouldSave:。我在一个叫做saveWithDuration:的方法中从一个计时器调用的shouldSave:方法。一旦saveWithDuration:收到非零持续时间,它就会继续并保存东西。为了避免等待太久,我现在使用一个尝试计数器 - 将来,我会改进这个(你会注意到错误实例目前还没有使用)
- (void)shouldSave:(NSTimer*)theTimer {
NSString * const TBDuration = @"duration";
NSString * const TBPlayable = @"playable";
__block float theDuration = TBZeroDuration;
__block NSError *error = nil;
NSArray *assetKeys = [NSArray arrayWithObjects:TBDuration, TBPlayable, nil];
[_audioAsset loadValuesAsynchronouslyForKeys:assetKeys completionHandler:^() {
AVKeyValueStatus playableStatus = [_audioAsset statusOfValueForKey:TBPlayable error:&error];
switch (playableStatus) {
case AVKeyValueStatusLoaded:
//go on
break;
default:
return;
}
AVKeyValueStatus durationStatus = [_audioAsset statusOfValueForKey:TBDuration error:&error];
switch (durationStatus) {
case AVKeyValueStatusLoaded:
theDuration = CMTimeGetSeconds(_audioAsset.duration);
break;
default:
return;
}
}];
NSUInteger attempt = [[[theTimer userInfo] objectForKey:TBAttemptKey] integerValue];
attempt++;
[self saveWithDuration:theDuration attempt:attempt error:&error];
}
答案 1 :(得分:2)
技术上你不能。 load {docs for loadValuesAsynchronouslyForKeys:completionHandler:表示
你的钥匙的完成状态 在键中指定不一定 相同的 - 一些可能被加载,和 其他人可能都失败了。你必须检查 每个密钥的状态。
在实践中,我认为这通常是一个安全的假设 - 正如您所指出的,Apple的StitchedStreamPlayer示例项目只是查看第一个键的状态。
答案 2 :(得分:0)
不,您不能这样假设。我通常依靠@"duration"
键来创建AVPlayerItem
并开始播放,因为加载@"playable"
通常不能保证资产已经准备就绪。然后,我产生了一个计时器,以定期检查是否加载了其他密钥,例如@"tracks"
,类似于上面提到的Elise van Looij。
此外,请注意-切记completionHandler
中的loadValuesAsynchronouslyForKeys
是在任意后台线程上调用的。如果要处理UI或AVPlayerLayer,则必须将其分派到主线程。