Documentation

Radiant Media Player

HLS streaming

HLS support in Radiant Media Player

Radiant Media Player provides a comprehensive and cross-device solution to display HLS streams for on-demand, live or DVR content. Our HLS to HTML5 video & audio implementation relies on media source extensions (MSE) and is based on hls.js. Where media source extensions are not available (e.g. iOS, older Android) we fallback to native HLS to HTML5 video.

A standard-compliant HLS streaming URL is all you need - the player will take care of opting for the best way to render it based on device capabilities.

Supported HLS features

  • Playback of H.264 + AAC in .ts fragments
  • Playback of H.264 + AAC in fmp4 fragments (CMAF / fragmented MP4 container)
  • Playback of H.265 (HEVC) + AAC in fmp4 fragments (CMAF / fragmented MP4 container) where supported
  • Playback of H.264 + MP3 content in .ts fragments
  • Live, DVR and on-demand video streaming
  • Low-latency live HLS streaming (LL-HLS)
  • Optimized adaptive bitrate streaming with automatic or manual bitrate selection
  • Multiple-audio tracks
  • AES-128/SAMPLE-AES decryption
  • ID3 tags
  • WebVTT, IMSC1 & CEA 608/708 captions
  • Program-date-time
  • SEI packets with resolution payloadType 5
  • Discontinuities
  • Resilience to errors
  • Redundant/Failover Playlists
  • Audio-only: AAC container or MPEG Audio container (MPEG-1/2 Audio Layer III)
  • App-store compliant HLS streams playback - see hlsJSAppleAppStoreCompliance setting below for compliance notes

Supported environments

See our compatibility table for a list of environments where HLS streaming is supported with Radiant Media Player.

CORS requirements

You must set up your streaming server to return proper CORS settings permitting GET requests for HLS streaming to Radiant Media Player to work as expected.

Player code example

<!-- Include Radiant Media Player - here we use the optimised build for hls.js -->
<script src="https://cdn.radiantmediatechs.com/rmp/6.4.10/js/rmp-hlsjs.min.js"></script>
<!-- Player container element -->
<div id="rmpPlayer"></div>
<!-- Set up player configuration options -->
<script>
// Here we set our HLS streaming source
var src = {
  hls: 'https://your-hls-url.m3u8'
};
var settings = {
  licenseKey: 'your-license-key',
  src: src,
  width: 640,
  height: 360,
  contentMetadata: {
    poster: [
      'https://your-poster-url.jpg'
    ]
  }
};
var elementID = 'rmpPlayer';
var rmp = new RadiantMP(elementID);
rmp.init(settings);
</script>

HLS player settings

General

hlsJSCapLevelToPlayerSize: Boolean

This setting limits bitrates usable in auto-quality depending on player size (width & height). Default: true. If set to true, width and height (defined in m3u8 playlist) will be compared with the actual player width and height and only the best match will be used as the maximum available bitrate, hence helping to preserve bandwidth usage while maintaining streaming quality. This setting is ignored in manual mode so all levels can be selected manually. For 360 video this setting is always set to false.

hlsJSCapLevelOnFPSDrop: Boolean

This setting limits bitrates usable in auto-quality depending on framerate. Default: false. This feature is currently in beta and should only be used when dealing with HFR content (high frame rate > 30 fps) when addressing specific frame rate issues.

hlsJSStopDownloadWhilePaused: Boolean

When set to true this setting will cause the player to stop downloading HLS fragments while it is in a paused or stopped state. This can help to preserve bandwidth. Default: false.

hlsJSAppleAppStoreCompliance: Boolean

For App-store compliant HLS video streams which include an audio-only rendition this setting should be set to true to insure proper playback across devices. Default: false.

hlsJSDefaultAudioCodec: String

If audio codec is not signaled in variant manifest, or if only a stream manifest is provided, the player will try to guess audio codec by parsing audio sampling rate in ADTS header. If sampling rate is less or equal than 22050 Hz, then the player assumes it is HE-AAC, otherwise it assumes it is AAC-LC. This could result in bad guess, leading to audio decode error, ending up in media error. It is possible to hint default audio codec to the player by setting hlsJSDefaultAudioCodec to:

  • 'mp4a.40.2': AAC-LC
  • 'mp4a.40.5': HE-AAC
  • 'auto': the player auto-guesses. This is the default.

hlsJSUseManifestRenditionName: Boolean

By default the player present renditions in the quality menu as "resolution · bitrate" pattern. Example: 400p · 1728 kbps. However a HLS manifest is also required to have a NAME attribute for each rendition. When set to true this setting will cause the player to display the NAME of the rendition in place of the "resolution · bitrate" default pattern. This also applies to audio tracks when multi-language audio tracks are available in a HLS manifest. Default: false.

forceNativeHlsOverHlsJS: Boolean

When set to true the player will use native HLS support on the targeted device over Media Source Extensions HLS (provided both are detected as available). This can be useful in OTT environments where Media Source Extensions are known to be less efficient than native HLS (Fire TV, lower-end Android TV). Default: false.

forceHlsJSOnMacOSIpadOSSafari: Boolean

When set to true the player will use hls.js over native HLS on iPadOS and macOS Safari. This can be used for specific use-cases like when using the backupSrc setting. Note that it is generally best to leave that setting to false unless you are trying to address a specific issue that cannot be resolved otherwise. Default: false.

manualSwitchingMode: String

Select what mode for manual bitrate switching should be used by the player (works for HLS and DASH). Available values are 'instant', 'smooth', 'conservative'. Default: 'smooth' which provides an intermediary setting between 'instant' (immediate) and 'conservative' (slow) bitrate switching.

hlsJSStartLevel: Number

Defines the preferred initial bitrate when playback starts. Default: -1.

  • -1: automatic start level selection, playback will start from level matching download bandwidth (determined from download of first segment based on first level appearing in manifest) and information provided by rmp-connection when available.
  • n: where n is an integer will cause the player to select the n th level at startup (where 0 is the lowest quality).

Best practice: when hlsJSStartLevel is set to -1, your HLS manifest should include a lower-end rendition (generally this should not exceed 500 kbps audio & video included) and this rendition should be the first listed in your HLS manifest. This should provide optimal performance.

hlsJSMinAutoBitrate: Number

Set the minimum value (in bps) that should be used by the ABR algorithm. Default: 0. For example setting hlsJSMinAutoBitrate to 500000 means that the player - while in auto mode - will pick the best matching level that has a bitrate above or equal to 500000 bps (500 kbps).

Captions

For information on closed captions styling (FCC compliant) see this article.

hlsJSCaptionsTextTrack1Label: String

Label for the text track generated for CEA-608/708 captions track 1. This is how it will appear in the player captions menu. Default: 'CC1'.

hlsJSCaptionsTextTrack2Label: String

Label for the text track generated for CEA-608/708 captions track 2. This is how it will appear in the player captions menu. Default: 'CC2'.

hlsJSCaptionsTextTrack3Label: String

Label for the text track generated for CEA-608/708 captions track 3. This is how it will appear in the player captions menu. Default: 'CC3'.

hlsJSCaptionsTextTrack4Label: String

Label for the text track generated for CEA-608/708 captions track 4. This is how it will appear in the player captions menu. Default: 'CC4'.

Low-latency live settings (LL-HLS)

For more information on low-latency live HLS streaming see our live documentation.

hlsJSLowLatencyMode: Boolean

Enables Low-Latency HLS part playlist and segment loading, and start live streams at playlist PART-HOLD-BACK rather than HOLD-BACK. Default: true.

hlsJSProgressive: Boolean

Enables streaming segment data with fetch loaderexperimental (rather than XHR). Default: false.

XMLHttpRequest tuning

hlsJSFetchXhrWithCredentials: Boolean

This setting indicates to the player whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates. This applies to all requests (Fetch or XHR) made in the context of HLS streaming. Setting hlsJSFetchXhrWithCredentials has no effect on same-site requests. Default: false.

Retry parameters

retryParameters: Object

This represents an Object to pass to the player to specify specific retry parameters when attempting to load HLS content. The following example shows the default player parameters:

retryParameters: {
  manifest: {
    timeout: 10000, // timeout in ms, after which we abort a request
    maxTimeout: 64000, // maximum timeout in ms for all attempts before we fail
    maxAttempts: 3, // the maximum number of requests before we fail
    delay: 1000 // the base delay in ms between retries
  },
  levels: {
    timeout: 10000,
    maxTimeout: 64000,
    maxAttempts: 5,
    delay: 1000
  },
  segment: {
    timeout: 20000,
    maxTimeout: 64000,
    maxAttempts: 7,
    delay: 1000
  }
};

Custom config

You may pass to the player any parameter available with hls.js using the hlsJSCustomConfig setting:

hlsJSCustomConfig: Object

Allow passing a custom config object to hls.js. As such any hls.js internal setting can be tuned. Note that this may override any setting previously documented on this page. Default: {}. Example:

var hlsJSCustomConfig = {
  fragLoadingTimeOut: 20000,
  fragLoadingMaxRetry: 6,
  fragLoadingRetryDelay: 500,
  fragLoadingMaxRetryTimeout: 64000
};
var settings = {
  licenseKey: 'your-license-key',
  src: {
    hls: 'https://your-hls-url.m3u8'
  },
  width: 640,
  height: 360,
  hlsJSCustomConfig: hlsJSCustomConfig
};

See this page for a list of all hls.js options.

Custom HTTP headers

var hlsJSCustomConfig = {
  xhrSetup: function(xhr, url) {
    xhr.setRequestHeader("Authorization", "abc-token-abc")
  }
};
var settings = {
  licenseKey: 'your-license-key',
  src: {
    hls: 'https://your-hls-url.m3u8'
  },
  width: 640,
  height: 360,
  hlsJSCustomConfig: hlsJSCustomConfig
};

Native HLS support notes

On iOS & macOS Safari and older Android devices, we display HLS to HTML5 video using native device support (this is where media source extensions are not available or not reliable enough). On those devices limitations may apply:

  • DVR controls may not be supported, in which case DVR streams will be treated as simple live streams - on iOS 12+ DVR controls are only available in fullscreen mode.
  • Manual bitrate switching is not supported - the player uses adaptive bitrate streaming in auto mode and the adaptation logic is left to the device.

HLS with ID3 frames

Radiant Media Player supports the retrieval & parsing of ID3 frames when streaming HLS (either through hls.js or native HLS in Safari). Usage examples vary from server-side ad insertion, metadata of audio-only streams (song title, album cover ...), slides attached to a video presentation and so on.

For more information on ID3 tags you can visit the id3.org site. A list of ID3 frames (id3v2.4) can be found here.

ID3 frames through player API

Since Radiant Media Player version 5.1.14 we provide native and easy-to-use extraction of ID3 frames through our player API:

ID3 API event

meta

Fires each time ID3 metadata are updated.

ID3 API method

getMetadata()

When invoked, this method will return Object|null representing the current ID3 metadata. The returned Object when available will have the following structure:

{
  data: {
    albumTitle: String, // TALB frame
    recordingTime: String, // TDRC frame
    releaseTime: String, // TDRL frame
    composer: String, // TCOM frame
    contentType: String, // TCON frame
    fileType: String, // TFLT frame
    contentGroup: String, // TIT1 frame
    title: String, // TIT2 frame
    duration: String, // TLEN frame
    artist: String, // TPE1 frame
    band: String, // TPE2 frame
    conductor: String, // TPE3 frame
    radioStationName: String, // TRSN frame
    radioStationOwner: String, // TRSO frame
    isrc: String, // TSRC frame
    commercialInfo: String, // WCOM frame
    copyrightInfo: String, // WCOP frame
    url: String, // WXXX frame (poster frame)
    start: Number, // start time of the metadata in seconds
    end: Number // end time of the metadata in seconds
  },
  type: "id3"
}

Depending on your HLS stream not all attributes from the data object may be available

Player code example - see this example here
<script src="https://cdn.radiantmediatechs.com/rmp/6.4.10/js/rmp.min.js"></script>
<div id="rmpPlayer"></div>
<script>
  var src = {
    // Test stream - courtesy of our partner indexcom.com
    hls: 'https://db2.indexcom.com/bucket/ram/00/05/05.m3u8'
  };
  var settings = {
    licenseKey: 'your-license-key',
    src: src,
    width: 640,
    height: 360,
    audioOnly: true
  };
  var elementID = 'rmpPlayer';
  var rmp = new RadiantMP(elementID);
  var rmpContainer = document.getElementById('rmpPlayer');
  // We listen to meta API event
  rmpContainer.addEventListener('meta', function () {
    // Each time meta event fires, getMetadata API method is updated and can be queried
    console.log(rmp.getMetadata());
  });
  rmp.init(settings);
</script>

SEI packets with resolution payloadType 5 with HLS

The player will parse SEI packets with resolution payloadType 5 based on H.264 specification for HLS (for default hls.js based streaming). Now you can write custom data to a HLS H.264 stream and get those data from API method getMetadata upon meta API event.

Getting SEI packets custom data through player API

SEI packets custom data API event

meta

Fires each time new SEI packets custom data are available

SEI packets custom data API method

getMetadata()

When invoked, this method will return Object|null representing the current SEI packets custom data. The returned Object when available will have the following structure:

{
  data: {
    samples: [
      pts: 0,
      payloadType: 5,
      uuid: "8fbb6c74-7c3e-4f78-9f7-8cb35d3c177e",
      userDataBytes: Object,
      userData: "some user data"
    ]
  },
  type: "sei"
}
Player code example
<script src="https://cdn.radiantmediatechs.com/rmp/6.4.10/js/rmp.min.js"></script>
<div id="rmpPlayer"></div>
<script>
  var src = {
    hls: 'your-hls-stream-with-sei-packets-with-resolution-payloadType-5'
  };
  var settings = {
    licenseKey: 'your-license-key',
    src: src,
    width: 640,
    height: 360
  };
  var elementID = 'rmpPlayer';
  var rmp = new RadiantMP(elementID);
  var rmpContainer = document.getElementById('rmpPlayer');
  // We listen to meta API event
  rmpContainer.addEventListener('meta', function () {
    // Each time meta event fires, getMetadata API method is updated and can be queried
    console.log(rmp.getMetadata());
  });
  rmp.init(settings);
</script>

HLS with program date time

The EXT-X-PROGRAM-DATE-TIME tag in HLS associates the first sample of a Media Segment with an absolute date and/or time. It applies only to the next Media Segment. More information can be found in HLS specification.

Program date time metadata through player API

Since Radiant Media Player version 5.2.1 we provide native and easy-to-use extraction of program date time metadata through our player API:

Program date time API event

meta

Fires each time program date time metadata are updated.

Program date time API method

getMetadata()

When invoked, this method will return Object|null representing the current program date time metadata. The returned Object when available will have the following structure:

{
  data: {
    programDateTime: Number, // epoch time in seconds for start of program date time
    rawProgramDateTime: String, // Date time for program date time (ISO/IEC 8601:2004)
    endProgramDateTime: Number, // epoch time in seconds for end of program date time
    start: Number, // start time of the metadata in seconds
    end: Number // end time of the metadata in seconds
  },
  type: "program-date-time"
}

On Apple devices (iOS, iPadOS and macOS Safari), we use the getStartDate method native to the HTML5 video tag to get program date time data - this is the only way to access program date time data on Apple devices. If there is a program date time in the HLS stream the first one will be stored as the date returned by this method. From there, you should be able to combine it with the player getCurrentTime or getLiveCurrentTime API methods to get the current program date time. With those two values you should be able to measure the delay time specific to your context.

Depending on your HLS stream not all attributes from the data object may be available - check property before usage

Player code example
<script src="https://cdn.radiantmediatechs.com/rmp/6.4.10/js/rmp.min.js"></script>
<div id="rmpPlayer"></div>
<script>
  var src = {
    hls: 'https://your-live-hls-stream-with-program-date-time-metadata.m3u8'
  };
  var settings = {
    licenseKey: 'your-license-key',
    src: src,
    width: 640,
    height: 360
  };
  var elementID = 'rmpPlayer';
  var rmp = new RadiantMP(elementID);
  var rmpContainer = document.getElementById('rmpPlayer');
  // We listen to meta API event
  rmpContainer.addEventListener('meta', function () {
    // Each time meta event fires, getMetadata API method is updated and can be queried
    console.log(rmp.getMetadata());
  });
  rmp.init(settings);
</script>

HLS with Shaka Player

HLS streaming with Shaka player is only reserved to specific use-cases: HLS with DRM, offline HLS, HLS with embedded TTML captions. For all other use-cases please use the default hls.js engine.

As an alternative to hls.js for streaming HLS content to Radiant Media Player, it is also possible to use Shaka player to support specific use-cases.

Supported HLS features with Shaka Player

  • Playback of H.264 or H.265 video in fmp4 fragments (CMAF / fragmented MP4 container)
  • Live, DVR and on-demand media content
  • Optimized adaptive bitrate streaming with automatic or manual bitrate selection
  • Multiple-audio tracks
  • Multiple WebVTT or TTML tracks (subtitles/captions)
  • DRM (Widevine) - requires fmp4 HLS
  • Resilience to errors

Player settings for HLS with Shaka Player

hlsEngine: String

Selects the HLS rendering engine. Default: 'hlsjs'. Other possible value is 'shakaplayer'.

All other player settings that apply to Shaka player can all be used even if they are not explicitly marked as compatible with HLS streaming.

Low-latency (LL-HLS) with Shaka Player

For more information on low-latency live HLS streaming see our live documentation.

shakaAutoLowLatencyMode: String

Enables Low-Latency HLS part playlist and segment loading, and start live streams at playlist PART-HOLD-BACK rather than HOLD-BACK. Default: true.

Player code examples for HLS with Shaka Player

<!-- Include Radiant Media Player - here we use the optimised build for Shaka player -->
<script src="https://cdn.radiantmediatechs.com/rmp/6.4.10/js/rmp-shaka.min.js"></script>
<!-- Player container element -->
<div id="rmpPlayer"></div>
<!-- Set up player configuration options -->
<script>
// Here we pass our HLS streaming source
  var src = {
    hls: 'https://your-fmp4-hls-url.m3u8'
  };
  var settings = {
    licenseKey: 'your-license-key',
    src: src,
    width: 640,
    height: 360,
    // Here we tell the player to use Shaka Player for HLS streaming
    hlsEngine: 'shakaplayer',
    contentMetadata: {
      poster: [
        'https://your-poster-url.jpg'
      ]
    }
  };
  var elementID = 'rmpPlayer';
  var rmp = new RadiantMP(elementID);
  rmp.init(settings);
</script>
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License.

©2015-2021 Radiant Media Player. All rights reserved.