使用AVPlayer实现流畅的视频清理

时间:2017-06-08 11:34:33

标签: ios iphone swift xcode avplayer

我正在尝试使用AVPlayerUISlider进行流畅的视频清理我已搜索过,似乎Apple有一个Technical Q&A并解释了如何实现这一目标,但我的问题是应该怎样我使用此方法并使用UISlider更改玩家当前时间: stopPlayingAndSeekSmoothlyToTime(newChaseTime:CMTime)

这是我的代码:

//Play Intro Movie
let videoURL = Bundle.main.url(forResource: "intro", withExtension: "mp4")
player = AVPlayer(url:videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.frame
view.layer.addSublayer(playerLayer)
//videoPlayer.play()


view.addSubview(slider)
slider.maximumValue = 0
slider.maximumValue = Float(CMTimeGetSeconds((player.currentItem?.asset.duration)!))

以下是Apple示例代码:

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.seek(to: seekTimeInProgress, toleranceBefore: kCMTimeZero,
                          toleranceAfter: kCMTimeZero, completionHandler:
            { (isFinished:Bool) -> Void in

                if CMTimeCompare(seekTimeInProgress, self.chaseTime) == 0
                {
                    self.isSeekInProgress = false
                }
                else
                {
                    self.trySeekToChaseTime()
                }
        })
    }

4 个答案:

答案 0 :(得分:4)

在滑块值更改事件中,只需调用

即可

stopPlayingAndSeekSmoothlyToTime(CMTime.init(seconds: (player.currentItem?.asset.duration.seconds)!* slider.value, preferredTimescale: 1000))

Apples示例代码将更改播放器当前时间。如果你非常快速地擦洗滑块,你也可以调整toleranceBefore和toleranceAfter。

答案 1 :(得分:4)

虽然我没有使用与你stopPlayingAndSeekSmoothlyToTime相同的方法,但我认为我应该帮助你寻找玩家的行动。

func sliderValueChanged() {
    var timeToSeek = player.currentItem?.asset.duration.seconds
    timeToSeek = timeToSeek * Double(slider.value)
    player.seek(to: CMTimeMake(Int64(timeToSeek), 1))
}

此外,您应该将slider.maximumValue设置为1.希望这会有所帮助。

注意:请不要忘记处理currentItem可选值。如果是nil,则应为timeToSeek变量设置值0。

答案 2 :(得分:2)

尝试在开头添加选择器,如下所示:

playerView.timeSlider.addTarget(self, action: #selector(PlayerViewController.timeSliderBeganTracking(_:)), for:.touchDown) // moved
        playerView.timeSlider.addTarget(self, action: #selector(PlayerViewController.timeSliderEndedTracking(_:)), for: .touchUpInside)
        playerView.timeSlider.addTarget(self, action: #selector(PlayerViewController.timeSliderEndedTracking(_:)), for: .touchUpOutside )

然后在timeSliderBeganTracking设置isSeekInProgresstrue并暂停您的播放器并使计时器无效并删除观察员(如果您有)

然后在timeSliderEndedTracking 寻求当前这样的时间:

let currentSeconds = Float64(self.playerView.timeSlider.value) container.player.seek(to: CMTimeMakeWithSeconds(currentSeconds, 100)) 然后将观察者和计时器添加回来,最后将isSeekInProgress设置为false

HERE您可以找到创建自定义videoPlayer的完整示例

答案 3 :(得分:0)

我知道这是一个老问题,我也遇到过。该解决方案现在可以帮助某人。苹果样品使滑块超级光滑漂亮。要使示例工作:

private static var context = 1
func playVideo() {
  ...
  player.addObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem.status), options: [.new, .initial], context: &VideoViewController.context)
  ...
 }

override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    guard let keyPath = keyPath else { return }
    guard context == &VideoViewController.context else { return }
    switch keyPath {
    case #keyPath(AVPlayer.currentItem.status):
        if let newStatus = change.map({ $0[.newKey] as? NSNumber }), 
           let parsedNewStatus = newStatus.map({ AVPlayerItem.Status(rawValue: $0.intValue) ?? .unknown})  {
            playerCurrentItemStatus = parsedNewStatus
        } else {
            playerCurrentItemStatus = .unknown
        }
    default: break
    }
}

观察并更新playerCurrentItemStatus