Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVPlayer Item get a nan duration

I'm playing a file. mp3 from url by stream. I'm using AVPlayer and when I am trying to get the total time to build a progress bar, I get whenever time is nan.

 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");

        }
    }
}

I've tried everything.

[item duration]; /// Fail

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

and nothing work

Anyone know why?

like image 417
Pedro Avatar asked May 26 '14 16:05

Pedro


4 Answers

The value of duration property will be reported as kCMTimeIndefinite until the duration of the underlying asset has been loaded. There are two ways to ensure that the value of duration is accessed only after it becomes available:

  1. Wait until the status of the AVPlayerItem is AVPlayerItemStatusReadyToPlay.

  2. Register for key-value observation of the duration property, requesting the initial value. If the initial value is reported as kCMTimeIndefinite, the AVPlayerItem will notify you of the availability of the item's duration via key-value observing as soon as its value becomes known.

like image 112
voromax Avatar answered Nov 13 '22 22:11

voromax


For swift:

if player.currentItem.status == .readyToPlay {

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

}
like image 22
Au Room Avatar answered Nov 13 '22 22:11

Au Room


I have this problem on iOS 12 (for iOS 13 everything works as expected). Current item's duration is always indefinite. I solve it by using player.currentItem?.asset.duration. Something like this:

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

See this answer for macOS: https://stackoverflow.com/a/52668213/7132300 It looks like it's also valid for iOS 12.

like image 4
algrid Avatar answered Nov 14 '22 00:11

algrid


@voromax is correct. I added the asset to the playerItem without getting the duration first and duration was nan:

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

When I loaded the asset.loadValuesAsynchronously first, no more nan and I got the correct 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)
    }
})
like image 2
Lance Samaria Avatar answered Nov 13 '22 22:11

Lance Samaria