【问题标题】:AVPlayer Item get a nan durationAVPlayer 项目的持续时间为 nan
【发布时间】:2014-05-26 16:46:03
【问题描述】:

我正在播放一个文件。来自 url 的 mp3 流。 我正在使用 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");

        }
    }
}

我什么都试过了。

[item duration]; /// Fail

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

没有任何效果

有人知道为什么吗?

【问题讨论】:

  • 我也有同样的问题。你想出来了吗?你是怎么做到的 ?即使我已经尝试了一切。所以帮我解决这个问题。
  • 我也有同样的问题。你找到解决方案了吗?请与我们分享。

标签: ios objective-c avplayer


【解决方案1】:

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

  1. 等到AVPlayerItem 的状态为AVPlayerItemStatusReadyToPlay

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

【讨论】:

  • 为了透明度 - 正是来自文档。
【解决方案2】:

对于迅捷:

if player.currentItem.status == .readyToPlay {

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

}

【讨论】:

    【解决方案3】:

    我在 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 也有效。

    【讨论】:

      【解决方案4】:

      @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)
          }
      })
      

      【讨论】:

      • 很高兴能帮上忙! ? ? ?
      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多