mattebox 0.1.0
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/LICENSE +21 -0
- package/README.md +106 -0
- package/dist/cdn/mattebox.dash-drm.min.js +2 -0
- package/dist/cdn/mattebox.dash.min.js +2 -0
- package/dist/cdn/mattebox.dual-drm.min.js +2 -0
- package/dist/cdn/mattebox.dual-ts-drm.min.js +3 -0
- package/dist/cdn/mattebox.dual-ts.min.js +3 -0
- package/dist/cdn/mattebox.dual.min.js +2 -0
- package/dist/cdn/mattebox.hls-drm.min.js +2 -0
- package/dist/cdn/mattebox.hls-ts-drm.min.js +3 -0
- package/dist/cdn/mattebox.hls-ts.min.js +3 -0
- package/dist/cdn/mattebox.hls.min.js +2 -0
- package/dist/cdn/mattebox.kernel.min.js +1 -0
- package/dist/cdn/mattebox.min.js +6 -0
- package/dist/cdn/transmux.worker.js +1 -0
- package/dist/containers/adts.d.ts +33 -0
- package/dist/containers/adts.d.ts.map +1 -0
- package/dist/containers/adts.js +66 -0
- package/dist/containers/adts.js.map +1 -0
- package/dist/containers/captions.d.ts +27 -0
- package/dist/containers/captions.d.ts.map +1 -0
- package/dist/containers/captions.js +36 -0
- package/dist/containers/captions.js.map +1 -0
- package/dist/containers/codec-probe/index.d.ts +35 -0
- package/dist/containers/codec-probe/index.d.ts.map +1 -0
- package/dist/containers/codec-probe/index.js +222 -0
- package/dist/containers/codec-probe/index.js.map +1 -0
- package/dist/containers/fmp4/writer.d.ts +62 -0
- package/dist/containers/fmp4/writer.d.ts.map +1 -0
- package/dist/containers/fmp4/writer.js +201 -0
- package/dist/containers/fmp4/writer.js.map +1 -0
- package/dist/containers/id3.d.ts +25 -0
- package/dist/containers/id3.d.ts.map +1 -0
- package/dist/containers/id3.js +75 -0
- package/dist/containers/id3.js.map +1 -0
- package/dist/containers/mp4-box/index.d.ts +79 -0
- package/dist/containers/mp4-box/index.d.ts.map +1 -0
- package/dist/containers/mp4-box/index.js +231 -0
- package/dist/containers/mp4-box/index.js.map +1 -0
- package/dist/containers/packed-audio/index.d.ts +7 -0
- package/dist/containers/packed-audio/index.d.ts.map +1 -0
- package/dist/containers/packed-audio/index.js +63 -0
- package/dist/containers/packed-audio/index.js.map +1 -0
- package/dist/containers/sei.d.ts +26 -0
- package/dist/containers/sei.d.ts.map +1 -0
- package/dist/containers/sei.js +100 -0
- package/dist/containers/sei.js.map +1 -0
- package/dist/containers/ts-transmux/demux.d.ts +49 -0
- package/dist/containers/ts-transmux/demux.d.ts.map +1 -0
- package/dist/containers/ts-transmux/demux.js +222 -0
- package/dist/containers/ts-transmux/demux.js.map +1 -0
- package/dist/containers/ts-transmux/h264.d.ts +48 -0
- package/dist/containers/ts-transmux/h264.d.ts.map +1 -0
- package/dist/containers/ts-transmux/h264.js +211 -0
- package/dist/containers/ts-transmux/h264.js.map +1 -0
- package/dist/containers/ts-transmux/index.d.ts +17 -0
- package/dist/containers/ts-transmux/index.d.ts.map +1 -0
- package/dist/containers/ts-transmux/index.js +34 -0
- package/dist/containers/ts-transmux/index.js.map +1 -0
- package/dist/containers/ts-transmux/runner.d.ts +23 -0
- package/dist/containers/ts-transmux/runner.d.ts.map +1 -0
- package/dist/containers/ts-transmux/runner.js +99 -0
- package/dist/containers/ts-transmux/runner.js.map +1 -0
- package/dist/containers/ts-transmux/transmux.d.ts +24 -0
- package/dist/containers/ts-transmux/transmux.d.ts.map +1 -0
- package/dist/containers/ts-transmux/transmux.js +212 -0
- package/dist/containers/ts-transmux/transmux.js.map +1 -0
- package/dist/containers/ts-transmux/transmux.worker.d.ts +2 -0
- package/dist/containers/ts-transmux/transmux.worker.d.ts.map +1 -0
- package/dist/containers/ts-transmux/transmux.worker.js +19 -0
- package/dist/containers/ts-transmux/transmux.worker.js.map +1 -0
- package/dist/es2015/_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/asyncToGenerator.js +27 -0
- package/dist/es2015/_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/defineProperty.js +12 -0
- package/dist/es2015/_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/objectSpread2.js +25 -0
- package/dist/es2015/_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/objectWithoutProperties.js +13 -0
- package/dist/es2015/_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/objectWithoutPropertiesLoose.js +12 -0
- package/dist/es2015/_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/toPrimitive.js +14 -0
- package/dist/es2015/_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/toPropertyKey.js +9 -0
- package/dist/es2015/_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/typeof.js +11 -0
- package/dist/es2015/containers/adts.js +77 -0
- package/dist/es2015/containers/captions.js +36 -0
- package/dist/es2015/containers/codec-probe/index.js +220 -0
- package/dist/es2015/containers/fmp4/writer.js +165 -0
- package/dist/es2015/containers/id3.js +72 -0
- package/dist/es2015/containers/mp4-box/index.js +209 -0
- package/dist/es2015/containers/packed-audio/index.js +67 -0
- package/dist/es2015/containers/sei.js +79 -0
- package/dist/es2015/containers/ts-transmux/demux.js +211 -0
- package/dist/es2015/containers/ts-transmux/h264.js +204 -0
- package/dist/es2015/containers/ts-transmux/index.js +37 -0
- package/dist/es2015/containers/ts-transmux/runner.js +95 -0
- package/dist/es2015/containers/ts-transmux/transmux.js +210 -0
- package/dist/es2015/containers/ts-transmux/transmux.worker.js +26 -0
- package/dist/es2015/index.js +356 -0
- package/dist/es2015/kernel/append-queue.js +148 -0
- package/dist/es2015/kernel/bus.js +134 -0
- package/dist/es2015/kernel/context.js +92 -0
- package/dist/es2015/kernel/effects.js +62 -0
- package/dist/es2015/kernel/evictor.js +67 -0
- package/dist/es2015/kernel/lifecycle.js +122 -0
- package/dist/es2015/kernel/loader.js +108 -0
- package/dist/es2015/kernel/mime.js +20 -0
- package/dist/es2015/kernel/mse.js +426 -0
- package/dist/es2015/kernel/reducer.js +1051 -0
- package/dist/es2015/kernel/rendition-select.js +263 -0
- package/dist/es2015/kernel/scheduler.js +82 -0
- package/dist/es2015/kernel/sinks/metadata-sink.js +7 -0
- package/dist/es2015/kernel/sinks/mse-sink.js +31 -0
- package/dist/es2015/kernel/sinks/text-track-sink.js +167 -0
- package/dist/es2015/kernel/timeline.js +127 -0
- package/dist/es2015/kernel/trace.js +134 -0
- package/dist/es2015/kernel/track-registry.js +47 -0
- package/dist/es2015/kernel/transport.js +242 -0
- package/dist/es2015/kernel/watchdog.js +38 -0
- package/dist/es2015/presets/dash/index.js +9 -0
- package/dist/es2015/presets/dash-drm/index.js +13 -0
- package/dist/es2015/presets/define.js +45 -0
- package/dist/es2015/presets/dual/index.js +14 -0
- package/dist/es2015/presets/dual-drm/index.js +14 -0
- package/dist/es2015/presets/dual-ts/index.js +14 -0
- package/dist/es2015/presets/dual-ts-drm/index.js +15 -0
- package/dist/es2015/presets/full/index.js +28 -0
- package/dist/es2015/presets/hls/index.js +9 -0
- package/dist/es2015/presets/hls-drm/index.js +13 -0
- package/dist/es2015/presets/hls-ts/index.js +13 -0
- package/dist/es2015/presets/hls-ts-drm/index.js +14 -0
- package/dist/es2015/presets/kernel/index.js +10 -0
- package/dist/es2015/presets/storage.js +24 -0
- package/dist/es2015/presets/tiers.js +93 -0
- package/dist/es2015/protocols/dash-cmaf/index.js +161 -0
- package/dist/es2015/protocols/dash-cmaf/parse.js +491 -0
- package/dist/es2015/protocols/dash-live/index.js +192 -0
- package/dist/es2015/protocols/hls-cmaf/index.js +168 -0
- package/dist/es2015/protocols/hls-cmaf/lexer.js +72 -0
- package/dist/es2015/protocols/hls-cmaf/parse.js +457 -0
- package/dist/es2015/protocols/hls-live/index.js +296 -0
- package/dist/es2015/protocols/live-shared.js +29 -0
- package/dist/es2015/stages/abr/index.js +126 -0
- package/dist/es2015/stages/abr-cap-size/index.js +22 -0
- package/dist/es2015/stages/abr-persist/index.js +52 -0
- package/dist/es2015/stages/aes-128/index.js +76 -0
- package/dist/es2015/stages/alt-audio/index.js +80 -0
- package/dist/es2015/stages/cmaf-timing/index.js +55 -0
- package/dist/es2015/stages/cmcd/index.js +70 -0
- package/dist/es2015/stages/codec-probe/index.js +65 -0
- package/dist/es2015/stages/codec-switch/index.js +48 -0
- package/dist/es2015/stages/content-steering/index.js +179 -0
- package/dist/es2015/stages/drm-shared.js +18 -0
- package/dist/es2015/stages/eme-cenc/index.js +46 -0
- package/dist/es2015/stages/eme-core/index.js +237 -0
- package/dist/es2015/stages/eme-fairplay/index.js +52 -0
- package/dist/es2015/stages/meta-id3/index.js +37 -0
- package/dist/es2015/stages/mp4-box/index.js +27 -0
- package/dist/es2015/stages/nal-scan/index.js +121 -0
- package/dist/es2015/stages/pdt/index.js +34 -0
- package/dist/es2015/stages/recovery/index.js +283 -0
- package/dist/es2015/stages/text-cea608/decode.js +201 -0
- package/dist/es2015/stages/text-cea608/index.js +71 -0
- package/dist/es2015/stages/text-webvtt/index.js +82 -0
- package/dist/es2015/stages/text-webvtt/parse.js +60 -0
- package/dist/es2015/stages/text-webvtt-segmented/index.js +57 -0
- package/dist/es2015/stages/thumbnails/index.js +73 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +423 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/append-queue.d.ts +47 -0
- package/dist/kernel/append-queue.d.ts.map +1 -0
- package/dist/kernel/append-queue.js +180 -0
- package/dist/kernel/append-queue.js.map +1 -0
- package/dist/kernel/bus.d.ts +50 -0
- package/dist/kernel/bus.d.ts.map +1 -0
- package/dist/kernel/bus.js +147 -0
- package/dist/kernel/bus.js.map +1 -0
- package/dist/kernel/context.d.ts +45 -0
- package/dist/kernel/context.d.ts.map +1 -0
- package/dist/kernel/context.js +116 -0
- package/dist/kernel/context.js.map +1 -0
- package/dist/kernel/effects.d.ts +33 -0
- package/dist/kernel/effects.d.ts.map +1 -0
- package/dist/kernel/effects.js +65 -0
- package/dist/kernel/effects.js.map +1 -0
- package/dist/kernel/evictor.d.ts +46 -0
- package/dist/kernel/evictor.d.ts.map +1 -0
- package/dist/kernel/evictor.js +92 -0
- package/dist/kernel/evictor.js.map +1 -0
- package/dist/kernel/lifecycle.d.ts +41 -0
- package/dist/kernel/lifecycle.d.ts.map +1 -0
- package/dist/kernel/lifecycle.js +129 -0
- package/dist/kernel/lifecycle.js.map +1 -0
- package/dist/kernel/loader.d.ts +28 -0
- package/dist/kernel/loader.d.ts.map +1 -0
- package/dist/kernel/loader.js +126 -0
- package/dist/kernel/loader.js.map +1 -0
- package/dist/kernel/mime.d.ts +13 -0
- package/dist/kernel/mime.d.ts.map +1 -0
- package/dist/kernel/mime.js +18 -0
- package/dist/kernel/mime.js.map +1 -0
- package/dist/kernel/mse.d.ts +62 -0
- package/dist/kernel/mse.d.ts.map +1 -0
- package/dist/kernel/mse.js +490 -0
- package/dist/kernel/mse.js.map +1 -0
- package/dist/kernel/reducer.d.ts +39 -0
- package/dist/kernel/reducer.d.ts.map +1 -0
- package/dist/kernel/reducer.js +1316 -0
- package/dist/kernel/reducer.js.map +1 -0
- package/dist/kernel/rendition-select.d.ts +102 -0
- package/dist/kernel/rendition-select.d.ts.map +1 -0
- package/dist/kernel/rendition-select.js +295 -0
- package/dist/kernel/rendition-select.js.map +1 -0
- package/dist/kernel/scheduler.d.ts +57 -0
- package/dist/kernel/scheduler.d.ts.map +1 -0
- package/dist/kernel/scheduler.js +98 -0
- package/dist/kernel/scheduler.js.map +1 -0
- package/dist/kernel/sinks/metadata-sink.d.ts +7 -0
- package/dist/kernel/sinks/metadata-sink.d.ts.map +1 -0
- package/dist/kernel/sinks/metadata-sink.js +5 -0
- package/dist/kernel/sinks/metadata-sink.js.map +1 -0
- package/dist/kernel/sinks/mse-sink.d.ts +17 -0
- package/dist/kernel/sinks/mse-sink.d.ts.map +1 -0
- package/dist/kernel/sinks/mse-sink.js +20 -0
- package/dist/kernel/sinks/mse-sink.js.map +1 -0
- package/dist/kernel/sinks/text-track-sink.d.ts +45 -0
- package/dist/kernel/sinks/text-track-sink.d.ts.map +1 -0
- package/dist/kernel/sinks/text-track-sink.js +184 -0
- package/dist/kernel/sinks/text-track-sink.js.map +1 -0
- package/dist/kernel/timeline.d.ts +57 -0
- package/dist/kernel/timeline.d.ts.map +1 -0
- package/dist/kernel/timeline.js +203 -0
- package/dist/kernel/timeline.js.map +1 -0
- package/dist/kernel/trace.d.ts +42 -0
- package/dist/kernel/trace.d.ts.map +1 -0
- package/dist/kernel/trace.js +165 -0
- package/dist/kernel/trace.js.map +1 -0
- package/dist/kernel/track-registry.d.ts +22 -0
- package/dist/kernel/track-registry.d.ts.map +1 -0
- package/dist/kernel/track-registry.js +42 -0
- package/dist/kernel/track-registry.js.map +1 -0
- package/dist/kernel/transport.d.ts +90 -0
- package/dist/kernel/transport.d.ts.map +1 -0
- package/dist/kernel/transport.js +256 -0
- package/dist/kernel/transport.js.map +1 -0
- package/dist/kernel/watchdog.d.ts +35 -0
- package/dist/kernel/watchdog.d.ts.map +1 -0
- package/dist/kernel/watchdog.js +43 -0
- package/dist/kernel/watchdog.js.map +1 -0
- package/dist/presets/dash/index.d.ts +4 -0
- package/dist/presets/dash/index.d.ts.map +1 -0
- package/dist/presets/dash/index.js +8 -0
- package/dist/presets/dash/index.js.map +1 -0
- package/dist/presets/dash-drm/index.d.ts +4 -0
- package/dist/presets/dash-drm/index.d.ts.map +1 -0
- package/dist/presets/dash-drm/index.js +8 -0
- package/dist/presets/dash-drm/index.js.map +1 -0
- package/dist/presets/define.d.ts +36 -0
- package/dist/presets/define.d.ts.map +1 -0
- package/dist/presets/define.js +39 -0
- package/dist/presets/define.js.map +1 -0
- package/dist/presets/dual/index.d.ts +4 -0
- package/dist/presets/dual/index.d.ts.map +1 -0
- package/dist/presets/dual/index.js +9 -0
- package/dist/presets/dual/index.js.map +1 -0
- package/dist/presets/dual-drm/index.d.ts +4 -0
- package/dist/presets/dual-drm/index.d.ts.map +1 -0
- package/dist/presets/dual-drm/index.js +13 -0
- package/dist/presets/dual-drm/index.js.map +1 -0
- package/dist/presets/dual-ts/index.d.ts +4 -0
- package/dist/presets/dual-ts/index.d.ts.map +1 -0
- package/dist/presets/dual-ts/index.js +8 -0
- package/dist/presets/dual-ts/index.js.map +1 -0
- package/dist/presets/dual-ts-drm/index.d.ts +4 -0
- package/dist/presets/dual-ts-drm/index.d.ts.map +1 -0
- package/dist/presets/dual-ts-drm/index.js +14 -0
- package/dist/presets/dual-ts-drm/index.js.map +1 -0
- package/dist/presets/full/index.d.ts +4 -0
- package/dist/presets/full/index.d.ts.map +1 -0
- package/dist/presets/full/index.js +27 -0
- package/dist/presets/full/index.js.map +1 -0
- package/dist/presets/hls/index.d.ts +4 -0
- package/dist/presets/hls/index.d.ts.map +1 -0
- package/dist/presets/hls/index.js +8 -0
- package/dist/presets/hls/index.js.map +1 -0
- package/dist/presets/hls-drm/index.d.ts +4 -0
- package/dist/presets/hls-drm/index.d.ts.map +1 -0
- package/dist/presets/hls-drm/index.js +8 -0
- package/dist/presets/hls-drm/index.js.map +1 -0
- package/dist/presets/hls-ts/index.d.ts +4 -0
- package/dist/presets/hls-ts/index.d.ts.map +1 -0
- package/dist/presets/hls-ts/index.js +8 -0
- package/dist/presets/hls-ts/index.js.map +1 -0
- package/dist/presets/hls-ts-drm/index.d.ts +4 -0
- package/dist/presets/hls-ts-drm/index.d.ts.map +1 -0
- package/dist/presets/hls-ts-drm/index.js +13 -0
- package/dist/presets/hls-ts-drm/index.js.map +1 -0
- package/dist/presets/kernel/index.d.ts +4 -0
- package/dist/presets/kernel/index.d.ts.map +1 -0
- package/dist/presets/kernel/index.js +9 -0
- package/dist/presets/kernel/index.js.map +1 -0
- package/dist/presets/storage.d.ts +9 -0
- package/dist/presets/storage.d.ts.map +1 -0
- package/dist/presets/storage.js +24 -0
- package/dist/presets/storage.js.map +1 -0
- package/dist/presets/tiers.d.ts +22 -0
- package/dist/presets/tiers.d.ts.map +1 -0
- package/dist/presets/tiers.js +78 -0
- package/dist/presets/tiers.js.map +1 -0
- package/dist/protocols/dash-cmaf/index.d.ts +20 -0
- package/dist/protocols/dash-cmaf/index.d.ts.map +1 -0
- package/dist/protocols/dash-cmaf/index.js +176 -0
- package/dist/protocols/dash-cmaf/index.js.map +1 -0
- package/dist/protocols/dash-cmaf/parse.d.ts +24 -0
- package/dist/protocols/dash-cmaf/parse.d.ts.map +1 -0
- package/dist/protocols/dash-cmaf/parse.js +586 -0
- package/dist/protocols/dash-cmaf/parse.js.map +1 -0
- package/dist/protocols/dash-live/index.d.ts +4 -0
- package/dist/protocols/dash-live/index.d.ts.map +1 -0
- package/dist/protocols/dash-live/index.js +188 -0
- package/dist/protocols/dash-live/index.js.map +1 -0
- package/dist/protocols/hls-cmaf/index.d.ts +17 -0
- package/dist/protocols/hls-cmaf/index.d.ts.map +1 -0
- package/dist/protocols/hls-cmaf/index.js +189 -0
- package/dist/protocols/hls-cmaf/index.js.map +1 -0
- package/dist/protocols/hls-cmaf/lexer.d.ts +25 -0
- package/dist/protocols/hls-cmaf/lexer.d.ts.map +1 -0
- package/dist/protocols/hls-cmaf/lexer.js +81 -0
- package/dist/protocols/hls-cmaf/lexer.js.map +1 -0
- package/dist/protocols/hls-cmaf/parse.d.ts +57 -0
- package/dist/protocols/hls-cmaf/parse.d.ts.map +1 -0
- package/dist/protocols/hls-cmaf/parse.js +572 -0
- package/dist/protocols/hls-cmaf/parse.js.map +1 -0
- package/dist/protocols/hls-live/index.d.ts +4 -0
- package/dist/protocols/hls-live/index.d.ts.map +1 -0
- package/dist/protocols/hls-live/index.js +309 -0
- package/dist/protocols/hls-live/index.js.map +1 -0
- package/dist/protocols/live-shared.d.ts +21 -0
- package/dist/protocols/live-shared.d.ts.map +1 -0
- package/dist/protocols/live-shared.js +32 -0
- package/dist/protocols/live-shared.js.map +1 -0
- package/dist/stages/abr/index.d.ts +16 -0
- package/dist/stages/abr/index.d.ts.map +1 -0
- package/dist/stages/abr/index.js +176 -0
- package/dist/stages/abr/index.js.map +1 -0
- package/dist/stages/abr-cap-size/index.d.ts +8 -0
- package/dist/stages/abr-cap-size/index.d.ts.map +1 -0
- package/dist/stages/abr-cap-size/index.js +21 -0
- package/dist/stages/abr-cap-size/index.js.map +1 -0
- package/dist/stages/abr-persist/index.d.ts +8 -0
- package/dist/stages/abr-persist/index.d.ts.map +1 -0
- package/dist/stages/abr-persist/index.js +44 -0
- package/dist/stages/abr-persist/index.js.map +1 -0
- package/dist/stages/aes-128/index.d.ts +15 -0
- package/dist/stages/aes-128/index.d.ts.map +1 -0
- package/dist/stages/aes-128/index.js +78 -0
- package/dist/stages/aes-128/index.js.map +1 -0
- package/dist/stages/alt-audio/index.d.ts +4 -0
- package/dist/stages/alt-audio/index.d.ts.map +1 -0
- package/dist/stages/alt-audio/index.js +90 -0
- package/dist/stages/alt-audio/index.js.map +1 -0
- package/dist/stages/cmaf-timing/index.d.ts +3 -0
- package/dist/stages/cmaf-timing/index.d.ts.map +1 -0
- package/dist/stages/cmaf-timing/index.js +56 -0
- package/dist/stages/cmaf-timing/index.js.map +1 -0
- package/dist/stages/cmcd/index.d.ts +22 -0
- package/dist/stages/cmcd/index.d.ts.map +1 -0
- package/dist/stages/cmcd/index.js +92 -0
- package/dist/stages/cmcd/index.js.map +1 -0
- package/dist/stages/codec-probe/index.d.ts +9 -0
- package/dist/stages/codec-probe/index.d.ts.map +1 -0
- package/dist/stages/codec-probe/index.js +68 -0
- package/dist/stages/codec-probe/index.js.map +1 -0
- package/dist/stages/codec-switch/index.d.ts +6 -0
- package/dist/stages/codec-switch/index.d.ts.map +1 -0
- package/dist/stages/codec-switch/index.js +59 -0
- package/dist/stages/codec-switch/index.js.map +1 -0
- package/dist/stages/content-steering/index.d.ts +4 -0
- package/dist/stages/content-steering/index.d.ts.map +1 -0
- package/dist/stages/content-steering/index.js +174 -0
- package/dist/stages/content-steering/index.js.map +1 -0
- package/dist/stages/drm-shared.d.ts +46 -0
- package/dist/stages/drm-shared.d.ts.map +1 -0
- package/dist/stages/drm-shared.js +28 -0
- package/dist/stages/drm-shared.js.map +1 -0
- package/dist/stages/eme-cenc/index.d.ts +12 -0
- package/dist/stages/eme-cenc/index.d.ts.map +1 -0
- package/dist/stages/eme-cenc/index.js +53 -0
- package/dist/stages/eme-cenc/index.js.map +1 -0
- package/dist/stages/eme-core/index.d.ts +29 -0
- package/dist/stages/eme-core/index.d.ts.map +1 -0
- package/dist/stages/eme-core/index.js +244 -0
- package/dist/stages/eme-core/index.js.map +1 -0
- package/dist/stages/eme-fairplay/index.d.ts +20 -0
- package/dist/stages/eme-fairplay/index.d.ts.map +1 -0
- package/dist/stages/eme-fairplay/index.js +59 -0
- package/dist/stages/eme-fairplay/index.js.map +1 -0
- package/dist/stages/meta-id3/index.d.ts +14 -0
- package/dist/stages/meta-id3/index.d.ts.map +1 -0
- package/dist/stages/meta-id3/index.js +30 -0
- package/dist/stages/meta-id3/index.js.map +1 -0
- package/dist/stages/mp4-box/index.d.ts +3 -0
- package/dist/stages/mp4-box/index.d.ts.map +1 -0
- package/dist/stages/mp4-box/index.js +19 -0
- package/dist/stages/mp4-box/index.js.map +1 -0
- package/dist/stages/nal-scan/index.d.ts +3 -0
- package/dist/stages/nal-scan/index.d.ts.map +1 -0
- package/dist/stages/nal-scan/index.js +123 -0
- package/dist/stages/nal-scan/index.js.map +1 -0
- package/dist/stages/pdt/index.d.ts +14 -0
- package/dist/stages/pdt/index.d.ts.map +1 -0
- package/dist/stages/pdt/index.js +34 -0
- package/dist/stages/pdt/index.js.map +1 -0
- package/dist/stages/recovery/index.d.ts +16 -0
- package/dist/stages/recovery/index.d.ts.map +1 -0
- package/dist/stages/recovery/index.js +270 -0
- package/dist/stages/recovery/index.js.map +1 -0
- package/dist/stages/text-cea608/decode.d.ts +44 -0
- package/dist/stages/text-cea608/decode.d.ts.map +1 -0
- package/dist/stages/text-cea608/decode.js +225 -0
- package/dist/stages/text-cea608/decode.js.map +1 -0
- package/dist/stages/text-cea608/index.d.ts +3 -0
- package/dist/stages/text-cea608/index.d.ts.map +1 -0
- package/dist/stages/text-cea608/index.js +84 -0
- package/dist/stages/text-cea608/index.js.map +1 -0
- package/dist/stages/text-webvtt/index.d.ts +3 -0
- package/dist/stages/text-webvtt/index.d.ts.map +1 -0
- package/dist/stages/text-webvtt/index.js +82 -0
- package/dist/stages/text-webvtt/index.js.map +1 -0
- package/dist/stages/text-webvtt/parse.d.ts +19 -0
- package/dist/stages/text-webvtt/parse.d.ts.map +1 -0
- package/dist/stages/text-webvtt/parse.js +62 -0
- package/dist/stages/text-webvtt/parse.js.map +1 -0
- package/dist/stages/text-webvtt-segmented/index.d.ts +5 -0
- package/dist/stages/text-webvtt-segmented/index.d.ts.map +1 -0
- package/dist/stages/text-webvtt-segmented/index.js +63 -0
- package/dist/stages/text-webvtt-segmented/index.js.map +1 -0
- package/dist/stages/thumbnails/index.d.ts +34 -0
- package/dist/stages/thumbnails/index.d.ts.map +1 -0
- package/dist/stages/thumbnails/index.js +58 -0
- package/dist/stages/thumbnails/index.js.map +1 -0
- package/dist/types/error.d.ts +33 -0
- package/dist/types/error.d.ts.map +1 -0
- package/dist/types/error.js +7 -0
- package/dist/types/error.js.map +1 -0
- package/dist/types/facade.d.ts +104 -0
- package/dist/types/facade.d.ts.map +1 -0
- package/dist/types/facade.js +2 -0
- package/dist/types/facade.js.map +1 -0
- package/dist/types/ir.d.ts +238 -0
- package/dist/types/ir.d.ts.map +1 -0
- package/dist/types/ir.js +7 -0
- package/dist/types/ir.js.map +1 -0
- package/dist/types/kernel.d.ts +217 -0
- package/dist/types/kernel.d.ts.map +1 -0
- package/dist/types/kernel.js +2 -0
- package/dist/types/kernel.js.map +1 -0
- package/dist/types/messages.d.ts +288 -0
- package/dist/types/messages.d.ts.map +1 -0
- package/dist/types/messages.js +2 -0
- package/dist/types/messages.js.map +1 -0
- package/dist/types/quality.d.ts +108 -0
- package/dist/types/quality.d.ts.map +1 -0
- package/dist/types/quality.js +2 -0
- package/dist/types/quality.js.map +1 -0
- package/dist/types/sink.d.ts +27 -0
- package/dist/types/sink.d.ts.map +1 -0
- package/dist/types/sink.js +2 -0
- package/dist/types/sink.js.map +1 -0
- package/dist/types/stage.d.ts +139 -0
- package/dist/types/stage.d.ts.map +1 -0
- package/dist/types/stage.js +2 -0
- package/dist/types/stage.js.map +1 -0
- package/package.json +132 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { normalizeMimeType } from "../../kernel/mime.js";
|
|
2
|
+
import _objectSpread2 from "../../_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/objectSpread2.js";
|
|
3
|
+
import { mergePlaylist, parse, parseMediaPlaylist } from "./parse.js";
|
|
4
|
+
//#region src/protocols/hls-cmaf/index.ts
|
|
5
|
+
/**
|
|
6
|
+
* The hls-cmaf protocol adapter as a stage. Inert module: exports a
|
|
7
|
+
* factory, registers nothing at import time.
|
|
8
|
+
*
|
|
9
|
+
* The choreography is a slice reducer, so the whole protocol lives inside
|
|
10
|
+
* the message loop and the trace: manifest bytes arrive as SEGMENT_LOADED
|
|
11
|
+
* facts, parsing is pure, and results loop back through zero-delay
|
|
12
|
+
* schedule effects carrying MANIFEST_LOADED. Media playlists fetch under
|
|
13
|
+
* `hls:pl:` tokens the transport correlates back by token.
|
|
14
|
+
*/
|
|
15
|
+
const PLAYLIST_TOKEN = "hls:pl:";
|
|
16
|
+
/** The playlist MIME types, RFC 8216 §4: the registered type and the three in common use. */
|
|
17
|
+
const MANIFEST_TYPES = [
|
|
18
|
+
"application/vnd.apple.mpegurl",
|
|
19
|
+
"application/x-mpegurl",
|
|
20
|
+
"audio/mpegurl",
|
|
21
|
+
"audio/x-mpegurl"
|
|
22
|
+
];
|
|
23
|
+
const INITIAL = {
|
|
24
|
+
manifestUrl: null,
|
|
25
|
+
mimeType: null,
|
|
26
|
+
pending: {}
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Whether this adapter owns the manifest bytes. An explicit mimeType
|
|
30
|
+
* decides alone: a foreign type declines without reading, an own type
|
|
31
|
+
* parses without sniffing, so a broken playlist reports a parse failure
|
|
32
|
+
* instead of falling through. Without one, RFC 8216 §4.3.1.1: the first
|
|
33
|
+
* line of every playlist is #EXTM3U.
|
|
34
|
+
*/
|
|
35
|
+
function claims(state, text) {
|
|
36
|
+
if (state.mimeType !== null) return MANIFEST_TYPES.includes(state.mimeType);
|
|
37
|
+
return text.trimStart().startsWith("#EXTM3U");
|
|
38
|
+
}
|
|
39
|
+
function findRendition(presentation, renditionId) {
|
|
40
|
+
for (const period of presentation.periods) for (const track of period.tracks) for (const rendition of track.renditions) if (rendition.id === renditionId) return {
|
|
41
|
+
rendition,
|
|
42
|
+
track
|
|
43
|
+
};
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The renditions whose media playlists still need fetching: every rendition of
|
|
48
|
+
* every active track. Fetching only the "chosen" one is not enough, because ABR
|
|
49
|
+
* (or any switch policy) selects independently and can pick a rendition this
|
|
50
|
+
* slice would not have; its segments would then stay empty and the scheduler
|
|
51
|
+
* would stall the moment ABR ramped onto it, which looks like playback dying
|
|
52
|
+
* once the buffer drains. Fetching all of an active track's playlists means the
|
|
53
|
+
* rendition ABR lands on is already loaded, and a switch never stalls.
|
|
54
|
+
*/
|
|
55
|
+
function neededPlaylists(kernel) {
|
|
56
|
+
const presentation = kernel.presentation;
|
|
57
|
+
if (presentation === null) return [];
|
|
58
|
+
const activeIds = new Set([
|
|
59
|
+
"video",
|
|
60
|
+
"audio",
|
|
61
|
+
"text"
|
|
62
|
+
].map((contentType) => kernel.tracks.active.get(contentType)).filter((id) => id !== void 0));
|
|
63
|
+
const needed = [];
|
|
64
|
+
for (const period of presentation.periods) for (const track of period.tracks) {
|
|
65
|
+
if (!activeIds.has(track.id)) continue;
|
|
66
|
+
for (const rendition of track.renditions) if (rendition.playlistUrl !== void 0 && Array.isArray(rendition.segments) && rendition.segments.length === 0) needed.push(rendition);
|
|
67
|
+
}
|
|
68
|
+
return needed;
|
|
69
|
+
}
|
|
70
|
+
/** Loops a message back into the bus through a zero-delay schedule effect. */
|
|
71
|
+
function feed(message) {
|
|
72
|
+
return {
|
|
73
|
+
kind: "schedule",
|
|
74
|
+
token: "hls:loopback",
|
|
75
|
+
delayMs: 0,
|
|
76
|
+
then: message
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function loopBack(presentation) {
|
|
80
|
+
return feed({
|
|
81
|
+
type: "MANIFEST_LOADED",
|
|
82
|
+
presentation
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const reduceHls = (slice, msg, kernel) => {
|
|
86
|
+
const state = slice !== null && slice !== void 0 ? slice : INITIAL;
|
|
87
|
+
if (msg.type === "LOAD") return [{
|
|
88
|
+
manifestUrl: msg.url,
|
|
89
|
+
mimeType: msg.mimeType === void 0 ? null : normalizeMimeType(msg.mimeType),
|
|
90
|
+
pending: {}
|
|
91
|
+
}, []];
|
|
92
|
+
if (msg.type === "UNLOAD" || msg.type === "DETACH") return [INITIAL, []];
|
|
93
|
+
if (msg.type === "SEGMENT_LOADED" && msg.trackId === "manifest" && state.manifestUrl !== null) {
|
|
94
|
+
const text = new TextDecoder().decode(msg.bytes);
|
|
95
|
+
if (!claims(state, text)) return [state, []];
|
|
96
|
+
const result = parse(text, state.manifestUrl);
|
|
97
|
+
if (result.presentation === null) {
|
|
98
|
+
var _result$error;
|
|
99
|
+
return [state, [feed({
|
|
100
|
+
type: "MANIFEST_FAILED",
|
|
101
|
+
error: (_result$error = result.error) !== null && _result$error !== void 0 ? _result$error : {
|
|
102
|
+
category: "manifest",
|
|
103
|
+
code: "MANIFEST_PARSE_FAILED",
|
|
104
|
+
fatal: true,
|
|
105
|
+
recoverable: false
|
|
106
|
+
}
|
|
107
|
+
})]];
|
|
108
|
+
}
|
|
109
|
+
return [state, [loopBack(result.presentation)]];
|
|
110
|
+
}
|
|
111
|
+
if (msg.type === "SEGMENT_LOADED" && msg.trackId.startsWith(PLAYLIST_TOKEN)) {
|
|
112
|
+
const renditionId = state.pending[msg.trackId];
|
|
113
|
+
if (renditionId === void 0 || kernel.presentation === null) return [state, []];
|
|
114
|
+
const site = findRendition(kernel.presentation, renditionId);
|
|
115
|
+
const pending = _objectSpread2({}, state.pending);
|
|
116
|
+
delete pending[msg.trackId];
|
|
117
|
+
if (site === null || site.rendition.playlistUrl === void 0) return [_objectSpread2(_objectSpread2({}, state), {}, { pending }), []];
|
|
118
|
+
const text = new TextDecoder().decode(msg.bytes);
|
|
119
|
+
const media = parseMediaPlaylist(text, site.rendition.playlistUrl);
|
|
120
|
+
if (media.playlist === null) {
|
|
121
|
+
var _media$error;
|
|
122
|
+
return [_objectSpread2(_objectSpread2({}, state), {}, { pending }), [feed({
|
|
123
|
+
type: "MANIFEST_FAILED",
|
|
124
|
+
error: (_media$error = media.error) !== null && _media$error !== void 0 ? _media$error : {
|
|
125
|
+
category: "manifest",
|
|
126
|
+
code: "MANIFEST_PARSE_FAILED",
|
|
127
|
+
fatal: true,
|
|
128
|
+
recoverable: false
|
|
129
|
+
}
|
|
130
|
+
})]];
|
|
131
|
+
}
|
|
132
|
+
const merged = mergePlaylist(kernel.presentation, renditionId, media.playlist);
|
|
133
|
+
return [_objectSpread2(_objectSpread2({}, state), {}, { pending }), [loopBack(merged)]];
|
|
134
|
+
}
|
|
135
|
+
if (msg.type === "MANIFEST_LOADED" || msg.type === "SELECT_TRACK" || msg.type === "TIME_UPDATE") {
|
|
136
|
+
const needed = neededPlaylists(kernel).filter((rendition) => !Object.values(state.pending).includes(rendition.id));
|
|
137
|
+
if (needed.length === 0) return [state, []];
|
|
138
|
+
const effects = [];
|
|
139
|
+
const pending = _objectSpread2({}, state.pending);
|
|
140
|
+
for (const rendition of needed) {
|
|
141
|
+
const token = `${PLAYLIST_TOKEN}${rendition.id}`;
|
|
142
|
+
if (pending[token] !== void 0) continue;
|
|
143
|
+
pending[token] = rendition.id;
|
|
144
|
+
effects.push({
|
|
145
|
+
kind: "fetch",
|
|
146
|
+
token,
|
|
147
|
+
url: rendition.playlistUrl
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return [_objectSpread2(_objectSpread2({}, state), {}, { pending }), effects];
|
|
151
|
+
}
|
|
152
|
+
return [state, []];
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* The stage factory. `mattebox({ stages: [hlsCmaf()] })` is all a consumer
|
|
156
|
+
* needs for HLS-CMAF VOD.
|
|
157
|
+
*/
|
|
158
|
+
function hlsCmaf() {
|
|
159
|
+
return {
|
|
160
|
+
name: "hls-cmaf",
|
|
161
|
+
provides: ["hls-cmaf", ...MANIFEST_TYPES],
|
|
162
|
+
install(ctx) {
|
|
163
|
+
ctx.reduce("hls", reduceHls);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
//#endregion
|
|
168
|
+
export { hlsCmaf as default };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
//#region src/protocols/hls-cmaf/lexer.ts
|
|
2
|
+
/** Tags with attribute lists; everything else keeps its raw value. */
|
|
3
|
+
const ATTRIBUTE_TAGS = /* @__PURE__ */ new Set([
|
|
4
|
+
"EXT-X-STREAM-INF",
|
|
5
|
+
"EXT-X-MEDIA",
|
|
6
|
+
"EXT-X-MAP",
|
|
7
|
+
"EXT-X-KEY",
|
|
8
|
+
"EXT-X-SESSION-KEY",
|
|
9
|
+
"EXT-X-I-FRAME-STREAM-INF",
|
|
10
|
+
"EXT-X-CONTENT-STEERING"
|
|
11
|
+
]);
|
|
12
|
+
/**
|
|
13
|
+
* RFC 8216 §4.2: comma-separated KEY=VALUE pairs where a quoted-string
|
|
14
|
+
* value may contain commas. Walk characters; never split.
|
|
15
|
+
*/
|
|
16
|
+
function parseAttributeList(text) {
|
|
17
|
+
const out = {};
|
|
18
|
+
let at = 0;
|
|
19
|
+
while (at < text.length) {
|
|
20
|
+
const eq = text.indexOf("=", at);
|
|
21
|
+
if (eq === -1) break;
|
|
22
|
+
const key = text.slice(at, eq).trim();
|
|
23
|
+
at = eq + 1;
|
|
24
|
+
let value;
|
|
25
|
+
if (text[at] === "\"") {
|
|
26
|
+
const close = text.indexOf("\"", at + 1);
|
|
27
|
+
if (close === -1) {
|
|
28
|
+
value = text.slice(at + 1);
|
|
29
|
+
at = text.length;
|
|
30
|
+
} else {
|
|
31
|
+
value = text.slice(at + 1, close);
|
|
32
|
+
at = close + 1;
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
let end = text.indexOf(",", at);
|
|
36
|
+
if (end === -1) end = text.length;
|
|
37
|
+
value = text.slice(at, end).trim();
|
|
38
|
+
at = end;
|
|
39
|
+
}
|
|
40
|
+
if (key !== "") out[key] = value;
|
|
41
|
+
if (text[at] === ",") at += 1;
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
/** Tokenizes a playlist into tag and URI lines. Comments and blanks drop. */
|
|
46
|
+
function lex(text) {
|
|
47
|
+
const lines = [];
|
|
48
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
49
|
+
const line = raw.trim();
|
|
50
|
+
if (line === "") continue;
|
|
51
|
+
if (!line.startsWith("#")) {
|
|
52
|
+
lines.push({
|
|
53
|
+
kind: "uri",
|
|
54
|
+
uri: line
|
|
55
|
+
});
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (!line.startsWith("#EXT")) continue;
|
|
59
|
+
const colon = line.indexOf(":");
|
|
60
|
+
const name = colon === -1 ? line.slice(1) : line.slice(1, colon);
|
|
61
|
+
const value = colon === -1 ? "" : line.slice(colon + 1);
|
|
62
|
+
lines.push({
|
|
63
|
+
kind: "tag",
|
|
64
|
+
name,
|
|
65
|
+
value,
|
|
66
|
+
attributes: ATTRIBUTE_TAGS.has(name) ? parseAttributeList(value) : {}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return lines;
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
export { lex, parseAttributeList };
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
import _objectSpread2 from "../../_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/objectSpread2.js";
|
|
2
|
+
import { lex } from "./lexer.js";
|
|
3
|
+
//#region src/protocols/hls-cmaf/parse.ts
|
|
4
|
+
function manifestError(reason) {
|
|
5
|
+
return {
|
|
6
|
+
category: "manifest",
|
|
7
|
+
code: "MANIFEST_PARSE_FAILED",
|
|
8
|
+
fatal: true,
|
|
9
|
+
recoverable: false,
|
|
10
|
+
context: { reason }
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function resolve(uri, baseUrl) {
|
|
14
|
+
try {
|
|
15
|
+
return new URL(uri, baseUrl).href;
|
|
16
|
+
} catch (_unused) {
|
|
17
|
+
return uri;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** n@o or n (continuing after the previous range). RFC 8216 §4.3.2.2. */
|
|
21
|
+
function parseByteRange(value, previousEnd) {
|
|
22
|
+
const [lengthText, offsetText] = value.split("@");
|
|
23
|
+
const length = Number(lengthText);
|
|
24
|
+
if (!Number.isFinite(length)) return null;
|
|
25
|
+
const start = offsetText !== void 0 ? Number(offsetText) : previousEnd === null ? 0 : previousEnd + 1;
|
|
26
|
+
if (!Number.isFinite(start)) return null;
|
|
27
|
+
return {
|
|
28
|
+
start,
|
|
29
|
+
end: start + length - 1
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* METHOD=AES-128 as a segment key. Anything else (NONE, SAMPLE-AES, the
|
|
34
|
+
* FairPlay and Widevine forms) is not a segment key: NONE ends keying, the
|
|
35
|
+
* rest are DRM and go through `protectionFrom`.
|
|
36
|
+
*/
|
|
37
|
+
function segmentKeyFrom(key, baseUrl) {
|
|
38
|
+
if (key.attributes.METHOD !== "AES-128" || key.attributes.URI === void 0) return null;
|
|
39
|
+
const iv = key.attributes.IV;
|
|
40
|
+
return _objectSpread2({
|
|
41
|
+
method: "AES-128",
|
|
42
|
+
uri: resolve(key.attributes.URI, baseUrl)
|
|
43
|
+
}, iv !== void 0 ? { iv: iv.replace(/^0x/i, "").toLowerCase().padStart(32, "0") } : {});
|
|
44
|
+
}
|
|
45
|
+
function protectionFrom(key, baseUrl) {
|
|
46
|
+
var _key$attributes$METHO, _key$attributes$KEYFO, _key$attributes$KEYID;
|
|
47
|
+
const method = (_key$attributes$METHO = key.attributes.METHOD) !== null && _key$attributes$METHO !== void 0 ? _key$attributes$METHO : "";
|
|
48
|
+
if (method === "" || method === "NONE" || method === "AES-128") return null;
|
|
49
|
+
return { schemes: [{
|
|
50
|
+
systemId: (_key$attributes$KEYFO = key.attributes.KEYFORMAT) !== null && _key$attributes$KEYFO !== void 0 ? _key$attributes$KEYFO : null,
|
|
51
|
+
scheme: method.toLowerCase(),
|
|
52
|
+
keyId: (_key$attributes$KEYID = key.attributes.KEYID) !== null && _key$attributes$KEYID !== void 0 ? _key$attributes$KEYID : null,
|
|
53
|
+
licenseUrl: key.attributes.URI !== void 0 ? resolve(key.attributes.URI, baseUrl) : null,
|
|
54
|
+
initData: null,
|
|
55
|
+
initDataType: null
|
|
56
|
+
}] };
|
|
57
|
+
}
|
|
58
|
+
const AUDIO_CODECS = /^(mp4a|ac-3|ec-3|opus|flac)/i;
|
|
59
|
+
/**
|
|
60
|
+
* Rewrites the legacy decimal AVC codec form some packagers still emit into
|
|
61
|
+
* the RFC 6381 hex form MSE demands. `avc1.66.30` (profile 66, level 30) is
|
|
62
|
+
* accepted by Firefox but rejected by Chrome's isTypeSupported, which is why a
|
|
63
|
+
* stream like Unified Streaming's plays audio but no video on one browser and
|
|
64
|
+
* nothing on the other. The constraint byte is not carried in this form, so it
|
|
65
|
+
* is emitted as zero; the real flags ride in the avcC the transmux writes.
|
|
66
|
+
*/
|
|
67
|
+
function normalizeAvcCodec(codec) {
|
|
68
|
+
const match = /^(avc1|avc3)\.(\d+)\.(\d+)$/.exec(codec);
|
|
69
|
+
if (match === null) return codec;
|
|
70
|
+
const hex = (n) => (Number(n) & 255).toString(16).padStart(2, "0");
|
|
71
|
+
return `${match[1]}.${hex(Number(match[2]))}00${hex(Number(match[3]))}`;
|
|
72
|
+
}
|
|
73
|
+
function splitCodecs(value) {
|
|
74
|
+
if (value === void 0) return {
|
|
75
|
+
video: null,
|
|
76
|
+
audio: null
|
|
77
|
+
};
|
|
78
|
+
let video = null;
|
|
79
|
+
let audio = null;
|
|
80
|
+
for (const codec of value.split(",").map((c) => c.trim())) {
|
|
81
|
+
if (codec === "") continue;
|
|
82
|
+
if (AUDIO_CODECS.test(codec)) {
|
|
83
|
+
var _audio;
|
|
84
|
+
audio = (_audio = audio) !== null && _audio !== void 0 ? _audio : codec;
|
|
85
|
+
} else {
|
|
86
|
+
var _video;
|
|
87
|
+
video = (_video = video) !== null && _video !== void 0 ? _video : normalizeAvcCodec(codec);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
video,
|
|
92
|
+
audio
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/** parse a media playlist body into segments. */
|
|
96
|
+
function parseMediaPlaylist(text, baseUrl) {
|
|
97
|
+
if (!text.trimStart().startsWith("#EXTM3U")) return {
|
|
98
|
+
playlist: null,
|
|
99
|
+
error: manifestError("missing #EXTM3U")
|
|
100
|
+
};
|
|
101
|
+
const lines = lex(text);
|
|
102
|
+
const segments = [];
|
|
103
|
+
let init = null;
|
|
104
|
+
let targetDuration = 0;
|
|
105
|
+
let mediaSequence = 0;
|
|
106
|
+
let endlist = false;
|
|
107
|
+
let playlistType = null;
|
|
108
|
+
let protection = null;
|
|
109
|
+
let pendingKey = null;
|
|
110
|
+
let dateAnchor;
|
|
111
|
+
let pendingDate = null;
|
|
112
|
+
let pendingDuration = null;
|
|
113
|
+
let pendingRange = null;
|
|
114
|
+
let pendingDiscontinuity = false;
|
|
115
|
+
let previousRangeEnd = null;
|
|
116
|
+
let start = 0;
|
|
117
|
+
let seq = 0;
|
|
118
|
+
for (const line of lines) {
|
|
119
|
+
if (line.kind === "tag") {
|
|
120
|
+
switch (line.name) {
|
|
121
|
+
case "EXT-X-TARGETDURATION":
|
|
122
|
+
targetDuration = Number(line.value) || 0;
|
|
123
|
+
break;
|
|
124
|
+
case "EXT-X-MEDIA-SEQUENCE":
|
|
125
|
+
mediaSequence = Number(line.value) || 0;
|
|
126
|
+
seq = mediaSequence;
|
|
127
|
+
break;
|
|
128
|
+
case "EXT-X-PLAYLIST-TYPE":
|
|
129
|
+
playlistType = line.value;
|
|
130
|
+
break;
|
|
131
|
+
case "EXT-X-ENDLIST":
|
|
132
|
+
endlist = true;
|
|
133
|
+
break;
|
|
134
|
+
case "EXTINF": {
|
|
135
|
+
const comma = line.value.indexOf(",");
|
|
136
|
+
pendingDuration = Number(comma === -1 ? line.value : line.value.slice(0, comma));
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
case "EXT-X-BYTERANGE":
|
|
140
|
+
pendingRange = parseByteRange(line.value, previousRangeEnd);
|
|
141
|
+
break;
|
|
142
|
+
case "EXT-X-DISCONTINUITY":
|
|
143
|
+
pendingDiscontinuity = true;
|
|
144
|
+
break;
|
|
145
|
+
case "EXT-X-MAP": {
|
|
146
|
+
const uri = line.attributes.URI;
|
|
147
|
+
if (uri !== void 0) {
|
|
148
|
+
const range = line.attributes.BYTERANGE !== void 0 ? parseByteRange(line.attributes.BYTERANGE, null) : null;
|
|
149
|
+
init = _objectSpread2({ url: resolve(uri, baseUrl) }, range !== null ? { byteRange: range } : {});
|
|
150
|
+
}
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
case "EXT-X-KEY":
|
|
154
|
+
var _protectionFrom;
|
|
155
|
+
pendingKey = segmentKeyFrom(line, baseUrl);
|
|
156
|
+
protection = (_protectionFrom = protectionFrom(line, baseUrl)) !== null && _protectionFrom !== void 0 ? _protectionFrom : protection;
|
|
157
|
+
break;
|
|
158
|
+
case "EXT-X-PROGRAM-DATE-TIME": {
|
|
159
|
+
const parsed = Date.parse(line.value);
|
|
160
|
+
if (Number.isFinite(parsed)) pendingDate = parsed / 1e3;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (pendingDuration === null || !Number.isFinite(pendingDuration)) return {
|
|
167
|
+
playlist: null,
|
|
168
|
+
error: manifestError(`segment URI without EXTINF: ${line.uri}`)
|
|
169
|
+
};
|
|
170
|
+
if (pendingDate !== null && dateAnchor === void 0) dateAnchor = {
|
|
171
|
+
wallClock: pendingDate,
|
|
172
|
+
presentationTime: start
|
|
173
|
+
};
|
|
174
|
+
pendingDate = null;
|
|
175
|
+
segments.push(_objectSpread2(_objectSpread2(_objectSpread2({
|
|
176
|
+
seq,
|
|
177
|
+
start,
|
|
178
|
+
duration: pendingDuration,
|
|
179
|
+
url: resolve(line.uri, baseUrl)
|
|
180
|
+
}, pendingRange !== null ? { byteRange: pendingRange } : {}), pendingDiscontinuity ? { discontinuity: true } : {}), pendingKey !== null ? { key: pendingKey } : {}));
|
|
181
|
+
previousRangeEnd = pendingRange !== null ? pendingRange.end : previousRangeEnd;
|
|
182
|
+
start += pendingDuration;
|
|
183
|
+
seq += 1;
|
|
184
|
+
pendingDuration = null;
|
|
185
|
+
pendingRange = null;
|
|
186
|
+
pendingDiscontinuity = false;
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
playlist: _objectSpread2({
|
|
190
|
+
segments,
|
|
191
|
+
init,
|
|
192
|
+
targetDuration,
|
|
193
|
+
mediaSequence,
|
|
194
|
+
endlist,
|
|
195
|
+
playlistType,
|
|
196
|
+
protection
|
|
197
|
+
}, dateAnchor !== void 0 ? { dateAnchor } : {}),
|
|
198
|
+
error: null
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function mediaContentType(type) {
|
|
202
|
+
if (type === "AUDIO") return "audio";
|
|
203
|
+
if (type === "SUBTITLES") return "text";
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
/** parse either playlist form into a Presentation. Never throws. */
|
|
207
|
+
function parse(text, baseUrl) {
|
|
208
|
+
if (!text.trimStart().startsWith("#EXTM3U")) return {
|
|
209
|
+
presentation: null,
|
|
210
|
+
error: manifestError("missing #EXTM3U")
|
|
211
|
+
};
|
|
212
|
+
const lines = lex(text);
|
|
213
|
+
if (!lines.some((line) => line.kind === "tag" && line.name === "EXT-X-STREAM-INF")) {
|
|
214
|
+
const media = parseMediaPlaylist(text, baseUrl);
|
|
215
|
+
if (media.playlist === null) {
|
|
216
|
+
var _media$error;
|
|
217
|
+
return {
|
|
218
|
+
presentation: null,
|
|
219
|
+
error: (_media$error = media.error) !== null && _media$error !== void 0 ? _media$error : manifestError("unparsable playlist")
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
if (media.playlist.segments.length === 0) return {
|
|
223
|
+
presentation: null,
|
|
224
|
+
error: {
|
|
225
|
+
category: "manifest",
|
|
226
|
+
code: "MANIFEST_EMPTY",
|
|
227
|
+
fatal: true,
|
|
228
|
+
recoverable: false,
|
|
229
|
+
context: { reason: "no variants and no segments" }
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
const duration = media.playlist.segments.reduce((sum, s) => sum + s.duration, 0);
|
|
233
|
+
const audioOnly = media.playlist.segments.every((s) => /\.(aac|mp3|ac3|ec3|m4a)(\?|$)/i.test(s.url));
|
|
234
|
+
const contentType = audioOnly ? "audio" : "video";
|
|
235
|
+
const mimeType = audioOnly ? "audio/mp4" : "video/mp4";
|
|
236
|
+
const rendition = _objectSpread2({
|
|
237
|
+
id: "r-0",
|
|
238
|
+
bitrate: 0,
|
|
239
|
+
codecs: null,
|
|
240
|
+
mimeType,
|
|
241
|
+
segments: media.playlist.segments
|
|
242
|
+
}, media.playlist.init !== null ? { init: media.playlist.init } : {});
|
|
243
|
+
return {
|
|
244
|
+
presentation: _objectSpread2(_objectSpread2(_objectSpread2({
|
|
245
|
+
id: baseUrl,
|
|
246
|
+
isLive: !media.playlist.endlist
|
|
247
|
+
}, media.playlist.endlist ? { duration } : {}), media.playlist.endlist ? {} : { live: _objectSpread2({ updatePeriod: media.playlist.targetDuration || 4 }, media.playlist.dateAnchor !== void 0 ? { dateAnchor: media.playlist.dateAnchor } : {}) }), {}, {
|
|
248
|
+
periods: [{
|
|
249
|
+
id: "p0",
|
|
250
|
+
start: 0,
|
|
251
|
+
tracks: [{
|
|
252
|
+
id: "main",
|
|
253
|
+
contentType,
|
|
254
|
+
mimeType,
|
|
255
|
+
protection: media.playlist.protection,
|
|
256
|
+
renditions: [rendition]
|
|
257
|
+
}]
|
|
258
|
+
}],
|
|
259
|
+
couplings: []
|
|
260
|
+
}),
|
|
261
|
+
error: null
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
const mediaEntries = [];
|
|
265
|
+
const variants = [];
|
|
266
|
+
let sessionProtection = null;
|
|
267
|
+
let steering;
|
|
268
|
+
let pendingStreamInf = null;
|
|
269
|
+
for (const line of lines) {
|
|
270
|
+
if (line.kind === "tag") {
|
|
271
|
+
if (line.name === "EXT-X-MEDIA") {
|
|
272
|
+
var _line$attributes$TYPE, _line$attributes$GROU, _line$attributes$NAME;
|
|
273
|
+
mediaEntries.push({
|
|
274
|
+
type: (_line$attributes$TYPE = line.attributes.TYPE) !== null && _line$attributes$TYPE !== void 0 ? _line$attributes$TYPE : "",
|
|
275
|
+
groupId: (_line$attributes$GROU = line.attributes["GROUP-ID"]) !== null && _line$attributes$GROU !== void 0 ? _line$attributes$GROU : "",
|
|
276
|
+
name: (_line$attributes$NAME = line.attributes.NAME) !== null && _line$attributes$NAME !== void 0 ? _line$attributes$NAME : "",
|
|
277
|
+
attributes: line.attributes,
|
|
278
|
+
uri: line.attributes.URI !== void 0 ? resolve(line.attributes.URI, baseUrl) : null
|
|
279
|
+
});
|
|
280
|
+
} else if (line.name === "EXT-X-STREAM-INF") pendingStreamInf = line;
|
|
281
|
+
else if (line.name === "EXT-X-SESSION-KEY") {
|
|
282
|
+
var _protectionFrom2;
|
|
283
|
+
sessionProtection = (_protectionFrom2 = protectionFrom(line, baseUrl)) !== null && _protectionFrom2 !== void 0 ? _protectionFrom2 : sessionProtection;
|
|
284
|
+
} else if (line.name === "EXT-X-CONTENT-STEERING") {
|
|
285
|
+
const serverUri = line.attributes["SERVER-URI"];
|
|
286
|
+
if (serverUri !== void 0) steering = _objectSpread2({ serverUri: resolve(serverUri, baseUrl) }, line.attributes["PATHWAY-ID"] !== void 0 ? { defaultPathway: line.attributes["PATHWAY-ID"] } : {});
|
|
287
|
+
}
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
if (pendingStreamInf !== null) {
|
|
291
|
+
variants.push({
|
|
292
|
+
attributes: pendingStreamInf.attributes,
|
|
293
|
+
uri: resolve(line.uri, baseUrl)
|
|
294
|
+
});
|
|
295
|
+
pendingStreamInf = null;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (variants.length === 0) return {
|
|
299
|
+
presentation: null,
|
|
300
|
+
error: manifestError("multivariant playlist with no variants")
|
|
301
|
+
};
|
|
302
|
+
const renditions = [];
|
|
303
|
+
const audioOnlyVariants = [];
|
|
304
|
+
const couplings = [];
|
|
305
|
+
for (const variant of variants) {
|
|
306
|
+
const bandwidth = Number(variant.attributes.BANDWIDTH) || 0;
|
|
307
|
+
const resolution = variant.attributes.RESOLUTION;
|
|
308
|
+
const [width, height] = resolution !== void 0 ? resolution.split("x").map((n) => Number(n)) : [];
|
|
309
|
+
const { video, audio } = splitCodecs(variant.attributes.CODECS);
|
|
310
|
+
if (video === null && audio !== null) {
|
|
311
|
+
audioOnlyVariants.push(variant);
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
const hasAudioGroup = variant.attributes.AUDIO !== void 0;
|
|
315
|
+
const codecs = video !== null && !hasAudioGroup && audio !== null ? `${video}, ${audio}` : video;
|
|
316
|
+
const frameRate = Number(variant.attributes["FRAME-RATE"]);
|
|
317
|
+
const pathway = variant.attributes["PATHWAY-ID"];
|
|
318
|
+
const id = pathway !== void 0 ? `v-${bandwidth}-${pathway}` : `v-${bandwidth}`;
|
|
319
|
+
if (renditions.some((r) => r.id === id)) continue;
|
|
320
|
+
renditions.push(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({
|
|
321
|
+
id,
|
|
322
|
+
bitrate: bandwidth,
|
|
323
|
+
codecs,
|
|
324
|
+
mimeType: "video/mp4",
|
|
325
|
+
segments: [],
|
|
326
|
+
playlistUrl: variant.uri
|
|
327
|
+
}, pathway !== void 0 ? { pathway } : {}), width !== void 0 && Number.isFinite(width) ? { width } : {}), height !== void 0 && Number.isFinite(height) ? { height } : {}), Number.isFinite(frameRate) ? { frameRate } : {}));
|
|
328
|
+
const requires = {};
|
|
329
|
+
if (variant.attributes.AUDIO !== void 0) requires.audio = variant.attributes.AUDIO;
|
|
330
|
+
if (variant.attributes.SUBTITLES !== void 0) requires.text = variant.attributes.SUBTITLES;
|
|
331
|
+
if (Object.keys(requires).length > 0) couplings.push({
|
|
332
|
+
renditionId: id,
|
|
333
|
+
requires
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
const tracks = [];
|
|
337
|
+
if (renditions.length > 0) tracks.push({
|
|
338
|
+
id: "video-main",
|
|
339
|
+
contentType: "video",
|
|
340
|
+
mimeType: "video/mp4",
|
|
341
|
+
protection: sessionProtection,
|
|
342
|
+
renditions
|
|
343
|
+
});
|
|
344
|
+
else if (audioOnlyVariants.length > 0) {
|
|
345
|
+
const audioRenditions = [];
|
|
346
|
+
for (const variant of audioOnlyVariants) {
|
|
347
|
+
const bandwidth = Number(variant.attributes.BANDWIDTH) || 0;
|
|
348
|
+
const id = `a-${bandwidth}`;
|
|
349
|
+
if (audioRenditions.some((r) => r.id === id)) continue;
|
|
350
|
+
const { audio } = splitCodecs(variant.attributes.CODECS);
|
|
351
|
+
audioRenditions.push({
|
|
352
|
+
id,
|
|
353
|
+
bitrate: bandwidth,
|
|
354
|
+
codecs: audio,
|
|
355
|
+
mimeType: "audio/mp4",
|
|
356
|
+
segments: [],
|
|
357
|
+
playlistUrl: variant.uri
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
tracks.push({
|
|
361
|
+
id: "audio-main",
|
|
362
|
+
contentType: "audio",
|
|
363
|
+
mimeType: "audio/mp4",
|
|
364
|
+
protection: sessionProtection,
|
|
365
|
+
renditions: audioRenditions
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
for (const entry of mediaEntries) {
|
|
369
|
+
var _variants$find;
|
|
370
|
+
const contentType = mediaContentType(entry.type);
|
|
371
|
+
if (contentType === null || entry.uri === null) continue;
|
|
372
|
+
const { audio } = splitCodecs((_variants$find = variants.find((v) => v.attributes.AUDIO === entry.groupId)) === null || _variants$find === void 0 ? void 0 : _variants$find.attributes.CODECS);
|
|
373
|
+
const mimeType = contentType === "audio" ? "audio/mp4" : "text/vtt";
|
|
374
|
+
tracks.push(_objectSpread2(_objectSpread2(_objectSpread2({
|
|
375
|
+
id: `${entry.groupId}:${entry.name}`,
|
|
376
|
+
contentType,
|
|
377
|
+
mimeType,
|
|
378
|
+
protection: sessionProtection
|
|
379
|
+
}, entry.attributes.LANGUAGE !== void 0 ? { lang: entry.attributes.LANGUAGE } : {}), entry.attributes.DEFAULT === "YES" ? { role: "main" } : { role: "alternate" }), {}, { renditions: [{
|
|
380
|
+
id: `${entry.groupId}:${entry.name}`,
|
|
381
|
+
bitrate: 0,
|
|
382
|
+
codecs: contentType === "audio" ? audio : null,
|
|
383
|
+
mimeType,
|
|
384
|
+
segments: [],
|
|
385
|
+
playlistUrl: entry.uri
|
|
386
|
+
}] }));
|
|
387
|
+
}
|
|
388
|
+
return {
|
|
389
|
+
presentation: _objectSpread2({
|
|
390
|
+
id: baseUrl,
|
|
391
|
+
isLive: false,
|
|
392
|
+
periods: [{
|
|
393
|
+
id: "p0",
|
|
394
|
+
start: 0,
|
|
395
|
+
tracks
|
|
396
|
+
}],
|
|
397
|
+
couplings
|
|
398
|
+
}, steering !== void 0 ? { steering } : {}),
|
|
399
|
+
error: null
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* The presentation-time shift that puts a refreshed live window back on the
|
|
404
|
+
* timeline the previous window established. parseMediaPlaylist numbers every
|
|
405
|
+
* window from zero, but playback needs one stable seq->time map across
|
|
406
|
+
* reloads: without it a sliding window keeps handing the newest segment the
|
|
407
|
+
* same low start, the buffer never advances past the first window, and live
|
|
408
|
+
* stalls with no recovery. The media sequence number shared by the old and new
|
|
409
|
+
* window fixes the offset; a fresh load (no prior segments) shifts by zero.
|
|
410
|
+
*/
|
|
411
|
+
function timelineShift(previous, next) {
|
|
412
|
+
if (!Array.isArray(previous) || previous.length === 0 || next.length === 0) return 0;
|
|
413
|
+
const prior = previous;
|
|
414
|
+
const startBySeq = new Map(prior.map((s) => [s.seq, s.start]));
|
|
415
|
+
for (const segment of next) {
|
|
416
|
+
const priorStart = startBySeq.get(segment.seq);
|
|
417
|
+
if (priorStart !== void 0) return priorStart - segment.start;
|
|
418
|
+
}
|
|
419
|
+
const last = prior[prior.length - 1];
|
|
420
|
+
const first = next[0];
|
|
421
|
+
const average = prior.reduce((sum, s) => sum + s.duration, 0) / prior.length;
|
|
422
|
+
return last.start + (first.seq - last.seq) * average - first.start;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Immutably merges a fetched media playlist into the rendition that
|
|
426
|
+
* referenced it. Duration, liveness, init, and protection all come from
|
|
427
|
+
* the media playlist; the presentation learns them here. On a live refresh
|
|
428
|
+
* the new window is rebased onto the running timeline first, so segment start
|
|
429
|
+
* times stay absolute across reloads.
|
|
430
|
+
*/
|
|
431
|
+
function mergePlaylist(presentation, renditionId, playlist) {
|
|
432
|
+
var _presentation$duratio;
|
|
433
|
+
let previous = [];
|
|
434
|
+
for (const period of presentation.periods) for (const track of period.tracks) for (const rendition of track.renditions) if (rendition.id === renditionId) previous = rendition.segments;
|
|
435
|
+
const knownLast = Array.isArray(previous) ? previous[previous.length - 1] : void 0;
|
|
436
|
+
const incomingLast = playlist.segments[playlist.segments.length - 1];
|
|
437
|
+
if (knownLast !== void 0 && incomingLast !== void 0 && !playlist.endlist && incomingLast.seq < knownLast.seq) return presentation;
|
|
438
|
+
const shift = timelineShift(previous, playlist.segments);
|
|
439
|
+
const segments = shift === 0 ? playlist.segments : playlist.segments.map((s) => _objectSpread2(_objectSpread2({}, s), {}, { start: s.start + shift }));
|
|
440
|
+
const duration = segments.reduce((sum, s) => sum + s.duration, 0);
|
|
441
|
+
const dateAnchor = playlist.dateAnchor !== void 0 ? {
|
|
442
|
+
wallClock: playlist.dateAnchor.wallClock,
|
|
443
|
+
presentationTime: playlist.dateAnchor.presentationTime + shift
|
|
444
|
+
} : void 0;
|
|
445
|
+
const periods = presentation.periods.map((period) => _objectSpread2(_objectSpread2({}, period), {}, { tracks: period.tracks.map((track) => {
|
|
446
|
+
var _track$protection;
|
|
447
|
+
if (!track.renditions.some((r) => r.id === renditionId)) return track;
|
|
448
|
+
return _objectSpread2(_objectSpread2({}, track), {}, {
|
|
449
|
+
protection: (_track$protection = track.protection) !== null && _track$protection !== void 0 ? _track$protection : playlist.protection,
|
|
450
|
+
renditions: track.renditions.map((rendition) => rendition.id === renditionId ? _objectSpread2(_objectSpread2({}, rendition), {}, { segments }, playlist.init !== null ? { init: playlist.init } : {}) : rendition)
|
|
451
|
+
});
|
|
452
|
+
}) }));
|
|
453
|
+
const knownDuration = (_presentation$duratio = presentation.duration) !== null && _presentation$duratio !== void 0 ? _presentation$duratio : 0;
|
|
454
|
+
return _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, presentation), {}, { isLive: !playlist.endlist }, playlist.endlist ? { duration: Math.max(knownDuration, duration) } : {}), playlist.endlist ? {} : { live: _objectSpread2(_objectSpread2({}, presentation.live), {}, { updatePeriod: playlist.targetDuration || 4 }, dateAnchor !== void 0 ? { dateAnchor } : {}) }), {}, { periods });
|
|
455
|
+
}
|
|
456
|
+
//#endregion
|
|
457
|
+
export { mergePlaylist, normalizeAvcCodec, parse, parseMediaPlaylist };
|