@videojs/spf 10.0.0-beta.22 → 10.0.0-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{dev/core → default/core/actors}/create-machine-actor.js +3 -3
- package/dist/default/core/actors/create-machine-actor.js.map +1 -0
- package/dist/default/core/{create-transition-actor.js → actors/create-transition-actor.js} +3 -3
- package/dist/default/core/actors/create-transition-actor.js.map +1 -0
- package/dist/default/core/composition/create-composition.js +85 -0
- package/dist/default/core/composition/create-composition.js.map +1 -0
- package/dist/default/core/composition/share-signals.js +37 -0
- package/dist/default/core/composition/share-signals.js.map +1 -0
- package/dist/{dev/core → default/core/reactors}/create-machine-reactor.js +4 -4
- package/dist/default/core/reactors/create-machine-reactor.js.map +1 -0
- package/dist/default/core/signals/primitives.js +33 -11
- package/dist/default/core/signals/primitives.js.map +1 -1
- package/dist/default/core/{task.js → tasks/task.js} +2 -2
- package/dist/default/core/tasks/task.js.map +1 -0
- package/dist/default/dom.js +9 -10
- package/dist/default/hls.js +3 -0
- package/dist/default/index.js +12 -3
- package/dist/default/index.js.map +1 -1
- package/dist/default/media/abr/quality-selection.js +83 -0
- package/dist/default/media/abr/quality-selection.js.map +1 -0
- package/dist/default/{core → media}/buffer/back-buffer.js +2 -2
- package/dist/default/media/buffer/back-buffer.js.map +1 -0
- package/dist/{dev/core → default/media}/buffer/forward-buffer.js +14 -2
- package/dist/default/media/buffer/forward-buffer.js.map +1 -0
- package/dist/{dev/dom/media → default/media/dom/mse}/append-segment.js +1 -1
- package/dist/default/media/dom/mse/append-segment.js.map +1 -0
- package/dist/default/{dom/media → media/dom/mse}/buffer-flusher.js +1 -1
- package/dist/default/media/dom/mse/buffer-flusher.js.map +1 -0
- package/dist/default/media/dom/mse/duration.js +78 -0
- package/dist/default/media/dom/mse/duration.js.map +1 -0
- package/dist/default/media/dom/mse/end-of-stream.js +20 -0
- package/dist/default/media/dom/mse/end-of-stream.js.map +1 -0
- package/dist/default/{dom/media → media/dom/mse}/mediasource-setup.js +63 -18
- package/dist/default/media/dom/mse/mediasource-setup.js.map +1 -0
- package/dist/default/{dom/text/parse-vtt-segment.js → media/dom/text/resolve-vtt-segment.js} +5 -5
- package/dist/default/media/dom/text/resolve-vtt-segment.js.map +1 -0
- package/dist/default/media/dom/text/text-track-slots.js +69 -0
- package/dist/default/media/dom/text/text-track-slots.js.map +1 -0
- package/dist/{dev/core → default/media}/hls/parse-attributes.js +1 -1
- package/dist/default/media/hls/parse-attributes.js.map +1 -0
- package/dist/{dev/core → default/media}/hls/parse-media-playlist.js +1 -1
- package/dist/default/media/hls/parse-media-playlist.js.map +1 -0
- package/dist/{dev/core → default/media}/hls/parse-multivariant.js +2 -2
- package/dist/default/media/hls/parse-multivariant.js.map +1 -0
- package/dist/default/{core → media}/hls/resolve-url.js +1 -1
- package/dist/default/media/hls/resolve-url.js.map +1 -0
- package/dist/default/media/primitives/select-tracks.js +45 -0
- package/dist/default/media/primitives/select-tracks.js.map +1 -0
- package/dist/default/media/types/index.js +36 -0
- package/dist/default/media/types/index.js.map +1 -0
- package/dist/default/media/utils/preload.js +22 -0
- package/dist/default/media/utils/preload.js.map +1 -0
- package/dist/default/media/utils/track-selection.js +47 -0
- package/dist/default/media/utils/track-selection.js.map +1 -0
- package/dist/default/media/utils/tracks.js +103 -0
- package/dist/default/media/utils/tracks.js.map +1 -0
- package/dist/default/{core/abr → network}/bandwidth-estimator.js +6 -5
- package/dist/default/network/bandwidth-estimator.js.map +1 -0
- package/dist/{dev/dom → default}/network/chunked-stream-iterable.js +1 -1
- package/dist/default/network/chunked-stream-iterable.js.map +1 -0
- package/dist/{dev/core/abr → default/network}/ewma.js +1 -1
- package/dist/default/network/ewma.js.map +1 -0
- package/dist/default/network/fetch.js +109 -0
- package/dist/default/network/fetch.js.map +1 -0
- package/dist/{dev/dom/features/segment-loader-actor.js → default/playback/actors/dom/segment-loader.js} +24 -15
- package/dist/default/playback/actors/dom/segment-loader.js.map +1 -0
- package/dist/{dev/dom/media/source-buffer-actor.js → default/playback/actors/dom/source-buffer.js} +8 -8
- package/dist/default/playback/actors/dom/source-buffer.js.map +1 -0
- package/dist/{dev/dom/features/text-tracks-actor.js → default/playback/actors/dom/text-tracks.js} +7 -3
- package/dist/default/playback/actors/dom/text-tracks.js.map +1 -0
- package/dist/default/playback/actors/text-track-segment-loader.js +135 -0
- package/dist/default/playback/actors/text-track-segment-loader.js.map +1 -0
- package/dist/default/playback/behaviors/calculate-presentation-duration.js +58 -0
- package/dist/default/playback/behaviors/calculate-presentation-duration.js.map +1 -0
- package/dist/default/playback/behaviors/dom/end-of-stream.js +178 -0
- package/dist/default/playback/behaviors/dom/end-of-stream.js.map +1 -0
- package/dist/default/playback/behaviors/dom/load-segments.js +177 -0
- package/dist/default/playback/behaviors/dom/load-segments.js.map +1 -0
- package/dist/default/playback/behaviors/dom/setup-buffer-actors.js +173 -0
- package/dist/default/playback/behaviors/dom/setup-buffer-actors.js.map +1 -0
- package/dist/default/playback/behaviors/dom/setup-mediasource.js +89 -0
- package/dist/default/playback/behaviors/dom/setup-mediasource.js.map +1 -0
- package/dist/default/playback/behaviors/dom/setup-text-track-actors.js +54 -0
- package/dist/default/playback/behaviors/dom/setup-text-track-actors.js.map +1 -0
- package/dist/default/playback/behaviors/dom/sync-text-tracks.js +99 -0
- package/dist/default/playback/behaviors/dom/sync-text-tracks.js.map +1 -0
- package/dist/default/playback/behaviors/dom/track-current-time.js +46 -0
- package/dist/default/playback/behaviors/dom/track-current-time.js.map +1 -0
- package/dist/default/playback/behaviors/dom/track-load-triggers.js +94 -0
- package/dist/default/playback/behaviors/dom/track-load-triggers.js.map +1 -0
- package/dist/default/playback/behaviors/dom/track-playback-rate.js +37 -0
- package/dist/default/playback/behaviors/dom/track-playback-rate.js.map +1 -0
- package/dist/default/playback/behaviors/dom/update-mediasource-duration.js +90 -0
- package/dist/default/playback/behaviors/dom/update-mediasource-duration.js.map +1 -0
- package/dist/default/playback/behaviors/quality-switching.js +96 -0
- package/dist/default/playback/behaviors/quality-switching.js.map +1 -0
- package/dist/default/playback/behaviors/resolve-presentation.js +85 -0
- package/dist/default/playback/behaviors/resolve-presentation.js.map +1 -0
- package/dist/default/playback/behaviors/resolve-track.js +97 -0
- package/dist/default/playback/behaviors/resolve-track.js.map +1 -0
- package/dist/default/playback/behaviors/select-tracks.js +132 -0
- package/dist/default/playback/behaviors/select-tracks.js.map +1 -0
- package/dist/default/playback/behaviors/sync-preload.js +59 -0
- package/dist/default/playback/behaviors/sync-preload.js.map +1 -0
- package/dist/default/playback/behaviors/track-types.js +61 -0
- package/dist/default/playback/behaviors/track-types.js.map +1 -0
- package/dist/default/{dom/playback-engine → playback/engines/hls}/adapter.js +36 -25
- package/dist/default/playback/engines/hls/adapter.js.map +1 -0
- package/dist/default/playback/engines/hls/engine.js +102 -0
- package/dist/default/playback/engines/hls/engine.js.map +1 -0
- package/dist/dev/core/{actor.d.ts → actors/actor.d.ts} +2 -2
- package/dist/dev/core/actors/actor.d.ts.map +1 -0
- package/dist/dev/core/actors/create-machine-actor.d.ts +125 -0
- package/dist/dev/core/actors/create-machine-actor.d.ts.map +1 -0
- package/dist/{default/core → dev/core/actors}/create-machine-actor.js +3 -3
- package/dist/dev/core/actors/create-machine-actor.js.map +1 -0
- package/dist/dev/core/actors/create-transition-actor.d.ts +42 -0
- package/dist/dev/core/actors/create-transition-actor.d.ts.map +1 -0
- package/dist/dev/core/{create-transition-actor.js → actors/create-transition-actor.js} +3 -3
- package/dist/dev/core/actors/create-transition-actor.js.map +1 -0
- package/dist/dev/core/composition/create-composition.d.ts +274 -0
- package/dist/dev/core/composition/create-composition.d.ts.map +1 -0
- package/dist/dev/core/composition/create-composition.js +85 -0
- package/dist/dev/core/composition/create-composition.js.map +1 -0
- package/dist/dev/core/composition/share-signals.d.ts +45 -0
- package/dist/dev/core/composition/share-signals.d.ts.map +1 -0
- package/dist/dev/core/composition/share-signals.js +37 -0
- package/dist/dev/core/composition/share-signals.js.map +1 -0
- package/dist/dev/core/machine.d.ts +0 -1
- package/dist/dev/core/machine.d.ts.map +1 -1
- package/dist/dev/core/reactors/create-machine-reactor.d.ts +93 -0
- package/dist/dev/core/reactors/create-machine-reactor.d.ts.map +1 -0
- package/dist/{default/core → dev/core/reactors}/create-machine-reactor.js +4 -4
- package/dist/dev/core/reactors/create-machine-reactor.js.map +1 -0
- package/dist/dev/core/signals/primitives.d.ts +38 -1
- package/dist/dev/core/signals/primitives.d.ts.map +1 -1
- package/dist/dev/core/signals/primitives.js +33 -11
- package/dist/dev/core/signals/primitives.js.map +1 -1
- package/dist/dev/core/tasks/task.d.ts +115 -0
- package/dist/dev/core/tasks/task.d.ts.map +1 -0
- package/dist/dev/core/{task.js → tasks/task.js} +2 -2
- package/dist/dev/core/tasks/task.js.map +1 -0
- package/dist/dev/dom.d.ts +9 -10
- package/dist/dev/dom.js +9 -10
- package/dist/dev/hls.d.ts +3 -0
- package/dist/dev/hls.js +3 -0
- package/dist/dev/index.d.ts +15 -3
- package/dist/dev/index.d.ts.map +1 -1
- package/dist/dev/index.js +12 -3
- package/dist/dev/index.js.map +1 -1
- package/dist/dev/media/abr/quality-selection.d.ts +22 -0
- package/dist/dev/media/abr/quality-selection.d.ts.map +1 -0
- package/dist/dev/media/abr/quality-selection.js +83 -0
- package/dist/dev/media/abr/quality-selection.js.map +1 -0
- package/dist/dev/media/buffer/back-buffer.d.ts +14 -0
- package/dist/dev/media/buffer/back-buffer.d.ts.map +1 -0
- package/dist/dev/{core → media}/buffer/back-buffer.js +2 -2
- package/dist/dev/media/buffer/back-buffer.js.map +1 -0
- package/dist/dev/media/buffer/forward-buffer.d.ts +14 -0
- package/dist/dev/media/buffer/forward-buffer.d.ts.map +1 -0
- package/dist/{default/core → dev/media}/buffer/forward-buffer.js +14 -2
- package/dist/dev/media/buffer/forward-buffer.js.map +1 -0
- package/dist/dev/{dom/media → media/dom/mse}/append-segment.d.ts +1 -1
- package/dist/dev/media/dom/mse/append-segment.d.ts.map +1 -0
- package/dist/{default/dom/media → dev/media/dom/mse}/append-segment.js +1 -1
- package/dist/dev/media/dom/mse/append-segment.js.map +1 -0
- package/dist/dev/{dom/media → media/dom/mse}/buffer-flusher.d.ts +1 -1
- package/dist/dev/media/dom/mse/buffer-flusher.d.ts.map +1 -0
- package/dist/dev/{dom/media → media/dom/mse}/buffer-flusher.js +1 -1
- package/dist/dev/media/dom/mse/buffer-flusher.js.map +1 -0
- package/dist/dev/media/dom/mse/duration.js +78 -0
- package/dist/dev/media/dom/mse/duration.js.map +1 -0
- package/dist/dev/media/dom/mse/end-of-stream.js +20 -0
- package/dist/dev/media/dom/mse/end-of-stream.js.map +1 -0
- package/dist/dev/{dom/media → media/dom/mse}/mediasource-setup.js +63 -18
- package/dist/dev/media/dom/mse/mediasource-setup.js.map +1 -0
- package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts +12 -0
- package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts.map +1 -0
- package/dist/dev/{dom/text/parse-vtt-segment.js → media/dom/text/resolve-vtt-segment.js} +5 -5
- package/dist/dev/media/dom/text/resolve-vtt-segment.js.map +1 -0
- package/dist/dev/media/dom/text/text-track-slots.d.ts +31 -0
- package/dist/dev/media/dom/text/text-track-slots.d.ts.map +1 -0
- package/dist/dev/media/dom/text/text-track-slots.js +69 -0
- package/dist/dev/media/dom/text/text-track-slots.js.map +1 -0
- package/dist/{default/core → dev/media}/hls/parse-attributes.js +1 -1
- package/dist/dev/media/hls/parse-attributes.js.map +1 -0
- package/dist/{default/core → dev/media}/hls/parse-media-playlist.js +1 -1
- package/dist/dev/media/hls/parse-media-playlist.js.map +1 -0
- package/dist/{default/core → dev/media}/hls/parse-multivariant.js +2 -2
- package/dist/dev/media/hls/parse-multivariant.js.map +1 -0
- package/dist/dev/{core → media}/hls/resolve-url.js +1 -1
- package/dist/dev/media/hls/resolve-url.js.map +1 -0
- package/dist/dev/media/primitives/select-tracks.js +45 -0
- package/dist/dev/media/primitives/select-tracks.js.map +1 -0
- package/dist/dev/{core → media}/types/index.d.ts +30 -2
- package/dist/dev/media/types/index.d.ts.map +1 -0
- package/dist/dev/media/types/index.js +36 -0
- package/dist/dev/media/types/index.js.map +1 -0
- package/dist/dev/media/utils/preload.js +22 -0
- package/dist/dev/media/utils/preload.js.map +1 -0
- package/dist/dev/media/utils/track-selection.js +47 -0
- package/dist/dev/media/utils/track-selection.js.map +1 -0
- package/dist/dev/media/utils/tracks.js +103 -0
- package/dist/dev/media/utils/tracks.js.map +1 -0
- package/dist/dev/{core/abr → network}/bandwidth-estimator.d.ts +17 -2
- package/dist/dev/network/bandwidth-estimator.d.ts.map +1 -0
- package/dist/dev/{core/abr → network}/bandwidth-estimator.js +6 -5
- package/dist/dev/network/bandwidth-estimator.js.map +1 -0
- package/dist/{default/dom → dev}/network/chunked-stream-iterable.js +1 -1
- package/dist/dev/network/chunked-stream-iterable.js.map +1 -0
- package/dist/{default/core/abr → dev/network}/ewma.js +1 -1
- package/dist/dev/network/ewma.js.map +1 -0
- package/dist/dev/network/fetch.js +109 -0
- package/dist/dev/network/fetch.js.map +1 -0
- package/dist/dev/playback/actors/dom/segment-loader.d.ts +36 -0
- package/dist/dev/playback/actors/dom/segment-loader.d.ts.map +1 -0
- package/dist/{default/dom/features/segment-loader-actor.js → dev/playback/actors/dom/segment-loader.js} +24 -15
- package/dist/dev/playback/actors/dom/segment-loader.js.map +1 -0
- package/dist/dev/{dom/media/source-buffer-actor.d.ts → playback/actors/dom/source-buffer.d.ts} +5 -5
- package/dist/dev/playback/actors/dom/source-buffer.d.ts.map +1 -0
- package/dist/{default/dom/media/source-buffer-actor.js → dev/playback/actors/dom/source-buffer.js} +8 -8
- package/dist/dev/playback/actors/dom/source-buffer.js.map +1 -0
- package/dist/dev/playback/actors/dom/text-tracks.d.ts +1 -0
- package/dist/{default/dom/features/text-tracks-actor.js → dev/playback/actors/dom/text-tracks.js} +7 -3
- package/dist/dev/playback/actors/dom/text-tracks.js.map +1 -0
- package/dist/dev/playback/actors/text-track-segment-loader.d.ts +59 -0
- package/dist/dev/playback/actors/text-track-segment-loader.d.ts.map +1 -0
- package/dist/dev/playback/actors/text-track-segment-loader.js +135 -0
- package/dist/dev/playback/actors/text-track-segment-loader.js.map +1 -0
- package/dist/dev/playback/actors/text-tracks.d.ts +42 -0
- package/dist/dev/playback/actors/text-tracks.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts +17 -0
- package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/calculate-presentation-duration.js +58 -0
- package/dist/dev/playback/behaviors/calculate-presentation-duration.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/end-of-stream.js +178 -0
- package/dist/dev/playback/behaviors/dom/end-of-stream.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/load-segments.d.ts +62 -0
- package/dist/dev/playback/behaviors/dom/load-segments.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/dom/load-segments.js +177 -0
- package/dist/dev/playback/behaviors/dom/load-segments.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js +173 -0
- package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/setup-mediasource.js +89 -0
- package/dist/dev/playback/behaviors/dom/setup-mediasource.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts +31 -0
- package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js +54 -0
- package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/sync-text-tracks.js +99 -0
- package/dist/dev/playback/behaviors/dom/sync-text-tracks.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-current-time.d.ts +34 -0
- package/dist/dev/playback/behaviors/dom/track-current-time.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-current-time.js +46 -0
- package/dist/dev/playback/behaviors/dom/track-current-time.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts +48 -0
- package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-load-triggers.js +94 -0
- package/dist/dev/playback/behaviors/dom/track-load-triggers.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts +34 -0
- package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/dom/track-playback-rate.js +37 -0
- package/dist/dev/playback/behaviors/dom/track-playback-rate.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js +90 -0
- package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js.map +1 -0
- package/dist/dev/playback/behaviors/quality-switching.js +96 -0
- package/dist/dev/playback/behaviors/quality-switching.js.map +1 -0
- package/dist/dev/playback/behaviors/resolve-presentation.d.ts +7 -0
- package/dist/dev/playback/behaviors/resolve-presentation.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/resolve-presentation.js +85 -0
- package/dist/dev/playback/behaviors/resolve-presentation.js.map +1 -0
- package/dist/dev/playback/behaviors/resolve-track.js +97 -0
- package/dist/dev/playback/behaviors/resolve-track.js.map +1 -0
- package/dist/dev/playback/behaviors/select-tracks.js +132 -0
- package/dist/dev/playback/behaviors/select-tracks.js.map +1 -0
- package/dist/dev/playback/behaviors/sync-preload.js +59 -0
- package/dist/dev/playback/behaviors/sync-preload.js.map +1 -0
- package/dist/dev/playback/behaviors/track-types.js +61 -0
- package/dist/dev/playback/behaviors/track-types.js.map +1 -0
- package/dist/dev/{dom/playback-engine → playback/engines/hls}/adapter.d.ts +14 -10
- package/dist/dev/playback/engines/hls/adapter.d.ts.map +1 -0
- package/dist/dev/{dom/playback-engine → playback/engines/hls}/adapter.js +36 -25
- package/dist/dev/playback/engines/hls/adapter.js.map +1 -0
- package/dist/dev/playback/engines/hls/engine.d.ts +177 -0
- package/dist/dev/playback/engines/hls/engine.d.ts.map +1 -0
- package/dist/dev/playback/engines/hls/engine.js +102 -0
- package/dist/dev/playback/engines/hls/engine.js.map +1 -0
- package/package.json +8 -9
- package/dist/default/core/abr/bandwidth-estimator.js.map +0 -1
- package/dist/default/core/abr/ewma.js.map +0 -1
- package/dist/default/core/abr/quality-selection.js +0 -53
- package/dist/default/core/abr/quality-selection.js.map +0 -1
- package/dist/default/core/buffer/back-buffer.js.map +0 -1
- package/dist/default/core/buffer/forward-buffer.js.map +0 -1
- package/dist/default/core/create-machine-actor.js.map +0 -1
- package/dist/default/core/create-machine-reactor.js.map +0 -1
- package/dist/default/core/create-transition-actor.js.map +0 -1
- package/dist/default/core/features/calculate-presentation-duration.js +0 -53
- package/dist/default/core/features/calculate-presentation-duration.js.map +0 -1
- package/dist/default/core/features/quality-switching.js +0 -69
- package/dist/default/core/features/quality-switching.js.map +0 -1
- package/dist/default/core/features/resolve-presentation.js +0 -73
- package/dist/default/core/features/resolve-presentation.js.map +0 -1
- package/dist/default/core/features/resolve-track.js +0 -66
- package/dist/default/core/features/resolve-track.js.map +0 -1
- package/dist/default/core/features/select-tracks.js +0 -130
- package/dist/default/core/features/select-tracks.js.map +0 -1
- package/dist/default/core/features/sync-preload-attribute.js +0 -26
- package/dist/default/core/features/sync-preload-attribute.js.map +0 -1
- package/dist/default/core/hls/parse-attributes.js.map +0 -1
- package/dist/default/core/hls/parse-media-playlist.js.map +0 -1
- package/dist/default/core/hls/parse-multivariant.js.map +0 -1
- package/dist/default/core/hls/resolve-url.js.map +0 -1
- package/dist/default/core/task.js.map +0 -1
- package/dist/default/core/types/index.js +0 -15
- package/dist/default/core/types/index.js.map +0 -1
- package/dist/default/core/utils/generate-id.js +0 -21
- package/dist/default/core/utils/generate-id.js.map +0 -1
- package/dist/default/core/utils/track-selection.js +0 -39
- package/dist/default/core/utils/track-selection.js.map +0 -1
- package/dist/default/dom/features/end-of-stream.js +0 -145
- package/dist/default/dom/features/end-of-stream.js.map +0 -1
- package/dist/default/dom/features/load-segments.js +0 -192
- package/dist/default/dom/features/load-segments.js.map +0 -1
- package/dist/default/dom/features/load-text-track-cues.js +0 -104
- package/dist/default/dom/features/load-text-track-cues.js.map +0 -1
- package/dist/default/dom/features/segment-loader-actor.js.map +0 -1
- package/dist/default/dom/features/setup-mediasource.js +0 -48
- package/dist/default/dom/features/setup-mediasource.js.map +0 -1
- package/dist/default/dom/features/setup-sourcebuffer.js +0 -78
- package/dist/default/dom/features/setup-sourcebuffer.js.map +0 -1
- package/dist/default/dom/features/sync-text-tracks.js +0 -95
- package/dist/default/dom/features/sync-text-tracks.js.map +0 -1
- package/dist/default/dom/features/text-track-segment-loader-actor.js +0 -55
- package/dist/default/dom/features/text-track-segment-loader-actor.js.map +0 -1
- package/dist/default/dom/features/text-tracks-actor.js.map +0 -1
- package/dist/default/dom/features/track-current-time.js +0 -49
- package/dist/default/dom/features/track-current-time.js.map +0 -1
- package/dist/default/dom/features/track-playback-initiated.js +0 -66
- package/dist/default/dom/features/track-playback-initiated.js.map +0 -1
- package/dist/default/dom/features/track-playback-rate.js +0 -32
- package/dist/default/dom/features/track-playback-rate.js.map +0 -1
- package/dist/default/dom/features/update-duration.js +0 -78
- package/dist/default/dom/features/update-duration.js.map +0 -1
- package/dist/default/dom/media/append-segment.js.map +0 -1
- package/dist/default/dom/media/buffer-flusher.js.map +0 -1
- package/dist/default/dom/media/mediasource-setup.js.map +0 -1
- package/dist/default/dom/media/source-buffer-actor.js.map +0 -1
- package/dist/default/dom/network/chunked-stream-iterable.js.map +0 -1
- package/dist/default/dom/network/fetch.js +0 -54
- package/dist/default/dom/network/fetch.js.map +0 -1
- package/dist/default/dom/playback-engine/adapter.js.map +0 -1
- package/dist/default/dom/playback-engine/engine.js +0 -142
- package/dist/default/dom/playback-engine/engine.js.map +0 -1
- package/dist/default/dom/playback-engine.js +0 -4
- package/dist/default/dom/text/parse-vtt-segment.js.map +0 -1
- package/dist/dev/core/abr/bandwidth-estimator.d.ts.map +0 -1
- package/dist/dev/core/abr/bandwidth-estimator.js.map +0 -1
- package/dist/dev/core/abr/ewma.js.map +0 -1
- package/dist/dev/core/abr/quality-selection.js +0 -53
- package/dist/dev/core/abr/quality-selection.js.map +0 -1
- package/dist/dev/core/actor.d.ts.map +0 -1
- package/dist/dev/core/buffer/back-buffer.js.map +0 -1
- package/dist/dev/core/buffer/forward-buffer.js.map +0 -1
- package/dist/dev/core/create-machine-actor.d.ts +0 -12
- package/dist/dev/core/create-machine-actor.d.ts.map +0 -1
- package/dist/dev/core/create-machine-actor.js.map +0 -1
- package/dist/dev/core/create-machine-reactor.d.ts +0 -8
- package/dist/dev/core/create-machine-reactor.d.ts.map +0 -1
- package/dist/dev/core/create-machine-reactor.js.map +0 -1
- package/dist/dev/core/create-transition-actor.d.ts +0 -23
- package/dist/dev/core/create-transition-actor.d.ts.map +0 -1
- package/dist/dev/core/create-transition-actor.js.map +0 -1
- package/dist/dev/core/features/calculate-presentation-duration.js +0 -53
- package/dist/dev/core/features/calculate-presentation-duration.js.map +0 -1
- package/dist/dev/core/features/quality-switching.js +0 -69
- package/dist/dev/core/features/quality-switching.js.map +0 -1
- package/dist/dev/core/features/resolve-presentation.js +0 -73
- package/dist/dev/core/features/resolve-presentation.js.map +0 -1
- package/dist/dev/core/features/resolve-track.js +0 -66
- package/dist/dev/core/features/resolve-track.js.map +0 -1
- package/dist/dev/core/features/select-tracks.js +0 -130
- package/dist/dev/core/features/select-tracks.js.map +0 -1
- package/dist/dev/core/features/sync-preload-attribute.js +0 -26
- package/dist/dev/core/features/sync-preload-attribute.js.map +0 -1
- package/dist/dev/core/hls/parse-attributes.js.map +0 -1
- package/dist/dev/core/hls/parse-media-playlist.js.map +0 -1
- package/dist/dev/core/hls/parse-multivariant.js.map +0 -1
- package/dist/dev/core/hls/resolve-url.js.map +0 -1
- package/dist/dev/core/task.js.map +0 -1
- package/dist/dev/core/types/index.d.ts.map +0 -1
- package/dist/dev/core/types/index.js +0 -15
- package/dist/dev/core/types/index.js.map +0 -1
- package/dist/dev/core/utils/generate-id.js +0 -21
- package/dist/dev/core/utils/generate-id.js.map +0 -1
- package/dist/dev/core/utils/track-selection.d.ts +0 -16
- package/dist/dev/core/utils/track-selection.d.ts.map +0 -1
- package/dist/dev/core/utils/track-selection.js +0 -39
- package/dist/dev/core/utils/track-selection.js.map +0 -1
- package/dist/dev/dom/features/end-of-stream.js +0 -145
- package/dist/dev/dom/features/end-of-stream.js.map +0 -1
- package/dist/dev/dom/features/load-segments.d.ts +0 -72
- package/dist/dev/dom/features/load-segments.d.ts.map +0 -1
- package/dist/dev/dom/features/load-segments.js +0 -192
- package/dist/dev/dom/features/load-segments.js.map +0 -1
- package/dist/dev/dom/features/load-text-track-cues.d.ts +0 -85
- package/dist/dev/dom/features/load-text-track-cues.d.ts.map +0 -1
- package/dist/dev/dom/features/load-text-track-cues.js +0 -104
- package/dist/dev/dom/features/load-text-track-cues.js.map +0 -1
- package/dist/dev/dom/features/segment-loader-actor.d.ts +0 -1
- package/dist/dev/dom/features/segment-loader-actor.js.map +0 -1
- package/dist/dev/dom/features/setup-mediasource.js +0 -48
- package/dist/dev/dom/features/setup-mediasource.js.map +0 -1
- package/dist/dev/dom/features/setup-sourcebuffer.d.ts +0 -9
- package/dist/dev/dom/features/setup-sourcebuffer.d.ts.map +0 -1
- package/dist/dev/dom/features/setup-sourcebuffer.js +0 -78
- package/dist/dev/dom/features/setup-sourcebuffer.js.map +0 -1
- package/dist/dev/dom/features/sync-text-tracks.js +0 -95
- package/dist/dev/dom/features/sync-text-tracks.js.map +0 -1
- package/dist/dev/dom/features/text-track-segment-loader-actor.d.ts +0 -12
- package/dist/dev/dom/features/text-track-segment-loader-actor.d.ts.map +0 -1
- package/dist/dev/dom/features/text-track-segment-loader-actor.js +0 -55
- package/dist/dev/dom/features/text-track-segment-loader-actor.js.map +0 -1
- package/dist/dev/dom/features/text-tracks-actor.d.ts +0 -31
- package/dist/dev/dom/features/text-tracks-actor.d.ts.map +0 -1
- package/dist/dev/dom/features/text-tracks-actor.js.map +0 -1
- package/dist/dev/dom/features/track-current-time.d.ts +0 -40
- package/dist/dev/dom/features/track-current-time.d.ts.map +0 -1
- package/dist/dev/dom/features/track-current-time.js +0 -49
- package/dist/dev/dom/features/track-current-time.js.map +0 -1
- package/dist/dev/dom/features/track-playback-initiated.d.ts +0 -46
- package/dist/dev/dom/features/track-playback-initiated.d.ts.map +0 -1
- package/dist/dev/dom/features/track-playback-initiated.js +0 -66
- package/dist/dev/dom/features/track-playback-initiated.js.map +0 -1
- package/dist/dev/dom/features/track-playback-rate.d.ts +0 -34
- package/dist/dev/dom/features/track-playback-rate.d.ts.map +0 -1
- package/dist/dev/dom/features/track-playback-rate.js +0 -32
- package/dist/dev/dom/features/track-playback-rate.js.map +0 -1
- package/dist/dev/dom/features/update-duration.js +0 -78
- package/dist/dev/dom/features/update-duration.js.map +0 -1
- package/dist/dev/dom/media/append-segment.d.ts.map +0 -1
- package/dist/dev/dom/media/append-segment.js.map +0 -1
- package/dist/dev/dom/media/buffer-flusher.d.ts.map +0 -1
- package/dist/dev/dom/media/buffer-flusher.js.map +0 -1
- package/dist/dev/dom/media/mediasource-setup.js.map +0 -1
- package/dist/dev/dom/media/source-buffer-actor.d.ts.map +0 -1
- package/dist/dev/dom/media/source-buffer-actor.js.map +0 -1
- package/dist/dev/dom/network/chunked-stream-iterable.js.map +0 -1
- package/dist/dev/dom/network/fetch.js +0 -54
- package/dist/dev/dom/network/fetch.js.map +0 -1
- package/dist/dev/dom/playback-engine/adapter.d.ts.map +0 -1
- package/dist/dev/dom/playback-engine/adapter.js.map +0 -1
- package/dist/dev/dom/playback-engine/engine.d.ts +0 -124
- package/dist/dev/dom/playback-engine/engine.d.ts.map +0 -1
- package/dist/dev/dom/playback-engine/engine.js +0 -142
- package/dist/dev/dom/playback-engine/engine.js.map +0 -1
- package/dist/dev/dom/playback-engine.d.ts +0 -4
- package/dist/dev/dom/playback-engine.js +0 -4
- package/dist/dev/dom/text/parse-vtt-segment.d.ts +0 -12
- package/dist/dev/dom/text/parse-vtt-segment.d.ts.map +0 -1
- package/dist/dev/dom/text/parse-vtt-segment.js.map +0 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { computed } from "../../core/signals/primitives.js";
|
|
2
|
+
import { defineBehavior } from "../../core/composition/create-composition.js";
|
|
3
|
+
import { createMachineReactor } from "../../core/reactors/create-machine-reactor.js";
|
|
4
|
+
import { isResolvedPresentation } from "../../media/types/index.js";
|
|
5
|
+
import { fetchResolvable, getResponseText } from "../../network/fetch.js";
|
|
6
|
+
import { isBlockingPreload } from "../../media/utils/preload.js";
|
|
7
|
+
//#region src/playback/behaviors/resolve-presentation.ts
|
|
8
|
+
/**
|
|
9
|
+
* **Resolve an unresolved presentation by fetching and parsing its manifest.**
|
|
10
|
+
*
|
|
11
|
+
* Reads `state.presentation`; when it holds `{ url }` (unresolved) and the
|
|
12
|
+
* preload / load-activation gate is met, fetches the manifest, parses it via
|
|
13
|
+
* the **required** `config.parsePresentation`, and writes the resolved
|
|
14
|
+
* `Presentation` back to the same slot. The behavior is format-neutral: the
|
|
15
|
+
* composing engine wires in its parser (e.g. the HLS engine supplies the
|
|
16
|
+
* multivariant-playlist parser).
|
|
17
|
+
*
|
|
18
|
+
* Source-identity-driven, expressed as a 4-state machine:
|
|
19
|
+
*
|
|
20
|
+
* ```
|
|
21
|
+
* 'preconditions-unmet' → 'idle' → 'resolving' → 'resolved'
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* - `'preconditions-unmet'`: no presentation, or presentation has no URL.
|
|
25
|
+
* - `'idle'`: URL present, unresolved, gate unmet (blocking preload + no
|
|
26
|
+
* load-activation). Waits for the gate to open.
|
|
27
|
+
* - `'resolving'`: URL present, unresolved, gate met. Entry starts the fetch
|
|
28
|
+
* and returns the AbortController — the reactor calls `.abort()` on state
|
|
29
|
+
* exit, so source change / gate-close / destroy all cancel cleanly.
|
|
30
|
+
* - `'resolved'`: `state.presentation` holds a resolved `Presentation`.
|
|
31
|
+
*
|
|
32
|
+
* Gate semantics: `state.preload` (or `config.defaultPreload`, default
|
|
33
|
+
* `'metadata'`, when state.preload is unset) blocks resolution when its
|
|
34
|
+
* value is `'none'` (see `isBlockingPreload` in `media/utils/preload`).
|
|
35
|
+
* `state.loadActivated` is an override — true bypasses the preload gate
|
|
36
|
+
* entirely.
|
|
37
|
+
*
|
|
38
|
+
* Multi-writer with the engine adapter, which writes the initial unresolved
|
|
39
|
+
* `{ url }` to `state.presentation` from src input. Different domains
|
|
40
|
+
* (config-input vs. derived state via fetch) — legitimate multi-writer.
|
|
41
|
+
*/
|
|
42
|
+
function deriveState(presentation, preload, loadActivated, defaultPreload) {
|
|
43
|
+
if (!presentation?.url) return "preconditions-unmet";
|
|
44
|
+
if (isResolvedPresentation(presentation)) return "resolved";
|
|
45
|
+
return !!loadActivated || !isBlockingPreload(preload, defaultPreload) ? "resolving" : "idle";
|
|
46
|
+
}
|
|
47
|
+
function resolvePresentationSetup({ state, config }) {
|
|
48
|
+
const { parsePresentation } = config;
|
|
49
|
+
const defaultPreload = config.defaultPreload ?? "metadata";
|
|
50
|
+
const derivedStateSignal = computed(() => deriveState(state.presentation.get(), state.preload.get(), state.loadActivated.get(), defaultPreload));
|
|
51
|
+
return createMachineReactor({
|
|
52
|
+
initial: "preconditions-unmet",
|
|
53
|
+
monitor: () => derivedStateSignal.get(),
|
|
54
|
+
states: {
|
|
55
|
+
"preconditions-unmet": {},
|
|
56
|
+
idle: {},
|
|
57
|
+
resolving: { entry: () => {
|
|
58
|
+
const presentation = state.presentation.get();
|
|
59
|
+
const ac = new AbortController();
|
|
60
|
+
fetchResolvable(presentation, { signal: ac.signal }).then((response) => getResponseText(response)).then((text) => {
|
|
61
|
+
const parsed = parsePresentation(text, presentation);
|
|
62
|
+
state.presentation.set(parsed);
|
|
63
|
+
}).catch((error) => {
|
|
64
|
+
if (error instanceof Error && error.name === "AbortError") return;
|
|
65
|
+
console.error("[resolvePresentation] manifest fetch/parse failed:", error);
|
|
66
|
+
});
|
|
67
|
+
return ac;
|
|
68
|
+
} },
|
|
69
|
+
resolved: {}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const resolvePresentation = defineBehavior({
|
|
74
|
+
stateKeys: [
|
|
75
|
+
"presentation",
|
|
76
|
+
"preload",
|
|
77
|
+
"loadActivated"
|
|
78
|
+
],
|
|
79
|
+
contextKeys: [],
|
|
80
|
+
setup: resolvePresentationSetup
|
|
81
|
+
});
|
|
82
|
+
//#endregion
|
|
83
|
+
export { resolvePresentation };
|
|
84
|
+
|
|
85
|
+
//# sourceMappingURL=resolve-presentation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-presentation.js","names":[],"sources":["../../../../src/playback/behaviors/resolve-presentation.ts"],"sourcesContent":["/**\n * **Resolve an unresolved presentation by fetching and parsing its manifest.**\n *\n * Reads `state.presentation`; when it holds `{ url }` (unresolved) and the\n * preload / load-activation gate is met, fetches the manifest, parses it via\n * the **required** `config.parsePresentation`, and writes the resolved\n * `Presentation` back to the same slot. The behavior is format-neutral: the\n * composing engine wires in its parser (e.g. the HLS engine supplies the\n * multivariant-playlist parser).\n *\n * Source-identity-driven, expressed as a 4-state machine:\n *\n * ```\n * 'preconditions-unmet' → 'idle' → 'resolving' → 'resolved'\n * ```\n *\n * - `'preconditions-unmet'`: no presentation, or presentation has no URL.\n * - `'idle'`: URL present, unresolved, gate unmet (blocking preload + no\n * load-activation). Waits for the gate to open.\n * - `'resolving'`: URL present, unresolved, gate met. Entry starts the fetch\n * and returns the AbortController — the reactor calls `.abort()` on state\n * exit, so source change / gate-close / destroy all cancel cleanly.\n * - `'resolved'`: `state.presentation` holds a resolved `Presentation`.\n *\n * Gate semantics: `state.preload` (or `config.defaultPreload`, default\n * `'metadata'`, when state.preload is unset) blocks resolution when its\n * value is `'none'` (see `isBlockingPreload` in `media/utils/preload`).\n * `state.loadActivated` is an override — true bypasses the preload gate\n * entirely.\n *\n * Multi-writer with the engine adapter, which writes the initial unresolved\n * `{ url }` to `state.presentation` from src input. Different domains\n * (config-input vs. derived state via fetch) — legitimate multi-writer.\n */\nimport { defineBehavior } from '../../core/composition/create-composition';\nimport type { Reactor } from '../../core/reactors/create-machine-reactor';\nimport { createMachineReactor } from '../../core/reactors/create-machine-reactor';\nimport { computed, type ReadonlySignal, type Signal } from '../../core/signals/primitives';\nimport { isResolvedPresentation, type MaybeResolvedPresentation, type Presentation } from '../../media/types';\nimport { DEFAULT_PRELOAD, isBlockingPreload, type StandardPreload } from '../../media/utils/preload';\nimport { fetchResolvable, getResponseText } from '../../network/fetch';\n\nexport interface PresentationState {\n presentation?: MaybeResolvedPresentation;\n preload?: 'auto' | 'metadata' | 'none' | undefined;\n /** True once a preload-overriding event has fired for the current source — enables resolution regardless of preload. */\n loadActivated?: boolean;\n}\n\nexport type ParsePresentation = (text: string, presentation: MaybeResolvedPresentation) => Presentation;\n\nexport interface ResolvePresentationConfig {\n /**\n * Parses a manifest body into a resolved `Presentation`. **Required** —\n * the behavior is format-neutral and the composing engine supplies its\n * own parser (HLS, DASH, etc.).\n */\n parsePresentation: ParsePresentation;\n /**\n * Fallback used when `state.preload` is unset (undefined / empty) for the\n * resolution-gate decision. Defaults to `'metadata'`, matching\n * `syncPreload`'s own `defaultPreload`.\n */\n defaultPreload?: StandardPreload;\n}\n\nexport type ResolvePresentationState = 'preconditions-unmet' | 'idle' | 'resolving' | 'resolved';\n\nfunction deriveState(\n presentation: MaybeResolvedPresentation | undefined,\n preload: PresentationState['preload'],\n loadActivated: boolean | undefined,\n defaultPreload: StandardPreload\n): ResolvePresentationState {\n if (!presentation?.url) return 'preconditions-unmet';\n if (isResolvedPresentation(presentation)) return 'resolved';\n const gateOpen = !!loadActivated || !isBlockingPreload(preload, defaultPreload);\n return gateOpen ? 'resolving' : 'idle';\n}\n\nfunction resolvePresentationSetup({\n state,\n config,\n}: {\n state: {\n presentation: Signal<PresentationState['presentation']>;\n preload: ReadonlySignal<PresentationState['preload']>;\n loadActivated: ReadonlySignal<PresentationState['loadActivated']>;\n };\n config: ResolvePresentationConfig;\n}): Reactor<ResolvePresentationState | 'destroying' | 'destroyed'> {\n const { parsePresentation } = config;\n const defaultPreload: StandardPreload = config.defaultPreload ?? DEFAULT_PRELOAD;\n\n const derivedStateSignal = computed(() =>\n deriveState(state.presentation.get(), state.preload.get(), state.loadActivated.get(), defaultPreload)\n );\n\n return createMachineReactor<ResolvePresentationState>({\n initial: 'preconditions-unmet',\n monitor: () => derivedStateSignal.get(),\n states: {\n 'preconditions-unmet': {},\n idle: {},\n resolving: {\n entry: () => {\n const presentation = state.presentation.get()!;\n const ac = new AbortController();\n\n fetchResolvable(presentation, { signal: ac.signal })\n .then((response) => getResponseText(response))\n .then((text) => {\n const parsed = parsePresentation(text, presentation);\n state.presentation.set(parsed);\n })\n .catch((error) => {\n if (error instanceof Error && error.name === 'AbortError') return;\n // TODO(error-management): route to a state-error slot once one exists.\n console.error('[resolvePresentation] manifest fetch/parse failed:', error);\n });\n\n return ac;\n },\n },\n resolved: {},\n },\n });\n}\n\nexport const resolvePresentation = defineBehavior({\n stateKeys: ['presentation', 'preload', 'loadActivated'],\n contextKeys: [],\n setup: resolvePresentationSetup,\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEA,SAAS,YACP,cACA,SACA,eACA,gBAC0B;AAC1B,KAAI,CAAC,cAAc,IAAK,QAAO;AAC/B,KAAI,uBAAuB,aAAa,CAAE,QAAO;AAEjD,QADiB,CAAC,CAAC,iBAAiB,CAAC,kBAAkB,SAAS,eAAe,GAC7D,cAAc;;AAGlC,SAAS,yBAAyB,EAChC,OACA,UAQiE;CACjE,MAAM,EAAE,sBAAsB;CAC9B,MAAM,iBAAkC,OAAO,kBAAA;CAE/C,MAAM,qBAAqB,eACzB,YAAY,MAAM,aAAa,KAAK,EAAE,MAAM,QAAQ,KAAK,EAAE,MAAM,cAAc,KAAK,EAAE,eAAe,CACtG;AAED,QAAO,qBAA+C;EACpD,SAAS;EACT,eAAe,mBAAmB,KAAK;EACvC,QAAQ;GACN,uBAAuB,EAAE;GACzB,MAAM,EAAE;GACR,WAAW,EACT,aAAa;IACX,MAAM,eAAe,MAAM,aAAa,KAAK;IAC7C,MAAM,KAAK,IAAI,iBAAiB;AAEhC,oBAAgB,cAAc,EAAE,QAAQ,GAAG,QAAQ,CAAC,CACjD,MAAM,aAAa,gBAAgB,SAAS,CAAC,CAC7C,MAAM,SAAS;KACd,MAAM,SAAS,kBAAkB,MAAM,aAAa;AACpD,WAAM,aAAa,IAAI,OAAO;MAC9B,CACD,OAAO,UAAU;AAChB,SAAI,iBAAiB,SAAS,MAAM,SAAS,aAAc;AAE3D,aAAQ,MAAM,sDAAsD,MAAM;MAC1E;AAEJ,WAAO;MAEV;GACD,UAAU,EAAE;GACb;EACF,CAAC;;AAGJ,MAAa,sBAAsB,eAAe;CAChD,WAAW;EAAC;EAAgB;EAAW;EAAgB;CACvD,aAAa,EAAE;CACf,OAAO;CACR,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { computed, peek, update } from "../../core/signals/primitives.js";
|
|
2
|
+
import { defineBehavior } from "../../core/composition/create-composition.js";
|
|
3
|
+
import { ConcurrentRunner, Task } from "../../core/tasks/task.js";
|
|
4
|
+
import { createMachineReactor } from "../../core/reactors/create-machine-reactor.js";
|
|
5
|
+
import { isResolvedPresentation, isResolvedTrack } from "../../media/types/index.js";
|
|
6
|
+
import { findTrack, updateTrackInPresentation } from "../../media/utils/tracks.js";
|
|
7
|
+
import { AUDIO_TYPE_CONFIG, TEXT_TYPE_CONFIG, VIDEO_TYPE_CONFIG } from "./track-types.js";
|
|
8
|
+
import { fetchResolvable, getResponseText } from "../../network/fetch.js";
|
|
9
|
+
import { parseMediaPlaylist } from "../../media/hls/parse-media-playlist.js";
|
|
10
|
+
//#region src/playback/behaviors/resolve-track.ts
|
|
11
|
+
function setupTrackResolution({ state, config: { selectedKey, findTrackToResolve } }) {
|
|
12
|
+
const runner = new ConcurrentRunner();
|
|
13
|
+
const derivedStateSignal = computed(() => isResolvedPresentation(state.presentation.get()) ? "presentation-resolved" : "presentation-unresolved");
|
|
14
|
+
return createMachineReactor({
|
|
15
|
+
initial: "presentation-unresolved",
|
|
16
|
+
monitor: () => derivedStateSignal.get(),
|
|
17
|
+
states: {
|
|
18
|
+
"presentation-unresolved": {},
|
|
19
|
+
"presentation-resolved": {
|
|
20
|
+
entry: () => () => runner.abortAll(),
|
|
21
|
+
effects: [() => {
|
|
22
|
+
const presentation = peek(state.presentation);
|
|
23
|
+
const trackId = state[selectedKey].get();
|
|
24
|
+
if (!presentation || !trackId) return;
|
|
25
|
+
const track = findTrackToResolve(presentation, trackId);
|
|
26
|
+
if (!track || isResolvedTrack(track)) return;
|
|
27
|
+
runner.schedule(new Task(async (signal) => {
|
|
28
|
+
const mediaTrack = parseMediaPlaylist(await getResponseText(await fetchResolvable(track, { signal })), track);
|
|
29
|
+
update(state.presentation, (current) => isResolvedPresentation(current) ? updateTrackInPresentation(current, mediaTrack) : current);
|
|
30
|
+
}, { id: track.id }));
|
|
31
|
+
}]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const VIDEO_TRACK_RESOLUTION_CONFIG = {
|
|
37
|
+
...VIDEO_TYPE_CONFIG,
|
|
38
|
+
findTrackToResolve: (presentation, trackId) => findTrack(presentation, "video", trackId)
|
|
39
|
+
};
|
|
40
|
+
const AUDIO_TRACK_RESOLUTION_CONFIG = {
|
|
41
|
+
...AUDIO_TYPE_CONFIG,
|
|
42
|
+
findTrackToResolve: (presentation, trackId) => findTrack(presentation, "audio", trackId)
|
|
43
|
+
};
|
|
44
|
+
const TEXT_TRACK_RESOLUTION_CONFIG = {
|
|
45
|
+
...TEXT_TYPE_CONFIG,
|
|
46
|
+
findTrackToResolve: (presentation, trackId) => findTrack(presentation, "text", trackId)
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Resolve unresolved video tracks. Schedules a fetch task whenever the
|
|
50
|
+
* selected video track is partially resolved, parses the manifest, and
|
|
51
|
+
* writes the resolved track back into `state.presentation`.
|
|
52
|
+
*/
|
|
53
|
+
const resolveVideoTrack = defineBehavior({
|
|
54
|
+
stateKeys: ["presentation", "selectedVideoTrackId"],
|
|
55
|
+
contextKeys: [],
|
|
56
|
+
setup: ({ state, config = {} }) => setupTrackResolution({
|
|
57
|
+
state,
|
|
58
|
+
config: {
|
|
59
|
+
...VIDEO_TRACK_RESOLUTION_CONFIG,
|
|
60
|
+
...config
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* Resolve unresolved audio tracks. Same shape as `resolveVideoTrack`,
|
|
66
|
+
* narrowed to audio.
|
|
67
|
+
*/
|
|
68
|
+
const resolveAudioTrack = defineBehavior({
|
|
69
|
+
stateKeys: ["presentation", "selectedAudioTrackId"],
|
|
70
|
+
contextKeys: [],
|
|
71
|
+
setup: ({ state, config = {} }) => setupTrackResolution({
|
|
72
|
+
state,
|
|
73
|
+
config: {
|
|
74
|
+
...AUDIO_TRACK_RESOLUTION_CONFIG,
|
|
75
|
+
...config
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
});
|
|
79
|
+
/**
|
|
80
|
+
* Resolve unresolved text tracks. Same shape as `resolveVideoTrack`,
|
|
81
|
+
* narrowed to text.
|
|
82
|
+
*/
|
|
83
|
+
const resolveTextTrack = defineBehavior({
|
|
84
|
+
stateKeys: ["presentation", "selectedTextTrackId"],
|
|
85
|
+
contextKeys: [],
|
|
86
|
+
setup: ({ state, config = {} }) => setupTrackResolution({
|
|
87
|
+
state,
|
|
88
|
+
config: {
|
|
89
|
+
...TEXT_TRACK_RESOLUTION_CONFIG,
|
|
90
|
+
...config
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
});
|
|
94
|
+
//#endregion
|
|
95
|
+
export { resolveAudioTrack, resolveTextTrack, resolveVideoTrack };
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=resolve-track.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-track.js","names":[],"sources":["../../../../src/playback/behaviors/resolve-track.ts"],"sourcesContent":["import { defineBehavior } from '../../core/composition/create-composition';\nimport { createMachineReactor } from '../../core/reactors/create-machine-reactor';\nimport { computed, peek, type ReadonlySignal, type Signal, update } from '../../core/signals/primitives';\nimport { ConcurrentRunner, Task } from '../../core/tasks/task';\nimport { parseMediaPlaylist } from '../../media/hls/parse-media-playlist';\nimport type { MaybeResolvedPresentation, PartiallyResolvedTrack, ResolvedTrack } from '../../media/types';\nimport { isResolvedPresentation, isResolvedTrack } from '../../media/types';\nimport { findTrack, updateTrackInPresentation } from '../../media/utils/tracks';\nimport { fetchResolvable, getResponseText } from '../../network/fetch';\nimport { AUDIO_TYPE_CONFIG, TEXT_TYPE_CONFIG, VIDEO_TYPE_CONFIG } from './track-types';\n\n// ============================================================================\n// Specialization helper\n//\n// `setupTrackResolution` has the same shape as a Behavior `setup` function:\n// `({ state, config }) => cleanup`. Each `resolveXTrack` export below calls it\n// from inside its own `defineBehavior` setup, supplying its per-type config\n// inline. The orchestration — gate on a selection, short-circuit when the\n// track is already resolved or missing, schedule the fetch+parse, and patch\n// the resolved track back into `state.presentation` — is shared.\n// ============================================================================\n\n/**\n * State shape for track resolution. Uses `MaybeResolvedPresentation` so it\n * matches the engine's slot type; resolution narrows internally.\n */\nexport interface ResolveTrackState {\n presentation?: MaybeResolvedPresentation;\n selectedVideoTrackId?: string;\n selectedAudioTrackId?: string;\n selectedTextTrackId?: string;\n}\n\ntype SelectedTrackKey = 'selectedVideoTrackId' | 'selectedAudioTrackId' | 'selectedTextTrackId';\n\ntype ResolveTrackStateMap<K extends SelectedTrackKey> = {\n presentation: Signal<ResolveTrackState['presentation']>;\n} & { [P in K]: ReadonlySignal<ResolveTrackState[P]> };\n\ninterface TrackResolutionConfig<K extends SelectedTrackKey> {\n selectedKey: K;\n findTrackToResolve: (\n presentation: MaybeResolvedPresentation,\n trackId: string\n ) => PartiallyResolvedTrack | ResolvedTrack | undefined;\n}\n\nfunction setupTrackResolution<K extends SelectedTrackKey>({\n state,\n config: { selectedKey, findTrackToResolve },\n}: {\n state: ResolveTrackStateMap<K>;\n config: TrackResolutionConfig<K>;\n}) {\n // NOTE: This can/maybe will be pulled into a per-use case factory (e.g. something like createTaskRunner() with args TBD),\n // likely eventually passed down via config or a new \"definitions\" argument. This will allow us to decide if we want our task runner/scheduler\n // to e.g. run concurrently (like we currently are), serially with a queue, or abort the previous task and replace it with the newly scheduled one. (CJP).\n const runner = new ConcurrentRunner();\n\n // Reactor states model the FSM the previous effect-based body was\n // hand-rolling. 'presentation-resolved' is entered when the\n // presentation is fully parsed (has a Ham id + selectionSets); leaving\n // it (presentation cleared or reset to an unresolved value) aborts all\n // in-flight tasks via the entry-cleanup. Most URL changes go through\n // 'presentation-unresolved' naturally (set undefined → set new partial\n // → re-parse), so the common case is covered by state-exit alone; the\n // task body's commit-time id check covers the pathological\n // resolved→resolved-without-unresolved transition.\n const derivedStateSignal = computed(() =>\n isResolvedPresentation(state.presentation.get())\n ? ('presentation-resolved' as const)\n : ('presentation-unresolved' as const)\n );\n\n return createMachineReactor({\n initial: 'presentation-unresolved',\n monitor: () => derivedStateSignal.get(),\n states: {\n 'presentation-unresolved': {},\n 'presentation-resolved': {\n // `entry` runs on state entry; the function it returns is the\n // state-exit cleanup. Returning `() => runner.abortAll()` binds\n // abort-of-in-flight-resolutions to leaving 'presentation-resolved'\n // (presentation cleared/reset, or behavior destroyed) —\n // source-change cancellation expressed structurally through the\n // state machine.\n entry: () => () => runner.abortAll(),\n effects: [\n () => {\n // The reactor's state transitions handle relevant presentation\n // changes (presentation-resolved ↔ presentation-unresolved);\n // within 'presentation-resolved' we peek (untracked read) so\n // internal updates (segments added by sibling tasks) don't\n // re-fire the effect.\n const presentation = peek(state.presentation);\n const trackId = state[selectedKey].get();\n if (!presentation || !trackId) return;\n\n const track = findTrackToResolve(presentation, trackId);\n if (!track || isResolvedTrack(track)) return;\n\n runner.schedule(\n // NOTE: This can/maybe will be pulled into a per-use case factory (e.g. something like createResolveTrackTask(track, context, config)),\n // likely eventually passed down via config or a new \"definitions\" argument (CJP).\n new Task(\n async (signal) => {\n const response = await fetchResolvable(track, { signal });\n const text = await getResponseText(response);\n const mediaTrack = parseMediaPlaylist(text, track);\n\n // Updater handles undefined inputs by returning current\n // unchanged; isResolvedPresentation narrows for the patch.\n // State-exit on resolving→unresolved fires runner.abortAll\n // before any URL change settles, and per the Fetch spec the\n // signal abort cancels in-flight body reads — so by the\n // time we reach this point the presentation we resolved\n // against is the live one.\n update(state.presentation, (current) =>\n isResolvedPresentation(current) ? updateTrackInPresentation(current, mediaTrack) : current\n );\n },\n { id: track.id }\n )\n );\n },\n ],\n },\n },\n });\n}\n\n// ============================================================================\n// Per-helper-per-type configs — defaults that variants spread engine config over\n// ============================================================================\n\nconst VIDEO_TRACK_RESOLUTION_CONFIG = {\n ...VIDEO_TYPE_CONFIG,\n findTrackToResolve: (presentation: MaybeResolvedPresentation, trackId: string) =>\n findTrack(presentation, 'video', trackId),\n} as const;\n\nconst AUDIO_TRACK_RESOLUTION_CONFIG = {\n ...AUDIO_TYPE_CONFIG,\n findTrackToResolve: (presentation: MaybeResolvedPresentation, trackId: string) =>\n findTrack(presentation, 'audio', trackId),\n} as const;\n\nconst TEXT_TRACK_RESOLUTION_CONFIG = {\n ...TEXT_TYPE_CONFIG,\n findTrackToResolve: (presentation: MaybeResolvedPresentation, trackId: string) =>\n findTrack(presentation, 'text', trackId),\n} as const;\n\n// ============================================================================\n// Specialized exports — one per track type\n// ============================================================================\n\n/**\n * Resolve unresolved video tracks. Schedules a fetch task whenever the\n * selected video track is partially resolved, parses the manifest, and\n * writes the resolved track back into `state.presentation`.\n */\nexport const resolveVideoTrack = defineBehavior({\n stateKeys: ['presentation', 'selectedVideoTrackId'],\n contextKeys: [],\n setup: ({ state, config = {} }: { state: ResolveTrackStateMap<'selectedVideoTrackId'>; config?: object }) =>\n setupTrackResolution({\n state,\n config: { ...VIDEO_TRACK_RESOLUTION_CONFIG, ...config },\n }),\n});\n\n/**\n * Resolve unresolved audio tracks. Same shape as `resolveVideoTrack`,\n * narrowed to audio.\n */\nexport const resolveAudioTrack = defineBehavior({\n stateKeys: ['presentation', 'selectedAudioTrackId'],\n contextKeys: [],\n setup: ({ state, config = {} }: { state: ResolveTrackStateMap<'selectedAudioTrackId'>; config?: object }) =>\n setupTrackResolution({\n state,\n config: { ...AUDIO_TRACK_RESOLUTION_CONFIG, ...config },\n }),\n});\n\n/**\n * Resolve unresolved text tracks. Same shape as `resolveVideoTrack`,\n * narrowed to text.\n */\nexport const resolveTextTrack = defineBehavior({\n stateKeys: ['presentation', 'selectedTextTrackId'],\n contextKeys: [],\n setup: ({ state, config = {} }: { state: ResolveTrackStateMap<'selectedTextTrackId'>; config?: object }) =>\n setupTrackResolution({\n state,\n config: { ...TEXT_TRACK_RESOLUTION_CONFIG, ...config },\n }),\n});\n"],"mappings":";;;;;;;;;;AA+CA,SAAS,qBAAiD,EACxD,OACA,QAAQ,EAAE,aAAa,wBAItB;CAID,MAAM,SAAS,IAAI,kBAAkB;CAWrC,MAAM,qBAAqB,eACzB,uBAAuB,MAAM,aAAa,KAAK,CAAC,GAC3C,0BACA,0BACN;AAED,QAAO,qBAAqB;EAC1B,SAAS;EACT,eAAe,mBAAmB,KAAK;EACvC,QAAQ;GACN,2BAA2B,EAAE;GAC7B,yBAAyB;IAOvB,mBAAmB,OAAO,UAAU;IACpC,SAAS,OACD;KAMJ,MAAM,eAAe,KAAK,MAAM,aAAa;KAC7C,MAAM,UAAU,MAAM,aAAa,KAAK;AACxC,SAAI,CAAC,gBAAgB,CAAC,QAAS;KAE/B,MAAM,QAAQ,mBAAmB,cAAc,QAAQ;AACvD,SAAI,CAAC,SAAS,gBAAgB,MAAM,CAAE;AAEtC,YAAO,SAGL,IAAI,KACF,OAAO,WAAW;MAGhB,MAAM,aAAa,mBADN,MAAM,gBADF,MAAM,gBAAgB,OAAO,EAAE,QAAQ,CAAC,CACb,EACA,MAAM;AASlD,aAAO,MAAM,eAAe,YAC1B,uBAAuB,QAAQ,GAAG,0BAA0B,SAAS,WAAW,GAAG,QACpF;QAEH,EAAE,IAAI,MAAM,IAAI,CACjB,CACF;MAEJ;IACF;GACF;EACF,CAAC;;AAOJ,MAAM,gCAAgC;CACpC,GAAG;CACH,qBAAqB,cAAyC,YAC5D,UAAU,cAAc,SAAS,QAAQ;CAC5C;AAED,MAAM,gCAAgC;CACpC,GAAG;CACH,qBAAqB,cAAyC,YAC5D,UAAU,cAAc,SAAS,QAAQ;CAC5C;AAED,MAAM,+BAA+B;CACnC,GAAG;CACH,qBAAqB,cAAyC,YAC5D,UAAU,cAAc,QAAQ,QAAQ;CAC3C;;;;;;AAWD,MAAa,oBAAoB,eAAe;CAC9C,WAAW,CAAC,gBAAgB,uBAAuB;CACnD,aAAa,EAAE;CACf,QAAQ,EAAE,OAAO,SAAS,EAAE,OAC1B,qBAAqB;EACnB;EACA,QAAQ;GAAE,GAAG;GAA+B,GAAG;GAAQ;EACxD,CAAC;CACL,CAAC;;;;;AAMF,MAAa,oBAAoB,eAAe;CAC9C,WAAW,CAAC,gBAAgB,uBAAuB;CACnD,aAAa,EAAE;CACf,QAAQ,EAAE,OAAO,SAAS,EAAE,OAC1B,qBAAqB;EACnB;EACA,QAAQ;GAAE,GAAG;GAA+B,GAAG;GAAQ;EACxD,CAAC;CACL,CAAC;;;;;AAMF,MAAa,mBAAmB,eAAe;CAC7C,WAAW,CAAC,gBAAgB,sBAAsB;CAClD,aAAa,EAAE;CACf,QAAQ,EAAE,OAAO,SAAS,EAAE,OAC1B,qBAAqB;EACnB;EACA,QAAQ;GAAE,GAAG;GAA8B,GAAG;GAAQ;EACvD,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { computed } from "../../core/signals/primitives.js";
|
|
2
|
+
import { defineBehavior } from "../../core/composition/create-composition.js";
|
|
3
|
+
import { createMachineReactor } from "../../core/reactors/create-machine-reactor.js";
|
|
4
|
+
import { isResolvedPresentation } from "../../media/types/index.js";
|
|
5
|
+
import { AUDIO_TYPE_CONFIG, TEXT_TYPE_CONFIG, VIDEO_TYPE_CONFIG } from "./track-types.js";
|
|
6
|
+
import { pickFirstTrackId, pickTextTrack } from "../../media/primitives/select-tracks.js";
|
|
7
|
+
//#region src/playback/behaviors/select-tracks.ts
|
|
8
|
+
/**
|
|
9
|
+
* **Default audio/text track selection on src load / unselect on src unload.**
|
|
10
|
+
* When a presentation is resolved, sets `selectedAudioTrackId` /
|
|
11
|
+
* `selectedTextTrackId` to a per-type-picker default if no selection already
|
|
12
|
+
* exists. When the presentation is unset/reset (transitions back to
|
|
13
|
+
* unresolved), clears the selection so a stale id from the previous source
|
|
14
|
+
* doesn't persist.
|
|
15
|
+
*
|
|
16
|
+
* Lifecycle-driven: each transition fires its work once. Does not police
|
|
17
|
+
* the selection between transitions; external writes (user picks) are left
|
|
18
|
+
* alone.
|
|
19
|
+
*
|
|
20
|
+
* Picker is config-driven: each per-type export wires a sensible default
|
|
21
|
+
* (`pickFirstTrackId` for audio, `pickTextTrack` for text) and the caller
|
|
22
|
+
* can supply their own via `config.picker` for custom selection logic
|
|
23
|
+
* (language preferences, default-track handling, etc.). The behavior's
|
|
24
|
+
* `config` is forwarded to the picker as its second argument, so options
|
|
25
|
+
* like `preferredAudioLanguage` / `preferredSubtitleLanguage` reach the
|
|
26
|
+
* picker without an intermediate wrapping layer.
|
|
27
|
+
*
|
|
28
|
+
* Compose `selectVideoTrack` for the simple "pick a default video track"
|
|
29
|
+
* behavior, or `switchVideoQuality` (`./quality-switching.ts`) for the
|
|
30
|
+
* ABR-driven variant — they're alternatives, not stackable (both write
|
|
31
|
+
* `selectedVideoTrackId`). The simple variant tree-shakes out the
|
|
32
|
+
* ABR machinery (bandwidth-estimator, quality-selection algorithms).
|
|
33
|
+
*/
|
|
34
|
+
function setupTrackSelection({ state, config: { selectedKey, picker, pickerConfig } }) {
|
|
35
|
+
const derivedStateSignal = computed(() => isResolvedPresentation(state.presentation.get()) ? "presentation-resolved" : "presentation-unresolved");
|
|
36
|
+
return createMachineReactor({
|
|
37
|
+
initial: "presentation-unresolved",
|
|
38
|
+
monitor: () => derivedStateSignal.get(),
|
|
39
|
+
states: {
|
|
40
|
+
"presentation-unresolved": {},
|
|
41
|
+
"presentation-resolved": { entry: () => {
|
|
42
|
+
if (!state[selectedKey].get()) {
|
|
43
|
+
const id = picker(state.presentation.get(), pickerConfig);
|
|
44
|
+
if (id) state[selectedKey].set(id);
|
|
45
|
+
}
|
|
46
|
+
return () => state[selectedKey].set(void 0);
|
|
47
|
+
} }
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** Default video picker: first track in the video selection set. */
|
|
52
|
+
const defaultVideoPicker = (presentation) => pickFirstTrackId(presentation, "video");
|
|
53
|
+
const VIDEO_TRACK_SELECTION_CONFIG = {
|
|
54
|
+
...VIDEO_TYPE_CONFIG,
|
|
55
|
+
picker: defaultVideoPicker
|
|
56
|
+
};
|
|
57
|
+
/** Default audio picker: first track in the audio selection set. */
|
|
58
|
+
const defaultAudioPicker = (presentation) => pickFirstTrackId(presentation, "audio");
|
|
59
|
+
const AUDIO_TRACK_SELECTION_CONFIG = {
|
|
60
|
+
...AUDIO_TYPE_CONFIG,
|
|
61
|
+
picker: defaultAudioPicker
|
|
62
|
+
};
|
|
63
|
+
const TEXT_TRACK_SELECTION_CONFIG = {
|
|
64
|
+
...TEXT_TYPE_CONFIG,
|
|
65
|
+
picker: pickTextTrack
|
|
66
|
+
};
|
|
67
|
+
defineBehavior({
|
|
68
|
+
stateKeys: ["presentation", "selectedVideoTrackId"],
|
|
69
|
+
contextKeys: [],
|
|
70
|
+
setup: ({ state, config }) => setupTrackSelection({
|
|
71
|
+
state,
|
|
72
|
+
config: {
|
|
73
|
+
...VIDEO_TRACK_SELECTION_CONFIG,
|
|
74
|
+
picker: config?.picker ?? VIDEO_TRACK_SELECTION_CONFIG.picker,
|
|
75
|
+
pickerConfig: config
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
});
|
|
79
|
+
/**
|
|
80
|
+
* Select an audio track when a presentation loads. Clears the selection
|
|
81
|
+
* on src unload.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* const reactor = selectAudioTrack.setup({ state });
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* // Custom picker with language preference
|
|
88
|
+
* const reactor = selectAudioTrack.setup({
|
|
89
|
+
* state,
|
|
90
|
+
* config: { preferredAudioLanguage: 'en', picker: myLanguageAwarePicker },
|
|
91
|
+
* });
|
|
92
|
+
*/
|
|
93
|
+
const selectAudioTrack = defineBehavior({
|
|
94
|
+
stateKeys: ["presentation", "selectedAudioTrackId"],
|
|
95
|
+
contextKeys: [],
|
|
96
|
+
setup: ({ state, config }) => setupTrackSelection({
|
|
97
|
+
state,
|
|
98
|
+
config: {
|
|
99
|
+
...AUDIO_TRACK_SELECTION_CONFIG,
|
|
100
|
+
picker: config?.picker ?? AUDIO_TRACK_SELECTION_CONFIG.picker,
|
|
101
|
+
pickerConfig: config
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
});
|
|
105
|
+
/**
|
|
106
|
+
* Select a text track based on user preferences (preferred language,
|
|
107
|
+
* default-track auto-select, forced-track filtering). Clears the selection
|
|
108
|
+
* on src unload.
|
|
109
|
+
*
|
|
110
|
+
* Unlike audio selection, the default text picker returns `undefined` when
|
|
111
|
+
* no preference matches, leaving the selection unset — text-track
|
|
112
|
+
* selection is user opt-in.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* const reactor = selectTextTrack.setup({ state, config: { preferredSubtitleLanguage: 'en' } });
|
|
116
|
+
*/
|
|
117
|
+
const selectTextTrack = defineBehavior({
|
|
118
|
+
stateKeys: ["presentation", "selectedTextTrackId"],
|
|
119
|
+
contextKeys: [],
|
|
120
|
+
setup: ({ state, config }) => setupTrackSelection({
|
|
121
|
+
state,
|
|
122
|
+
config: {
|
|
123
|
+
...TEXT_TRACK_SELECTION_CONFIG,
|
|
124
|
+
picker: config?.picker ?? TEXT_TRACK_SELECTION_CONFIG.picker,
|
|
125
|
+
pickerConfig: config
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
});
|
|
129
|
+
//#endregion
|
|
130
|
+
export { selectAudioTrack, selectTextTrack };
|
|
131
|
+
|
|
132
|
+
//# sourceMappingURL=select-tracks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-tracks.js","names":[],"sources":["../../../../src/playback/behaviors/select-tracks.ts"],"sourcesContent":["/**\n * **Default audio/text track selection on src load / unselect on src unload.**\n * When a presentation is resolved, sets `selectedAudioTrackId` /\n * `selectedTextTrackId` to a per-type-picker default if no selection already\n * exists. When the presentation is unset/reset (transitions back to\n * unresolved), clears the selection so a stale id from the previous source\n * doesn't persist.\n *\n * Lifecycle-driven: each transition fires its work once. Does not police\n * the selection between transitions; external writes (user picks) are left\n * alone.\n *\n * Picker is config-driven: each per-type export wires a sensible default\n * (`pickFirstTrackId` for audio, `pickTextTrack` for text) and the caller\n * can supply their own via `config.picker` for custom selection logic\n * (language preferences, default-track handling, etc.). The behavior's\n * `config` is forwarded to the picker as its second argument, so options\n * like `preferredAudioLanguage` / `preferredSubtitleLanguage` reach the\n * picker without an intermediate wrapping layer.\n *\n * Compose `selectVideoTrack` for the simple \"pick a default video track\"\n * behavior, or `switchVideoQuality` (`./quality-switching.ts`) for the\n * ABR-driven variant — they're alternatives, not stackable (both write\n * `selectedVideoTrackId`). The simple variant tree-shakes out the\n * ABR machinery (bandwidth-estimator, quality-selection algorithms).\n */\n\nimport { defineBehavior } from '../../core/composition/create-composition';\nimport { createMachineReactor } from '../../core/reactors/create-machine-reactor';\nimport { computed, type ReadonlySignal, type Signal } from '../../core/signals/primitives';\nimport {\n type AudioSelectionConfig,\n pickFirstTrackId,\n pickTextTrack,\n type TextSelectionConfig,\n type TrackPicker,\n type TrackSelectionState,\n type VideoSelectionConfig,\n} from '../../media/primitives/select-tracks';\nimport { isResolvedPresentation } from '../../media/types';\nimport { AUDIO_TYPE_CONFIG, TEXT_TYPE_CONFIG, VIDEO_TYPE_CONFIG } from './track-types';\n\n// ============================================================================\n// Specialization helper\n//\n// `setupTrackSelection` has the same shape as a Behavior `setup` function:\n// `({ state, config }) => Reactor`. Each `selectXTrack` export below calls\n// it from inside its own `defineBehavior` setup, supplying its per-type\n// `selectedKey`, default picker, and forwarded picker config. The lifecycle\n// — pick on entering 'presentation-resolved' if not already selected; clear\n// on entering 'presentation-unresolved' — is shared.\n// ============================================================================\n\ntype SelectedTrackKey = 'selectedVideoTrackId' | 'selectedAudioTrackId' | 'selectedTextTrackId';\n\ntype SelectStateMap<K extends SelectedTrackKey> = {\n presentation: ReadonlySignal<TrackSelectionState['presentation']>;\n} & { [P in K]: Signal<TrackSelectionState[P]> };\n\ninterface TrackSelectionSetupConfig<K extends SelectedTrackKey, PickerConfig> {\n selectedKey: K;\n picker: TrackPicker<PickerConfig>;\n pickerConfig?: PickerConfig;\n}\n\nfunction setupTrackSelection<K extends SelectedTrackKey, PickerConfig>({\n state,\n config: { selectedKey, picker, pickerConfig },\n}: {\n state: SelectStateMap<K>;\n config: TrackSelectionSetupConfig<K, PickerConfig>;\n}) {\n const derivedStateSignal = computed(() =>\n isResolvedPresentation(state.presentation.get())\n ? ('presentation-resolved' as const)\n : ('presentation-unresolved' as const)\n );\n\n return createMachineReactor({\n initial: 'presentation-unresolved',\n monitor: () => derivedStateSignal.get(),\n states: {\n 'presentation-unresolved': {},\n 'presentation-resolved': {\n // Entry: pick a default on entering presentation-resolved if none\n // is set. External writes (user picks, ABR) that already populated\n // the slot are left alone.\n //\n // The returned cleanup runs on state exit — which fires on src\n // unload (presentation-resolved → presentation-unresolved) AND on\n // behavior destroy (presentation-resolved → destroying →\n // destroyed). Putting the clear here rather than as\n // presentation-unresolved.entry is more cohesive (operation +\n // cleanup co-located) and correctly covers destroy (destroy\n // doesn't pass through presentation-unresolved).\n entry: () => {\n if (!state[selectedKey].get()) {\n // `state.presentation.get()` is non-null inside this entry —\n // the reactor's `'presentation-resolved'` gate is exactly\n // `isResolvedPresentation(state.presentation.get())`, which\n // requires a truthy Presentation.\n const id = picker(state.presentation.get()!, pickerConfig);\n if (id) state[selectedKey].set(id);\n }\n return () => state[selectedKey].set(undefined);\n },\n },\n },\n });\n}\n\n// ============================================================================\n// Per-helper-per-type configs — defaults that variants spread engine config over\n//\n// The engine-facing config carries `picker?` (optional override) plus\n// fields the default picker consults (preferred language, etc.). The\n// variant resolves the final picker (engine override or default) and\n// forwards the whole engine config as `pickerConfig` so rich pickers can\n// read their options.\n// ============================================================================\n\n/** Default video picker: first track in the video selection set. */\nconst defaultVideoPicker: TrackPicker = (presentation) => pickFirstTrackId(presentation, 'video');\n\nconst VIDEO_TRACK_SELECTION_CONFIG = {\n ...VIDEO_TYPE_CONFIG,\n picker: defaultVideoPicker,\n} as const;\n\n/** Default audio picker: first track in the audio selection set. */\nconst defaultAudioPicker: TrackPicker = (presentation) => pickFirstTrackId(presentation, 'audio');\n\nconst AUDIO_TRACK_SELECTION_CONFIG = {\n ...AUDIO_TYPE_CONFIG,\n picker: defaultAudioPicker,\n} as const;\n\nconst TEXT_TRACK_SELECTION_CONFIG = {\n ...TEXT_TYPE_CONFIG,\n picker: pickTextTrack,\n} as const;\n\n// ============================================================================\n// Specialized exports — one per track type\n// ============================================================================\n\n/**\n * Config for `selectVideoTrack`. Pass `picker` to fully override selection\n * logic; otherwise the default `pickFirstTrackId` is used.\n */\nexport interface SelectVideoTrackConfig extends Omit<VideoSelectionConfig, 'type'> {\n picker?: TrackPicker<SelectVideoTrackConfig>;\n}\n\n/**\n * Select a video track when a presentation loads. Clears the selection on\n * src unload.\n *\n * This is the simple, non-ABR counterpart to `switchVideoQuality` — compose\n * one or the other, not both (both write `selectedVideoTrackId`). Composing\n * `selectVideoTrack` alone tree-shakes out the ABR code path\n * (bandwidth-estimator, quality-selection); use it for sources without\n * meaningful quality variants, test setups, or players that intentionally\n * pin a quality.\n *\n * @example\n * const reactor = selectVideoTrack.setup({ state });\n */\nexport const selectVideoTrack = defineBehavior({\n stateKeys: ['presentation', 'selectedVideoTrackId'],\n contextKeys: [],\n setup: ({ state, config }: { state: SelectStateMap<'selectedVideoTrackId'>; config?: SelectVideoTrackConfig }) =>\n setupTrackSelection({\n state,\n config: {\n ...VIDEO_TRACK_SELECTION_CONFIG,\n picker: config?.picker ?? VIDEO_TRACK_SELECTION_CONFIG.picker,\n pickerConfig: config,\n },\n }),\n});\n\n/**\n * Config for `selectAudioTrack`. Pass `picker` to fully override selection\n * logic; otherwise the default `pickFirstTrackId` is used (which ignores\n * the other fields — they reach the picker as its second arg for callers\n * who supply a richer picker, like a language-aware one).\n */\nexport interface SelectAudioTrackConfig extends Omit<AudioSelectionConfig, 'type'> {\n picker?: TrackPicker<SelectAudioTrackConfig>;\n}\n\n/**\n * Select an audio track when a presentation loads. Clears the selection\n * on src unload.\n *\n * @example\n * const reactor = selectAudioTrack.setup({ state });\n *\n * @example\n * // Custom picker with language preference\n * const reactor = selectAudioTrack.setup({\n * state,\n * config: { preferredAudioLanguage: 'en', picker: myLanguageAwarePicker },\n * });\n */\nexport const selectAudioTrack = defineBehavior({\n stateKeys: ['presentation', 'selectedAudioTrackId'],\n contextKeys: [],\n setup: ({ state, config }: { state: SelectStateMap<'selectedAudioTrackId'>; config?: SelectAudioTrackConfig }) =>\n setupTrackSelection({\n state,\n config: {\n ...AUDIO_TRACK_SELECTION_CONFIG,\n picker: config?.picker ?? AUDIO_TRACK_SELECTION_CONFIG.picker,\n pickerConfig: config,\n },\n }),\n});\n\n/**\n * Config for `selectTextTrack`. Pass `picker` to fully override selection\n * logic; otherwise the default `pickTextTrack` is used, which honors the\n * other fields.\n */\nexport interface SelectTextTrackConfig extends TextSelectionConfig {\n picker?: TrackPicker<SelectTextTrackConfig>;\n}\n\n/**\n * Select a text track based on user preferences (preferred language,\n * default-track auto-select, forced-track filtering). Clears the selection\n * on src unload.\n *\n * Unlike audio selection, the default text picker returns `undefined` when\n * no preference matches, leaving the selection unset — text-track\n * selection is user opt-in.\n *\n * @example\n * const reactor = selectTextTrack.setup({ state, config: { preferredSubtitleLanguage: 'en' } });\n */\nexport const selectTextTrack = defineBehavior({\n stateKeys: ['presentation', 'selectedTextTrackId'],\n contextKeys: [],\n setup: ({ state, config }: { state: SelectStateMap<'selectedTextTrackId'>; config?: SelectTextTrackConfig }) =>\n setupTrackSelection({\n state,\n config: {\n ...TEXT_TRACK_SELECTION_CONFIG,\n picker: config?.picker ?? TEXT_TRACK_SELECTION_CONFIG.picker,\n pickerConfig: config,\n },\n }),\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiEA,SAAS,oBAA8D,EACrE,OACA,QAAQ,EAAE,aAAa,QAAQ,kBAI9B;CACD,MAAM,qBAAqB,eACzB,uBAAuB,MAAM,aAAa,KAAK,CAAC,GAC3C,0BACA,0BACN;AAED,QAAO,qBAAqB;EAC1B,SAAS;EACT,eAAe,mBAAmB,KAAK;EACvC,QAAQ;GACN,2BAA2B,EAAE;GAC7B,yBAAyB,EAYvB,aAAa;AACX,QAAI,CAAC,MAAM,aAAa,KAAK,EAAE;KAK7B,MAAM,KAAK,OAAO,MAAM,aAAa,KAAK,EAAG,aAAa;AAC1D,SAAI,GAAI,OAAM,aAAa,IAAI,GAAG;;AAEpC,iBAAa,MAAM,aAAa,IAAI,KAAA,EAAU;MAEjD;GACF;EACF,CAAC;;;AAcJ,MAAM,sBAAmC,iBAAiB,iBAAiB,cAAc,QAAQ;AAEjG,MAAM,+BAA+B;CACnC,GAAG;CACH,QAAQ;CACT;;AAGD,MAAM,sBAAmC,iBAAiB,iBAAiB,cAAc,QAAQ;AAEjG,MAAM,+BAA+B;CACnC,GAAG;CACH,QAAQ;CACT;AAED,MAAM,8BAA8B;CAClC,GAAG;CACH,QAAQ;CACT;AA4B+B,eAAe;CAC7C,WAAW,CAAC,gBAAgB,uBAAuB;CACnD,aAAa,EAAE;CACf,QAAQ,EAAE,OAAO,aACf,oBAAoB;EAClB;EACA,QAAQ;GACN,GAAG;GACH,QAAQ,QAAQ,UAAU,6BAA6B;GACvD,cAAc;GACf;EACF,CAAC;CACL,CAAC;;;;;;;;;;;;;;;AA0BF,MAAa,mBAAmB,eAAe;CAC7C,WAAW,CAAC,gBAAgB,uBAAuB;CACnD,aAAa,EAAE;CACf,QAAQ,EAAE,OAAO,aACf,oBAAoB;EAClB;EACA,QAAQ;GACN,GAAG;GACH,QAAQ,QAAQ,UAAU,6BAA6B;GACvD,cAAc;GACf;EACF,CAAC;CACL,CAAC;;;;;;;;;;;;;AAuBF,MAAa,kBAAkB,eAAe;CAC5C,WAAW,CAAC,gBAAgB,sBAAsB;CAClD,aAAa,EAAE;CACf,QAAQ,EAAE,OAAO,aACf,oBAAoB;EAClB;EACA,QAAQ;GACN,GAAG;GACH,QAAQ,QAAQ,UAAU,4BAA4B;GACtD,cAAc;GACf;EACF,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { computed, peek } from "../../core/signals/primitives.js";
|
|
2
|
+
import { defineBehavior } from "../../core/composition/create-composition.js";
|
|
3
|
+
import { effect } from "../../core/signals/effect.js";
|
|
4
|
+
import { isStandardPreload } from "../../media/utils/preload.js";
|
|
5
|
+
//#region src/playback/behaviors/sync-preload.ts
|
|
6
|
+
/**
|
|
7
|
+
* **Bidirectional sync between `state.preload` and `mediaElement.preload`.**
|
|
8
|
+
*
|
|
9
|
+
* Two effects:
|
|
10
|
+
* - **Read (DOM → state)** — on `context.mediaElement` swap or
|
|
11
|
+
* `state.presentation.url` change, copies `mediaElement.preload` into
|
|
12
|
+
* `state.preload` if it's a W3C value and `state.preload` isn't holding
|
|
13
|
+
* an extended (non-W3C) value. When the DOM has no W3C opinion and
|
|
14
|
+
* `state.preload` is undefined, backfills from `config.defaultPreload`
|
|
15
|
+
* (default-default `'metadata'`) so `state.preload` is never undefined
|
|
16
|
+
* in steady state.
|
|
17
|
+
* - **Write (state → DOM)** — on `state.preload` change or
|
|
18
|
+
* `context.mediaElement` swap, writes `state.preload` back to
|
|
19
|
+
* `mediaElement.preload` if the value is W3C.
|
|
20
|
+
*
|
|
21
|
+
* Extended values (e.g. `'canplay'`) written externally to `state.preload`
|
|
22
|
+
* are sticky: read won't overwrite them, write won't push them to the DOM.
|
|
23
|
+
* All writes are deduped to break echo loops and avoid spurious re-triggers
|
|
24
|
+
* downstream (notably `resolvePresentation`, which reads `state.preload`).
|
|
25
|
+
*/
|
|
26
|
+
function syncPreloadSetup({ state, context, config }) {
|
|
27
|
+
const defaultPreload = config?.defaultPreload ?? "metadata";
|
|
28
|
+
const presentationUrl = computed(() => state.presentation.get()?.url);
|
|
29
|
+
const cleanupRead = effect(() => {
|
|
30
|
+
presentationUrl.get();
|
|
31
|
+
const mediaElement = context.mediaElement.get();
|
|
32
|
+
const current = peek(state.preload);
|
|
33
|
+
if (current !== void 0 && !isStandardPreload(current)) return;
|
|
34
|
+
const target = mediaElement && isStandardPreload(mediaElement.preload) ? mediaElement.preload : current === void 0 ? defaultPreload : void 0;
|
|
35
|
+
if (target === void 0 || target === current) return;
|
|
36
|
+
state.preload.set(target);
|
|
37
|
+
});
|
|
38
|
+
const cleanupWrite = effect(() => {
|
|
39
|
+
const next = state.preload.get();
|
|
40
|
+
const mediaElement = context.mediaElement.get();
|
|
41
|
+
if (!mediaElement) return;
|
|
42
|
+
if (!isStandardPreload(next)) return;
|
|
43
|
+
if (mediaElement.preload === next) return;
|
|
44
|
+
mediaElement.preload = next;
|
|
45
|
+
});
|
|
46
|
+
return () => {
|
|
47
|
+
cleanupRead();
|
|
48
|
+
cleanupWrite();
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const syncPreload = defineBehavior({
|
|
52
|
+
stateKeys: ["preload", "presentation"],
|
|
53
|
+
contextKeys: ["mediaElement"],
|
|
54
|
+
setup: syncPreloadSetup
|
|
55
|
+
});
|
|
56
|
+
//#endregion
|
|
57
|
+
export { syncPreload };
|
|
58
|
+
|
|
59
|
+
//# sourceMappingURL=sync-preload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-preload.js","names":[],"sources":["../../../../src/playback/behaviors/sync-preload.ts"],"sourcesContent":["/**\n * **Bidirectional sync between `state.preload` and `mediaElement.preload`.**\n *\n * Two effects:\n * - **Read (DOM → state)** — on `context.mediaElement` swap or\n * `state.presentation.url` change, copies `mediaElement.preload` into\n * `state.preload` if it's a W3C value and `state.preload` isn't holding\n * an extended (non-W3C) value. When the DOM has no W3C opinion and\n * `state.preload` is undefined, backfills from `config.defaultPreload`\n * (default-default `'metadata'`) so `state.preload` is never undefined\n * in steady state.\n * - **Write (state → DOM)** — on `state.preload` change or\n * `context.mediaElement` swap, writes `state.preload` back to\n * `mediaElement.preload` if the value is W3C.\n *\n * Extended values (e.g. `'canplay'`) written externally to `state.preload`\n * are sticky: read won't overwrite them, write won't push them to the DOM.\n * All writes are deduped to break echo loops and avoid spurious re-triggers\n * downstream (notably `resolvePresentation`, which reads `state.preload`).\n */\nimport { defineBehavior } from '../../core/composition/create-composition';\nimport { effect } from '../../core/signals/effect';\nimport { computed, peek, type ReadonlySignal, type Signal } from '../../core/signals/primitives';\nimport type { MediaElementLike } from '../../media/types';\nimport { DEFAULT_PRELOAD, isStandardPreload, type StandardPreload } from '../../media/utils/preload';\nimport type { PresentationState } from './resolve-presentation';\n\nexport interface SyncPreloadConfig {\n /**\n * Backfill applied to `state.preload` when neither the host element nor\n * external code has supplied a W3C value. Defaults to `'metadata'`.\n */\n defaultPreload?: StandardPreload;\n}\n\ntype State = Pick<PresentationState, 'preload' | 'presentation'>;\n\nfunction syncPreloadSetup({\n state,\n context,\n config,\n}: {\n state: {\n preload: Signal<State['preload']>;\n presentation: ReadonlySignal<State['presentation']>;\n };\n context: { mediaElement: ReadonlySignal<MediaElementLike | undefined> };\n config?: SyncPreloadConfig;\n}): () => void {\n const defaultPreload: StandardPreload = config?.defaultPreload ?? DEFAULT_PRELOAD;\n const presentationUrl = computed(() => state.presentation.get()?.url);\n\n // Read must be registered before write: effects re-run in registration\n // order (see core/signals/effect.ts → runPending). On a shared-signal\n // change (e.g. `context.mediaElement` swap), read fires first and gets to\n // claim `state.preload`, giving \"most-recent-wins on attach\" — a freshly\n // mounted <video> with a W3C `preload` attribute overrides whatever\n // `state.preload` previously held. Swap the order or split these into\n // separate behaviors and the \"most-recent-wins on attach\" test pins the\n // regression.\n const cleanupRead = effect(() => {\n presentationUrl.get();\n const mediaElement = context.mediaElement.get();\n // peek (not get): external writes to state.preload shouldn't re-trigger\n // this effect, only mediaElement / presentation-url changes should.\n const current = peek(state.preload);\n // Extended sticky: leave non-W3C values (e.g. 'canplay') alone.\n if (current !== undefined && !isStandardPreload(current)) return;\n\n const target: StandardPreload | undefined =\n mediaElement && isStandardPreload(mediaElement.preload)\n ? mediaElement.preload\n : current === undefined\n ? defaultPreload\n : undefined;\n if (target === undefined || target === current) return;\n state.preload.set(target);\n });\n\n const cleanupWrite = effect(() => {\n const next = state.preload.get();\n const mediaElement = context.mediaElement.get();\n if (!mediaElement) return;\n if (!isStandardPreload(next)) return;\n if (mediaElement.preload === next) return;\n mediaElement.preload = next;\n });\n\n return () => {\n cleanupRead();\n cleanupWrite();\n };\n}\n\nexport const syncPreload = defineBehavior({\n stateKeys: ['preload', 'presentation'],\n contextKeys: ['mediaElement'],\n setup: syncPreloadSetup,\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,SAAS,iBAAiB,EACxB,OACA,SACA,UAQa;CACb,MAAM,iBAAkC,QAAQ,kBAAA;CAChD,MAAM,kBAAkB,eAAe,MAAM,aAAa,KAAK,EAAE,IAAI;CAUrE,MAAM,cAAc,aAAa;AAC/B,kBAAgB,KAAK;EACrB,MAAM,eAAe,QAAQ,aAAa,KAAK;EAG/C,MAAM,UAAU,KAAK,MAAM,QAAQ;AAEnC,MAAI,YAAY,KAAA,KAAa,CAAC,kBAAkB,QAAQ,CAAE;EAE1D,MAAM,SACJ,gBAAgB,kBAAkB,aAAa,QAAQ,GACnD,aAAa,UACb,YAAY,KAAA,IACV,iBACA,KAAA;AACR,MAAI,WAAW,KAAA,KAAa,WAAW,QAAS;AAChD,QAAM,QAAQ,IAAI,OAAO;GACzB;CAEF,MAAM,eAAe,aAAa;EAChC,MAAM,OAAO,MAAM,QAAQ,KAAK;EAChC,MAAM,eAAe,QAAQ,aAAa,KAAK;AAC/C,MAAI,CAAC,aAAc;AACnB,MAAI,CAAC,kBAAkB,KAAK,CAAE;AAC9B,MAAI,aAAa,YAAY,KAAM;AACnC,eAAa,UAAU;GACvB;AAEF,cAAa;AACX,eAAa;AACb,gBAAc;;;AAIlB,MAAa,cAAc,eAAe;CACxC,WAAW,CAAC,WAAW,eAAe;CACtC,aAAa,CAAC,eAAe;CAC7B,OAAO;CACR,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//#region src/playback/behaviors/track-types.ts
|
|
2
|
+
/**
|
|
3
|
+
* **Per-type config bundles for per-type behavior variants.**
|
|
4
|
+
*
|
|
5
|
+
* Each `*_TYPE_CONFIG` constant names the per-type slot keys that
|
|
6
|
+
* per-type-variant setup-shape helpers consume. Variants reference the
|
|
7
|
+
* shared constant at their `defineBehavior` setup body rather than
|
|
8
|
+
* constructing the config inline, so the per-type identity (which state
|
|
9
|
+
* slot, which context slot, which discriminant) lives in one place per
|
|
10
|
+
* type.
|
|
11
|
+
*
|
|
12
|
+
* Variants spread their composition-time `config` over the defaults so
|
|
13
|
+
* engines can layer composition-supplied additions on top (e.g. a
|
|
14
|
+
* custom fetch closure, a non-default segment resolver). Defaults
|
|
15
|
+
* first, engine config second.
|
|
16
|
+
*
|
|
17
|
+
* Helpers continue to consume their slice via the existing typed-key
|
|
18
|
+
* generics (`<K extends SelectedTrackKey>` etc.); the extra fields on
|
|
19
|
+
* the config object (carrying facets other helpers care about) are fine
|
|
20
|
+
* under structural typing.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Type-identity bundle for video-track-typed behaviors.
|
|
24
|
+
*
|
|
25
|
+
* @see setupVideoBufferActors, loadVideoSegments
|
|
26
|
+
*/
|
|
27
|
+
const VIDEO_TYPE_CONFIG = {
|
|
28
|
+
type: "video",
|
|
29
|
+
selectedKey: "selectedVideoTrackId",
|
|
30
|
+
actorKey: "videoBufferActor",
|
|
31
|
+
loaderKey: "videoSegmentLoaderActor"
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Type-identity bundle for audio-track-typed behaviors.
|
|
35
|
+
*
|
|
36
|
+
* @see setupAudioBufferActors, loadAudioSegments
|
|
37
|
+
*/
|
|
38
|
+
const AUDIO_TYPE_CONFIG = {
|
|
39
|
+
type: "audio",
|
|
40
|
+
selectedKey: "selectedAudioTrackId",
|
|
41
|
+
actorKey: "audioBufferActor",
|
|
42
|
+
loaderKey: "audioSegmentLoaderActor"
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Type-identity bundle for text-track-typed behaviors. Text tracks have
|
|
46
|
+
* no `SourceBufferActor` (MSE doesn't apply), so this bundle omits
|
|
47
|
+
* `actorKey`. The `loaderKey` points at the text-track-segment-loader
|
|
48
|
+
* actor (a `MessageActor` with continue-vs-preempt semantics, parallel
|
|
49
|
+
* to v/a's `SegmentLoaderActor`).
|
|
50
|
+
*
|
|
51
|
+
* @see loadTextTrackSegments, setupTextTrackActors
|
|
52
|
+
*/
|
|
53
|
+
const TEXT_TYPE_CONFIG = {
|
|
54
|
+
type: "text",
|
|
55
|
+
selectedKey: "selectedTextTrackId",
|
|
56
|
+
loaderKey: "textTrackSegmentLoaderActor"
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
export { AUDIO_TYPE_CONFIG, TEXT_TYPE_CONFIG, VIDEO_TYPE_CONFIG };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=track-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-types.js","names":[],"sources":["../../../../src/playback/behaviors/track-types.ts"],"sourcesContent":["/**\n * **Per-type config bundles for per-type behavior variants.**\n *\n * Each `*_TYPE_CONFIG` constant names the per-type slot keys that\n * per-type-variant setup-shape helpers consume. Variants reference the\n * shared constant at their `defineBehavior` setup body rather than\n * constructing the config inline, so the per-type identity (which state\n * slot, which context slot, which discriminant) lives in one place per\n * type.\n *\n * Variants spread their composition-time `config` over the defaults so\n * engines can layer composition-supplied additions on top (e.g. a\n * custom fetch closure, a non-default segment resolver). Defaults\n * first, engine config second.\n *\n * Helpers continue to consume their slice via the existing typed-key\n * generics (`<K extends SelectedTrackKey>` etc.); the extra fields on\n * the config object (carrying facets other helpers care about) are fine\n * under structural typing.\n */\n\n/**\n * Type-identity bundle for video-track-typed behaviors.\n *\n * @see setupVideoBufferActors, loadVideoSegments\n */\nexport const VIDEO_TYPE_CONFIG = {\n type: 'video',\n selectedKey: 'selectedVideoTrackId',\n actorKey: 'videoBufferActor',\n loaderKey: 'videoSegmentLoaderActor',\n} as const;\n\n/**\n * Type-identity bundle for audio-track-typed behaviors.\n *\n * @see setupAudioBufferActors, loadAudioSegments\n */\nexport const AUDIO_TYPE_CONFIG = {\n type: 'audio',\n selectedKey: 'selectedAudioTrackId',\n actorKey: 'audioBufferActor',\n loaderKey: 'audioSegmentLoaderActor',\n} as const;\n\n/**\n * Type-identity bundle for text-track-typed behaviors. Text tracks have\n * no `SourceBufferActor` (MSE doesn't apply), so this bundle omits\n * `actorKey`. The `loaderKey` points at the text-track-segment-loader\n * actor (a `MessageActor` with continue-vs-preempt semantics, parallel\n * to v/a's `SegmentLoaderActor`).\n *\n * @see loadTextTrackSegments, setupTextTrackActors\n */\nexport const TEXT_TYPE_CONFIG = {\n type: 'text',\n selectedKey: 'selectedTextTrackId',\n loaderKey: 'textTrackSegmentLoaderActor',\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAa,oBAAoB;CAC/B,MAAM;CACN,aAAa;CACb,UAAU;CACV,WAAW;CACZ;;;;;;AAOD,MAAa,oBAAoB;CAC/B,MAAM;CACN,aAAa;CACb,UAAU;CACV,WAAW;CACZ;;;;;;;;;;AAWD,MAAa,mBAAmB;CAC9B,MAAM;CACN,aAAa;CACb,WAAW;CACZ"}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Composition } from "../../../core/composition/create-composition.js";
|
|
2
|
+
import { SimpleHlsEngineContext, SimpleHlsEngineState } from "./engine.js";
|
|
2
3
|
import { Constructor, MixinReturn } from "@videojs/utils/types";
|
|
3
4
|
|
|
4
|
-
//#region src/
|
|
5
|
-
interface
|
|
6
|
-
readonly engine: PlaybackEngine;
|
|
5
|
+
//#region src/playback/engines/hls/adapter.d.ts
|
|
6
|
+
interface SimpleHlsMediaProps {
|
|
7
7
|
src: string;
|
|
8
8
|
preload: '' | 'none' | 'metadata' | 'auto';
|
|
9
|
+
}
|
|
10
|
+
declare const simpleHlsMediaDefaultProps: SimpleHlsMediaProps;
|
|
11
|
+
interface SimpleHlsMediaAPI extends SimpleHlsMediaProps {
|
|
12
|
+
readonly engine: Composition<SimpleHlsEngineState, SimpleHlsEngineContext>;
|
|
9
13
|
attach(mediaElement: HTMLMediaElement): void;
|
|
10
14
|
detach(): void;
|
|
11
15
|
destroy(): void;
|
|
@@ -23,18 +27,18 @@ interface SpfMediaAPI {
|
|
|
23
27
|
* changes and re-applied to the new engine automatically.
|
|
24
28
|
*
|
|
25
29
|
* @example
|
|
26
|
-
* class SimpleHlsMedia extends
|
|
30
|
+
* class SimpleHlsMedia extends SimpleHlsMediaMixin(HTMLVideoElementHost) {}
|
|
27
31
|
*
|
|
28
32
|
* const media = new SimpleHlsMedia();
|
|
29
33
|
* media.attach(document.querySelector('video'));
|
|
30
34
|
* media.src = 'https://stream.mux.com/abc123.m3u8';
|
|
31
35
|
*/
|
|
32
|
-
declare function
|
|
33
|
-
declare const
|
|
36
|
+
declare function SimpleHlsMediaMixin<Base extends Constructor<any>>(BaseClass: Base): MixinReturn<Base, SimpleHlsMediaAPI>;
|
|
37
|
+
declare const SimpleHlsMediaElement_base: MixinReturn<{
|
|
34
38
|
new (): {};
|
|
35
|
-
},
|
|
39
|
+
}, SimpleHlsMediaAPI>;
|
|
36
40
|
/** Standalone SPF media adapter with no base class. */
|
|
37
|
-
declare class
|
|
41
|
+
declare class SimpleHlsMediaElement extends SimpleHlsMediaElement_base {}
|
|
38
42
|
//#endregion
|
|
39
|
-
export {
|
|
43
|
+
export { SimpleHlsMediaAPI, SimpleHlsMediaElement, SimpleHlsMediaMixin, SimpleHlsMediaProps, simpleHlsMediaDefaultProps };
|
|
40
44
|
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","names":[],"sources":["../../../../../src/playback/engines/hls/adapter.ts"],"mappings":";;;;;UAUiB,mBAAA;EACf,GAAA;EACA,OAAA;AAAA;AAAA,cAGW,0BAAA,EAA4B,mBAAA;AAAA,UAKxB,iBAAA,SAA0B,mBAAA;EAAA,SAChC,MAAA,EAAQ,WAAA,CAAY,oBAAA,EAAsB,sBAAA;EACnD,MAAA,CAAO,YAAA,EAAc,gBAAA;EACrB,MAAA;EACA,OAAA;EACA,IAAA,IAAQ,OAAA;AAAA;AALV;;;;;;;;;;;;;;;;;;AAAA,iBA0BgB,mBAAA,cAAiC,WAAA,MAAA,CAAkB,SAAA,EAAW,IAAA,GAmJpC,WAAA,CAAY,IAAA,EAAM,iBAAA;AAAA,cAC3D,0BAAA;;;;cAGY,qBAAA,SAA8B,0BAAA"}
|