Moving slider getting jumpy while playing Avplayer in iOS

本秂侑毒 提交于 2020-07-20 05:45:26

问题


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.

My code is

  /* ----------------------------------------------------
         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.

But, Still it's getting issue.

Any suggestions?


回答1:


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.

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

Now it is working fine.



来源:https://stackoverflow.com/questions/62774834/moving-slider-getting-jumpy-while-playing-avplayer-in-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!