packages/drm-plugin/README.md
DRM plugin for react-native-video. It adds Widevine (Android) and FairPlay (iOS, visionOS) playback support via the react-native-video plugin system.
npm install @react-native-video/drm react-native-video react-native-nitro-modules
# then for iOS
npx pod-install
Notes
Enable the plugin once at app start, then pass DRM params on your video source.
import React from 'react';
import { Platform } from 'react-native';
import { VideoView, useVideoPlayer } from 'react-native-video';
import { enable, isEnabled } from '@react-native-video/drm';
// Enable at startup (required on Android; safe on iOS)
enable();
export default function Player() {
const player = useVideoPlayer({
uri: 'https://example.com/stream.m3u8',
// Request headers used by the media request and (on iOS default flow) the license request
headers: { Authorization: 'Bearer <token>' },
drm: {
// Optional: defaults to platform (fairplay on Apple, widevine on Android)
type: Platform.select({ ios: 'fairplay', default: 'widevine' }),
// Android (Widevine)
licenseUrl: 'https://license.example.com/widevine',
licenseHeaders: { 'x-custom': 'value' },
multiSession: true,
// iOS (FairPlay)
// For FairPlay provide certificateUrl and (optionally) contentId.
// When contentId is not provided, the plugin tries to infer it from the skd:// key URL.
certificateUrl: Platform.OS === 'ios' ? 'https://license.example.com/fps.cer' : undefined,
},
});
return <VideoView player={player} style={{ flex: 1 }} />;
}
From @react-native-video/drm:
enable(): void — registers the plugin. Call once during app startup (Android requires it; iOS tries to auto-enable, but calling is safe).disable(): void — unregisters the plugin.isEnabled: boolean — plugin registration status.DRM params (provided via useVideoPlayer({ drm: ... }) or equivalent config in react-native-video):
type?: 'widevine' | 'fairplay' | string — DRM system. Defaults: Android → widevine, Apple → fairplay.licenseUrl?: string — license server URL. Required for both Widevine and FairPlay default flows.licenseHeaders?: Record<string, string> — headers for license requests (Android only).multiSession?: boolean — allow multiple sessions (Android only).certificateUrl?: string — FairPlay application certificate URL (iOS/visionOS).contentId?: string — FairPlay content ID (iOS/visionOS). If omitted, inferred from skd:// key URL when possible.getLicense?: (payload) => Promise<string> — iOS custom license fetch. Receives { contentId, licenseUrl, keyUrl, spc } and must resolve to a base64-encoded CKC.licenseUrl and uses source.headers (not licenseHeaders). Use getLicense for full control.certificateUrl; set contentId if your server needs it.licenseHeaders for request headers and multiSession if needed.source.headers.drm.type appropriately or omit it to use platform defaults.MIT