28

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

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

Float64 duration = CMTimeGetSeconds(self.avPlayer.currentItem.duration);

这在 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>
4

4 回答 4

51

在尝试了不同的初始化对象的方法之后,我找到了一个可行的解决方案:

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

似乎持续时间值并不总是可以立即从 AVPlayerItem 获得,但它似乎可以立即与 AVAsset 一起正常工作。

于 2013-09-27T20:24:17.687 回答
27

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

CMTimeGetSeconds([[[[self player] currentItem] asset] duration]);

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

CMTimeGetSeconds([[[self player] currentItem] duration]);
于 2013-12-27T07:17:55.393 回答
6

手册中所述,推荐的方法是观察播放器项目状态:

[self.avPlayer.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial context:nil];

然后,在里面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);
        // ...
    }
}

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

if (self.avPlayer.currentItem) {
    [self.avPlayer.currentItem removeObserver:self forKeyPath:@"status"];
}

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

于 2015-01-06T11:25:32.873 回答
0

斯威夫特版本

您可以使用AVAssetwhich is AVPlayerItemproperty 获取持续时间:

func getVideoDuration(from player: AVPlayer) -> Double? {
    guard let duration = player.currentItem?.asset.duration else { return nil }
    let durationSeconds = CMTimeGetSeconds(duration)
    return durationSeconds
}

AVAsset从头开始创建:

func getVideoDuration(for videoUrl: URL) -> Double {
    let asset = AVAsset(url: videoUrl)
    let duration = asset.duration
    let durationSeconds = CMTimeGetSeconds(duration)
    return durationSeconds
}
于 2019-04-17T15:33:46.040 回答