gpt4 book ai didi

ios - AVPlayerItem 初始 timedMetadata 未被观察(KVO)

转载 作者:可可西里 更新时间:2023-11-01 06:11:30 25 4
gpt4 key购买 nike

我有一个处理 AVPlayer(和 AVPlayerItem)的类,它向委托(delegate)人报告状态、时间和 timedMetadata。

除了大约 70-80% 的时间,初始 timedMetadata 不是“观察到的关键值”外,效果很好。然而,在错过第一个 timedMetadata 实例之后,似乎可以毫无问题地观察到所有其他 timedMetadata。

作为临时修复,我已经开始在视频的开头嵌入虚拟的 timedMetadata 标签,可以说除了“踢轮胎”什么都不做,之后一切正常。然而,这似乎很笨拙。我怀疑我是否以次优方式设置 AVPlayerItem 和 KVO,或者这里只是一个错误。

非常感谢任何关于为什么会发生这种情况的想法!下面的代码....

// CL: Define constants for the key-value observation contexts.
static const NSString *ItemStatusContext;
static const NSString *ItemMetadataContext;
static const NSString *ItemPlaybackForcastContext;


- (id)initWithURL:(NSURL *)url
{
if (self = [super init]) {

__weak TFPAVController *_self = self;

AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
NSString *tracksKey = @"tracks";

[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracksKey] completionHandler:
^{
dispatch_async(dispatch_get_main_queue(),
^{
NSError *error = nil;
AVKeyValueStatus status = [asset statusOfValueForKey:tracksKey error:&error];

if (status == AVKeyValueStatusLoaded) {
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];
[item addObserver:_self forKeyPath:@"status" options:0 context:&ItemStatusContext];
[item addObserver:_self forKeyPath:@"timedMetadata" options:0 context:&ItemMetadataContext];
[item addObserver:_self forKeyPath:@"playbackLikelyToKeepUp" options:0 context:&ItemPlaybackForcastContext];

[[NSNotificationCenter defaultCenter] addObserver:_self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:item];

AVPlayer *player = [AVPlayer playerWithPlayerItem:item];
_self.totalRunTime = CMTimeGetSeconds(item.duration);
[_self.delegate avPlayerNeedsView:player];

_self.playerItem = item;
_self.player = player;
}
else {
NSLog(@"The asset's tracks were not loaded: %@ // [%@ %@]",
error.localizedDescription,
NSStringFromClass([self class]),
NSStringFromSelector(_cmd));
}

_self.playerObserver = [_self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, _FrameRate_)
queue:NULL
usingBlock: ^(CMTime time) {
_self.currentVideoTime = CMTimeGetSeconds([_self.playerItem currentTime]);
}];
});
}];
}

return self;
}
#pragma mark - KVO Response Methods
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
__weak TFPAVController *_self = self;

if (context == &ItemStatusContext) {
dispatch_async(dispatch_get_main_queue(),
^{
if (((AVPlayerItem *)object).status == AVPlayerItemStatusReadyToPlay) {

[_self.delegate videoIsLoadedInPlayer:_self];
}
});
return;
}
else if (context == &ItemMetadataContext) {
dispatch_async(dispatch_get_main_queue(),
^{
[_self checkMetaDataForPlayerItem: (AVPlayerItem *)object];
});
return;
}
else if (context == &ItemPlaybackForcastContext) {
dispatch_async(dispatch_get_main_queue(),
^{
AVPlayerItem *playerItem = object;
if (CMTimeGetSeconds([playerItem currentTime]) <= 0) return;

NSDictionary *notificationDictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:playerItem.playbackLikelyToKeepUp]
forKey:kAVPlayerStateKey];

[[NSNotificationCenter defaultCenter] postNotificationName:kAVPlayerNotification
object:self
userInfo:notificationDictionary];
});
return;
}

[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];

}

- (void)checkMetaDataForPlayerItem:(AVPlayerItem *)item
{
NSMutableDictionary *metaDict = [NSMutableDictionary dictionary];

// CL: make sure there's stuff there
if (item.timedMetadata != nil && [item.timedMetadata count] > 0) {
// CL: if there is, cycle through the items and create a Dictionary
for (AVMetadataItem *metadata in item.timedMetadata) {
[metaDict setObject:[metadata valueForKey:@"value"] forKey:[metadata valueForKey:@"key"]];
}
// CL: pass it to the delegate
[self.delegate parseNewMetaData:[NSDictionary dictionaryWithDictionary:metaDict]];
}
}

最佳答案

啊哈,KVO。可能是 Apple 有史以来最糟糕的设计决策之一。

我猜它不再相关,但我猜你遇到的问题是,有时当你开始将自己添加为观察者时,你试图观察的值已经分配给了键,所以您的观察者选择器未被调用。

为避免这种情况,您可以在调用 addObserver:forKeyPath:options:context: 时将 NSKeyValueObservingOptionInitial 添加到 options,您的观察者方法将使用当前值立即调用。

关于ios - AVPlayerItem 初始 timedMetadata 未被观察(KVO),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12065811/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com