iOS 7中的iOS 7 AVPlayer AVPlayerItem持续时间不正确

Mat*_*lfe 28 avfoundation ios avplayer avasset ios7

我的应用程序中有以下代码:

NSURL *url = [NSURL fileURLWithPath: [self.DocDir stringByAppendingPathComponent: self.FileName] isDirectory: NO];
self.avPlayer = [AVPlayer playerWithURL: url];

Float64 duration = CMTimeGetSeconds(self.avPlayer.currentItem.duration);
Run Code Online (Sandbox Code Playgroud)

这适用于iOS 6,但由于某种原因,iOS 7会返回NaN.检查self.avPlayer.currentItem.duration时,CMTime对象的值为0,标志为17.

有趣的是,玩家工作正常,只是持续时间是错误的.

还有其他人遇到过同样的问题吗?我正在导入以下内容:

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
#import <CoreMedia/CoreMedia.h>
#import <AVFoundation/AVAsset.h>
Run Code Online (Sandbox Code Playgroud)

Mat*_*lfe 50

在使用不同的初始化对象的方法后,我到达了一个有效的解决方案:

AVURLAsset *asset = [AVURLAsset assetWithURL: url];
Float64 duration = CMTimeGetSeconds(asset.duration);
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset: asset]; 
self.avPlayer = [[AVPlayer alloc] initWithPlayerItem: item];
Run Code Online (Sandbox Code Playgroud)

看起来持续时间值并不总是立即从AVPlayerItem可用,但它似乎立即与AVAsset一起正常工作.

  • 我还使用了[[AVPlayer currentItem] duration],它在iOS 7中返回NaN以获取有效的媒体文件.在iOS 6中,如果它返回NaN,则意味着该文件无法播放.切换到AVURLAsset的想法解决了这个问题. (2认同)

Der*_* Li 27

在iOS 7中,对于已创建的AVPlayerItem,您还可以从底层资产中获取持续时间:

CMTimeGetSeconds([[[[self player] currentItem] asset] duration]);
Run Code Online (Sandbox Code Playgroud)

而不是直接从AVPlayerItem获取它,它给你一个NaN:

CMTimeGetSeconds([[[self player] currentItem] duration]);
Run Code Online (Sandbox Code Playgroud)


Ja͢*_*͢ck 6

手册中所述,推荐的方法是观察玩家的物品状态:

[self.avPlayer.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial context:nil];
Run Code Online (Sandbox Code Playgroud)

然后,在里面observeValueForKeyPath:ofObject:change:context

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    // TODO: use either keyPath or context to differentiate between value changes
    if (self.avPlayer.currentItem.status == AVPlayerStatusReadyToPlay) {
        Float64 duration = CMTimeGetSeconds(self.avPlayer.currentItem.duration);
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,请确保在更改播放器项目时删除观察者:

if (self.avPlayer.currentItem) {
    [self.avPlayer.currentItem removeObserver:self forKeyPath:@"status"];
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您也可以duration直接观察该属性。但是,根据我的个人经验,结果并不像预期的那样可靠;-)