Swift AVPlayer seekToTime问题

时间:2016-07-20 08:05:17

标签: swift avplayer

我有这段代码:

let punto = sender.locationInView(self.barraVideo).x
        let larghezzaImg : Double = Double((self.barraVideoInvisTocco?.frame.width)!)

        let percTocco : Double = (100 / larghezzaImg) * Double(punto)

        let lunghezzaVideo : Double = Double(CGFloat((avPlayer?.currentItem?.asset.duration.value)!) / CGFloat(1000.0));
        let frameRate : Int32 = (avPlayer?.currentItem?.currentTime().timescale)!

        let secondo : Float64 = Float64((lunghezzaVideo/100)*percTocco)
        print("Val : \(secondo)");

        avPlayer?.currentItem?.seekToTime(CMTimeMakeWithSeconds(secondo, frameRate))

        avPlayer?.play()
        videoInPlay = true;
        playPauseBtn!.image = UIImage(named: "iconaPausa.png")!;

在the seekBar上点击一个x坐标并寻找视频。 该代码适用于日志视频,但对于短视频工作非常糟糕。 当我点击短视频时,AVPlayer只在视频的开头或接近结尾处寻找,而不是在中间

打印:

Val : 3.36008475976495
Val : 7.14189817632069
Val : 13.3303201306846
Val : 3.70388597945183
Val : 3.93308679257642
Val : 3.24548435320265
Val : 3.70388597945183
Val : 18.8311396456748
Val : 27.0823689181601
Val : 40.1468152662618
Val : 51.3776551093667
Val : 17.2267339538027
Val : 9.54850671412889
Val : 23.4151559081666
Val : 37.6256063218913

val表示我不会寻求的秒的正确值。 抱歉英语不好,我是意大利人

4 个答案:

答案 0 :(得分:6)

对于AVPlayer,有不同的方式让游戏寻求时间;

player.seekToTime(<#time: CMTime#CMTime#>)

对于这种方法,玩家将寻求快速搜索时间但不寻求搜索时间的确切位置,这意味着搜索时间会有一些偏移

Apple的文档

使用此方法搜索当前玩家项目的指定时间。

所寻求的时间可能与指定的效率时间不同。

对于样本的准确搜索,请参阅seekToTime:toleranceBefore:toleranceAfter:。

player.seekToTime(<#T##time: CMTime##CMTime#>, completionHandler: <#T##(Bool) -> Void#>)

对于这种方法,玩家将寻求快速搜索时间,并且,使用偏移量,您可以使用completionHandler做一些事情

Apple的文档

使用此方法搜索当前玩家项目的指定时间,并在搜寻操作完成时收到通知。

将使用完成的参数

立即调用仍处于进行中的任何先前搜索请求的完成处理程序

设为NO。如果新请求完成而没有被另一个搜索请求或指定的任何其他操作中断

将调用完成处理程序,并将完成的参数设置为YES。

如果您想要更准确,请使用以下方法

player.seekToTime(<#T##time: CMTime##CMTime#>, toleranceBefore: <#T##CMTime#>, toleranceAfter: <#T##CMTime#>)

player.seekToTime(<#T##time: CMTime##CMTime#>, toleranceBefore: <#T##CMTime#>, toleranceAfter: <#T##CMTime#>, completionHandler: <#T##(Bool) -> Void#>)

这种方法会让玩家在你要求的指定时间内寻找,但会慢一些(好吧......主要取决于当前的媒体)

Apple的文档

使用此方法搜索当前玩家项目的指定时间。

所寻求的时间将在[time-toleranceBefore,time + toleranceAfter]的范围内,并且可能与指定的效率时间不同。

通过kCMTimeZero for toleranceBefore和toleranceAfter请求样本准确搜索,这可能会导致额外的解码延迟。

使用beforeTolerance传递此方法:kCMTimePositiveInfinity和afterTolerance:kCMTimePositiveInfinity与消息传递seekToTime:直接相同。

我注意到你当前正在使用

avPlayer?.currentItem?.seekToTime(CMTimeMakeWithSeconds(secondo, frameRate))

您可以尝试使用此方法来查找指定的时间 (当然慢)

avPlayer?.currentItem?.seekToTime(CMTimeMakeWithSeconds(secondo, frameRate), toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
希望可以帮助你

答案 1 :(得分:2)

我怀疑所提供的任何答案是否真的奏效了。试试这个:

技术Q&amp; A QA1820 如何使用AVPlayer seekToTime实现流畅的视频清理:?

问:我的应用程序允许用户使用滑块控件和AVPlayer seekToTime来清理视频文件:但视频帧的显示存在相当大的延迟。如何实现更顺畅的擦洗?

答:避免快速连续调用AVPlayer seekToTime。这将取消正在进行的搜索,导致大量搜索而不是大量显示目标帧。相反,使用AVPlayer seekToTime:的完成处理程序变体,并等待正在进行的搜索在发出另一个之前完成。清单1和清单2给出了这种技术的示例(注意:这些示例假设已经创建了一个有效的播放器对象,并且通过键值观察来维护播放器的当前项目状态。有关更多信息,请参阅“AV Foundation编程指南”): / p>

使用AVPlayer seekToTime的完成处理程序变体:更平滑的擦洗(Swift)。

import AVFoundation

class MyClass {

    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()
            }
        })
    }

}

答案 2 :(得分:1)

在Swift 4.2和Xcode 10.1中

player?.seek(to: CMTimeMakeWithSeconds(100, preferredTimescale: 1), toleranceBefore: CMTime.zero, toleranceAfter: CMTime.zero)

答案 3 :(得分:0)

这对我有用。关键是将kCMTimeZero放在两个容差字段中。

player.seek(to: CMTimeMakeWithSeconds(value, duration), toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)