加载资产后立即在AVPlayer中寻找特定位置

22

这段代码可以正常工作:我有一个AVPlayer,在视频加载完成之后立即开始播放。它能够正常工作。

以下代码无法正常工作:

与其从开头开始播放视频,我想要在给定的位置开始播放。所以我使用 KVO 等待资源准备好后再播放:

BOOL isReadyToSeek = (self.playerItem.status == AVPlayerStatusReadyToPlay)

然后寻找给定的时间。

[playerItem seekToTime:timeInTheMiddleOfTheVideo completionHandler:myHandler];

然而,在初始搜索时,播放器始终会从视频开头开始。

更新 我尝试了几秒钟的dispatch_after,但那也不起作用。它在播放后可以工作,但一开始就不行。

当我观察self.player.currentItem.duration时,我一直得到0作为valuetimescale的值。


你是说如果延迟它,它就能工作? - Carl Veazey
你确定你传递了一个有效的时间参数吗?timeInTheMiddleOfTheVideo的值是多少? - Carl Veazey
视频大约30分钟。我还尝试了CMTimakewotgseconds(15,1),它肯定在范围内。 - Besi
你说它在播放后可以工作。也许这是我一个愚蠢的问题,但如果你播放后立即寻找会发生什么? - Carl Veazey
这并不是一个愚蠢的问题 :-) 问题在于设置滑块会触发初始播放,因此除非滑块设置为曲目的开头,否则我不想从头开始... - Besi
你已经解决了这个问题吗?请更新问题并分享你的发现。非常感谢。 - rajneesh
1个回答

51

以下是可能帮助你的几件事:

  1. 在检查玩家是否准备好播放时,我会同时检查玩家本身和当前项目。

    if(self.player.status == AVPlayerStatusReadyToPlay &&
       self.player.currentItem.status == AVPlayerItemStatusReadyToPlay) {
        [self.player play];
    }
    
  2. 如果你寻找到例如15秒的位置,但最近的关键帧是视频的开头,那么它可能会从视频的开头开始而不是指定的位置。为了强制播放器定位到确切的位置(注意:这将需要几秒钟的时间),请执行以下操作:

    Float64 seconds = 500.0f;
    CMTime targetTime = CMTimeMakeWithSeconds(seconds, NSEC_PER_SEC);
    [self.player seekToTime:targetTime
     toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
    

    或者你可以通过将其中一个参数指定为无穷大来明确地寻找指定点之前/之后的关键帧:

    [self.player seekToTime:targetTime
     toleranceBefore:kCMTimePositiveInfinity toleranceAfter:kCMTimeZero];
    

AVPlayerStatusReadyToPlay难道不是检查的终极方式吗?为什么要检查项目状态? - pronebird
1
我遇到过这样的情况,即播放器已准备就绪,但项目未准备就绪,或者反之亦然。 [AVPlayer status] 文档说“表示播放器已准备好播放 AVPlayerItem 实例。” 而 [AVPlayerItem status] 则是“该项目已准备好播放”。因此,在能够播放项目和当前项目实际准备就绪之间存在差异。 - user244343
1
我只使用AVPlayerItemStatusReadyToPlay。 - onmyway133
很棒的答案。特别是对于较短的视频,kCMTimeZero容忍度没有延迟,并显示非常平滑的过渡。 - trdavidson
你真是太神了。解释得非常好,示例也很棒。它完美地运作! - anonymous
即使播放器中没有AVPlayerItem,您仍然可以调用[AVPlayer play]。播放器会记录意图,当您附加playerItem时,您可以节省几毫秒的时间,因为播放器不需要生成静态图像。 - Juraj Antas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接