AVPlayer项目获得持续时间

时间:2014-05-26 16:46:03

标签: ios objective-c avplayer

我正在播放文件。来自url的mp3流。 我正在使用AVPlayer,当我试图获得构建进度条的总时间时,只要时间是南,我就会得到。

 NSError *setCategoryError = nil;
    if ([ [AVAudioSession sharedInstance] isOtherAudioPlaying]) { // mix sound effects with music already playing
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:&setCategoryError];
    } else {
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&setCategoryError];
    }
    if (setCategoryError) {
        NSLog(@"Error setting category! %ld", (long)[setCategoryError code]);
    }
    NSURL *url = [NSURL URLWithString:@"http://..//46698"];

    AVPlayer *player = [AVPlayer playerWithURL:url];
    songPlayer=player;
    [songPlayer addObserver:self forKeyPath:@"status" options:0 context:nil];



- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    if (object == songPlayer && [keyPath isEqualToString:@"status"]) {
        if (songPlayer.status == AVPlayerStatusFailed) {
            NSLog(@"AVPlayer Failed");

        } else if (songPlayer.status == AVPlayerStatusReadyToPlay) {
            NSLog(@"AVPlayerStatusReadyToPlay");
            [songPlayer play];
            [songPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time){
                CMTime aux = [songPlayer currentTime];
                AVPlayerItem *item=[songPlayer currentItem];
                CMTime dur=[item duration];
                NSLog(@"%f/%f", CMTimeGetSeconds(aux),  CMTimeGetSeconds(dur));
            }];
        } else if (songPlayer.status == AVPlayerItemStatusUnknown) {
            NSLog(@"AVPlayer Unknown");

        }
    }
}

我已经尝试了一切。

[item duration]; /// Fail

[[item asset] duration]; /// Fail

并且没有任何作用

任何人都知道为什么?

6 个答案:

答案 0 :(得分:8)

duration属性的值将报告为kCMTimeIndefinite,直到加载基础资产的持续时间为止。有两种方法可以确保只有在可用时才访问持续时间值:

  1. 等到AVPlayerItem的状态为AVPlayerItemStatusReadyToPlay

  2. 注册duration属性的键值观察,请求初始值。如果初始值报告为kCMTimeIndefinite,则AVPlayerItem会在知道其值后立即通过键值观察通知您项目持续时间的可用性。

答案 1 :(得分:4)

要迅速:

if player.currentItem.status == .readyToPlay {

    print(currentItem.duration.seconds) // it't not nan

}

答案 2 :(得分:1)

我遇到了同样的问题,但我能够用不同的方法获得持续时间。请在此处查看我的回答:https://stackoverflow.com/a/38406295/3629481

答案 3 :(得分:1)

您可以使用资产属性。它会给你持续时间。

self.player.currentItem?.asset.duration.seconds ?? 0

答案 4 :(得分:0)

我在iOS 12上遇到此问题(对于iOS 13,一切正常。)当前项目的持续时间始终是不确定的。我使用player.currentItem?.asset.duration解决了这个问题。像这样:

private var currentItemDuration: CMTime? {
    if #available(iOS 13.0, *) {
        return player?.currentItem?.duration
    } else {
        return player?.currentItem?.asset.duration
    }
}

对于macOS,请参见以下答案:https://stackoverflow.com/a/52668213/7132300似乎也适用于iOS 12。

答案 5 :(得分:0)

@voromax是正确的。我将asset添加到playerItem时没有先获得duration,持续时间为nan

let asset = AVAsset(url: videoUrl)
self.playerItem = AVPlayerItem(asset: asset)

当我首先加载asset.loadValuesAsynchronously时,再也没有nan了,我得到了正确的duration

let assetKeys = ["playable", "duration"]

let asset = AVAsset(url: url)
asset.loadValuesAsynchronously(forKeys: assetKeys, completionHandler: {
    DispatchQueue.main.async { [weak self] in
        self?.playerItem = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: assetKeys)
    }
})