How FairPlay Streaming Integrates with EME in Safari
This article provides a technical overview of how Apple’s FairPlay Streaming (FPS) integrates with the W3C Encrypted Media Extensions (EME) API to play DRM-protected video in the Safari web browser. It covers the role of the Content Decryption Module, the initialization of encrypted media, the cryptographic exchange between the browser and the license server, and the final decryption process that enables secure video playback.
The Core Components
To understand the integration, it is necessary to define the two main technologies involved:
- Encrypted Media Extensions (EME): A standard W3C JavaScript API that provides a communication bridge between a web application and a browser's built-in Digital Rights Management (DRM) software.
- FairPlay Streaming (FPS): Apple’s DRM technology. Within the EME framework in Safari, the native FairPlay client acts as the Content Decryption Module (CDM). The CDM is the secure environment responsible for handling keys and decrypting video content.
The Integration Workflow
FairPlay Streaming relies on the HTTP Live Streaming (HLS) protocol. When a user hits play on a protected video in Safari, EME and FairPlay execute a strict step-by-step handshake to authorize playback.
1. Detecting Encrypted Media
The process begins when the HTML5 <video> element
loads an HLS manifest (.m3u8 file). Safari parses the
manifest and encounters the #EXT-X-KEY tag, which indicates
that the stream is encrypted with FairPlay.
Upon detecting this tag, Safari triggers an encrypted
event on the video element. This event contains initialization data
(initData), which includes the URI needed to identify the
content key.
2. Initializing the FairPlay Key System
The web application listens for the encrypted event and
uses the EME API to request access to the FairPlay CDM.
The application calls
navigator.requestMediaKeySystemAccess() and passes the
FairPlay key system identifier (typically com.apple.fps).
Once Safari grants access, the application creates a
MediaKeys object and attaches it to the HTML5
<video> element. This links the video player directly
to the FairPlay CDM.
3. Supplying the Application Certificate
Before FairPlay can request a decryption key, it must establish a
secure communication channel. The web application fetches a public
FairPlay Application Certificate from a server and passes it to the CDM
using the mediaKeys.setServerCertificate() method. The CDM
uses this certificate to encrypt the upcoming license request.
4. Generating the Server Playback Context (SPC)
Next, the web application creates a MediaKeySession and
calls the generateRequest() method, passing in the
initData captured in step one.
The FairPlay CDM takes this data, combines it with device-specific
information, encrypts it using the Application Certificate, and
generates a payload known as the Server Playback Context
(SPC). Once the SPC is ready, the CDM fires a
message event back to the web application.
5. Acquiring the Content Key Context (CKC)
EME does not dictate how the license is transported; the web application must handle the network request.
The application intercepts the message event, extracts
the SPC payload, and sends it via an XMLHttpRequest or
fetch POST request to a FairPlay license server (also known
as a Key Security Module or KSM). The license server decrypts the SPC,
verifies that the user is authorized to watch the video, and packages
the actual video decryption key into an encrypted response called the
Content Key Context (CKC). The server then sends the
CKC back to the browser.
6. Decryption and Playback
Upon receiving the CKC from the license server, the web application
passes it into the FairPlay CDM by calling the
mediaKeySession.update() method.
The CDM securely decrypts the CKC, extracts the content key, and begins decrypting the protected video segments. Because the FairPlay CDM is integrated directly into the Apple operating system (macOS or iOS), the decryption happens at the hardware level. The decrypted video frames are sent directly to the device's display pipeline, ensuring the raw video data is never exposed to the browser or the JavaScript environment.