AVPlayer seekToTime无法在正确的位置播放

Jor*_*gel 29 video-streaming ios avplayer

我有一个播放HLS视频流的AVPlayer.我的用户界面提供了一行按钮,一个用于视频中的每个"章节"(按钮标记为"1","2","3").该应用程序从服务器下载一些元数据,该服务器包含以秒表示的章节切入点列表.例如,一个视频的长度为12分钟 - 章节切入点的列表为0,58,71,230,530等,等等.

当用户点击其中一个"章节按钮"时,按钮处理程序代码执行以下操作:

            [self.avPlayer pause];

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

其中"seekTime"是包含切入点的局部变量(如上所述).

问题是视频并不总是从正确的点开始.有时确实如此.但有时它会在请求的seekTime之前的任何时间从十分之一秒到2秒.它永远不会在请求的seekTime之后启动.

以下是视频编码的一些统计信息:

编码器:handbrakeCLI编解码器:h.264帧率:24(实际上,23.976 - 与拍摄方式相同)视频比特率:多比特率(64/150/300/500/800/1200)音频比特率:128k关键帧:23.976(每秒1次)

我当然使用Apple mediafilesegmenter工具和variantplaylistcreator来生成播放列表.

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

我仍然不清楚的一个领域是CMTimeMakeWithSeconds - 我已经根据我读过的不同文章/文档尝试了几种变体.例如,在上面的摘录我使用:

CMTimeMakeWithSeconds(seekTime,600)

我也尝试过:

CMTimeMakeWithSeconds(seekTime,1)

我不知道哪个是正确的,虽然两个似乎产生相同的不一致结果!

我也尝试过:

CMTimeMakeWithSeconds(seekTime,23.967)

有些文章声称这就像分子/分母一样,所以n/1应该是正确的,其中'n'是秒数(如CMTimeMakeWithseconds(n,1)).但是,代码最初是由一个不同的程序员(现在已经不在了)创建的,他使用600数字作为preferredTimeScale(即CMTimeMakeWithseconds(n,600)).

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

如果有人想要提供"替代"解决方案,我们已经在考虑将视频分成不同的流,每章一个,但我们不相信这会给我们带来相同的性能,因为更改章节需要更长的时间因为新的AVPlayerItem必须被创建和加载等等,所以如果你认为这是唯一可行的解​​决方案(我们希望这将达到我们想要的结果 - 即每一章都会准确地开始我们想要的地方)随意说出来.

提前致谢!

小智 85

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

我遇到了'seekToTime'的问题.我用这段代码解决了我的问题.'timescale'是解决这个问题的绝招.

Swift版本:

let playerTimescale = self.player.currentItem?.asset.duration.timescale ?? 1
let time =  CMTime(seconds: 77.000000, preferredTimescale: playerTimescale)
self.player.seek(to: time, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero) { (finished) in /* Add your completion code here */
}
Run Code Online (Sandbox Code Playgroud)

  • @ jordan-bigel这应该被选为正确的答案. (7认同)
  • [此](/sf/ask/991801331/)解释了此解决方案为何有效。重点是它不能与“seekToTime:”一起使用,但也必须实现零容忍。 (2认同)

pra*_*jul 1

请使用类似 的函数[player seekToTime:CMTimeMakeWithSeconds(seekTime,1)]
因为您的容差值kCMTimeZero将花费更多时间来查找。您可以使用kCMTimeIndefinite代替使用 kCMTimeZero 的容差值,它相当于我之前指定的函数。