Article

Responding to Playback State Changes

Respond to changes in a player's playback state.

Overview

AVPlayer and AVPlayerItem are dynamic objects whose states change frequently. A simple way to observe and respond to these state changes is to use key-value observing (KVO). With KVO, an object can register to observe another object’s state. When the observed object’s state changes, the observer is notified with details of the state change. (For more information about KVO, see Key-Value Observing Programming Guide.)

Observe the Player's State

One of the most important AVPlayerItem properties to observe is status. This property indicates whether the player item is ready for playback and generally available for use. When you first create a player item, its status value is AVPlayerItem.Status.unknown, meaning its media hasn’t been loaded or been enqueued for playback. When you associate a player item with AVPlayer, it immediately begins enqueuing the item’s media and preparing it for playback. The player item becomes ready for use when the status value changes to AVPlayerItem.Status.readyToPlay. The following example shows how you can observe this state change:

let url: URL = // Asset URL
var asset: AVAsset!
var player: AVPlayer!
var playerItem: AVPlayerItem!

// Key-value observing context
private var playerItemContext = 0

let requiredAssetKeys = [
    "playable",
    "hasProtectedContent"
]

func prepareToPlay() {
    // Create the asset to play
    asset = AVAsset(url: url)

    // Create a new AVPlayerItem with the asset and an
    // array of asset keys to be automatically loaded
    playerItem = AVPlayerItem(asset: asset,
                              automaticallyLoadedAssetKeys: requiredAssetKeys)

    // Register as an observer of the player item's status property
    playerItem.addObserver(self,
                           forKeyPath: #keyPath(AVPlayerItem.status),
                           options: [.old, .new],
                           context: &playerItemContext)
    
    // Associate the player item with the player
    player = AVPlayer(playerItem: playerItem)
}

The prepareToPlay() method registers to observe the player item’s status property using the addObserver(_:forKeyPath:options:context:) method. Call this method before associating the player item with the player to make sure you capture all state changes to the item’s status.

Respond to a State Change

To be notified of state changes, you implement the observeValue(forKeyPath:of:change:context:) method. This method is invoked whenever the status value changes, giving you the chance to take some action:

override func observeValue(forKeyPath keyPath: String?,
                           of object: Any?,
                           change: [NSKeyValueChangeKey : Any]?,
                           context: UnsafeMutableRawPointer?) {

    // Only handle observations for the playerItemContext
    guard context == &playerItemContext else {
        super.observeValue(forKeyPath: keyPath,
                           of: object,
                           change: change,
                           context: context)
        return
    }

    if keyPath == #keyPath(AVPlayerItem.status) {
        let status: AVPlayerItemStatus
        if let statusNumber = change?[.newKey] as? NSNumber {
            status = AVPlayerItemStatus(rawValue: statusNumber.intValue)!
        } else {
            status = .unknown
        }

        // Switch over status value
        switch status {
        case .readyToPlay:
            // Player item is ready to play.
        case .failed:
            // Player item failed. See error.
        case .unknown:
            // Player item is not yet ready.
        }
    }
}

The example retrieves the new status value from the change dictionary and switches over its value. If the player item’s status value is AVPlayerItem.Status.readyToPlay, then it’s ready for use. If a problem is encountered while attempting to load the player item’s media, the status value is AVPlayerItem.Status.failed. If a failure occurred, you can retrieve the NSError object providing the details of the failure by querying the player item’s error property.

See Also

Media Playback

Observing the Playback Time

Observe the playback time for an asset in order to update the player's state.

Seeking Through Media

Seek or scrub across a media item to quickly access a specific time point.

Asset Playback

Play audio and video assets modeled by a player item.

Sample Buffer Playback

Play audio and video sample buffers using a custom player.

QuickTime and ISO-Related Media

Create, play, and modify QuickTime and ISO-related media assets.

Creating a Movie Player App with Basic Playback Controls

Play movies using a custom interface that implements simple playback functionality.

Using HEVC Video with Alpha

Play, write, and export HEVC video with an alpha channel to add overlay effects to your video processing.