Improve HLS Performance
Media Source Extensions (MSE) players such as Shaka Player, Hls.js, and Bitmovin perform CPU-intensive tasks in JavaScript. These include parsing multiple HLS media manifests, which can impact UI responsiveness and fluidity of the application. This impact is particularly noticeable during Live TV playback with large DVR windows that has large manifest sizes. This documentation explains how to optimize performance by leveraging the native implementation of HLS playlist parser.
Moving to native parsing offers a significant performance improvement, but not all applications are required to switch to native HLS parser support. These optimizations are particularly beneficial for apps handling Live TV playback with large DVR windows as frequent refresh and parsing of large manifest resulting in frequent JS thread blockages, Key events and UI processing getting delayed. Apps can also use this optimization to improve video startup latencies.
React Native for Vega APIs
You can offload HLS manifest parsing to the native layer using the following functions:
Step 1: Enable native parsing
To enable native parsing, the app must register the native functions by calling registerNativePlayerUtils()
. If the device supports native fuctions, the call returns true
, otherwise false
.
The call registers the app and enables calls to the native HLS parser.
global.registerNativePlayerUtils();
Step 2: Checks availability of native support for HLS playlist parsing
To check whether native support for HLS playlist parsing is available for a specific player and player version call isNativeHlsParserSupported()
and pass the following parameters:
playerName
: Name of the player. Supported values are "shaka" and "hlsjs".playerVersion
: Version of the player. For "shaka" "4.6.18" or "4.3.6". For "hlsjs" "1.5.11".
Supported player versions:
- The native HLS parser is currently supported for ShakaPlayer version "4.6.18" and "4.3.6".
- The native HLS parser is currently supported for Hls.js version "1.5.11".
#Shaka Player
if(global.isNativeHlsParserSupported("shaka", "4.3.6")) {
console.log('platform supports native parser for this version of shaka player');
}
#Hls.js Player
if(global.isNativeHlsParserSupported("hlsjs", "1.5.11")) {
console.log('platform supports native parser for this version of hls.js player');
}
Step 3: Call the manifest parsing function
The global.parseHlsManifest
function implements the HLS manifest parsing. The app must first register itself and then call the parsing function.
To parse the manifest call parseHlsManifest()
and pass the following parameters:
playerName
: String that contains the player name "shaka".playerVersion
: String that contains the player version: "4.6.18" or "4.3.6".absoluteUri
: String that contains the absolute URI of the manifest.manifest
: And ArrayBuffer that contains the downloaded manifest.shaka
: For ShakaPlayer only, pass the Shaka object as shown in the next section.
global.parseHlsManifest(
playerName, playerVersion, absoluteuri, manifest, shaka);
To parse the manifest call parseHlsManifest()
and pass the following parameters:
playerName
: String that contains the player name "hlsjs".playerVersion
: String that contains player version : "1.5.11"absoluteUri
: String that contains the absolute URI of the manifest.manifest
: ArrayBuffer that contains the downloaded manifest.id
: Playlist Level Id. This is of number type.type
: Playlist Level Type from imported hlsplayer lib object.HlsPlayerLib
: Imported hlsplayer lib object from Hls.mjs.
global.parseHlsManifest(
playerName, playerVersion, absoluteuri, manifest, id, type, HlsPlayerLib);
The following section provides additional details on the usage of these.
Integration Changes
The following section provides additional details on the usage of the functions shown in the previous steps.
The native HLS parser is supported for the 4.6.18
and 4.3.6
versions of Shaka player. For information about using the Shaka Player in your app with all the required patches applied, see Play adaptive content (HLS/DASH) with Shaka Player.
Note: Before building the player, make sure that the Shaka Player release tarball contains the Shaka-Player-optimizations.patch file and that it is applied. This enables the hook to register the HLS parsing function. This patch is included starting with the following versions:
- ShakaPlayer v4.6.18: shaka-rel-v4.6.18-r2.9.tar.gz
- ShakaPlayer v4.3.6: shaka-rel-v4.3.6-r2.2.tar.gz
To use this functionality, make the following changes in your apps src/shakaplayer/ShakaPlayer.ts file:
-
Define the Shaka Player version in src/shakaplayer/ShakaPlayer.ts.
const playerName: string = "shaka"; const playerVersion: string = "4.6.18";
-
You can also define flag to enable or disable native parsing. As an example, the following flag is used in Step 4 to enable native parsing.
static readonly enableNativeParsing = true;
-
Add the call to
parseHlsManifest()
.import shaka from "./dist/shaka-player.compiled"; async nativeParsePlaylist( manifest: ArrayBuffer, absoluteuri:string) : Array<shaka.hls.Playlist> { console.log('shaka: nativeParsePlaylist+'); const playlist = await global.parseHlsManifest( playerName, playerVersion, absoluteuri, manifest, shaka); console.log('shaka: nativeParsePlaylist-'); return playlist; }
-
Register your implementation of the
parseHlsManifest()
function before loading Shaka Player. ThesetNativeFunctions()
function allows the app to pass the implementation to the nativeparseHlsManifest
function. It accepts a function as an argument which is called from Shaka Player during HLS Parsing.override async load(content: any, autoplay: boolean): void { if (ShakaPlayer.enableNativeParsing) { // check if the platform supports native player utils and // if the shaka player hook to register native function for HLS parser. if (global.registerNativePlayerUtils && shaka.hls.HlsParser.setNativeFunctions) { console.log("shakaplayer: registerNativePlayerUtils found"); // now register native player utils. if (!global.isNativeHlsParserSupported) { const ret = global.registerNativePlayerUtils(); console.log("shaka: native functions registered: " + ret); } // now check if this specific player and player version // supports native HLS parser. if (global.isNativeHlsParserSupported && global.parseHlsManifest) { const nativeHlsParserSupported = global.isNativeHlsParserSupported(playerName, playerVersion); // if this player and player version supports native HLS parser // register the wrapper function to shaka. if (nativeHlsParserSupported) { console.log('shaka: setting native functions'); shaka.hls.HlsParser.setNativeFunctions(this.nativeParsePlaylist); } else { console.log('shaka: nativeHlsParser not supported for player version'); } } else { console.log('shaka: native func not set even after register, skipping it'); } } else { console.log(`shakaplayer: native offload not enabled! registerNativePlayerUtils: ${!!global.registerNativePlayerUtils}, setNativeFunctions: ${!!shaka.hls.HlsParser.setNativeFunctions}`); } } else { console.log(`shaka: native playlist parsing is disabled`); } }
These integration changes are also present in ShakaPlayer.ts which is available as part of externalized release tarball which you can be use as a reference.
The native HLS parser is supported for the 1.5.11
version of the Hls.js player. For information about using the Hls.js Player in your app with all the required patches applied, see Play adaptive content using Hls.js Player.
Note: Before building the player, make sure that the hls.js player release tarball contains the HLSJS-Nativize-HLS-manifest-parser-function.patch and that it is applied. This enables the hook to register HLS parsing function. This patch is included starting with the following tarball:
- Hls.js: hls-rel-v1.5.11-r1.4.tar.gz
setNativeFunctions
Allows app to pass the implementation to call native parseHlsManifest from Hls.js Player. It accepts a function as an argument which is further called from Hls.js Player during HLS Parsing.
To use this functionality, make the following changes in your apps src/hlsjsplayer/HlsJsPlayer.ts file:
-
Define the hls.js player version in src/hlsjsplayer/HlsJsPlayer.ts:
const playerName: string = "hlsjs"; const playerVersion: string = "1.5.11";
-
You can also define flag to enable or disable native parsing. As an example, the following flag is used in Step 5 to enable native parsing.
static readonly enableNativeParsing = true;
- Update the required import. We rely on ./dist/hls.mjs in place of ./dist/hls.js. Update the lib object accordingly.
The lines to update are identifies by '-'. Replace them with the lines identified by '+'.
##### import update ##### - import Hls from './dist/hls.js'; + import * as HlsPlayerLib from './dist/hls.mjs' ###### lib object update ##### - this.hls = new Hls({ + this.hls = new HlsPlayerLib.Hls({
-
Add the call to
parseHlsManifest()
.nativeParseLevelPlaylist( manifest: string, absoluteuri:string, id: number, type: HlsPlayerLib.PlaylistLevelType ) : HlsPlayerLib.LevelDetails { console.log('HlsJs: nativeParseLevelPlaylist +'); let levels: HlsPlayerLib.LevelDetails = global.parseHlsManifest( playerName, playerVersion, absoluteuri, manifest, id, type, HlsPlayerLib); console.log(`HlsJs: nativeParseLevelPlaylist -`); return levels; }
-
Register this function to Hls.js player before loading the player.
override async load(content: any, _autoplay: boolean): void { console.log("Hlsjs: Load +"); if (HlsJsPlayer.enableNativeParsing) { if (global.registerNativePlayerUtils && HlsPlayerLib.M3U8Parser.setNativeFunctions) { console.log("Hlsjs: registerNativePlayerUtils found"); if (!global.isNativeHlsParserSupported) { const ret = global.registerNativePlayerUtils(); console.log("Hlsjs: native functions registered: " + ret); } if (global.isNativeHlsParserSupported && global.parseHlsManifest) { const nativeHlsParserSupported = global.isNativeHlsParserSupported(playerName, playerVersion); if (nativeHlsParserSupported) { console.log('Hlsjs: setting native functions'); HlsPlayerLib.M3U8Parser.setNativeFunctions(this.nativeParseLevelPlaylist); } else { console.log('hlsjs: nativeHlsParser not supported for player version'); } } else { console.log('hlsjs: native func not set even after register, skipping it'); } } else { console.log(`hlsjs: native offload not enabled! registerNativePlayerUtils: ${!!global.registerNativePlayerUtils}, setNativeFunctions: ${!!HlsPlayerLib.M3U8Parser.setNativeFunctions}`); } } else { console.log(`hlsjs: native playlist parsing is disabled`); }
These integration changes are also present in HlsjsPlayer.ts which is available as part of externalized release tarball which you can be use as a reference.
Supported tags
Shaka Player
- ShakaPlayer v4.6.18: All tag supported by Shakaplayer version v4.6.18.
- ShakaPlayer v4.3.6: All tag supported by Shakaplayer version v4.3.6.
Hls.js Player
The following lists contain the supported tags:
Media Playlist
- EXT_X_VERSION
- EXT_X_TARGETDURATION
- EXT_X_MEDIA_SEQUENCE
- EXT_X_DISCONTINUITY_SEQUENCE
- EXT_X_PLAYLIST_TYPE
- EXT_X_ENDLIST
Media Segment
- EXTINF
- EXT_X_BYTERANGE
- EXT_X_DISCONTINUITY
- EXT_X_PROGRAM_DATE_TIME
- EXT_X_KEY
- EXT_X_MAP
For the description of these tags, see RFC 8216.
TroubleShooting
-
After integrating changes, if the following log entry is observed, nativization is not enabled. To enable it, set the nativization enablement flag. For an example of setting the flag, see step 2 of the ShakePlayer integration.
hlsjs: native playlist parsing is disabled
-
After integrating changes, if the following log entry is observed, nativization is not enabled. The most likely cause is that the Vega OS release version is not compatible and doesn't have the required nativization changes. Make sure that your are using a version that is
OS 1.1 (201010432050)
or higher.hlsjs: native offload not enabled!
Last updated: Sep 30, 2025