Offline Storage & Playback

Scope of support

Since Radiant Media Player 5, we support download, storage and playback for offline content. This feature is provided as an event-driven API that allows developers to build an offline logic on top of the player. Our implementation is based on Shaka player offline capabilities which use IndexedDB for storage. Offline storage and playback support through hls.js or progressive download is not provided.

This feature should 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 article, this article and this article should help.

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:

  • DASH (CMAF / fMP4 or WebM)
  • CMAF / fMP4 HLS
  • Offline DRM
  • Audio-only offline support

Supported environments


  • Latest Chrome, Firefox, Opera and Safari for Desktop
  • MS Edge 79+ and MS Edge Legacy for Windows 7+
  • Latest Chrome, Firefox, Opera for Android 5+
  • Latest Safari for iPadOS 13+
  • Cordova/Ionic/WebView mobile apps for Android 5+
  • Cordova/Ionic/WebView mobile apps for iPadOS 13+
  • Electron-based apps for Desktop


  • iOS Safari (Shaka player does not go on iOS, only native HLS is currently available and Apple does not provide an offline API)

Storage limitations

How much can I store?

  • Chrome for Desktop and Android: < 6% of free space
  • Cordova/Ionic/WebView mobile app for Android: < 6% of free space
  • Firefox for Desktop and Android: < 10% of free space
  • Safari for Desktop and iPadOS: < 500MB - see WebKit note
  • MS Edge: < 20% of free space

Users may be prompt by the browser to allow for more storage capacity before the above limits can be reached.

Read Google article Offline Storage for Progressive Web Apps for more information on the subject.

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 in:

  • Chrome 64+, Samsung Internet 12+ for Android 6+
  • Chrome 64+ for macOS 10.12+
  • Chrome 64+, Opera 64+, MS 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/Cordova/WebView)

Note that you will need to use DASH streaming to support persistent licenses (PlayReady or Widevine DRM).

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 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

Note that persistent DRM licenses are not supported with HLS streaming.

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



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.



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

listDownloadedContent() asynchronous


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.



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 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;

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.



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


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


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


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

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.