hls.js README

The project's README from github.com/video-dev/hls.js. As one markdown file: README.md.

npm npm Sauce Test Status jsDeliver inspect.software

HLS.js

HLS.js is a JavaScript library that implements an HTTP Live Streaming client. It relies on HTML5 video and MediaSource Extensions for playback.

It works by transmuxing MPEG-2 Transport Stream and AAC/MP3 streams into ISO BMFF (MP4) fragments. Transmuxing is performed asynchronously using a Web Worker when available in the browser. HLS.js also supports HLS + fmp4, as announced during WWDC2016.

HLS.js works directly on top of a standard HTML<video> element.

HLS.js is written in ECMAScript6 (*.js) and TypeScript (*.ts) (strongly typed superset of ES6), and transpiled in ECMAScript5 using Babel and the TypeScript compiler.

Rollup is used to build the distro bundle and serve the local development environment.

Features

Supported HLS tags

For details on the HLS format and these tags' meanings, see https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis

Multivariant Playlist tags

Media Playlist tags

Parsed but missing feature support:

Not Supported

For a complete list of issues, see "Top priorities" in the Release Planning and Backlog project tab. Codec support is dependent on the runtime environment (for example, not all browsers on the same OS support HEVC).

Server-side-rendering (SSR) and require from a Node.js runtime

You can safely require this library in Node and absolutely nothing will happen. A dummy object is exported so that requiring the library does not throw an error. HLS.js is not instantiable in Node.js. See #1841 for more details.

Getting started with development

Open in StackBlitz

First, checkout the repository and install the required dependencies

git clone https://github.com/video-dev/hls.js.git
cd hls.js
# After cloning or pulling from the repository, make sure all dependencies are up-to-date
npm install ci
# Run dev-server for demo page (recompiles on file-watch, but doesn't write to actual dist fs artifacts)
npm run dev
# After making changes run the sanity-check task to verify all checks before committing changes
npm run sanity-check

The dev server will host files on port 8000. Once started, the demo can be found running at http://localhost:8000/demo/.

Before submitting a PR, please see our contribution guidelines. Join the discussion on Slack via video-dev.org in #hlsjs for updates and questions about development.

Build tasks

Build all flavors (suitable for prod-mode/CI):

npm install ci
npm run build

Only debug-mode artifacts:

npm run build:debug

Build and watch (customized dev setups where you'll want to host through another server - for example in a sub-module/project)

npm run build:watch

Only specific flavors (known configs are: full, fullMin, fullEsm, fullEsmMin, light, lightMin, lightEsm, lightEsmMin, worker, demo):

npm run build -- --configType fullMin # repeat --configType to build more than one

Report the size of the built dist/ files, and check them against the budgets in dist-size-budget.json (the same check CI runs):

npm run size
npm run size:check

NOTE: hls.light.*.js dist files do not include alternate-audio, subtitles, CMCD, EME (DRM), Variable Substitution, Interstitials, I-frame trick-play, Media Capabilities, or MPEG-2 TS advanced codec (HEVC and AC-3) support. Content Steering is included. In addition, the following types are not available in the light build:

Linter (ESlint)

Run linter:

npm run lint

Run linter with auto-fix mode:

npm run lint:fix

Run linter with errors only (no warnings)

npm run lint:quiet

Formatting Code

Run prettier to format code

npm run prettier

Type Check

Run type-check to verify TypeScript types

npm run type-check

Automated tests (Mocha/Karma)

Run all tests at once:

npm test

Run unit tests:

npm run test:unit

Run unit tests in watch mode:

npm run test:unit:watch

Run functional (integration) tests:

npm run test:func

Design

An overview of this project's design, it's modules, events, and error handling can be found here.

API docs and usage guide

Note you can access the docs for a particular version using "https://github.com/video-dev/hls.js/tree/deployments"

Demo

Latest Release

https://hlsjs.video-dev.org/demo

Master

https://hlsjs-dev.video-dev.org/demo

Specific Version

Find the commit on https://github.com/video-dev/hls.js/tree/deployments.

This project is tested with BrowserStack. This project is tested with SauceLabs.

Compatibility

HLS.js is only compatible with browsers supporting MediaSource extensions (MSE) API with 'video/MP4' mime-type inputs.

HLS.js is supported on:

These versions are the targets passed to @babel/preset-env when building the UMD bundles in dist/. They share an ES2016 runtime baseline: ES5-style syntax plus native ES2016 globals (Map, Set, Promise, Array.from, Uint8Array.from, Array.prototype.includes, etc.). To keep bundle size small, no core-js polyfills are bundled.

Optional features such as CMCD pull in ES2017 APIs (e.g. Object.entries), so the full UMD bundle effectively requires an ES2017-capable runtime. The light bundle excludes those features and stays at the ES2016 baseline.

The dist/ folder ships two distribution variants:

The ESM builds do not bundle the transmuxer Web Worker. The UMD builds inline it, but dist/hls.mjs and dist/hls.min.mjs do not, so transmuxing runs on the main thread unless you point workerPath at the separately published worker:

const hls = new Hls({
  workerPath: 'https://cdn.jsdelivr.net/npm/hls.js@1/dist/hls.worker.js',
});

If you import from src/ directly or include any of our runtime dependencies untranspiled in your own build, you bypass this Babel pipeline and become responsible for transpilation; those source modules can reach for ES2019+ APIs that are tree-shaken out of the bundles we publish.

To run on browsers below this baseline, supply your own polyfills for any missing globals before HLS.js loads.

Please note:

Safari browsers (iOS, iPadOS, and macOS) have built-in HLS support through the plain video "tag" source URL. See the example below (Using HLS.js) to run appropriate feature detection and choose between using HLS.js or natively built-in HLS support.

When a platform has neither MediaSource nor native HLS support, the browser cannot play HLS.

Keep in mind that if the intention is to support HLS on multiple platforms, beyond those compatible with HLS.js, the HLS streams need to strictly follow the specifications of RFC8216, especially if apps, smart TVs, and set-top boxes are to be supported.

Find a support matrix of the MediaSource API here: https://developer.mozilla.org/en-US/docs/Web/API/MediaSource

Using HLS.js

Installation

Prepackaged builds are included with each release. Or install the hls.js as a dependency of your project:

npm install --save hls.js

A canary channel is also available if you prefer to work off the development branch (master):

npm install hls.js@canary

Embedding HLS.js

Directly include dist/hls.js or dist/hls.min.js in a script tag on the page. This setup prioritizes HLS.js MSE playback over native browser support for HLS playback in HTMLMediaElements:

<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<!-- Or if you want the latest version from the main branch -->
<!-- <script src="https://cdn.jsdelivr.net/npm/hls.js@canary"></script> -->
<video id="video"></video>
<script>
  var video = document.getElementById('video');
  var videoSrc = 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8';
  if (Hls.isSupported()) {
    var hls = new Hls();
    hls.loadSource(videoSrc);
    hls.attachMedia(video);
  }
  // HLS.js is not supported on platforms that do not have Media Source
  // Extensions (MSE) enabled.
  //
  // When the browser has built-in HLS support (check using `canPlayType`),
  // we can provide an HLS manifest (i.e. .m3u8 URL) directly to the video
  // element through the `src` property. This is using the built-in support
  // of the plain video element, without using HLS.js.
  else if (video.canPlayType('application/vnd.apple.mpegurl')) {
    video.src = videoSrc;
  }
</script>

Alternative setup

To check for native browser support first and then fallback to HLS.js, swap these conditionals.

Note: video.canPlayType('application/vnd.apple.mpegurl') returns a non-empty string ("maybe") in Safari, Chrome, and potentially other browsers. However, not all browsers support HLS content equally — for example, Chrome 147 reports support but may fail to play certain streams natively. Using Hls.isSupported() first (the default setup above) is recommended unless you specifically need native playback.

<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<!-- Or if you want the latest version from the main branch -->
<!-- <script src="https://cdn.jsdelivr.net/npm/hls.js@canary"></script> -->
<video id="video"></video>
<script>
  var video = document.getElementById('video');
  var videoSrc = 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8';
  //
  // Only use native HLS in browsers with ManagedMediaSource (e.g. modern Safari)
  // where native playback is well-supported. Other browsers may report HLS support
  // via canPlayType but fail to play certain streams reliably.
  //
  if (
    video.canPlayType('application/vnd.apple.mpegurl') &&
    'ManagedMediaSource' in window
  ) {
    video.src = videoSrc;
    //
    // If not using native HLS, check if HLS.js is supported
    //
  } else if (Hls.isSupported()) {
    var hls = new Hls();
    hls.loadSource(videoSrc);
    hls.attachMedia(video);
  }
</script>

Ensure correct time in video

HLS transcoding of an original video file often pushes the time of the first frame a bit. If you depend on having an exact match of frame times between original video and HLS stream, you need to account for this:

let tOffset = 0;
const getAppendedOffset = (eventName, { frag }) => {
  if (frag.type === 'main' && frag.sn !== 'initSegment' && frag.elementaryStreams.video) {
    const { start, startDTS, startPTS, maxStartPTS, elementaryStreams } = frag;
    tOffset = elementaryStreams.video.startPTS - start;
    hls.off(Hls.Events.BUFFER_APPENDED, getAppendedOffset);
    console.log('video timestamp offset:', tOffset, { start, startDTS, startPTS, maxStartPTS, elementaryStreams });
  }
}
hls.on(Hls.Events.BUFFER_APPENDED, getAppendedOffset);
// and account for this offset, for example like this:
const video = document.querySelector('video');
video.addEventListener('timeupdate', () => setTime(Math.max(0, video.currentTime - tOffset))
const seek = (t) => video.currentTime = t + tOffset;
const getDuration = () => video.duration - tOffset;

For more embed and API examples see docs/API.md.

CORS

All HLS resources must be delivered with CORS headers permitting GET requests.

Video Control

Video is controlled through HTML <video> element HTMLVideoElement methods, events and optional UI controls (<video controls>).

Build a Custom UI

Player Integration

The following players integrate HLS.js for HLS playback:

They use HLS.js in production!

cdn77

Chrome/Firefox integration

made by gramk, plays hls from address bar and m3u8 links

License

HLS.js is released under Apache 2.0 License

hls.js (video-dev/hls.js)

video-streaming
Searching Database…

17K ·GitHub
What is this?A JavaScript library that plays HLS (HTTP Live Streaming) video directly in the browser. It relies on HTML5 video and Media Source Extensions, transmuxing MPEG-2 TS and AAC/MP3 streams into MP4 fragments asynchronously in a Web Worker.
Is this a ready-made player app or a library I build on?A library, not a player app: it works on top of a standard HTML5 video element and ships no UI of its own. You control playback through regular HTMLVideoElement methods, or use one of the players that integrate it.
How do I add it to my web page?Install it from npm as hls.js or embed dist/hls.min.js with a script tag, then attach it to a video element and hand it your playlist URL. UMD and ESM bundles ship in dist/, and docs/API.md has embed examples.
Do I need anything special on the server for streams to play?No backend component is needed — playback runs fully in the browser — but every HLS resource must be served with CORS headers permitting GET requests, or playback will fail.
Can it play DRM-protected streams?Yes, through Encrypted Media Extensions: FairPlay, PlayReady and Widevine CDMs with fMP4 segments, plus AES-128/AES-256 decryption. MPEG-2 TS segments with those DRMs are not supported, and ClearKey support is incomplete.
Which browsers can it play in?Any browser with Media Source Extensions: Chrome 47+, Firefox 51+, Edge on Windows 10+, Safari 10+ on macOS 10.11+, iPadOS 13+, and iOS 17.1+ (Managed Media Source, since v1.5.0), plus Chrome and Firefox on Android.
Does it handle live streams or only on-demand video?Both. It supports VOD and live playlists with DVR, plus Low-Latency HLS (partial segments, blocking playlist reload, delta updates) and adaptive quality switching with manual and auto modes that switch down when bandwidth suddenly drops.
Which codecs and containers does it work with?MPEG-2 TS and fragmented MP4 containers; H.264/H.265 video plus HEVC, AV1, VP9 and Dolby Vision where the browser supports them; AAC, MP3, AC-3, FLAC, Opus and ALAC audio, also subject to runtime support.
What is the difference between the full and light builds?The light build drops alternate audio, subtitles, CMCD, EME/DRM, variable substitution, interstitials, I-frame trick-play and MPEG-2 TS advanced codecs (HEVC, AC-3) to stay small. Content Steering is still included in it.
Can I use it in Node.js or with server-side rendering?You can safely require it in Node — a dummy object is exported so nothing throws — but it is not instantiable there. It is strictly a browser library.
Creator
video-dev
Size
244 MB
Stars
17K
Age
11y
Commits · 90 Days