AVPlayer seekToTime不能播放正确的位置

我有一个播放HLSvideostream的AVPlayer。 我的用户界面提供了一排button,video中每个“章节”都有一个button(button标记为“1”,“2”,“3”)。 应用程序从服务器下载一些元数据,其中包含以秒表示的章节切入点列表。 例如,一个video的长度是12分钟 – 章节切入点的列表是0,58,71,230,530等等。

当用户点击其中一个“章节button”时,button处理程序代码将执行以下操作:

[self.avPlayer pause]; [self.avPlayer seekToTime: CMTimeMakeWithSeconds(seekTime, 600) toleranceBefore: kCMTimeZero toleranceAfter: kCMTimeZero completionHandler: ^(BOOL finished) { [self.avPlayer play]; }]; 

其中“seekTime”是包含切入点的本地variables(如上所述)。

问题是video并不总是从正确的位置开始。 有时候确实如此。 但有时在请求的seekTime前十秒到两秒之间。 永远不会在请求的seekTime之后启动。

以下是关于video编码的一些统计数据:

编码器:handbrakeCLI编解码器:h.264帧速率:24(实际上,23.976 – 相同如它被拍摄)video比特率:多比特率(64/150/300/500/800/1200)audio比特率:128k关键帧:23.976 1每秒)

当然,我正在使用Apple mediafilesegmenter工具,并使用variantplaylistcreator来生成播放列表。

这些文件是从Amazon Cloud / S3存储桶提供的。

我仍然不清楚的一个领域是CMTimeMakeWithSeconds – 我已经尝试了几个基于不同的文章/文档我已经阅读的变化。 例如,在上面的摘录中,我正在使用:

CMTimeMakeWithSeconds(seekTime,600)

我也试过了:

CMTimeMakeWithSeconds(seekTime,1)

我不知道哪个是正确的,尽pipe两者似乎产生了相同的不一致的结果!

我也试过了:

CMTimeMakeWithSeconds(seekTime,23.967)

有些文章声称这是一个分子/否定的工作,所以n / 1应该是正确的,其中'n'是秒数(如CMTimeMakeWithseconds(n,1))。 但是,代码最初是由另外一个程序员创build的(他现在已经走了),并且他使用了600的数字作为preferredTimeScale(即CMTimeMakeWithseconds(n,600))。

任何人都可以提供任何我做错的线索,或者即使我尝试实现的那种准确性甚至是可能的吗?

如果有人试图提供“另类”解决scheme,我们已经在考虑把video分成不同的stream,每章一个,但是我们不相信这会给我们带来同样的performance,因为改变章节需要更长的时间作为一个新的AVPlayerItem将不得不被创build和加载等,等等,所以如果你认为这是唯一的解决scheme将工作(我们希望这将实现我们想要的结果 – 即每章将开始我们想要的地方)可以自由地这样说。

提前致谢!

 int32_t timeScale = self.player.currentItem.asset.duration.timescale; CMTime time = CMTimeMakeWithSeconds(77.000000, timeScale); [self.player seekToTime:time toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; 

我遇到了“seekToTime”的问题。 我用这个代码解决了我的问题。 “时间尺度”是这个问题的窍门。

我的build议:1)不要使用[avplayer seekToTime:toleranceBefore:toleranceAfter:],这会延迟你的寻找时间4-5秒。

2)HLSvideo剪辑每段10秒。 你的章节起始位置应该适合10的倍数。由于分段以I帧开始,这样就可以快速find时间和准确的时间。

请使用[player seekToTime:CMTimeMakeWithSeconds(seekTime,1)]等函数。
由于您的容差值kCMTimeZero将花费更多的时间来寻找。而不是使用kCMTimeZero的容差值,您可以使用kCMTimeIndefinite ,它相当于我之前指定的函数。

把这个代码可能是解决你的问题。

 let targetTime = CMTimeMakeWithSeconds(videoLastDuration, 1) // videoLastDuration hold the previous video state. self.playerController.player?.currentItem?.seekToTime(targetTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)