Skip to content

Multi-DRM for Developers: How to Protect Your Video Streams with Widevine, FairPlay, and PlayReady

You've built a video platform. You've wired up uploads, transcoding, and playback. Your content looks great. Then someone asks: "But how do we actually stop people from downloading and redistributing our premium videos?" You point to your signed URLs and HTTPS delivery, and they push back: "Is that really enough?"

The honest answer is: it depends — and for premium content, it probably isn't.

Digital Rights Management (DRM) is the answer the media industry converged on, and it's more implementable than most developers expect. The catch is that "DRM" isn't a single system. It's three separate systems — Widevine, FairPlay, and PlayReady — each controlled by a different tech giant, each covering a different slice of the device landscape. Ship support for only one, and you've broken playback for a significant portion of your users. Ship all three correctly, and you've got cryptographic content protection across effectively every major browser, mobile OS, and streaming device.

This post walks through how DRM actually works under the hood, why multi-DRM is the practical standard, and how to implement it without running three separate license servers yourself.

LinkWhat DRM Actually Does (and What It Doesn't)

Before getting into the mechanics, it's worth drawing a clean line between DRM and other access control mechanisms, because they're commonly conflated.

Signed URLs (like Mux's playback tokens) control who can request content. A JWT with an expiry and audience claim means an unauthorized user can't even start a download. That's genuinely useful — but once a valid signed URL is in hand, the video segments themselves are delivered in the clear over HTTPS. Someone with the right tools can intercept and save those segments.

HTTPS encrypts the connection, not the content. It protects against network-level interception, not against the person who is already authorized to watch.

DRM is different in kind, not just degree. It encrypts the content itself, and the decryption keys are never exposed to JavaScript or the browser's normal memory space. Instead, they're delivered to a hardware- or software-isolated subsystem called the Content Decryption Module (CDM). The CDM decrypts and renders video frames without those frames ever existing as accessible raw data in the browser process. Even if someone shares the stream URL, without a valid license — cryptographically bound to the requesting device — they get encrypted noise.

DRM doesn't make content theft impossible (nothing does — if someone can watch it, they can find ways to capture it). What it does is raise the bar high enough that casual redistribution becomes economically impractical, and it satisfies the studio-level content licensing requirements that many platforms need to meet.

LinkThe Three DRM Systems That Matter

No single DRM system runs everywhere. The three you need to know are:

Widevine is Google's DRM. It covers Chrome on desktop, Android devices, Chromecast, and most non-Apple smart TVs and streaming sticks. Widevine defines three security levels: L1 requires a hardware Trusted Execution Environment (TEE) and is required for HD/UHD content on certified Android devices; L2 and L3 use software-based protection and are common in Chrome on desktop. If you're building for the web and Android, Widevine is doing most of the heavy lifting.

FairPlay Streaming (FPS) is Apple's DRM. It's the only DRM that works in Safari on macOS, and it's required for any DRM-protected video on iOS and tvOS — full stop. Apple does not allow Widevine or PlayReady in the <video> element on Apple platforms. FairPlay uses a certificate-based key delivery model where the player first fetches an Apple-issued certificate, uses it to generate a Server Playback Context (SPC) blob, sends that to your license endpoint, and receives an encrypted Content Key Context (CKC) in return.

PlayReady is Microsoft's DRM. It runs in Edge on Windows, on Xbox, and on a variety of smart TV platforms. For most web-first platforms, PlayReady coverage overlaps significantly with Widevine (a user on Edge/Windows who has Widevine support often doesn't need PlayReady), but it becomes important for Xbox and certain HbbTV-based broadcast TV environments. PlayReady defines SL2000 (software security) and SL3000 (hardware TEE) security levels.

The key system strings you'll encounter in Encrypted Media Extensions (EME) code are:

  • Widevine: com.widevine.alpha
  • FairPlay: com.apple.fps.1_0
  • PlayReady: com.microsoft.playready

LinkHow the DRM Lifecycle Works

Understanding the flow helps enormously when debugging. Here's what happens from ingest to frame rendered on screen:

At packaging time, a content key (a random AES key) is generated for each asset. The video is encrypted with this key, and the key ID plus encrypted key material are registered with one or more license servers. The packaged stream embeds PSSH boxes (Protection System Specific Header) in the container — one per DRM system — which tell the player which DRM system to use and how to request a license.

At playback time, the player (via the browser's EME API) detects the PSSH data, selects the appropriate key system, and sends a license request to the license server. The license server authenticates the request — verifying that this device, user, and session are authorized — and returns an encrypted license containing the content key. The CDM decrypts the license, extracts the content key, and uses it to decrypt video segments as they stream in. The key never touches JavaScript.

The license server is the gatekeeper. Authenticating license requests — typically by requiring a signed JWT or session token alongside the license request — is how you enforce that only paying users can decrypt content.

LinkEncryption Modes: CENC vs. cbcs

Here's a detail that bites developers who try to handle packaging themselves: Widevine and PlayReady use CENC (Common Encryption in CTR mode), while FairPlay requires cbcs (Common Encryption in CBC mode with pattern encryption).

These are different AES block cipher modes operating on the same content. You can't use a single encrypted file for all three DRM systems. In practice, this means your packager needs to produce two differently-encrypted versions of each segment, or use a scheme like cbcs that has partial compatibility, depending on your target Widevine version.

This is one of the primary reasons multi-DRM is operationally complex to run yourself: dual-format packaging, three license server integrations, and per-DRM certificate management.

LinkDASH, HLS, and the Multi-DRM Packaging Reality

HLS and DASH split along DRM lines in a way that directly shapes your packaging strategy.

DASH natively supports CENC multi-DRM. A single DASH manifest can include PSSH boxes for both Widevine and PlayReady, so a DASH-capable player can pick whichever system is available on the current device. This is the cleanest multi-DRM story for the non-Apple world.

HLS is required for Apple platforms, and on Apple platforms, only FairPlay works. HLS with FairPlay uses a different key delivery mechanism (the #EXT-X-KEY tag pointing to a FairPlay license URL) and the cbcs encryption mode described above.

The practical conclusion: to cover all devices, you need both DASH (Widevine + PlayReady) and HLS (FairPlay). Your player needs to select the right manifest for the current platform, and your packaging pipeline needs to produce both. This is non-trivial infrastructure to build and maintain — which is exactly the problem a managed DRM solution solves.

LinkHow Mux Handles Multi-DRM Packaging and Licensing

Mux abstracts the dual-format packaging and three-license-server complexity behind a single API call.

When you create a playback ID with playback_policy set to "drm", Mux automatically packages your asset as both DASH (with Widevine and PlayReady PSSH boxes) and HLS (with FairPlay signaling), using the correct encryption mode for each. Mux operates as the license server intermediary, handling the Widevine, FairPlay, and PlayReady license exchanges on your behalf.

Enabling DRM on an asset looks like this:

bash
curl -X POST https://api.mux.com/video/v1/assets/{ASSET_ID}/playback-ids \ -H "Content-Type: application/json" \ -u $MUX_TOKEN_ID:$MUX_TOKEN_SECRET \ -d '{ "policy": "drm" }'

The response includes a playback_id that you use to construct DRM-protected playback URLs. Mux's license proxy handles routing license requests to the appropriate backend (Widevine's Google-operated license server, Apple's FairPlay infrastructure, or PlayReady) — you don't configure or authenticate against those systems directly.

For playback, <mux-player> handles EME/MSE negotiation and DRM key system selection automatically. In React:

jsx
import MuxPlayer from '@mux/mux-player-react'; export default function ProtectedPlayer({ playbackId, token }) { return ( <MuxPlayer playbackId={playbackId} tokens={{ playback: token }} envKey="your-mux-env-key" /> ); }

The player detects the browser/device, selects DASH+Widevine in Chrome, DASH+PlayReady in Edge where appropriate, and HLS+FairPlay in Safari and iOS — without you writing key system negotiation logic.

LinkHandling FairPlay in Safari Specifically

FairPlay requires fetching an Apple-issued application certificate before the license exchange can begin. Mux Player handles this automatically via the eme-credentials attribute, which tells the player where to fetch the certificate and how to format the SPC/CKC exchange. If you're building a custom player or integrating with a third-party player that supports EME, you'll need to implement the FairPlay certificate fetch flow manually — a step that's easy to miss if you've only tested in Chrome.

For React Native apps using WKWebView, be aware of certificate pinning conflicts: WKWebView's network stack can interfere with the FairPlay certificate fetch if you've implemented strict certificate pinning at the app level. The FairPlay handshake needs to reach Apple's certificate endpoint cleanly.

LinkDRM vs. Signed Tokens: Choosing the Right Tool

DRM and signed playback tokens aren't mutually exclusive — they're complementary controls at different layers.

Signed tokens (JWTs) provide URL-level access control. They're fast to implement, easy to revoke, and work without any special browser APIs. They're the right choice for access gating on content that doesn't require cryptographic protection: free-tier videos, internal training content, user-generated clips where piracy risk is low.

DRM provides cryptographic enforcement inside the CDM. The content can't be extracted even if the playback URL is shared, because without a valid license from an authenticated session, the encrypted segments are useless.

The practical use-case breakdown:

  • Free or ad-supported content: Signed tokens are likely sufficient. DRM adds complexity without meaningful benefit if the content has no restriction requirement.
  • Premium VOD (films, TV, paid courses): DRM is the right call. Studios often contractually require it. The user experience cost is low; the protection is meaningful.
  • Live pay-per-view events: DRM plus token-based session authentication. Time-bound licenses prevent post-event redistribution of captured streams.
  • Internal corporate video: Signed tokens with referrer validation usually satisfy compliance requirements without the overhead of DRM.

One common misconception worth naming directly: "just use HTTPS" is not DRM. HTTPS protects the connection between your CDN and the user's browser. It has nothing to say about what happens after the bytes arrive — and an authenticated user with ffmpeg and the right flags can record the decoded output regardless of transport encryption.

LinkCommon Implementation Mistakes

A few mistakes come up repeatedly when teams ship DRM for the first time:

Forgetting Safari and iOS entirely. Teams that build and test exclusively in Chrome often ship a broken FairPlay experience — or no FairPlay experience at all. Always test your DRM implementation on Safari macOS and a real iOS device before launch. Simulator behavior can differ from device behavior for DRM specifically.

Using the wrong encryption mode. Packaging everything in CENC CTR mode and wondering why FairPlay fails, or vice versa. The encryption mode has to match the DRM system. If you're doing custom packaging, verify your packager configuration explicitly.

License server latency causing playback start delays. The license request happens synchronously before the first frame can play. If your license server or proxy adds 500ms+ of latency, users notice. Minimize this by keeping license server infrastructure geographically close to users and by using player-side license pre-fetch where supported.

Breaking offline download workflows. DRM licenses can be configured with offline/persistent lease support, but this requires explicit configuration — both in the license policy and in your player integration. Over-restricting licenses to online-only when your product promises offline downloads is a support headache that DRM configuration, not code, has to solve.

LinkConclusion

Multi-DRM isn't a single technology — it's the coordination of three independent systems (Widevine, FairPlay, and PlayReady), two packaging formats (DASH and HLS), and two encryption modes (CENC and cbcs), all wired together so that the right system activates on the right device and the player never exposes decryption keys to the page.

That's a real amount of infrastructure. The good news for developers building on Mux is that the packaging, license server operations, and player-side key system negotiation are handled for you. You make one API call to enable DRM on a playback ID, use <mux-player> or the React wrapper, and get cross-platform DRM coverage without running your own Widevine proxy, FairPlay certificate server, or PlayReady license endpoint.

If you're deciding whether to add DRM to your platform, start with the use-case matrix above. For premium content with real monetization risk, DRM paired with signed playback tokens is the right combination — access gating at the URL layer and cryptographic enforcement at the decryption layer.

Ready to enable DRM on your Mux assets? Start with the official DRM guide in the Mux docs, explore the mux-player repository for player integration details, and enable DRM on an asset directly from the Mux dashboard.

For further reading: the Mux guide to secure video playback with signed URLs is the right next stop if you want to layer token-based access control on top of DRM-protected assets, and the video piracy deep-dive covers the broader threat landscape that DRM fits into.

Arrow RightBack to Articles

No credit card required to start using Mux.