Skip to main content

Track Selection in Offline Downloads

When downloading content with the Offline Video SDK, you can choose exactly which video, audio, and subtitle tracks to store locally. This is useful for:

  • Reducing file size
  • Selecting a specific language
  • Including/excluding subtitles
  • Downloading only the needed bitrate for offline playback
info

Track selection relies on two parts:

  • Inspect available tracks with getAvailableTracks(url)
  • Pass selected track ids via DownloadOptions.tracks to downloadStream

See full API in the API Reference.

Step 1 - Inspect Available Tracks

Before starting a download, call getAvailableTracks(url) to retrieve all available tracks in the manifest.

import { getAvailableTracks } from "@TheWidlarzGroup/react-native-video-stream-downloader";

const tracks = await getAvailableTracks("https://example.com/manifest.m3u8");
console.log(tracks);

You’ll get something like (IDs such as video_0, audio_0, text_1, including uri, bandwidth, and resolution):

{
"video": [
{
"id": "video_0",
"type": "video",
"uri": "https://example.cdn/hls/video/250kbit.m3u8",
"bandwidth": 258157,
"codecs": "avc1.4d400d",
"resolution": { "width": 422, "height": 180 },
"audioGroupId": "stereo",
"subtitlesGroupId": "subs",
"label": "422x180"
},
{
"id": "video_1",
"type": "video",
"uri": "https://example.cdn/hls/video/1000kbit.m3u8",
"bandwidth": 1048576,
"codecs": "avc1.4d401f",
"resolution": { "width": 960, "height": 540 },
"audioGroupId": "stereo",
"subtitlesGroupId": "subs",
"label": "960x540"
},
],
"audio": [
{
"id": "audio_0",
"type": "audio",
"uri": "https://example.cdn/hls/audio/stereo/en/128kbit.m3u8",
"groupId": "stereo",
"language": "en",
"name": "English",
"isDefault": true,
"autoSelect": true
},
],
"text": [
{
"id": "text_0",
"type": "text",
"uri": "https://example.cdn/hls/subtitles_en.m3u8",
"groupId": "subs",
"language": "en",
"name": "English",
"isDefault": true,
"forced": false,
"autoSelect": true
},
]
}

Step 2 - Choose the Tracks You Want

Example: choose a mid-quality video rendition (middle index), all audio, and all text tracks.

const selectedVideo = tracks.video?.[Math.floor(tracks.video.length / 2)];

const selectedTracks = {
video: selectedVideo ? [selectedVideo.id] : [],
text: tracks.text?.map((t) => t.id) || [],
audio: tracks.audio?.map((a) => a.id) || [],
};

We suggest exploring the example implementation in our Starter Kit.: react-native-offline-video-starter.

You can also:

  • Filter audio by language
  • Pick a single subtitle language
  • Choose only one audio/video track for maximum size reduction

Step 3 - Pass Tracks to downloadStream()

import { downloadStream } from "@TheWidlarzGroup/react-native-video-stream-downloader";

await downloadStream("https://example.com/video.m3u8", {
tracks: selectedTracks,
});

This ensures the download includes only the selected tracks.

Example - Download Lowest Bitrate Only

const lowestVideo = tracks.video?.reduce((min, track) =>
track.bandwidth < min.bandwidth ? track : min
);

await downloadStream("https://example.com/video.m3u8", {
tracks: { video: [lowestVideo!.id] },
});

Notes

  • Not selecting any tracks defaults to all available tracks (or use includeAllTracks: true).
  • Track IDs are manifest-specific - always call getAvailableTracks before downloading.