@streamiq/hls
v1.1.0
Published
HLS playback adapter for Streamq (lazy hls.js, Safari native fallback).
Downloads
280
Maintainers
Readme
@streamiq/hls
HLS playback adapter for Streamq — lazy hls.js (MSE), Safari native HLS fallback, normalized events on @streamiq/core.
Stable
1.0.x. Peers:@streamiq/core. Runtime workspace dep:@streamiq/shared.
Install
npm install @streamiq/core @streamiq/hlsUsage
import { Player } from '@streamiq/core';
import { createHlsPlaybackAdapter } from '@streamiq/hls';
const player = new Player({
target: videoElement,
createPlaybackAdapter: createHlsPlaybackAdapter,
});
player.on('qualitieschange', ({ levels }) => {
console.log('renditions', levels);
});
await player.load('https://example.com/master.m3u8');
await player.play();With React:
import { createHlsPlaybackAdapter } from '@streamiq/hls';
import { StreamqProvider, PlayerRoot, Video } from '@streamiq/react';
<StreamqProvider options={{ createPlaybackAdapter: createHlsPlaybackAdapter }}>
<PlayerRoot><Video /></PlayerRoot>
</StreamqProvider>Architecture
@streamiq/hls/src
├── createHlsPlaybackAdapter.ts Public factories (standard + LL-HLS)
├── HlsAdapter.ts PlaybackAdapter implementation
├── loadHlsJs.ts Dynamic import('hls.js') — never eager
├── safariNativeHlsQuality.ts Native-HLS quality synthesis
├── buildHlsQualities.ts Level list → QualitiesSnapshot
├── buildHlsAudioTracks.ts Media-group → AudioTracksSnapshot
├── buildHlsTextTracks.ts Subtitle discovery
├── hlsLivePlayback.ts isLive / latency / DVR / seek-to-live
├── hlsSubtitleConfig.ts HLS_DISABLE_NATIVE_SUBTITLES_CONFIG
├── hlsSubtitleHydration.ts Fragment WebVTT → core TextTrackManager
├── mapHlsParsedCues.ts hls.js cue → core TextCue
├── hlsDrmConfig.ts Generic DrmConfig → hls.js drm config
├── lowLatency.ts buildHlsLowLatencyConfig
├── validateLowLatencyHlsSetup.ts Manifest + policy validation
└── mapHlsError.ts hls.js fatal/recoverable → typed errorsEngine loading
| Behavior | Detail |
|----------|--------|
| Lazy hls.js | import('hls.js') at runtime — not in initial bundle |
| Safari native HLS | Falls back to <video src=...> when MSE / hls.js unavailable (typical iOS Safari) |
| Progressive fallback | Non-HLS URLs delegate to core's NativeAdapter |
Pipeline
manifest URL
│
▼
HlsAdapter.load()
├─ chooseEngine() ──► hls.js (MSE) or Safari native HLS
│ │
│ ▼
│ hls.js events → buildHls{Qualities,AudioTracks,TextTracks}
│ ──► PlayerEvents (qualitieschange, audiotrackschange,
│ texttrackdiscovery, …)
│ hls.js fragment WebVTT → hlsSubtitleHydration
│ ──► core TextTrackManager + CueSynchronizer
│ hls.js error → mapHlsError → PlaybackError | NetworkError | DRMError
│
└─ live ──► hlsAdapterIsLive / hlsAdapterGetLiveLatency / hlsAdapterSeekToLiveUI and hooks must not import hls.js directly — only the adapter knows the engine.
Features
Adapter factories
| Export | Description |
|--------|-------------|
| createHlsPlaybackAdapter | Standard HLS factory for PlayerOptions.createPlaybackAdapter |
| createLowLatencyHlsPlaybackAdapter | LL-HLS tuned factory |
| HLS_ADAPTER_ID | 'hls' — adapter identifier |
Qualities (ABR)
| Path | Behavior |
|------|----------|
| MSE (hls.js) | Full level list; selectQuality('auto' \| levelId) |
| Native HLS | One observed level; capabilities.manualSelection: false |
| Custom native | HlsAdapterOptions.nativeQualities, onNativeSelectQuality |
UI guard: hide manual quality menus when player.qualities.capabilities?.mode === 'native-hls'.
| Export | Purpose |
|--------|---------|
| buildSafariNativeHlsQualities | Snapshot for native path |
| SAFARI_NATIVE_HLS_CAPABILITIES | Constant capabilities for UI |
| NativeHlsQualitiesHandler, NativeHlsSelectQualityHandler | Custom integration types |
Audio tracks
Multi-rendition audio from HLS media groups → normalized audiotrackschange events.
Subtitles
| Feature | Detail |
|---------|--------|
| Discovery | texttrackdiscovery with normalized TextTrack list |
| Fragment hydration | WebVTT from HLS fragments → texttrackcuesupdate |
| Cue pruning | texttrackcuesprune on source change |
| Native captions disabled | HLS_DISABLE_NATIVE_SUBTITLES_CONFIG — headless cue pipeline |
Live streaming
| Export | Description |
|--------|-------------|
| hlsAdapterIsLive | Live presentation check |
| hlsAdapterGetLiveLatency | Latency seconds |
| hlsAdapterGetLiveSeekableRange | DVR window |
| hlsAdapterSeekToLive | Seek to live edge |
| HlsLiveLike | Type for swappable live source |
Low latency (LL-HLS)
import { createLowLatencyHlsPlaybackAdapter } from '@streamiq/hls';
import { DEFAULT_LOW_LATENCY_PLAYBACK_POLICY } from '@streamiq/shared';
new Player({
target: video,
createPlaybackAdapter: createLowLatencyHlsPlaybackAdapter(
DEFAULT_LOW_LATENCY_PLAYBACK_POLICY,
),
});| Export | Role |
|--------|------|
| buildHlsLowLatencyConfig | hls.js LL config builder |
| validateLowLatencyHlsSetup | Manifest + policy validation |
Validators come from @streamiq/shared.
Error mapping
HLS fatal / recoverable errors → PlaybackError / NetworkError / DRMError on the player bus (mapHlsError).
Public exports
| Category | Key exports |
|----------|-------------|
| Factory | createHlsPlaybackAdapter, createLowLatencyHlsPlaybackAdapter, HLS_ADAPTER_ID |
| Adapter | HlsAdapter, HlsAdapterOptions |
| Live | hlsAdapterIsLive, hlsAdapterGetLiveLatency, hlsAdapterGetLiveSeekableRange, hlsAdapterSeekToLive, HlsLiveLike |
| LL-HLS | buildHlsLowLatencyConfig, validateLowLatencyHlsSetup, ValidateLowLatencyHlsOptions |
| Safari | buildSafariNativeHlsQualities, SAFARI_NATIVE_HLS_CAPABILITIES, native handler types |
| Config | HLS_DISABLE_NATIVE_SUBTITLES_CONFIG |
Events normalized to core
| Engine fact | Player event |
|-------------|--------------|
| Level list / switch | qualitieschange |
| Audio group change | audiotrackschange |
| Subtitle tracks / cues | texttrackdiscovery, texttrackcuesupdate, cuechange |
| Buffering | buffering |
| Errors | error |
Bundle size
| Budget | Limit |
|--------|-------|
| Adapter wrapper (hls.js external) | 3 kB gzipped |
| { HLS_ADAPTER_ID } tree-shake | 50 B |
Dependencies
| | |
|-|-|
| Runtime | @streamiq/shared, hls.js ^1.6 |
| Peer | @streamiq/core ^1.0 |
License
MIT
