Configuration
Global Config
| name | type | default | description |
|---|---|---|---|
updateFrequencyMS | number | 1000 | How often to update the download progress |
maxParallelDownloads | number | 5 | How many files to download in parallel |
To update global config, you can use setConfig function.
import {
setConfig,
Config,
getConfig,
} from "@TheWidlarzGroup/react-native-video-stream-downloader";
setConfig({ updateFrequencyMS: 1000, maxParallelDownloads: 5 });
const config: Config = getConfig();
Download Config
| name | type | default | description |
|---|---|---|---|
includeAllTracks | boolean | false | Include all (audio and text) tracks from stream in the download |
tracks | object | undefined | Explicitly select track IDs to include (see Track Selection) |
expiresAt | number | 0 | Date when the download will expire. Once download is expired, it will be deleted from the device. |
drm | object | undefined | DRM configuration for protected content (see DRM Config) |
metadata | object | undefined | Custom metadata to store with the download (see Metadata) |
import { DownloadOptions } from "@TheWidlarzGroup/react-native-video-stream-downloader";
const downloadOptions: DownloadOptions = {
includeAllTracks: true, // or use `tracks` for precise selection
expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 30), // 30 days
};
// download stream with download options
const downloadStatus = await downloadStream(
"https://example.com/stream.m3u8",
downloadOptions
);
Track Selection
To precisely control which tracks are downloaded, pass tracks with arrays of track IDs obtained from getAvailableTracks(url).
import {
getAvailableTracks,
downloadStream,
} from "@TheWidlarzGroup/react-native-video-stream-downloader";
const tracks = await getAvailableTracks("https://example.com/manifest.m3u8");
const selectedVideo = tracks.video?.find((v) => v.height === 720);
await downloadStream("https://example.com/manifest.m3u8", {
tracks: {
video: selectedVideo ? [selectedVideo.id] : [],
audio: tracks.audio?.map((a) => a.id),
text: tracks.text?.map((t) => t.id),
},
});
Metadata
The metadata field allows you to store custom data with your download. You can add any key-value pairs, and they will be preserved and returned in the DownloadedAsset object.
Reserved Keys
Some metadata keys are used by the plugin:
title: Used to name the downloaded file on the device
Example Metadata Usage
const downloadOptions: DownloadOptions = {
metadata: {
title: "My Video Title", // Used by plugin for file naming
category: "movies",
genre: "action",
year: 2024,
rating: 4.5,
tags: ["action", "adventure"],
customData: {
userId: "12345",
playlistId: "playlist_1",
isFavorite: true,
},
},
};
const downloadStatus = await downloadStream(
"https://example.com/video.m3u8",
downloadOptions
);
Accessing Metadata in Downloaded Assets
import { getDownloadedAssets } from "@TheWidlarzGroup/react-native-video-stream-downloader";
const assets = getDownloadedAssets();
const asset = assets[0];
console.log(asset.metadata?.title); // "My Video Title"
console.log(asset.metadata?.category); // "movies"
console.log(asset.metadata?.customData?.userId); // "12345"
Metadata Type
The metadata field uses the Metadata type which allows any string key with any value:
interface Metadata {
title?: string; // Used by plugin for file naming
[key: string]: unknown; // Any other key-value pairs
}
DRM Config
When downloading DRM-protected content, you need to provide DRM configuration. You can either use licenseServer for automatic license acquisition or getLicense for custom license handling (iOS only).
drm?: {
/**
* The license server URL.
* @Platform Android - Widevine License Server URL
* @Platform iOS - FairPlay License Server URL
* @Note Either licenseServer or getLicense must be provided
*/
licenseServer?: string;
/**
* Optional URL to the DRM certificate.
* @Platform iOS - *required* FairPlay Certificate URL
* @Platform Android - not required for Widevine
*/
certificateUrl?: string;
/**
* Additional headers to include in the DRM request.
*/
headers?: { [key: string]: string };
/**
* Custom license acquisition function (iOS only).
* Instead of using licenseServer, you can manually acquire the license in JavaScript.
* @Platform iOS - FairPlay only
*/
getLicense?: (
spcString: string,
contentId: string,
licenseUrl: string,
loadedLicenseUrl: string
) => Promise<string> | string;
}
Example DRM Configuration
import { Platform } from "react-native";
const drmConfig = {
licenseServer:
Platform.OS === "ios"
? "https://your-fairplay-license-server.com/license"
: "https://your-widevine-license-server.com/license",
certificateUrl:
Platform.OS === "ios"
? "https://your-fairplay-certificate.com/certificate"
: undefined,
headers: {
"x-drm-usertoken": "your-drm-token",
},
};
const downloadOptions: DownloadOptions = {
drm: drmConfig,
};
const downloadStatus = await downloadStream(
"https://example.com/drm-video.m3u8",
downloadOptions
);
Custom License Acquisition (iOS Only)
Instead of using licenseServer, you can manually acquire the license using the getLicense function:
import { Platform } from "react-native";
const drmConfig = {
certificateUrl: "https://your-fairplay-certificate.com/certificate",
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": "your-custom-header",
"Content-Type": "application/x-www-form-urlencoded",
},
body: formData,
})
.then((response) => response.text())
.then((response) => response)
.catch((error) => console.error("Error", error));
},
};
const downloadOptions: DownloadOptions = {
drm: drmConfig,
};
const downloadStatus = await downloadStream(
"https://example.com/drm-video.m3u8",
downloadOptions
);
getLicense Parameters
The getLicense function receives the following parameters:
spcString: The SPC (Server Playback Context) used for DRM validationcontentId: The content ID from the DRM object orloadingRequest.request.url?.hostlicenseUrl: The URL passed in the DRM objectloadedLicenseUrl: The URL retrieved fromloadingRequest.request.URL.absoluteString, starting withskd://orclearkey://
You should return a Base64-encoded CKC response, either directly or as a Promise.