我有一个AVPlayer,正在播放HLS视频流。我的用户界面提供了一行按钮,每个按钮对应视频中的一个“章节”(按钮标记为“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”之前0.1秒到2秒的任意位置。它永远不会在请求的“seekTime”之后开始。
这里是关于视频编码的一些统计信息:
编码器: handbrakeCLI 编解码器: h.264 帧率: 24 (实际上是23.976 - 和拍摄方式相同) 视频比特率: 多个比特率 (64/150/300/500/800/1200) 音频比特率: 128k 关键帧: 23.976 (每秒1个)
当然,我正在使用苹果的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等等。所以如果你认为这是唯一可行的解决方案(我们确实希望这将实现我们想要的结果 - 即每个章节将从我们想要的地方精确开始),请随便说。
提前感谢!
seekToTime:
,还必须实现零容忍。 - danielhadarself.player.currentItem?.duration.timescale
可以工作吗?还是需要访问asset
? - Oleksii Nezhyborets