HLS
The video player uses hls.js for HLS playback.
The player core’s stream adapter wraps hls.js behind the IVideoBackend interface.
HDR-aware ABR is automatic.
How hls.js is wired in
hls.js installs automatically with the player (a direct dependency of the player package) — nothing extra to install for the npm / bundler path. See Installation for the CDN exception.
The build output marks hls.js as external so it is not inlined into the player’s own dist bundle.
At runtime the player loads it via a dynamic import on first HLS source, so it stays out of your initial bundle until you actually play .m3u8.
On Safari / iOS, native HLS is used and hls.js is never instantiated.
For the CDN / IIFE path (no bundler), the IIFE bundle expects Hls as a global, so load hls.js via a separate <script> before the player script.
See Quick Start: CDN embed.
Adaptive bitrate (ABR)
ABR is on by default. hls.js selects quality levels automatically based on estimated bandwidth.
player.setup({
defaultQuality: 'auto', // default, ABR active
});
Lock to a specific quality level (index into qualityLevels()):
player.quality(2); // lock to level index 2
player.quality('auto'); // back to adaptive (ABR)
Listen for level changes:
player.on('level-switched', ({ level }) => {
console.log(`Switched to quality level ${level}`);
});
player.on('levels', ({ levels }) => {
// levels becomes available after the HLS manifest is parsed
levels.forEach((level, idx) => {
console.log(`Level ${idx}: ${level.width}x${level.height} @ ${level.bitrate} bps`);
});
});
HDR-aware ABR
On SDR displays, the player filters HDR levels out of the ABR selection pool. hls.js will not automatically promote to an HDR level when the display cannot render it.
Display-HDR detection uses matchMedia('(dynamic-range: high)').
No configuration is required.
On HDR-capable displays, all levels are eligible.
Multi-monitor handling: when a player window moves across displays (e.g. from an HDR monitor to an SDR one), the player re-evaluates display capabilities and constrains the ABR pool accordingly.
The re-evaluation runs on the matchMedia('(dynamic-range: high)') change event.
Quality level shape
player.qualityLevels() returns QualityLevel[]:
interface QualityLevel {
bitrate: number; // stream bitrate in bits per second
height?: number; // encoded height in px, if known
width?: number; // encoded width in px, if known
label: string; // human-readable (e.g. '1080p')
index: number; // zero-based level index; pass to quality(idx)
supported?: boolean; // set when qualityLevels({ includeUnsupported: true })
dynamicRange?: 'sdr' | 'hdr'; // 'hdr' for PQ/HLG streams, 'sdr' otherwise
}
Auth on HLS segments
The player’s auth pipeline injects Authorization: Bearer <token> on every HLS manifest and segment request.
No hls.js config needed, the IVideoBackend intercepts requests before they reach hls.js.
See Core, Auth and Fetch for the full auth pipeline.
Stream registration
The player ships an HLS stream factory and a native stream factory. The stream registry picks the right one based on the URL and browser capabilities:
.m3u8URLs → HLS stream via hls.js- Other URLs → native
<video>src
Register additional stream types:
import { myDashStreamFactory } from './dash-adapter';
player.registerStream(myDashStreamFactory); // registered at highest priority
player.streams(); // ['dash', 'hls', 'native']
// (pass `true` to register at LOWEST priority instead, behind the built-ins)
Custom backend
For full control over the <video> element or for non-standard streaming protocols:
import type { IVideoBackend, VideoPlayerConfig } from '@nomercy-entertainment/nomercy-video-player';
import type { BasePlaylistItem } from '@nomercy-entertainment/nomercy-player-core';
class MyBackend implements IVideoBackend {
constructor(_config: VideoPlayerConfig<BasePlaylistItem>) {
// ... receive config
}
// ... implement the interface
}
player.setup({
backendFactory: (kind, config) => new MyBackend(config),
});
Low-latency HLS and custom hls.js config
The built-in Html5VideoBackend creates its hls.js instance internally and does not currently expose a hook for custom hls.js config — lowLatencyMode is off and cannot be toggled through the player config. Customizing hls.js settings (including LL-HLS) requires supplying your own backend via backendFactory that owns its Hls instance and implements IVideoBackend. See the Video Backend adapter for the contract.