In this tutorial, you will learn how to add a playback slider to AVPlayer in Swift to control audio playback.
By the end of this tutorial, you will have a working Swift code example that you can use in your mobile application.
If you are looking for SwiftUI code, then you can learn how to use AVPlayer and AVPlayeItem classes using both UIKit and SwiftUI in this tutorial: Play Music MP3 File From a Remote URL In Swift.
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)
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)
}
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)
}
Step 2: Create UIButton Programmatically
To create a play button programmatically, you first need to create an instance of UIButton
and then configure its properties. You can set the button’s frame, background color, title, and add a target-action method that will be called when the button is tapped.
playButton = UIButton(type: UIButton.ButtonType.system) as UIButton
let buttonWidth: CGFloat = 150
let buttonHeight: CGFloat = 45
playButton!.frame = CGRect(x: 50, y: 100, width: buttonWidth, height: buttonHeight)
playButton!.backgroundColor = UIColor.lightGray
playButton!.setTitle("Play", for: UIControl.State.normal)
playButton!.tintColor = UIColor.black
playButton!.addTarget(self, action: #selector(self.playButtonTapped(_:)), for: .touchUpInside)
self.view.addSubview(playButton!)
playButton = UIButton(type: UIButton.ButtonType.system) as UIButton
let buttonWidth: CGFloat = 150
let buttonHeight: CGFloat = 45
playButton!.frame = CGRect(x: 50, y: 100, width: buttonWidth, height: buttonHeight)
playButton!.backgroundColor = UIColor.lightGray
playButton!.setTitle("Play", for: UIControl.State.normal)
playButton!.tintColor = UIColor.black
playButton!.addTarget(self, action: #selector(self.playButtonTapped(_:)), for: .touchUpInside)
self.view.addSubview(playButton!)
playButton = UIButton(type: UIButton.ButtonType.system) as UIButton
let buttonWidth: CGFloat = 150
let buttonHeight: CGFloat = 45
playButton!.frame = CGRect(x: 50, y: 100, width: buttonWidth, height: buttonHeight)
playButton!.backgroundColor = UIColor.lightGray
playButton!.setTitle("Play", for: UIControl.State.normal)
playButton!.tintColor = UIColor.black
playButton!.addTarget(self, action: #selector(self.playButtonTapped(_:)), for: .touchUpInside)
self.view.addSubview(playButton!)
Step 3: Create AVPlayerLayer and Add it as a Subview
The AVPlayerLayer
is a layer that you add to your view hierarchy to display the video content of an AVPlayer
instance. You create an instance of AVPlayerLayer
, set its frame, and add it as a sublayer of your view’s layer.
let playerLayer = AVPlayerLayer(player: player!)
playerLayer.frame = CGRect(x: 0, y: 0, width: 10, height: 50)
self.view.layer.addSublayer(playerLayer)
let playerLayer = AVPlayerLayer(player: player!)
playerLayer.frame = CGRect(x: 0, y: 0, width: 10, height: 50)
self.view.layer.addSublayer(playerLayer)
let playerLayer = AVPlayerLayer(player: player!)
playerLayer.frame = CGRect(x: 0, y: 0, width: 10, height: 50)
self.view.layer.addSublayer(playerLayer)
Step 4: Handle Play Button Action to Pause and Play Music
You’ve already added a target-action method to the play button in the previous step. Now, you need to implement this method to handle the button tap. When the button is tapped, you check if the player is currently playing. If it is, you pause the player; otherwise, you play the player.
@objc func playButtonTapped(_ sender: UIButton) {
playButton!.setTitle("Pause", for: UIControl.State.normal)
playButton!.setTitle("Play", for: UIControl.State.normal)
@objc func playButtonTapped(_ sender: UIButton) {
if player?.rate == 0 {
player!.play()
playButton!.setTitle("Pause", for: UIControl.State.normal)
} else {
player!.pause()
playButton!.setTitle("Play", for: UIControl.State.normal)
}
}
@objc func playButtonTapped(_ sender: UIButton) {
if player?.rate == 0 {
player!.play()
playButton!.setTitle("Pause", for: UIControl.State.normal)
} else {
player!.pause()
playButton!.setTitle("Play", for: UIControl.State.normal)
}
}
Step 5: Playback Slider. Add UISlider as a Subview
As a playback slider, you can use the UISlider component.
To create a UISlider programmatically, set its frame and properties, and add it to your view’s subviews. The UISlider
is used to display the progress of the audio playback and to allow the user to seek to a different position in the audio.
let playbackSlider = UISlider(frame: CGRect(x: 10, y: 300, width: 300, height: 20))
playbackSlider.minimumValue = 0
self.view.addSubview(playbackSlider)
let playbackSlider = UISlider(frame: CGRect(x: 10, y: 300, width: 300, height: 20))
playbackSlider.minimumValue = 0
self.view.addSubview(playbackSlider)
let playbackSlider = UISlider(frame: CGRect(x: 10, y: 300, width: 300, height: 20))
playbackSlider.minimumValue = 0
self.view.addSubview(playbackSlider)
Step 6: Handle UISlider Value Changed Event
To handle the slider’s value change, you add a target-action method to the slider. This method will be called when the slider’s value changes, and you can use it to seek to the new position in the audio.
playbackSlider.addTarget(self, action: #selector(self.playbackSliderValueChanged(_:)), for: .valueChanged)
@objc func playbackSliderValueChanged(_ playbackSlider: UISlider) {
let seconds: Int64 = Int64(playbackSlider.value)
let targetTime: CMTime = CMTimeMake(value: seconds, timescale: 1)
player!.seek(to: targetTime)
playbackSlider.addTarget(self, action: #selector(self.playbackSliderValueChanged(_:)), for: .valueChanged)
@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()
}
}
playbackSlider.addTarget(self, action: #selector(self.playbackSliderValueChanged(_:)), for: .valueChanged)
@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()
}
}
Step 7: Determine Music File Duration in Seconds
To set the maximum value of the slider, you need to determine the duration of the audio file in seconds. You can get the duration from the asset
property of the AVPlayerItem
.
let duration: CMTime = playerItem.asset.duration
let seconds: Float64 = CMTimeGetSeconds(duration)
playbackSlider.maximumValue = Float(seconds)
let duration: CMTime = playerItem.asset.duration
let seconds: Float64 = CMTimeGetSeconds(duration)
playbackSlider.maximumValue = Float(seconds)
let duration: CMTime = playerItem.asset.duration
let seconds: Float64 = CMTimeGetSeconds(duration)
playbackSlider.maximumValue = Float(seconds)
Step 8: Update UISlider When mp3 is Playing
To keep the slider’s value in sync with the playback progress, you add a periodic time observer to the player. This observer will be called at regular intervals, and you can use it to update the slider’s value.
timer = player?.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 600), queue: DispatchQueue.main) { [weak self] time in
guard self != nil else { return }
let currentTime = CMTimeGetSeconds(time)
playbackSlider.value = Float(currentTime)
var timer: Any?
timer = player?.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 600), queue: DispatchQueue.main) { [weak self] time in
guard self != nil else { return }
let currentTime = CMTimeGetSeconds(time)
playbackSlider.value = Float(currentTime)
}
var timer: Any?
timer = player?.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 600), queue: DispatchQueue.main) { [weak self] time in
guard self != nil else { return }
let currentTime = CMTimeGetSeconds(time)
playbackSlider.value = Float(currentTime)
}
Playback Slider: Complete Code Example
Below is a complete code example in Swift that demonstrates how to add a playback slider to AVPlayer. You can try it and use it in your app to play music or video.
class ViewController: UIViewController {
var playerItem: AVPlayerItem?
var playButton: UIButton?
override func 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!.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY)
playButton!.backgroundColor = UIColor.lightGray
playButton!.setTitle("Play", for: UIControl.State.normal)
playButton!.tintColor = UIColor.black
playButton!.addTarget(self, action: #selector(self.playButtonTapped(_:)), for: .touchUpInside)
self.view.addSubview(playButton!)
let playbackSlider = UISlider(frame:CGRect(x:10, y:300, width:300, height:20))
playbackSlider.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY + 50)
playbackSlider.minimumValue = 0
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(self.playbackSliderValueChanged(_:)), for: .valueChanged)
// Set up the periodic time observer
timer = player?.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 600), queue: DispatchQueue.main) { [weak self] time in
guard self != nil else { return }
let currentTime = CMTimeGetSeconds(time)
playbackSlider.value = Float(currentTime)
self.view.addSubview(playbackSlider)
@objc func playbackSliderValueChanged(_ playbackSlider:UISlider)
let seconds : Int64 = Int64(playbackSlider.value)
let targetTime:CMTime = CMTimeMake(value: seconds, timescale: 1)
player!.seek(to: targetTime)
@objc func playButtonTapped(_ sender:UIButton)
playButton!.setTitle("Pause", for: UIControl.State.normal)
playButton!.setTitle("Play", for: UIControl.State.normal)
// Remember to remove the observer when the view disappears
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
player?.removeTimeObserver(timer)
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVPlayer?
var playerItem: AVPlayerItem?
var playButton: UIButton?
var duration: CMTime?
var timer: Any?
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!.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY)
playButton!.backgroundColor = UIColor.lightGray
playButton!.setTitle("Play", for: UIControl.State.normal)
playButton!.tintColor = UIColor.black
playButton!.addTarget(self, action: #selector(self.playButtonTapped(_:)), for: .touchUpInside)
self.view.addSubview(playButton!)
// Add playback slider
let playbackSlider = UISlider(frame:CGRect(x:10, y:300, width:300, height:20))
playbackSlider.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY + 50)
playbackSlider.minimumValue = 0
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(self.playbackSliderValueChanged(_:)), for: .valueChanged)
// Set up the periodic time observer
timer = player?.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 600), queue: DispatchQueue.main) { [weak self] time in
guard self != nil else { return }
let currentTime = CMTimeGetSeconds(time)
playbackSlider.value = Float(currentTime)
}
self.view.addSubview(playbackSlider)
}
@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!.setTitle("Pause", for: UIControl.State.normal)
} else {
player!.pause()
playButton!.setTitle("Play", for: UIControl.State.normal)
}
}
// Remember to remove the observer when the view disappears
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if let timer = timer {
player?.removeTimeObserver(timer)
}
}
}
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVPlayer?
var playerItem: AVPlayerItem?
var playButton: UIButton?
var duration: CMTime?
var timer: Any?
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!.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY)
playButton!.backgroundColor = UIColor.lightGray
playButton!.setTitle("Play", for: UIControl.State.normal)
playButton!.tintColor = UIColor.black
playButton!.addTarget(self, action: #selector(self.playButtonTapped(_:)), for: .touchUpInside)
self.view.addSubview(playButton!)
// Add playback slider
let playbackSlider = UISlider(frame:CGRect(x:10, y:300, width:300, height:20))
playbackSlider.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY + 50)
playbackSlider.minimumValue = 0
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(self.playbackSliderValueChanged(_:)), for: .valueChanged)
// Set up the periodic time observer
timer = player?.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 600), queue: DispatchQueue.main) { [weak self] time in
guard self != nil else { return }
let currentTime = CMTimeGetSeconds(time)
playbackSlider.value = Float(currentTime)
}
self.view.addSubview(playbackSlider)
}
@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!.setTitle("Pause", for: UIControl.State.normal)
} else {
player!.pause()
playButton!.setTitle("Play", for: UIControl.State.normal)
}
}
// Remember to remove the observer when the view disappears
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if let timer = timer {
player?.removeTimeObserver(timer)
}
}
}

Conclusion
I hope this tutorial was helpful to you and you were able to successfully add a playback slider to AVPlayer
in your mobile application.
For more Swift code examples and tutorials, please check the Swift Code Examples page on this website.
Happy learning!