I use AVPlayer to play audio files. I have problems. UISlider does not work correctly, the slider should move as a progress view and when you click the stop the audio is played again
@IBAction func play(_ sender: Any) {
let url = URL(string: self.urlAudio[0])
let playerItem = AVPlayerItem(url: url!)
player = AVPlayer(playerItem:playerItem)
player.rate = 1.0;
player.play()
let duration : CMTime = playerItem.asset.duration
let seconds : Float64 = CMTimeGetSeconds(duration)
playbackSlider.maximumValue = Float(seconds)
playbackSlider.isContinuous = true
playbackSlider.tintColor = UIColor.green
playbackSlider.addTarget(self, action: #selector(ViewControllerAudioDetail.playbackSliderValueChanged(_:)), for: .valueChanged)
if soundChange == true{
playChange.setImage(UIImage(named:"Pause.png"), for: UIControlState.normal)
soundChange = false
player.play()
} else {
playChange.setImage(UIImage(named:"Play.png"), for: UIControlState.normal)
soundChange = true
player.pause()
}
}
func playbackSliderValueChanged(_ playbackSlider:UISlider){
let seconds : Int64 = Int64(playbackSlider.value)
let targetTime:CMTime = CMTimeMake(seconds, 1)
player.seek(to: targetTime)
}
when you click the stop the audio is played again
In order to toggle play and pause check if avplayer is already playing or not. If playing pause it else play it.
if player.rate == 0 {
player.play()
//change your button image
}
else {
player.pause()
//change your button image
}
the slider should move as a progress view
You can use AVPlayer's PeriodicTime Observer to update your slider progress
let _ = player.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: DispatchQueue.main) { [weak self] (time) in
self?.audioPlayerSlider.value = Float(CMTimeGetSeconds(time)) / Float(totalDuration)
}
P.S:
Don't create player instance every time user taps on button. Create only when player is nil or you want to play a different track.
@IBAction func play(_ sender: Any) {
if player == nil {
let url = URL(string: self.urlAudio[0])
let playerItem = AVPlayerItem(url: url!)
player = AVPlayer(playerItem:playerItem)
player.rate = 1.0;
}
if player.rate == 0 {
player.play()
//change your button image
}
else {
player.pause()
//change your button image
}
}
EDIT:
I believe you are trying to find a way to scrub / seek to specific time of audio that AVPlayer is playing.
You can use AVPlayer's seek method to do that.
@IBAction func audioSliderDragged(_ sender: AnyObject) {
let value = self.audioPlayerSlider.value
let durationToSeek = Float(totalDuration) * value
player.seek(to: CMTimeMakeWithSeconds(Float64(durationToSeek),player.currentItem!.duration.timescale)) { [weak self](state) in
//do what is relevant to your app on seeing to particular offset
}
}