Configuring Now Playing Information

This guide explains how to configure Now Playing information for your app. Enabling Now Playing information allows the app to advertise media playback externally, e.g. on the lock screen or in the control center.

Overview

The Bitmovin Player iOS SDK provides a NowPlayingConfig which is located under PlayerConfig.nowPlayingConfig. The NowPlayingConfig can be used to configure and display Now Playing information for your media playback app.

This feature displays metadata like title, artwork, and playback status, and allows to control playback on the lock screen and in the control center.

This guide explains how to enable the feature and how to customize it to your needs.

Enable Now Playing Information

By default, Now Playing information is disabled. To enable it, set isNowPlayingInfoEnabled to true in your player configuration:

let playerConfig = PlayerConfig()
playerConfig.nowPlayingConfig.isNowPlayingInfoEnabled = true

Default Behavior

Enabling Now Playing information displays metadata such as the title and playback duration and enables remote commands like play/pause and skip forward/backward. The default supported metadata and commands are:

Default Metadata

Those metadata fields are populated automatically by Bitmovin Player:

  • MPNowPlayingInfoPropertyAssetURL
  • MPMediaItemPropertyTitle
  • MPMediaItemPropertyArtwork
  • MPNowPlayingInfoPropertyIsLiveStream
  • MPNowPlayingInfoPropertyPlaybackRate
  • MPNowPlayingInfoPropertyDefaultPlaybackRate
  • MPNowPlayingInfoPropertyElapsedPlaybackTime
  • MPMediaItemPropertyPlaybackDuration

Default Commands

Those commands are by default configured to interact with the Bitmovin Player:

  • Play/Pause (togglePlayPauseCommand)
  • Skip Forward (skipForwardCommand)
  • Skip Backward (skipBackwardCommand)
  • Change Playback Position (changePlaybackPositionCommand)

Customizing Now Playing Information

You can customize or extend Now Playing information after initializing the player. Below are some common customization scenarios:

Enabling Commands That Are Not Enabled by Default

Enable a command, by adding a handler for a command that is not part of the default commands:

let commandCenter = MPRemoteCommandCenter.shared()

commandCenter.likeCommand.addTarget { event in
    commandCenter.likeCommand.isActive.toggle()
    return .success
}

Disabling Default Commands

To disable a default command, remove all of its targets:

let commandCenter = MPRemoteCommandCenter.shared()

commandCenter.skipBackwardCommand.removeTarget(nil)

Customizing Command Behavior

You can modify certain command properties, like setting a custom skip interval for skip commands:

let commandCenter = MPRemoteCommandCenter.shared()

commandCenter.skipForwardCommand.preferredIntervals = [15]
commandCenter.skipBackwardCommand.preferredIntervals = [15]

Overriding Default Commands

To completely override a default command’s behavior, first remove the existing targets and then add your own:

let commandCenter = MPRemoteCommandCenter.shared()

commandCenter.skipBackwardCommand.removeTarget(nil)
commandCenter.skipBackwardCommand.addTarget { [weak player] _ in
    guard let player else { return .commandFailed }
    // Custom skip backward action
    return .success
}

Using Now Playing Info in Your App

Below a complete example how to enable and configure Now Playing information in your app:

import BitmovinPlayer
import SwiftUI
import MediaPlayer

private let streamUrl = URL(string: "https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8")!
private let posterUrl = URL(string: "https://bitmovin-a.akamaihd.net/content/MI201109210084_1/poster.jpg")!

struct ContentView: View {
    private let player: Player
    private let sourceConfig: SourceConfig

    init() {
        // Create player configuration with Now Playing information enabled
        let playerConfig = PlayerConfig()
        playerConfig.nowPlayingConfig.isNowPlayingInfoEnabled = true

        // Create a source config with a poster image and title
        sourceConfig = SourceConfig(url: streamUrl, type: .hls)
        sourceConfig.posterSource = posterUrl
        sourceConfig.title = "Now Playing info demo"

        // Create player based on player configuration
        player = PlayerFactory.createPlayer(
            playerConfig: playerConfig
        )

        // Get the shared remote command center
        let commandCenter = MPRemoteCommandCenter.shared()

        // Enable a command, by adding a handler for a command that is not part of the default commands
        commandCenter.likeCommand.addTarget { event in
            commandCenter.likeCommand.isActive.toggle()
            return .success
        }

        // Customization: Some commands have customization options. E.g. the skip commands
        commandCenter.skipForwardCommand.preferredIntervals = [15]
        commandCenter.skipBackwardCommand.preferredIntervals = [15]
    }

    var body: some View {
        ZStack {
            Color.black

            VideoPlayerView(
                player: player,
                playerViewConfig: PlayerViewConfig()
            )
        }
        .padding()
        .onAppear {
            player.load(sourceConfig: sourceConfig)
        }
    }
}