HLS.js - JavaScript HLS Client
HLS.js is a robust, open-source JavaScript library that implements an HLS (HTTP Live Streaming) client. It enables the playback of HLS streams directly in modern web browsers by leveraging the Media Source Extensions (MSE) API, eliminating the need for native browser HLS support. The current stable version is 1.6.16, with frequent patch releases addressing bug fixes and performance improvements. An active pre-release series, such as 1.7.0-alpha.1, indicates continuous development and upcoming significant changes. HLS.js differentiates itself through its extensive feature set, including adaptive bitrate streaming, DVR support, low-latency HLS (LL-HLS), DRM (via EME), CEA-608/708 captions, WebVTT subtitles, and advertising insertion, making it a comprehensive solution for HLS playback in web applications.
Common errors
-
Uncaught ReferenceError: Hls is not defined
cause HLS.js was not properly imported or made globally available (e.g., when using a CDN script without a global `Hls` object, or incorrect module import).fixEnsure HLS.js is imported using `import Hls from 'hls.js';` in modern module environments, or that the library's UMD build is loaded via a `<script>` tag before it's referenced, making `Hls` available globally. -
HLS.js error: networkError - fatal: true - manifestLoadError
cause The HLS manifest (.m3u8 file) could not be retrieved or parsed due to an incorrect URL, network issues, CORS restrictions, or server configuration problems.fixVerify the manifest URL is correct and accessible. Check browser developer tools for network errors (404, 403, CORS issues) and server logs. Ensure the server is correctly configured to serve `.m3u8` files with appropriate MIME types and CORS headers. Load the manifest URL directly in a browser to confirm accessibility. -
Hls.js fatal error: keySystemError - keySystemNoKeys
cause This error indicates a problem with the Encrypted Media Extensions (EME) setup for DRM, specifically that no valid decryption keys were provided or could be obtained from the license server. This often occurs with FairPlay Streaming, PlayReady, or Widevine.fixReview your DRM configuration, license server URL, and key acquisition process. Ensure `keyDrmSystem` is correctly specified and that the license server is responding with valid decryption keys for the content. Check browser console for EME-specific errors. -
MediaSource is not supported
cause The browser or device does not support the Media Source Extensions (MSE) API, which HLS.js relies upon for playback. This is common on older browsers or some mobile Safari versions (which have native HLS support).fixImplement a fallback for browsers without MSE support. For iOS Safari, this typically means directly assigning the HLS manifest URL to the `<video src>` attribute, as Safari has native HLS support. For other unsupported browsers, display an error message or provide an alternative player. -
HLS.js error: mediaError - fatal: true - bufferStalledError
cause The video buffer has stalled, meaning HLS.js could not append new media segments fast enough, leading to playback interruption. This can be caused by network issues, slow servers, incorrect segment parsing, or excessive buffering limits.fixImplement error recovery mechanisms using `hls.recoverMediaError()` for `MEDIA_ERROR`. Check network conditions, server performance, and stream health. Adjust HLS.js configuration parameters related to buffering, such as `maxBufferLength` or `maxMaxBufferLength`, or `liveMaxLatencyDuration` for live streams.
Warnings
- breaking HLS.js v1.0.0 and above transitioned to an ESM-first architecture. Projects relying on CommonJS `require()` or older browser compatibility (e.g., Internet Explorer) will encounter breaking changes. This also affects how web workers are configured when using bundlers with ESM.
- gotcha Content Protection (DRM) setups, particularly for PlayReady and FairPlay Streaming, are complex and frequently involve specific platform requirements and manifest parsing nuances. Common issues include incorrect key ID handling or endianness problems, leading to 'keyId is null' errors or failed decryption.
- deprecated The `hls.currentLevel` property no longer pauses the media element by default when switching quality levels. This change can lead to stall errors if playback doesn't resume quickly enough after a level change, particularly in manual quality switching implementations.
- gotcha HLS.js cannot be instantiated or used in Node.js environments. Attempting to `require()` or `import` the library in Node.js will result in a dummy object being exported, and no HLS playback functionality will be available.
- breaking The `v1.7.0-alpha.x` releases introduce a number of significant changes that are likely to be breaking. These are not feature-complete and are intended for early testing and feedback.
Install
-
npm install hls.js -
yarn add hls.js -
pnpm add hls.js
Imports
- Hls
const Hls = require('hls.js');import Hls from 'hls.js';
- Hls.Events
import { Events } from 'hls.js';import Hls from 'hls.js'; hls.on(Hls.Events.MANIFEST_PARSED, handler);
- HlsConfig
import { HlsConfig } from 'hls.js';import type { HlsConfig } from 'hls.js';
Quickstart
import Hls from 'hls.js';
const video = document.getElementById('video') as HTMLVideoElement;
const manifestUrl = 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8';
if (Hls.isSupported()) {
const hls = new Hls({
// Example configuration for a live stream with limited back buffer
liveSyncDurationCount: 3,
liveMaxLatencyDuration: 10,
// workerPath: '/path/to/hls.worker.js' // Required if using ESM build with workers
});
hls.on(Hls.Events.MEDIA_ATTACHED, () => {
console.log('Media attached to video element.');
hls.loadSource(manifestUrl);
});
hls.on(Hls.Events.MANIFEST_PARSED, (event, data) => {
console.log(`Manifest loaded, found ${data.levels.length} quality level(s).`);
// Optionally set quality level, e.g., to the highest available
// hls.currentLevel = data.levels.length - 1;
video.play();
});
hls.on(Hls.Events.ERROR, (event, data) => {
if (data.fatal) {
console.error(`Hls.js fatal error: ${data.type} - ${data.details}`, data);
switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR:
console.error('Network error detected, trying to recover...');
hls.startLoad();
break;
case Hls.ErrorTypes.MEDIA_ERROR:
console.error('Media error detected, trying to recover...');
hls.recoverMediaError();
break;
default:
// Cannot recover
hls.destroy();
break;
}
}
});
hls.attachMedia(video);
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
// Native HLS support for Safari, etc.
video.src = manifestUrl;
video.addEventListener('loadedmetadata', () => {
video.play();
});
} else {
console.error('This browser does not support HLS playback.');
}