SeekToTime只为前锋而顺利工作,向后冷冻

时间:2016-04-12 13:54:30

标签: objective-c swift avfoundation avplayer seektotime

我知道有很多帖子,但没有一个帮助过。 我的设备上有不同FPS的视频(如果它以某种方式重要)。 我正在计算确切的CMTime(如果我们将它们翻译为秒,它们将是10.33333,10.4444等)。 我正在寻求使用此代码:

  self.player.seekToTime( time, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)

它只能顺利向前运行,但向后运行却没有。有什么想法吗?

3 个答案:

答案 0 :(得分:2)

这是因为压缩视频使用“关键帧”。关键帧是完全渲染的视频帧,但并非每个帧都是关键帧。关键帧后面的帧仅存储为与该关键帧的增量差异。这意味着当你向前移动视频时,玩家会显示一个关键帧,移动到下一帧并绘制更改,移动到下一帧等等。当向后移动视频时,玩家可以实际显示的唯一内容是关键帧。通常它会使用编码数据来显示关键帧以及关键帧之后的几帧,这样您就可以看到视频中该点发生了什么。解决这个问题的唯一方法是将视频解压缩到一个缓冲区并向后扫描 - 显然这对于​​大多数用途来说太慢了。

http://www.dacast.com/blog/what-is-a-key-frame-for-video/

答案 1 :(得分:2)

当您调用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

答案 2 :(得分:1)

试试这个希望

     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)