Quick start
Install the package, import one function, call it on your dash.js player.
$ npm install @hevcjs/dashjs-plugin dashjs
import dashjs from 'dashjs';
import { attachHevcSupport } from '@hevcjs/dashjs-plugin';
const video = document.querySelector('video');
const player = dashjs.MediaPlayer().create();
// One line — that's it
attachHevcSupport(player);
player.initialize(video, 'https://example.com/stream/manifest.mpd', true);
How it works
The plugin intercepts the MSE pipeline. The player never knows HEVC was involved.
MediaSource.isTypeSupported()
— returns true for HEVC codecs (hev1/hvc1)
navigator.mediaCapabilities.decodingInfo()
— same, for dash.js 4.x+
addSourceBuffer()
— creates an H.264 SourceBuffer and returns a Proxy
appendBuffer()
— demux, decode HEVC (WASM), encode H.264 (WebCodecs), mux fMP4, append to real SourceBuffer
updating state management
— the proxy reports updating = true during transcoding, so dash.js waits between segments
Browser compatibility
~94% of browsers play HEVC natively (hardware decode). hevc.js activates only for the ~6% that don't.
| Browser | Native HEVC | hevc.js needed? | Transcoding works? |
|---|---|---|---|
| Safari 13+ | Yes (hardware) | No — bypassed | — |
| Chrome/Edge 107+ (Win/Mac) | Yes (hardware GPU) | No — bypassed | — |
| Chrome 94-106 (all) | No | Yes | Yes (WebCodecs H.264) |
| Chrome < 94 | No | Yes | No (no WebCodecs) — falls back to AVC |
| Firefox 137+ (Win) | Partial (hardware) | No — bypassed | — |
| Firefox (Linux, older) | No | Yes | No — H.264 encoding broken |
| Linux Chrome (no VAAPI) | No | Yes | Yes (software encode) |
Other requirements (supported by all modern browsers):
API reference
One function to set up, one function to tear down.
attachHevcSupport(player, config?)
Patches the browser APIs and registers the dash.js capabilities filter.
Returns a cleanup() function that reverses all patches.
const cleanup = attachHevcSupport(player, {
workerUrl: '/transcode-worker.js', // Web Worker URL
wasmUrl: '/hevc-decode.js', // WASM glue location
fps: 25, // Target framerate
bitrate: 4_000_000, // H.264 encode bitrate
});
// Remove all patches when done
cleanup();
Options
workerUrl
string
URL of the Web Worker script for off-main-thread transcoding. If omitted, transcoding runs on the main thread.
wasmUrl
string
Path to the WASM glue JS file. Auto-detected from the package if omitted.
fps
number
default: 25
Target framerate for H.264 encoding. Should match the source stream.
bitrate
number
H.264 encode bitrate in bits/second. If omitted, WebCodecs chooses automatically.
Lower-level API
For advanced use cases — manual MSE patching or direct transcoding without dash.js.
import { installMSEIntercept, uninstallMSEIntercept }
from '@hevcjs/dashjs-plugin';
import { SegmentTranscoder }
from '@hevcjs/dashjs-plugin';
// Manual MSE patching (without dash.js)
installMSEIntercept({ wasmUrl: '/hevc-decode.js' });
// Or use the transcoder directly
const transcoder = new SegmentTranscoder({ fps: 25 });
await transcoder.init();
await transcoder.processInitSegment(initSegmentBytes);
const h264Segment = await transcoder.processMediaSegment(mediaSegmentBytes);
Performance
Real numbers from a single-threaded WebAssembly decoder.
FAQ
Does it work with live streams?
Yes. The plugin intercepts segments as they arrive, so live (low-latency) and VOD streams both work. The only difference is that the first segment takes 2-3 seconds to transcode, which adds to the initial live edge latency.
What happens when native HEVC is available?
Nothing. The plugin checks for native HEVC support at startup. If the browser can play HEVC natively (Safari, Chrome 107+ on Windows/Mac), the plugin does not patch anything and the WASM decoder is never loaded. Zero overhead.
Do I need special server headers?
No. The WASM decoder is single-threaded and does not use SharedArrayBuffer, so no Cross-Origin-Embedder-Policy or Cross-Origin-Opener-Policy headers are needed. It works on any static file server with HTTPS.
What about HLS?
There is no hls.js plugin at this time. The MSE intercept pattern works the same way, but hls.js support has not been implemented yet. Only dash.js is supported via @hevcjs/dashjs-plugin.