@streamiq/dash
v1.1.0
Published
DASH playback adapter for Streamq (lazy shaka-player).
Downloads
309
Maintainers
Readme
@streamiq/dash
MPEG-DASH playback adapter for Streamq — lazy shaka-player, multi-DRM bridge, capturing text displayer for headless subtitles, normalized events on @streamiq/core.
Stable
1.0.x. Peer:@streamiq/core. Runtime workspace dep:@streamiq/shared.
Install
npm install @streamiq/core @streamiq/dashUsage
import { Player } from '@streamiq/core';
import { createDashPlaybackAdapter } from '@streamiq/dash';
const player = new Player({
target: videoElement,
createPlaybackAdapter: createDashPlaybackAdapter,
});
await player.load('https://example.com/manifest.mpd');
await player.play();With React:
import { createDashPlaybackAdapter } from '@streamiq/dash';
import { StreamqProvider, PlayerRoot, Video } from '@streamiq/react';
<StreamqProvider options={{ createPlaybackAdapter: createDashPlaybackAdapter }}>
<PlayerRoot><Video /></PlayerRoot>
</StreamqProvider>Architecture
@streamiq/dash/src
├── createDashPlaybackAdapter.ts Public factories (standard + LL-DASH)
├── ShakaDashAdapter.ts PlaybackAdapter implementation
├── shakaPolyfills.ts ensureShakaPolyfills (gated)
│
├── buildShakaQualities.ts Variants → QualitiesSnapshot
├── shakaQualitiesControl.ts apply / persisted / ABR toggle
├── shakaQualityPreference.ts Session preference store
│
├── buildShakaAudioTracks.ts Audio tracks snapshot
├── shakaAudioTracksControl.ts apply / persisted
├── shakaAudioPreference.ts Session preference store
│
├── buildShakaTextTracks.ts Text track discovery
├── shakaTextTracksControl.ts apply / disable / read active
├── ShakaCapturingTextDisplayer.ts Captures Shaka cues (no DOM render)
├── shakaSubtitleConfig.ts Builds Shaka player config for subtitles
├── mapShakaCues.ts Shaka cue → core TextCue
├── parseTtmlXml.ts TTML support
│
├── shakaLivePlayback.ts isLive / latency / DVR / seek-to-live
├── shakaLowLatency.ts Apply policy to Shaka
├── validateLowLatencyDashSetup.ts Manifest + policy validation
│
├── shakaDrmConfig.ts buildShakaPlayerDrmConfig / applyShakaDrmConfig
├── drmMediaRegistry.ts Per-element DRM registry (Shaka layer)
├── shakaKeySystems.ts SHAKA_WIDEVINE_KEY_SYSTEM, …
│
└── mapShakaError.ts Shaka error → typed errorEngine loading
| Behavior | Detail |
|----------|--------|
| Lazy Shaka | import('shaka-player') at runtime |
| Polyfills on demand | ensureShakaPolyfills runs only when adapter is used |
| Progressive fallback | Non-DASH URLs delegate to core NativeAdapter |
Pipeline
manifest URL
│
▼
ShakaDashAdapter.load()
├─ ensureShakaPolyfills()
├─ import('shaka-player')
├─ apply DRM config (from generic DrmConfig + ShakaDrmConfig registry)
├─ install ShakaCapturingTextDisplayer (intercepts cues — Shaka doesn't render)
│
│ Shaka events
│ ├─ trackschanged → buildShaka{Qualities,AudioTracks,TextTracks}
│ ├─ adaptation → qualitieschange (auto)
│ ├─ buffering → buffering
│ ├─ text cues → mapShakaTextCues → core TextTrackManager
│ └─ error → mapShakaError → typed error
│
├─ live ──► shakaAdapterIsLive / shakaAdapterGetLiveLatency / shakaAdapterSeekToLive
└─ on trackschanged ──► applyPersisted{Quality,Audio} (from preference stores)Features
Adapter factories
| Export | Description |
|--------|-------------|
| createDashPlaybackAdapter | Standard DASH factory |
| createLowLatencyDashPlaybackAdapter | LL-DASH tuned factory |
| DASH_ADAPTER_ID | 'dash' |
| ShakaDashAdapter, ShakaDashAdapterOptions | Direct adapter access |
Qualities & ABR
| Feature | Detail |
|---------|--------|
| Level discovery | Variant tracks → qualitieschange |
| Manual selection | selectQuality('auto' \| id) |
| ABR toggle | setShakaAbrEnabled, isShakaAbrEnabled |
| Persistence | initialPreferredQualityId re-applied on trackschanged |
| Export | Role |
|--------|------|
| buildShakaQualitiesSnapshot | Build snapshot from Shaka tracks |
| findActiveVariantTrack | Resolve current variant |
| pickRepresentativeVariantTracks | Collapse variants per resolution |
| resolveShakaQualitySelection | Resolve user selection |
| ShakaQualityPreferenceStore | Session preference |
| applyShakaQualitySelection, applyPersistedShakaQuality | Apply to player |
Audio tracks
| Feature | Detail |
|---------|--------|
| Discovery | audiotrackschange |
| Selection | selectAudioTrack(id) |
| Persistence | initialPreferredAudioTrackId |
| Export | Role |
|--------|------|
| buildShakaAudioTracksSnapshot | Snapshot builder |
| resolveShakaAudioTrack, shakaAudioTrackId | Stable id helpers |
| ShakaAudioPreferenceStore | Session preference |
| applyShakaAudioSelection, applyPersistedShakaAudio | Apply to player |
Subtitles (WebVTT / TTML)
Headless pipeline — Shaka does not render captions to DOM. The capturing text displayer intercepts cues into core's TextTrackManager.
| Export | Role |
|--------|------|
| buildShakaTextTrackDiscovery | Track list from Shaka |
| resolveShakaTextTrackById | Track lookup by id |
| applyShakaTextTrackSelection | Select active text track |
| disableShakaTextTracks | Turn captions off |
| readActiveShakaTextTrackId | Read currently active id |
| ShakaCapturingTextDisplayer (+ factory) | Capture cues into core pipeline |
| buildShakaSubtitlePlayerConfig | Subtitle config builder |
| mapShakaTextCues | Cue normalization |
| parseTtmlXml | TTML support |
DRM
Multi-key-system support that flows through core's generic DRM types.
import { setShakaDrmConfigForMedia } from '@streamiq/dash';
setShakaDrmConfigForMedia(mediaElement, {
'com.widevine.alpha': {
licenseUrl: 'https://license.example/wv',
headers: { Authorization: 'Bearer short-lived-token' },
},
});| Export | Role |
|--------|------|
| setShakaDrmConfigForMedia / getShakaDrmConfigForMedia | Per-element DRM registry |
| setDrmLicenseServersForMedia / getDrmLicenseServersForMedia | License server map |
| setPendingDrmCertFetch / awaitPendingDrmCertFetch / clearPendingDrmCertFetch | Cert preflight coordination |
| applyShakaDrmConfig, buildShakaPlayerDrmConfig | Apply to Shaka player |
| SHAKA_WIDEVINE_KEY_SYSTEM, SHAKA_FAIRPLAY_KEY_SYSTEM, SHAKA_PLAYREADY_KEY_SYSTEM | Constants |
| ShakaDrmConfig, ShakaDrmKeySystemConfig, ShakaDrmRequest, ShakaDrmResponse, ShakaDrmRequestFilter, ShakaDrmResponseFilter | Types |
For higher-level OEM-shaped configuration, use @streamiq/plugin-drm.
Live streaming
| Export | Description |
|--------|-------------|
| shakaAdapterIsLive | Live check |
| shakaAdapterGetLiveLatency | Latency seconds |
| shakaAdapterGetLiveSeekableRange | DVR range |
| shakaAdapterSeekToLive | Seek to edge |
| ShakaPlayerLiveLike | Type for swappable live source |
Low latency (LL-DASH)
import { createLowLatencyDashPlaybackAdapter } from '@streamiq/dash';
import { DEFAULT_LOW_LATENCY_PLAYBACK_POLICY } from '@streamiq/shared';
new Player({
target: video,
createPlaybackAdapter: createLowLatencyDashPlaybackAdapter(
DEFAULT_LOW_LATENCY_PLAYBACK_POLICY,
),
});| Export | Role |
|--------|------|
| applyShakaLowLatencyPlaybackPolicy | Apply policy to Shaka |
| validateLowLatencyDashSetup | Manifest validation |
| expectedShakaLowLatencyGoals | Target latency goals |
Polyfills & internals
| Export | Role |
|--------|------|
| ensureShakaPolyfills | Gated runtime polyfill install |
| _resetShakaPolyfillsForTest | Test-only |
| mapShakaError | Shaka error → typed error |
Events normalized to core
Same contract as HLS — UI never branches on Shaka APIs.
Bundle size
| Budget | Limit | Notes |
|--------|-------|-------|
| Adapter wrapper | 12 kB gzipped | shaka-player external |
| { DASH_ADAPTER_ID } | 50 B | Tree-shake probe |
Dependencies
| | |
|-|-|
| Runtime | @streamiq/shared, shaka-player ^5.1 |
| Peer | @streamiq/core ^1.0 |
License
MIT
