在iOS中播放Avplayer时移动滑块跳动 [英] Moving slider getting jumpy while playing Avplayer in iOS

查看:73
本文介绍了在iOS中播放Avplayer时移动滑块跳动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Avplayer中播放mp3网址.它工作正常,我正在向Slider演示音频播放器的进度.当试图向前移动滑块时,它变得跳动起来.但是音频搜索效果很好.只有滑块UI变得跳动.

I am playing mp3 urls in Avplayer. It is working fine, and I am showing Slider for progress of the audio player. While trying to moving forward slider, It is getting jumpy. But audio seeking is working fine. Only slider UI getting jumpy.

我的代码是

  /* ----------------------------------------------------
         Player setup
         ------------------------------------------------------ */
        func playerSetup(url:String) {
            do {
                let audioURL = url
                avPlayerItem = AVPlayerItem( url:NSURL( string:audioURL )! as URL )
                avPlayer = AVPlayer(playerItem:avPlayerItem)
                avPlayer?.rate = 1.0
                avPlayer?.play()
                self.sliderSetup()
                self.timeObserverSetup()
            }
        }

/* ----------------------------------------------------
     Slider setup
     ------------------------------------------------------ */
    func sliderSetup() {
        DispatchQueue.global(qos: .background).async {
            let duration : CMTime = self.avPlayerItem!.asset.duration
            let seconds : Float64 = CMTimeGetSeconds(duration)
            DispatchQueue.main.async {
                self.slider!.maximumValue = Float(seconds)
            }
        }
        slider.isContinuous = false
        slider!.minimumValue = 0
        slider!.value = 0
        slider.addTarget(self, action: #selector(MyViewController.playbackSliderValueChanged(_:event:)), for: .valueChanged)
    }
    /* ----------------------------------------------------
     Avplayer Observer timer setup
     ------------------------------------------------------ */
    func timeObserverSetup() {
        let interval = CMTime(seconds: 0.05, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
        timeObserver = avPlayer!.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: { [weak self] elapsedTime in
            //  print("observer running")
            self!.updateSlider(elapsedTime: elapsedTime)
        })
    }
    
    /* ----------------------------------------------------
     update slider with avplayer duration
     ------------------------------------------------------ */
    func updateSlider(elapsedTime: CMTime) {
        let playerDuration = playerItemDuration()
        if CMTIME_IS_INVALID(playerDuration) {
            slider.minimumValue = 0.0
            return
        }
        let duration = Float(CMTimeGetSeconds(playerDuration))
        if duration.isFinite && duration > 0 {
            slider.minimumValue = 0.0
            slider.maximumValue = duration
            let time = Float(CMTimeGetSeconds(elapsedTime))
            slider.setValue(time, animated: true)
        }
    }
    
    /* ----------------------------------------------------
     avplayeritem duration
     ------------------------------------------------------ */
    private func playerItemDuration() -> CMTime {
        let thePlayerItem = avPlayer?.currentItem
        if thePlayerItem?.status == .readyToPlay {
            return thePlayerItem!.duration
        }
        return CMTime.invalid
    }
    
    /* ----------------------------------------------------
     Slider Action
     ------------------------------------------------------ */
    @objc func playbackSliderValueChanged(_ playbackSlider:UISlider, event: UIEvent) {
        DispatchQueue.main.async {

            let seconds : Int64 = Int64(self.slider.value)
            let targetTime:CMTime = CMTimeMake(value: seconds, timescale: 1)
            self.avPlayer!.seek(to: targetTime)
            
            if let touchEvent = event.allTouches?.first {
                switch touchEvent.phase {
                case .began:
                    self.removeTimerObserver()
                    self.pauseAudio()
                    break
                    
                case .moved:
                    break
                    
                case .ended:
                    self.timeObserverSetup()
                    self.playAudio()
                    break
                    
                default:
                    break
                }
            }
        }
    }
    
    /* ----------------------------------------------------
     Remove timer observer
     ------------------------------------------------------ */
    func removeTimerObserver() {
        if ((self.timeObserver) != nil) {
            if self.avPlayer?.rate == 1.0 { // it is required as you have to check if player is playing
                self.avPlayer?.removeTimeObserver(self.timeObserver as Any)
                self.timeObserver = nil
            }
        }
    }

我看过其他论坛,他们建议在开始滑动触摸时,我们可以删除时间观察器,然后在滑动触摸结束时可以添加观察器,因此,我已经关注了.

I have seen other forums, They suggested while began the slider touch, We can remove Time observer and then slider touch ends we can add observer, So, I have followed that.

但是,仍然有问题.

有什么建议吗?

推荐答案

我已经解决了这个问题.

I have figured out the issue.

由于滑块的以下属性而导致发生此问题.

The issue is happening due to below property from slider.

    slider.isContinuous = false

所以,我已经删除了它,现在可以正常工作了.

So, this I have removed, Now its working fine.

我也在DispatchQueue.main.async中运行滑块操作方法.因此,我将其更改为以下.

Also I am running slider action method in DispatchQueue.main.async. So, I changed it to following.

/* ----------------------------------------------------
 Slider Action
 ------------------------------------------------------ */
@objc func playbackSliderValueChanged(_ playbackSlider:UISlider, event: UIEvent) {

        let seconds : Int64 = Int64(self.slider.value)
        let targetTime:CMTime = CMTimeMake(value: seconds, timescale: 1)
        self.avPlayer!.seek(to: targetTime)
        
        if let touchEvent = event.allTouches?.first {
            switch touchEvent.phase {
            case .began:
                self.removeTimerObserver()
                self.pauseAudio()
                break
                
            case .moved:
                break
                
            case .ended:
                self.timeObserverSetup()
                self.playAudio()
                break
                
            default:
                break
            }
        }
}

现在一切正常.

这篇关于在iOS中播放Avplayer时移动滑块跳动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆