我有一个正在播放 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];
}];
其中“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 数字作为首选时间刻度(即 CMTimeMakeWithseconds(n, 600))。
任何人都可以提供任何关于我做错了什么的线索,或者即使我试图达到的那种准确性是可能的?
如果有人想提供“替代”解决方案,我们已经在考虑将视频分成单独的流,每章一个,但我们不相信这会给我们带来相同的性能,因为更改章节需要更长的时间作为一个新的 AVPlayerItem 必须被创建和加载,等等,等等,等等。所以如果你认为这是唯一可行的解决方案(我们确实希望这会达到我们想要的结果 - 即每一章都会从我们想要的地方开始)随意这么说。
提前致谢!