How to play DRM-protected sources when casting

Overview

A common use case is leveraging our Player iOS SDK to play HLS streams with FairPlay DRM protection on iOS devices. This solution works very well for protecting the content while ensuring compatibility with the iOS operating system.

However, this presents some issues if you'd like to enable casting from your iOS app to devices such as Chromecast, which doesn't support FairPlay. In scenarios like this, it's possible to instruct your app to switch to a different streaming and DRM format that is Chromecast-compatible, such as DASH + Widevine DRM.

Switch from HLS FairPlay to DASH Widevine

As shown in this github example, switching to a different streaming and DRM format is easy when casting to a 3rd party device. Here is the relevant piece of code that handles this:

// Provide a different SourceConfig for casting. For local playback we use a HLS stream and for casting a
// Widevine protected DASH stream with the same content.
        config.remoteControlConfig.prepareSource = { type, sourceConfig in
            switch type {
            case .cast:
                // Create a different source for casting
                guard let streamUrl = URL(string: "https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd"),
                      let licenseUrl = URL(string: "https://widevine-proxy.appspot.com/proxy") else {
                    return nil
                }

                // Create DASHSource as a DASH stream is used for casting
                let castSourceConfig = SourceConfig(url: streamUrl, type: .dash)
                castSourceConfig.title = sourceConfig.title
                castSourceConfig.sourceDescription = sourceConfig.sourceDescription

                let widevineConfig = WidevineConfig(license: licenseUrl)
                castSourceConfig.drmConfig = widevineConfig

                return castSourceConfig
            }
        }

When using the playlist feature of the Player iOS SDK

When using the built-in Player iOS SDK feature, called Playlists (example can be found here) - while still supporting casting - it is necessary to account for the different sources in RemoteControlConfig.prepareSource.

This mapping has to be available at the moment of starting the casting session for the whole playlist.

Here is a redacted code snippet to showcase such a setup:

let movie1SourceConfig = ... // Setup your SourceConfig for Movie 1 with e.g. FairPlay for iOS playback
let movie2SourceConfig = ... // Setup your SourceConfig for Movie 2 with e.g. FairPlay for iOS playback
let movie3SourceConfig = ... // Setup your SourceConfig for Movie 3 with e.g. FairPlay for iOS playback

let movie1SourceConfigCasting = ... // Setup your SourceConfig for Movie 1 with e.g. Widewine for cast playback
let movie2SourceConfigCasting = ... // Setup your SourceConfig for Movie 2 with e.g. Widewine for cast playback
let movie3SourceConfigCasting = ... // Setup your SourceConfig for Movie 3 with e.g. Widewine for cast playback
  
config.remoteControlConfig.prepareSource = { _, sourceConfig in
    // Decide which SourceConfig - designated for casting - to return
    // based on the SourceConfig in question.
    switch sourceConfig.url {
    case movie1SourceConfig.url:
        return movie1SourceConfigCasting
    case movie2SourceConfig.url:
        return movie2SourceConfigCasting
    case movie3SourceConfig.url:
        return movie3SourceConfigCasting
    default:
        return nil
    }
}