Documentation

Offline Storage & Playback

Scope of support

Radiant Media Player supports download, storage and playback of offline content in MPEG-DASH & HLS. This feature is provided as an event-driven API that allows developers to build an application logic on top of the player. Our implementation is based on Shaka player offline capabilities which use IndexedDB for storage.

This feature should also help developers building media applications with Radiant Media Player to comply with Google Progressive Web Apps requirements.

While the player should provide a straight-forward approach to adding offline support to your application or site, we recommend developers looking to implement this feature to first familiarise themselves with general offline concepts and limitations. This storage for the web article should help.

Offline storage and playback support through hls.js or progressive download is not provided.

Offline support is only provided for on-demand video streaming. Live and DVR streaming are not supported for offline storage and playback due to their nature.

Supported features

Supported streaming protocols:

  • CMAF MPEG-DASH
  • CMAF HLS
  • Offline DRM (persistent license)
  • Audio-only streaming

Supported environments

Supported:

  • Latest Chrome, Firefox, Opera and Safari for Desktop
  • Latest Microsoft Edge and Microsoft Edge Legacy for Windows 7+
  • Latest Chrome, Firefox, Opera for Android 5.1+
  • Latest Safari for iOS 17+
  • Latest Safari for iPadOS 13+
  • Ionic, Flutter, Apache Cordova, WebView mobile apps for Android 5.1+
  • Ionic, Flutter, Apache Cordova, WebView mobile apps for iOS 17+
  • Ionic, Flutter, Apache Cordova, WebView mobile apps for iPadOS 13+
  • Electron-based apps for Desktop

Storage limitations

How much can I store?

Radiant Media Player makes use of IndexedDB to store content locally for offline playback. Data for an origin (e.g. a specific Internet domain) can be stored in two ways: persistent and best-effort. Radiant Media Player always stores content data as best-effort. Therefore content stored must be considered transient with Radiant Media Player offline feature, meaning your app needs to expect that the data will be lost eventually. This is because the OS will reclaim storage from browsers and WebViews if a device is running low on space. Note that research from the Chrome team shows that data is very rarely deleted by the browser. If a user visits a website regularly, there is very little chance that its stored data, even in best-effort mode, will get evicted by the browser. So the word "transient" mentioned above should not be blocking for most use-cases.

  • Chrome for Desktop and Android: up to 60% of the total disk space for an origin - but please note:
    • In incognito mode, Chrome reduces the amount of storage an origin can use to approximately 5% of the total disk space
    • If the user has enabled "Clear cookies and site data when you close all windows" in Chrome, the storage quota is significantly reduced to a maximum of approximately 300MB.
    • Other Chromium-based browsers like Microsoft Edge generally follows Chrome rules but they may also have limitations of their own
  • Ionic, Flutter, Apache Cordova, WebView mobile app for Android: up to 60% of the total disk space
  • Firefox for Desktop and Android: 10% of the total disk size or 10 Go, whichever is smaller for best-effort storage mode
  • Safari for iOS 17+, iPadOS 17+ and macOS Sonoma+: up to 60% of the total disk space - see WebKit note
  • Ionic, Flutter, Apache Cordova, WebView mobile app for iOS 17+, iPadOS 17+ and macOS+ Sonoma: up to 15% of the total disk space - see WebKit note

Persistent DRM licenses

The player automatically downloads and stores persistent licenses when available. Persistent licenses allow for offline playback of DRM protected content without the need for an Internet connection to access content.

Persistent licenses are supported for:

  • Widevine DRM

In the following environments:

  • Chrome 64+, Samsung Internet 12+ for Android 6+
  • Chrome 64+ for macOS 10.12+
  • Chrome 64+, Opera 64+, Microsoft Edge 79+, for Windows 10+
  • Chrome 64+ for Chromebooks (ChromeOS)

Persistent licenses are NOT supported in the following environments:

  • Safari (all platforms)
  • Firefox (all platforms)
  • Mobile apps for Android or iOS (Ionic, Flutter, Apache Cordova, WebView)

For platforms where storage of persistent licenses is not available you will get offline storage of protected content on all DRM-enabled environments, at the cost of needing a network connection at playback time to retrieve licenses.

HLS support

While we generally recommend using MPEG-DASH for offline playback, you may also opt for HLS based on your project requirement. You will need the following:

  • A CMAF / fMP4 HLS stream (offline is not supported with HLS-TS)
  • Set hlsEngine: 'shakaplayer' player setting
  • Set forceHlsJSOnAppleDevices: true player setting to enable support for Apple devices

Offline player settings

shakaOffline: Boolean

Enables or not offline features in Radiant Media Player. Default: false.

shakaOfflinePreferredTrackQuality: Number

Specifies which quality to download for offline storage when multiple choices are available.

  • -4: uses Shaka player default selection algorithm which generally selects the highest non-HD quality
  • -3: pick the highest available quality
  • -2: pick the lowest available quality
  • -1: pick the upper average quality
  • n (where n is an integer >= 0): pick the nth quality

Default: -1.

Offline API events

  • downloadstarted fires when download of content for offline playback has started, after download API method has been called
  • downloadprogress fires each time new data is appended to offline storage for a given running download
  • downloadcompleted fires when download of content for offline playback has completed, after download API method has been called
  • downloadlistavailable fires when the current download list is available for query, after calling listDownloadedContent API method
  • downloadremoved fires when the targeted download has been removed from storage, after calling removeDownload API method
  • abortdownloadcompleted fires when the targeted download has been aborted, after calling abortDownload API method

Offline API methods

isOnline()

rmp.isOnline();

Returns Boolean stating if the targeted device is online or offline. This method is based on window.navigator.onLine API. It should be thus noted that a true result may not necessary mean that the viewer has a public access to the Internet as she/he may just be in an Intranet or proxied environment. On the other hand a false result always mean the user has no public Internet connection.

hasDownloadSupport()

rmp.hasDownloadSupport();

Returns Boolean stating if the targeted device can download, store and play offline content.

listDownloadedContent() asynchronous

rmp.listDownloadedContent();

Request the player to query the current list of downloaded content. This method is asynchronous and will provide result through the getDownloadedList API method when the downloadlistavailable API event fires.

getDownloadedList()

rmp.getDownloadedList();

This method must be queried when the downloadlistavailable API event fires. It will return an Array of Object representing the list of currently stored media item for offline playback by the player. Each item of the Array will have its information stored as an Object with the following structure:

{
  appMetadata: Object
  duration: Number
  expiration: Number
  offlineUri: String
  originalManifestUri: String
  size: Number
}

If no downloaded item is found the following default Array of Object will be returned.

[{
  appMetadata: {},
  duration: -1,
  expiration: -1,
  offlineUri: '',
  originalManifestUri: '',
  size: -1
}]

download() asynchronous

rmp.download();

Request the player to start downloading content for offline storage. This downloadcompleted API event will fire when download has finished, while the downloadstarted and downloadprogress API events will give you status information about the download.

getDownloadProgress()

rmp.getDownloadProgress();

This method must be queried when downloadprogress API event fire and will return a Number between 0 and 1 representing the progress for the current download. Returns -1 if this value is not available.

loadDownload(storedItem) asynchronous

rmp.loadDownload(content);

When a downloaded item has been listed with the getDownloadedList API method, this item can be passed to the loadDownload API method to start playing this item. When playback starts for a stored item the player will fire a playing API event. If the player was not able to load and player the stored item a warning API event will fire.

removeDownload(storedItem) asynchronous

rmp.removeDownload(content);

When a downloaded item has been listed with the getDownloadedList API method, this item can be passed to the removeDownload API method to be removed from storage. When a item has been removed from storage, the downloadremoved API event will fire.

abortDownload() asynchronous

rmp.abortDownload();

When a download is currently running it is possible to abort it by calling this method. When a download has been aborted, the abortdownloadcompleted API event will fire.

Offline API error management

The player will fire the following warning API event through the offline API. See the error management docs for more information.

  • 3001: storage has not been initialized (shakaOffline setting is set to false or stream is not on-demand)
  • 3002: could not download offline content
  • 3003: could not list offline downloaded content
  • 3004: could not remove offline downloaded content
  • 3005: could not load offline content - invalid input
  • 3006: could not query temporary storage usage and availability
  • 3007: offline storage is not supported in this environment
  • 3008: could not abort download of offline content

Implementation example

To help you get started we have released a full usage example with source code here.

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License.

©2015-2024 Radiant Media Player. All Rights Reserved.