简体   繁体   English

AVPlayer 项目获得 nan 持续时间

[英]AVPlayer Item get a nan duration

I'm playing a file.我正在播放文件。 mp3 from url by stream.来自 url 的 mp3 按流。 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.我正在使用 AVPlayer,当我试图获得构建进度条的总时间时,每当时间为 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?有谁知道为什么?

The value of duration property will be reported as kCMTimeIndefinite until the duration of the underlying asset has been loaded. duration属性的值将被报告为kCMTimeIndefinite直到基础资产的持续时间被加载。 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 .等到AVPlayerItem的状态为AVPlayerItemStatusReadyToPlay

  2. Register for key-value observation of the duration property, requesting the initial value.注册duration属性的键值观察,请求初始值。 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.如果初始值报告为kCMTimeIndefinite ,则AVPlayerItem将在其值已知后立即通过键值观察通知您该项目的持续时间的可用性。

For swift:对于快速:

if player.currentItem.status == .readyToPlay {

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

}

@voromax is correct. @voromax是正确的。 I added the asset to the playerItem without getting the duration first and duration was nan :我在没有先获取duration情况下将asset添加到playerItem并且持续时间为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 :当我首先加载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)
    }
})

I had the same problem but I was able to get the duration with a different method.我遇到了同样的问题,但我能够使用不同的方法获得持续时间。 Please see my answer here: https://stackoverflow.com/a/38406295/3629481请在此处查看我的回答: https : //stackoverflow.com/a/38406295/3629481

I have this problem on iOS 12 (for iOS 13 everything works as expected).我在 iOS 12 上遇到了这个问题(对于 iOS 13,一切都按预期工作)。 Current item's duration is always indefinite.当前项目的持续时间总是不确定的。 I solve it by using player.currentItem?.asset.duration .我通过使用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.请参阅 macOS 的此答案: https : //stackoverflow.com/a/52668213/7132300看起来它也适用于 iOS 12。

You can use asset property.您可以使用资产属性。 It will give you the duration.它会给你持续时间。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM