ios AVPlayer seekToTime 未在正确位置播放
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11462843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AVPlayer seekToTime does not play at correct position
提问by Jordan Bigel
I have an AVPlayer which is playing a HLS video stream. My user interface provides a row of buttons, one for each "chapter" in the video (the buttons are labeled "1", "2", "3"). The app downloads some meta-data from a server which contains the list of chapter cut-in points denoted in seconds. For example, one video is 12 minutes in length - the list of chapter cut-in points are 0, 58, 71, 230, 530, etc., etc.
我有一个正在播放 HLS 视频流的 AVPlayer。我的用户界面提供了一行按钮,视频中的每个“章节”对应一个按钮(按钮标记为“1”、“2”、“3”)。该应用程序从服务器下载一些元数据,其中包含以秒表示的章节切入点列表。例如,一个视频长度为12分钟——章节切入点列表为0、58、71、230、530等,等等。
When the user taps one of the "chapter buttons" the button handler code does this:
当用户点击“章节按钮”之一时,按钮处理程序代码执行以下操作:
[self.avPlayer pause];
[self.avPlayer seekToTime: CMTimeMakeWithSeconds(seekTime, 600)
toleranceBefore: kCMTimeZero
toleranceAfter: kCMTimeZero
completionHandler: ^(BOOL finished)
{
[self.avPlayer play];
}];
Where "seekTime" is a local var which contains the cut-in point (as described above).
其中“seekTime”是一个包含切入点的本地变量(如上所述)。
The problem is that the video does not always start at the correct point. Sometimes it does. But sometimes it is anywhere from a tenth of a second, to 2 seconds BEFORE the requested seekTime. It NEVER starts after the requested seekTime.
问题是视频并不总是从正确的点开始。有时确实如此。但有时它是在请求的seekTime 之前的十分之一秒到2 秒之间的任何时间。它永远不会在请求的 seekTime 之后启动。
Here are some stats on the video encoding:
以下是有关视频编码的一些统计数据:
Encoder: handbrakeCLI Codec: h.264 Frame rate: 24 (actually, 23.976 - same as how it was shot) Video Bitrate: multiple bitrates (64/150/300/500/800/1200) Audio Bitrate: 128k Keyframes: 23.976 (1 per second)
编码器:handbrakeCLI 编解码器:h.264 帧率:24(实际上是 23.976 - 与拍摄方式相同) 视频比特率:多个比特率(64/150/300/500/800/1200) 音频比特率:128k 关键帧:23.976每秒 1 个)
I am using the Apple mediafilesegmenter tool, of course, and the variantplaylistcreator to generate the playlist.
当然,我正在使用 Apple mediafilesegmenter 工具和变体播放列表创建器来生成播放列表。
The files are being served from an Amazon Cloud/S3 bucket.
这些文件由 Amazon Cloud/S3 存储桶提供。
One area which I remain unclear about is CMTimeMakeWithSeconds - I have tried several variations based on different articles/docs I have read. For example, in the above excerpt I am using:
我仍然不清楚的一个领域是 CMTimeMakeWithSeconds - 我已经根据我阅读的不同文章/文档尝试了几种变体。例如,在上面的摘录中,我使用的是:
CMTimeMakeWithSeconds(seekTime, 600)
CMTimeMakeWithSeconds(seekTime, 600)
I have also tried:
我也试过:
CMTimeMakeWithSeconds(seekTime, 1)
CMTimeMakeWithSeconds(seekTime, 1)
I can't tell which is correct, though BOTH seem to produce the same inconsistent results!
我不知道哪个是正确的,尽管两者似乎都产生了相同的不一致结果!
I have also tried:
我也试过:
CMTimeMakeWithSeconds(seekTime, 23.967)
CMTimeMakeWithSeconds(seekTime, 23.967)
Some articles claim this works like a numerator/denomenator, so n/1 should be correct where 'n' is number of seconds (as in CMTimeMakeWithseconds(n, 1)). But, the code was originally created by a different programmer (who is gone now) and he used the 600 number for the preferredTimeScale (ie. CMTimeMakeWithseconds(n, 600)).
一些文章声称这像分子/分母一样工作,因此 n/1 应该是正确的,其中 'n' 是秒数(如 CMTimeMakeWithseconds(n, 1))。但是,该代码最初是由不同的程序员(现在已经不在了)创建的,他使用了 600 数字作为 preferredTimeScale(即 CMTimeMakeWithseconds(n, 600))。
Can anyone offer any clues as to what I am doing wrong, or even if the kind of accuracy I am trying to achieve is even possible?
任何人都可以提供任何关于我做错了什么的线索,或者即使我试图达到的那种准确性是可能的?
And in case someone is tempted to offer "alternative" solutions, we are already considering breaking the video up into separate streams, one per chapter, but we do not believe that will give us the same performance in the sense that changing chapters will take longer as a new AVPlayerItem will have to be created and loaded, etc., etc., etc. So if you think this is the only solution that will work (and we do expect this will achieve the result we want - ie. each chapter WILL start exactly where we want it to) feel free to say so.
如果有人想提供“替代”解决方案,我们已经在考虑将视频分成单独的流,每章一个,但我们认为这不会给我们带来相同的性能,因为改变章节需要更长的时间作为一个新的 AVPlayerItem 必须被创建和加载,等等,等等。所以如果你认为这是唯一可行的解决方案(我们确实希望这会达到我们想要的结果 - 即每一章都会从我们想要的地方开始)随意说。
Thanks in advance!
提前致谢!
回答by Muhammed Tanr?verdi
int32_t timeScale = self.player.currentItem.asset.duration.timescale;
CMTime time = CMTimeMakeWithSeconds(77.000000, timeScale);
[self.player seekToTime:time toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
I had a problem with 'seekToTime'. I solved my problem with this code. 'timescale' is trick for this problem.
我遇到了“seekToTime”的问题。我用这段代码解决了我的问题。'timescale' 是解决这个问题的技巧。
Swift version:
迅捷版:
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 */
}
回答by Ron
My suggestion: 1) Don't use [avplayer seekToTime: toleranceBefore: toleranceAfter: ], this will delay your seek time 4-5 seconds.
我的建议: 1) 不要使用 [avplayer seekToTime: toleranceBefore: toleranceAfter: ],这会延迟你的搜索时间 4-5 秒。
2) HLS video cut to 10 seconds per segment. Your chapter start postion should fit the value which is multipes of 10. As the segment starts with I frame, on this way, you can get quick seek time and accurate time.
2) HLS 视频每段剪辑为 10 秒。你的章节开始位置应该适合10的倍数的值。由于段从I帧开始,这样你可以获得快速的搜索时间和准确的时间。
回答by prajul
please use function like [player seekToTime:CMTimeMakeWithSeconds(seekTime,1)]
.
Because your tolerance value kCMTimeZero
will take more time to seek.Instead of using tolerance value of kCMTimeZero you can use kCMTimeIndefinitewhich is equivalent the function that i specified earlier.
请使用类似的功能[player seekToTime:CMTimeMakeWithSeconds(seekTime,1)]
。
因为你的容差值kCMTimeZero
需要更多的时间来寻找。而不是使用 kCMTimeZero 的容差值,你可以使用kCMTimeIndetermin等价于我之前指定的函数。
回答by Sankalap Yaduraj Singh
Put this code it may be resolve your problem.
放置此代码可能会解决您的问题。
let targetTime = CMTimeMakeWithSeconds(videoLastDuration, 1) // videoLastDuration hold the previous video state.
self.playerController.player?.currentItem?.seekToTime(targetTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)