SeekToTime работает плавно только вперед, замораживается назад
Я знаю, что есть куча постов, но ни один из них не помог. У меня есть видео с другим FPS(если это имеет какое-то значение) на моем устройстве. Я рассчитываю точное CMTime
(если мы переведем их в секунды, они будут 10,33333,10,4444 и т. д.). Я ищу с помощью этого кода:
self.player.seekToTime( time, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
Он только плавно движется вперед, а назад - нет. Есть идеи почему?
3 ответа
Это связано с тем, что сжатое видео работает с "ключевыми кадрами". Ключевой кадр - это полностью визуализированный видеокадр, но не каждый кадр является ключевым кадром. Кадры, которые следуют за ключевым кадром, сохраняются только как инкрементные отличия от этого ключевого кадра. Это означает, что при перемещении вперед по видео проигрыватель отображает ключевой кадр, перемещается к следующему кадру и рисует изменения, перемещается к следующему кадру и т. Д. И т. Д. При перемещении назад по видео единственное, что игрок может отображать на самом деле ключевые кадры. Обычно он использует закодированные данные для отображения ключевого кадра плюс несколько кадров ПОСЛЕ ключевого кадра, чтобы вы могли видеть, что происходит в этот момент в видео. Единственный способ избежать этого - распаковать видео в буфер и просканировать его обратно - по понятным причинам это слишком медленно для большинства целей.
Попробуйте это Надежда
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)
Когда вы вызываете seekToTime, элемент проигрывателя отменяет предыдущие поиски, что приводит к большому количеству поисков и небольшому отображению кадров. Позвольте использовать 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