react-native-video/docs/pages/component/drm.mdx
Krzysztof Moch 0e4c95def9
feat(iOS): rewrite DRM Module (#4136)
* minimal api

* add suport for `getLicense`

* update logic for obtaining `assetId`

* add support for localSourceEncryptionKeyScheme

* fix typo

* fix pendingLicenses key bug

* lint code

* code clean

* code clean

* remove old files

* fix tvOS build

* fix errors loop

* move `localSourceEncryptionKeyScheme` into drm params

* add check for drm type

* use DebugLog

* lint

* update docs

* lint code

* fix bad rebase

* update docs

* fix crashes on simulators

* show error on simulator when using DRM

* fix typos

* code clean
2024-09-20 17:46:10 +02:00

204 lines
5.9 KiB
Plaintext

import PlatformsList from '../../components/PlatformsList/PlatformsList.tsx';
# DRM
> **Note:** DRM is not supported on visionOS yet.
## Provide DRM data (only tested with http/https assets)
You can provide some configuration to allow DRM playback.
This feature will disable the use of `TextureView` on Android.
DRM object allows this members:
### `base64Certificate`
<PlatformsList types={['iOS']} />
Type: bool\
Default: false
Whether or not the certificate url returns it on base64.
### `certificateUrl`
<PlatformsList types={['iOS']} />
Type: string\
Default: undefined
URL to fetch a valid certificate for FairPlay.
### `getLicense`
<PlatformsList types={['iOS']} />
Type: function\
Default: undefined
Rather than setting the `licenseServer` url to get the license, you can manually get the license on the JS part, and send the result to the native part to configure FairplayDRM for the stream
`licenseServer` and `headers` will be ignored. You will obtain as argument the `SPC`
(as ASCII string, you will probably need to convert it to base 64) obtained from
your `contentId` + the provided certificate via `objc [loadingRequest streamingContentKeyRequestDataForApp:certificateData
contentIdentifier:contentIdData options:nil error:&spcError]; `
Also, you will receive following parameter of getLicense:
* `contentId` contentId if passed to `drm` object or loadingRequest.request.url?.host
* `loadedLicenseUrl` URL defined as `loadingRequest.request.URL.absoluteString`, this url starts with `skd://` or `clearkey://`
* `licenseServer` prop if prop is passed to `drm` object.
* `spcString` the SPC used to validate playback with drm server
You should return on this method a `CKC` in Base64, either by just returning it or returning a `Promise` that resolves with the `CKC`.
With this prop you can override the license acquisition flow, as an example:
```js
getLicense: (spcString, contentId, licenseUrl, loadedLicenseUrl) => {
const base64spc = Base64.encode(spcString);
const formData = new FormData();
formData.append('spc', base64spc);
return fetch(`https://license.pallycon.com/ri/licenseManager.do`, {
method: 'POST',
headers: {
'pallycon-customdata-v2':
'd2VpcmRiYXNlNjRzdHJpbmcgOlAgRGFuaWVsIE1hcmnxbyB3YXMgaGVyZQ==',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData,
})
.then((response) => response.text())
.then((response) => {
return response;
})
.catch((error) => {
console.error('Error', error);
});
};
```
### `contentId`
<PlatformsList types={['iOS']} />
Type: string\
Default: undefined
Specify the content id of the stream, otherwise it will take the host value from `loadingRequest.request.URL.host` (f.e: `skd://testAsset` -> will take `testAsset`)
### `headers`
<PlatformsList types={['Android', 'iOS']} />
Type: Object\
Default: undefined
You can customize headers send to the licenseServer.
Example:
```js
source={{
uri: 'https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p.mpd',
}}
drm={{
type: DRMType.WIDEVINE,
licenseServer: 'https://drm-widevine-licensing.axtest.net/AcquireLicense',
headers: {
'X-AxDRM-Message': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImZpcnN0X3BsYXlfZXhwaXJhdGlvbiI6NjAsInBsYXlyZWFkeSI6eyJyZWFsX3RpbWVfZXhwaXJhdGlvbiI6dHJ1ZX0sImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.FAbIiPxX8BHi9RwfzD7Yn-wugU19ghrkBFKsaCPrZmU'
},
}}
```
### `licenseServer`
<PlatformsList types={['Android', 'iOS']} />
Type: string\
Default: false
The URL pointing to the licenseServer that will provide the authorization to play the protected stream.
### `multiDrm`
<PlatformsList types={['Android']} />
Type: boolean\
Default: false
Indicates that drm system shall support key rotation, see: https://developer.android.google.cn/media/media3/exoplayer/drm?hl=en#key-rotation
### `type`
<PlatformsList types={['Android', 'iOS']} />
Type: DRMType\
Default: undefined
You can specify the DRM type, either by string or using the exported DRMType enum.
Valid values are, for Android: DRMType.WIDEVINE / DRMType.PLAYREADY / DRMType.CLEARKEY.
for iOS: DRMType.FAIRPLAY
### `localSourceEncryptionKeyScheme`
<PlatformsList types={['iOS']} />
Set the url scheme for stream encryption key for local assets
Type: String
Example:
```
localSourceEncryptionKeyScheme="my-offline-key"
```
## Common Usage Scenarios
### Send cookies to license server
You can send Cookies to the license server via `headers` prop. Example:
```js
drm: {
type: DRMType.WIDEVINE
licenseServer: 'https://drm-widevine-licensing.axtest.net/AcquireLicense',
headers: {
'Cookie': 'PHPSESSID=etcetc; csrftoken=mytoken; _gat=1; foo=bar'
},
}
```
### Custom License Acquisition (only iOS for now)
```js
drm: {
type: DRMType.FAIRPLAY,
getLicense: (spcString) => {
const base64spc = Base64.encode(spcString);
return fetch('YOUR LICENSE SERVER HERE', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
getFairplayLicense: {
foo: 'bar',
spcMessage: base64spc,
}
})
})
.then(response => response.json())
.then((response) => {
if (response && response.getFairplayLicenseResponse
&& response.getFairplayLicenseResponse.ckcResponse) {
return response.getFairplayLicenseResponse.ckcResponse;
}
throw new Error('No correct response');
})
.catch((error) => {
console.error('CKC error', error);
});
}
}
```