The following guide helps you set up DRM with React Native Video
React Native Video is very popular player to play videos on react native applications. It can play both HLS and DASH streams and supports DRM.
Don't use simulator during development
iOS doesn't support fairplay protected playback on simulators, please use actual devices during development.
iOS:
React Native Video supports AVPlayer on iOS. Since AVPlayer does not support DRM out of the box, we need to explicitly configure React Native Video to pass certificate and licenses to the AVPlayer
To keep the scope of this document limited we expect you have already setup React Native development environment for iOS.
Secure your video assets from piracy and maximize ROI on your content. Easily set up fairplay DRM on your React Native apps with Gumlet.
Step 1: Install the react-native-video package
npm i --save react-native-video
Step 2: Import react-native-video in your component
import Video, {DRMType} from 'react-native-video';
Step 3: Add the video component to your code
For the simplicity of this document we are making the changes in App.js itself and our app would only have a video player in it. We have also added some basic styles to our video component.
const App: () => Node = () => {
return (
<>
<View style={{flex: 1}}>
<Video
source={{
uri: 'https://video.gumlet.io/5f462c1561cf8a766464ffc4/61ee745525fc01c00e08a2ec/1.m3u8',
}}
style={styles.mediaPlayer}
/>
</View>
</>
);
};
const styles = StyleSheet.create({
mediaPlayer: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
justifyContent: 'center',
backgroundColor: '#f8f8f8'
},
});
Step 4: Request for a license URL to play a video encrypted by DRM
DRM playback also needs Licence Server URL along with playback URL to play the content. The licence server URL will inform player the place from where the licence can be acquired.
Remember!
For security reasons, Licence Server URL needs authentication token to be passed so it knows the request for licence is legitimate, due to this reason the code for generating a Licence Server URL should be on the server and not reside in the application itself.
Refer to this guide to generate the licence server URL on a backend server with your choice of programming language.
Let us assume that your server root URL is https://example.com and sending a GET request on https://example.com/licence-url returns a licence server URL. We will call the fetch method in the components useEffect hook and set it to a state variable to be used to initialise the video player with the Licence Server URL.
const App: () => Node = () => {
const [isLoading, setLoading] = useState(true);
const [signedLicenseURL, setSignedLicenseURL] = React.useState('');
const getSignedLicenseURL = async () => {
try {
const response = await fetch('https://example.com/licence-url');
const json = await response.json();
setSignedLicenseURL(json.licence);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
useEffect(() => {
getSignedLicenseURL();
}, []);
// Wait for the signedLicenseURL to be available until then you can show a placeholder..
if (isLoading) {
return (
<View style={{flex: 1}}>
<Text>Loading Signed URL</Text>
</View>
)
}
return (
<>
<View style={{flex: 1}}>
<Video
source={{
uri: 'https://video.gumlet.io/<org_id>/<asset_id>/main.m3u8',
type: 'mpd'
}}
drm={{
type: DRMType.FAIRPLAY,
certificateUrl: fairplayCertificate,
licenseServer: signedLicenseURL,
getLicense: (spcString, contentId, licenseUrl, loadedLicenseUrl) => {
const body = JSON.stringify({spc: spcString});
return fetch(`${licenseUrl}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: body,
})
.then((response) => response.json())
.then((response) => {
return response.ckc;
})
.catch((error) => {
console.error('Error', error);
});
}
}}
/>
</View>
</>
);
};
Done
You can now play your DRM protected videos in a React Native Application
Full Code Snippet
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow strict-local
*/
import React, {useEffect, useState} from 'react';
import type {Node} from 'react';
import {
Text,
useColorScheme,
View,
} from 'react-native';
import {
Colors,
} from 'react-native/Libraries/NewAppScreen';
import Video, {DRMType} from 'react-native-video';
const App: () => Node = () => {
const [isLoading, setLoading] = useState(true);
const [signedLicenseURL, setSignedLicenseURL] = React.useState('');
// Make a request to get a signed Licence Server URL
const getSignedLicenseURL = async () => {
try {
const response = await fetch('https://example.com/licence-url');
const json = await response.json();
setSignedLicenseURL(json.licence);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
useEffect(() => {
getSignedLicenseURL();
}, []);
// Wait for the signedLicenseURL to be available until then you can show a placeholder..
if (isLoading) {
return (
<View style={{flex: 1}}>
<Text>Loading Signed URL</Text>
</View>
)
}
return (
<>
<View style={{flex: 1}}>
<Video
source={{
uri: 'https://video.gumlet.io/5f462c1561cf8a766464ffc4/627ccd5803f2239e6938820b/main.mpd',
type: 'mpd'
}}
drm={{
type: DRMType.FAIRPLAY,
certificateUrl: fairplayCertificate,
licenseServer: signedLicenseURL,
getLicense: (spcString, contentId, licenseUrl, loadedLicenseUrl) => {
const body = JSON.stringify({spc: spcString});
return fetch(`${licenseUrl}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: body,
})
.then((response) => response.json())
.then((response) => {
return response.ckc;
})
.catch((error) => {
console.error('Error', error);
});
}
}}
/>
</View>
</>
);
};
const styles = StyleSheet.create({
mediaPlayer: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
justifyContent: 'center',
backgroundColor: '#f8f8f8'
},
});
export default App;