SeekToTime 只为前进顺利工作,向后冻结
SeekToTime working smoothly just for forwards, freezy on backwards
我知道有很多帖子,但是 none 其中有帮助。
我的设备上有不同 FPS 的视频(如果有关系的话)。
我正在计算确切的 CMTime
(如果我们将它们转换为秒,它们将是 10.33333、10.4444 等)。
我正在寻找使用此代码的方法:
self.player.seekToTime( time, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
只能向前流畅,向后不流畅。有什么想法吗?
试试这个希望
let timeScale: Int32 = (self.playerController1.player?.currentItem!.asset.duration.timescale)!
let time: CMTime = CMTimeMakeWithSeconds(77.000000, timeScale)
self.playerController1.player?.seekToTime(time,toleranceBefore:kCMTimeZero ,toleranceAfter:kCMTimeZero)
这是因为压缩视频适用于 'key-frames'。关键帧是完全渲染的视频帧,但并非每一帧都是关键帧。关键帧之后的帧仅存储为与该关键帧的增量差异。这意味着当你在视频中向前移动时,播放器显示一个关键帧,移动到下一帧并绘制变化,移动到下一帧,等等。当通过视频向后移动时,播放器唯一可以实际显示的东西是关键帧。通常它会使用编码数据来显示关键帧以及关键帧之后的几帧,这样您就可以看到视频中那个点发生了什么。解决此问题的唯一方法是将视频解压缩到缓冲区中并向后扫描 - 出于显而易见的原因,这对于大多数用途来说太慢了。
调用seekToTime时,player item会取消之前正在进行的seeks,导致seeking很多,帧显示不多。
让我们使用 bool var isSeekInProgress 来指示播放器项目何时正在寻找。
让我们这样尝试:
var isSeekInProgress = false
let player = <#A valid player object #>
var chaseTime = kCMTimeZero
// your player.currentItem.status
var playerCurrentItemStatus:AVPlayerItemStatus = .Unknown
...
func stopPlayingAndSeekSmoothlyToTime(newChaseTime:CMTime)
{
player.pause()
if CMTimeCompare(newChaseTime, chaseTime) != 0
{
chaseTime = newChaseTime;
if !isSeekInProgress
{
trySeekToChaseTime()
}
}
}
func trySeekToChaseTime()
{
if playerCurrentItemStatus == .Unknown
{
// wait until item becomes ready (KVO player.currentItem.status)
}
else if playerCurrentItemStatus == .ReadyToPlay
{
actuallySeekToTime()
}
}
func actuallySeekToTime()
{
isSeekInProgress = true
let seekTimeInProgress = chaseTime
player.seekToTime(seekTimeInProgress, toleranceBefore: kCMTimeZero,
toleranceAfter: kCMTimeZero, completionHandler:
{ (isFinished:Bool) -> Void in
if CMTimeCompare(seekTimeInProgress, chaseTime) == 0
{
isSeekInProgress = false
}
else
{
trySeekToChaseTime()
}
})
}
更多信息:https://developer.apple.com/library/content/qa/qa1820/_index.html
我知道有很多帖子,但是 none 其中有帮助。
我的设备上有不同 FPS 的视频(如果有关系的话)。
我正在计算确切的 CMTime
(如果我们将它们转换为秒,它们将是 10.33333、10.4444 等)。
我正在寻找使用此代码的方法:
self.player.seekToTime( time, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
只能向前流畅,向后不流畅。有什么想法吗?
试试这个希望
let timeScale: Int32 = (self.playerController1.player?.currentItem!.asset.duration.timescale)!
let time: CMTime = CMTimeMakeWithSeconds(77.000000, timeScale)
self.playerController1.player?.seekToTime(time,toleranceBefore:kCMTimeZero ,toleranceAfter:kCMTimeZero)
这是因为压缩视频适用于 'key-frames'。关键帧是完全渲染的视频帧,但并非每一帧都是关键帧。关键帧之后的帧仅存储为与该关键帧的增量差异。这意味着当你在视频中向前移动时,播放器显示一个关键帧,移动到下一帧并绘制变化,移动到下一帧,等等。当通过视频向后移动时,播放器唯一可以实际显示的东西是关键帧。通常它会使用编码数据来显示关键帧以及关键帧之后的几帧,这样您就可以看到视频中那个点发生了什么。解决此问题的唯一方法是将视频解压缩到缓冲区中并向后扫描 - 出于显而易见的原因,这对于大多数用途来说太慢了。
调用seekToTime时,player item会取消之前正在进行的seeks,导致seeking很多,帧显示不多。 让我们使用 bool var isSeekInProgress 来指示播放器项目何时正在寻找。
让我们这样尝试:
var isSeekInProgress = false
let player = <#A valid player object #>
var chaseTime = kCMTimeZero
// your player.currentItem.status
var playerCurrentItemStatus:AVPlayerItemStatus = .Unknown
...
func stopPlayingAndSeekSmoothlyToTime(newChaseTime:CMTime)
{
player.pause()
if CMTimeCompare(newChaseTime, chaseTime) != 0
{
chaseTime = newChaseTime;
if !isSeekInProgress
{
trySeekToChaseTime()
}
}
}
func trySeekToChaseTime()
{
if playerCurrentItemStatus == .Unknown
{
// wait until item becomes ready (KVO player.currentItem.status)
}
else if playerCurrentItemStatus == .ReadyToPlay
{
actuallySeekToTime()
}
}
func actuallySeekToTime()
{
isSeekInProgress = true
let seekTimeInProgress = chaseTime
player.seekToTime(seekTimeInProgress, toleranceBefore: kCMTimeZero,
toleranceAfter: kCMTimeZero, completionHandler:
{ (isFinished:Bool) -> Void in
if CMTimeCompare(seekTimeInProgress, chaseTime) == 0
{
isSeekInProgress = false
}
else
{
trySeekToChaseTime()
}
})
}
更多信息:https://developer.apple.com/library/content/qa/qa1820/_index.html