AVPlayer. Add Periodic TimeObserver to Update Music Playback Slider

In this Swift code example, you will learn how to make the music playback slider smoothly move as the music continues to play so that the user is visually aware of how much of the music file has been already played and how much is left to play.

  • Create AVPlayer and AVPlayerItem
  • Create UIButton programmatically
  • Create AVPlayerLayer and add it as a subview
  • Handle Play Button action to Pause and Play music
  • Add UISlider as a subview
  • Handle UISlider value changed event
  • Determine music file duration in seconds
  • Set UISlider maximum value equal to music file duration in seconds
  • Add addPeriodicTimeObserverForInterval to AVPlayer

AVPlayer. addPeriodicTimeObserverForInterval Example in Swift.

Before we look at a more complex example of how the addPeriodicTimeObserver() function can be used with the AVPlayer to play the music file, let’s have a look at a very simple code example first.

Below is a very simple code example of how to use the addPeriodicTimeObserver() function with the AVPlayer.

player!.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1), queue: DispatchQueue.main) { (CMTime) -> Void in
     if self.player!.currentItem?.status == .readyToPlay {
         let time : Float64 = CMTimeGetSeconds(self.player!.currentTime());
         self.playbackSlider!.value = Float ( time );
     }
 }

Complete Code Example

Now that you have seen how to use the addPeriodicTimeObserver() function in a very simple code example above. Let’s have a look at how to use it in a UIViewController. Below is a complete code example of UIViewController that creates an AVPlayer and plays an MP3 music file. The music file is loaded from a remote location using its URL.

Try running this code example in your project. As music continues to place, the music playback slider should move smoothly.

import UIKit
import AVFoundation
class ViewController: UIViewController  {
    
    var player:AVPlayer?
    var playerItem:AVPlayerItem?
    var playButton:UIButton?
    var playbackSlider:UISlider?
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        let url = URL(string: "https://s3.amazonaws.com/kargopolov/kukushka.mp3")
        let playerItem:AVPlayerItem = AVPlayerItem(url: url!)
        player = AVPlayer(playerItem: playerItem)
        
        let playerLayer=AVPlayerLayer(player: player!)
        playerLayer.frame=CGRect(x: 0, y: 0, width: 10, height: 50)
        self.view.layer.addSublayer(playerLayer)
        
        playButton = UIButton(type: UIButton.ButtonType.system) as UIButton
        let xPostion:CGFloat = 50
        let yPostion:CGFloat = 100
        let buttonWidth:CGFloat = 150
        let buttonHeight:CGFloat = 45
        
        playButton!.frame = CGRect(x: xPostion, y: yPostion, width: buttonWidth, height: buttonHeight)
        playButton!.backgroundColor = UIColor.lightGray
        playButton!.setTitle("Play", for: UIControl.State.normal)
        playButton!.tintColor = UIColor.black
        //playButton!.addTarget(self, action: "playButtonTapped:", forControlEvents: .TouchUpInside)
        playButton!.addTarget(self, action: #selector(self.playButtonTapped(_:)), for: .touchUpInside)
        
        self.view.addSubview(playButton!)
        
        
        // Add playback slider
        
        playbackSlider = UISlider(frame:CGRect(x: 10, y: 300, width: 300, height: 20))
        playbackSlider!.minimumValue = 0
        
        
        let duration : CMTime = playerItem.asset.duration
        let seconds : Float64 = CMTimeGetSeconds(duration)
        
        playbackSlider!.maximumValue = Float(seconds)
        playbackSlider!.isContinuous = false
        playbackSlider!.tintColor = UIColor.green
        
        playbackSlider?.addTarget(self, action: #selector(self.playbackSliderValueChanged(_:)), for: .valueChanged)
        //playbackSlider!.addTarget(self, action: "playbackSliderValueChanged:", for: .valueChanged)
        self.view.addSubview(playbackSlider!)
        
        
        player!.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1), queue: DispatchQueue.main) { (CMTime) -> Void in
            if self.player!.currentItem?.status == .readyToPlay {
                let time : Float64 = CMTimeGetSeconds(self.player!.currentTime());
                self.playbackSlider!.value = Float ( time );
            }
        }
        
    }
    
    @objc func playbackSliderValueChanged(_ playbackSlider:UISlider)
    {
        
        let seconds : Int64 = Int64(playbackSlider.value)
        let targetTime:CMTime = CMTimeMake(value: seconds, timescale: 1)
        
        player!.seek(to: targetTime)
        
        if player!.rate == 0
        {
            player?.play()
        }
    }
    
    
    @objc func playButtonTapped(_ sender:UIButton)
    {
        if player?.rate == 0
        {
            player!.play()
            //playButton!.setImage(UIImage(named: "player_control_pause_50px.png"), forState: UIControlState.Normal)
            playButton!.setTitle("Pause", for: UIControl.State.normal)
        } else {
            player!.pause()
            //playButton!.setImage(UIImage(named: "player_control_play_50px.png"), forState: UIControlState.Normal)
            playButton!.setTitle("Play", for: UIControl.State.normal)
        }
    }
    
}

I hope that this Swift code example was helpful for you. There are more tutorials and Swift code examples that show how to play a music file in Swift if you check this page Swift Code Examples.

Leave a Reply

Your email address will not be published. Required fields are marked *

Free Video Lessons

Enter your email and stay on top of things,

Subscribe!