Mahalakshmi Saravanan
Mahalakshmi Saravanan

Reputation: 295

Slider is not moving along with audio in Swift

I am trying to implement an audio player in my application to play an audio file. I am using the AVFoundation framework in order to play the audio files. I have controls like a slider to change the audio flow and rate buttons to increase and decrease the audio speed. The slider should move along with audio and if the slider position is changed the audio should play from the position the slider is placed. And even if the rate buttons are clicked the audio should increase the speed from where it is playing. How can I make it work in Swift 5?

import AVFoundation

class AudioPlayer: UIViewController, AVAudioPlayerDelegate {
    @IBOutlet weak var slider: UISlider!
    @IBOutlet weak var currentTime: UILabel!
    @IBOutlet weak var totalDuration: UILabel!

    @IBAction func playButton(_ sender: Any) {
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: audioPath)
            guard let player = audioPlayer else { return }
            player.prepareToPlay()
            player.enableRate = true

            player.play()
        } catch let error {
            print(error.localizedDescription)
        }
    }

    @IBAction func slideMoved(_ sender: Any) {
        slider.maximumValue = Float(audioPlayer.duration)
    }

    var audioPlayer:AVAudioPlayer!

    override func viewDidLoad() {
        self.audioPlayer = try AVAudioPlayer(contentsOf: path)
        self.audioPlayer.enableRate = true
        self.audioPlayer.prepareToPlay()
        self.audioPlayer.delegate = self
    }

    @objc func speed1ViewTapped(_ sender: UITapGestureRecognizer? = nil) {
    }

    @objc func speed2ViewTapped(_ sender: UITapGestureRecognizer? = nil) {
    }

    @objc func speed3ViewTapped(_ sender: UITapGestureRecognizer? = nil) {
    }
}

Upvotes: 1

Views: 921

Answers (1)

Jawad Ali
Jawad Ali

Reputation: 14417

You can use AVPlayer's PeriodicTime Observer to update your slider progress

let _ = audioPlayer.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: DispatchQueue.main) { [weak self] (time) in
             self?.slider.value = Float(CMTimeGetSeconds(time)) / Float(totalDuration)
    }

instead of setting maximum value of slider ... change this function as well

@IBAction func slideMoved(_ sender: Any) {
        let value = self.slider.value
        let durationToSeek = Float(totalDuration) * value
        audioPlayer.seek(to: CMTimeMakeWithSeconds(Float64(durationToSeek),player.currentItem!.duration.timescale)) { [weak self](state) in

      }
}

Upvotes: 1

Related Questions