@editframe/elements 0.17.6-beta.0 → 0.18.3-beta.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/dist/EF_FRAMEGEN.js +1 -1
- package/dist/ScrubTrackManager.d.ts +2 -2
- package/dist/elements/EFAudio.d.ts +21 -2
- package/dist/elements/EFAudio.js +41 -11
- package/dist/elements/EFImage.d.ts +1 -0
- package/dist/elements/EFImage.js +11 -3
- package/dist/elements/EFMedia/AssetIdMediaEngine.d.ts +18 -0
- package/dist/elements/EFMedia/AssetIdMediaEngine.js +41 -0
- package/dist/elements/EFMedia/AssetMediaEngine.d.ts +47 -0
- package/dist/elements/EFMedia/AssetMediaEngine.js +116 -0
- package/dist/elements/EFMedia/BaseMediaEngine.d.ts +55 -0
- package/dist/elements/EFMedia/BaseMediaEngine.js +96 -0
- package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +43 -0
- package/dist/elements/EFMedia/BufferedSeekingInput.js +159 -0
- package/dist/elements/EFMedia/JitMediaEngine.browsertest.d.ts +0 -0
- package/dist/elements/EFMedia/JitMediaEngine.d.ts +31 -0
- package/dist/elements/EFMedia/JitMediaEngine.js +62 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.d.ts +16 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +48 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.d.ts +3 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +138 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.d.ts +4 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +16 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.d.ts +3 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +22 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.d.ts +7 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +24 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.d.ts +4 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +18 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.d.ts +4 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +16 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.d.ts +3 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +104 -0
- package/dist/elements/EFMedia/services/AudioElementFactory.d.ts +22 -0
- package/dist/elements/EFMedia/services/AudioElementFactory.js +72 -0
- package/dist/elements/EFMedia/services/MediaSourceService.browsertest.d.ts +1 -0
- package/dist/elements/EFMedia/services/MediaSourceService.d.ts +47 -0
- package/dist/elements/EFMedia/services/MediaSourceService.js +73 -0
- package/dist/elements/EFMedia/shared/AudioSpanUtils.d.ts +7 -0
- package/dist/elements/EFMedia/shared/AudioSpanUtils.js +54 -0
- package/dist/elements/EFMedia/shared/BufferUtils.d.ts +70 -0
- package/dist/elements/EFMedia/shared/BufferUtils.js +89 -0
- package/dist/elements/EFMedia/shared/MediaTaskUtils.d.ts +23 -0
- package/dist/elements/EFMedia/shared/RenditionHelpers.browsertest.d.ts +1 -0
- package/dist/elements/EFMedia/shared/RenditionHelpers.d.ts +19 -0
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.browsertest.d.ts +1 -0
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.d.ts +18 -0
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +60 -0
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.test.d.ts +1 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.d.ts +16 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +46 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.d.ts +4 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.js +16 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.d.ts +3 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.js +27 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSeekTask.d.ts +7 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSeekTask.js +25 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.d.ts +4 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.js +18 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.d.ts +4 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.js +16 -0
- package/dist/elements/EFMedia.browsertest.d.ts +1 -0
- package/dist/elements/EFMedia.d.ts +75 -111
- package/dist/elements/EFMedia.js +141 -1111
- package/dist/elements/EFTemporal.d.ts +1 -1
- package/dist/elements/EFTemporal.js +1 -1
- package/dist/elements/EFTimegroup.d.ts +11 -0
- package/dist/elements/EFTimegroup.js +88 -13
- package/dist/elements/EFVideo.d.ts +60 -29
- package/dist/elements/EFVideo.js +103 -203
- package/dist/elements/EFWaveform.js +2 -2
- package/dist/elements/SampleBuffer.d.ts +14 -0
- package/dist/elements/SampleBuffer.js +52 -0
- package/dist/getRenderInfo.d.ts +2 -2
- package/dist/getRenderInfo.js +2 -1
- package/dist/gui/ContextMixin.js +17 -70
- package/dist/gui/EFFilmstrip.d.ts +3 -3
- package/dist/gui/EFFilmstrip.js +1 -1
- package/dist/gui/EFFitScale.d.ts +2 -2
- package/dist/gui/TWMixin.js +1 -1
- package/dist/gui/services/ElementConnectionManager.browsertest.d.ts +1 -0
- package/dist/gui/services/ElementConnectionManager.d.ts +59 -0
- package/dist/gui/services/ElementConnectionManager.js +128 -0
- package/dist/gui/services/PlaybackController.browsertest.d.ts +1 -0
- package/dist/gui/services/PlaybackController.d.ts +103 -0
- package/dist/gui/services/PlaybackController.js +290 -0
- package/dist/services/MediaSourceManager.d.ts +62 -0
- package/dist/services/MediaSourceManager.js +211 -0
- package/dist/style.css +1 -1
- package/dist/transcoding/cache/CacheManager.d.ts +73 -0
- package/dist/transcoding/cache/RequestDeduplicator.d.ts +29 -0
- package/dist/transcoding/cache/RequestDeduplicator.js +53 -0
- package/dist/transcoding/cache/RequestDeduplicator.test.d.ts +1 -0
- package/dist/transcoding/types/index.d.ts +242 -0
- package/dist/transcoding/utils/MediaUtils.d.ts +9 -0
- package/dist/transcoding/utils/UrlGenerator.d.ts +26 -0
- package/dist/transcoding/utils/UrlGenerator.js +45 -0
- package/dist/transcoding/utils/constants.d.ts +27 -0
- package/dist/utils/LRUCache.d.ts +34 -0
- package/dist/utils/LRUCache.js +115 -0
- package/package.json +3 -2
- package/src/elements/EFAudio.browsertest.ts +183 -43
- package/src/elements/EFAudio.ts +59 -13
- package/src/elements/EFImage.browsertest.ts +42 -0
- package/src/elements/EFImage.ts +23 -3
- package/src/elements/EFMedia/AssetIdMediaEngine.test.ts +222 -0
- package/src/elements/EFMedia/AssetIdMediaEngine.ts +70 -0
- package/src/elements/EFMedia/AssetMediaEngine.ts +210 -0
- package/src/elements/EFMedia/BaseMediaEngine.test.ts +164 -0
- package/src/elements/EFMedia/BaseMediaEngine.ts +170 -0
- package/src/elements/EFMedia/BufferedSeekingInput.browsertest.ts +400 -0
- package/src/elements/EFMedia/BufferedSeekingInput.ts +267 -0
- package/src/elements/EFMedia/JitMediaEngine.browsertest.ts +165 -0
- package/src/elements/EFMedia/JitMediaEngine.ts +110 -0
- package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.ts +554 -0
- package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.ts +81 -0
- package/src/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.ts +241 -0
- package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.ts +59 -0
- package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.ts +23 -0
- package/src/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.ts +55 -0
- package/src/elements/EFMedia/audioTasks/makeAudioInputTask.ts +35 -0
- package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.ts +42 -0
- package/src/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.ts +34 -0
- package/src/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.ts +23 -0
- package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +174 -0
- package/src/elements/EFMedia/services/AudioElementFactory.browsertest.ts +325 -0
- package/src/elements/EFMedia/services/AudioElementFactory.ts +119 -0
- package/src/elements/EFMedia/services/MediaSourceService.browsertest.ts +257 -0
- package/src/elements/EFMedia/services/MediaSourceService.ts +102 -0
- package/src/elements/EFMedia/shared/AudioSpanUtils.ts +128 -0
- package/src/elements/EFMedia/shared/BufferUtils.ts +310 -0
- package/src/elements/EFMedia/shared/MediaTaskUtils.ts +44 -0
- package/src/elements/EFMedia/shared/RenditionHelpers.browsertest.ts +247 -0
- package/src/elements/EFMedia/shared/RenditionHelpers.ts +79 -0
- package/src/elements/EFMedia/tasks/makeMediaEngineTask.browsertest.ts +128 -0
- package/src/elements/EFMedia/tasks/makeMediaEngineTask.test.ts +233 -0
- package/src/elements/EFMedia/tasks/makeMediaEngineTask.ts +89 -0
- package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.browsertest.ts +555 -0
- package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.ts +79 -0
- package/src/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.browsertest.ts +59 -0
- package/src/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.ts +23 -0
- package/src/elements/EFMedia/videoTasks/makeVideoInputTask.browsertest.ts +55 -0
- package/src/elements/EFMedia/videoTasks/makeVideoInputTask.ts +45 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSeekTask.ts +44 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.browsertest.ts +57 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.ts +32 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.browsertest.ts +56 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.ts +23 -0
- package/src/elements/EFMedia.browsertest.ts +658 -265
- package/src/elements/EFMedia.ts +173 -1763
- package/src/elements/EFTemporal.ts +3 -4
- package/src/elements/EFTimegroup.browsertest.ts +6 -3
- package/src/elements/EFTimegroup.ts +152 -21
- package/src/elements/EFVideo.browsertest.ts +115 -37
- package/src/elements/EFVideo.ts +123 -452
- package/src/elements/EFWaveform.ts +1 -1
- package/src/elements/MediaController.ts +2 -12
- package/src/elements/SampleBuffer.ts +97 -0
- package/src/gui/ContextMixin.ts +23 -104
- package/src/gui/services/ElementConnectionManager.browsertest.ts +263 -0
- package/src/gui/services/ElementConnectionManager.ts +224 -0
- package/src/gui/services/PlaybackController.browsertest.ts +437 -0
- package/src/gui/services/PlaybackController.ts +521 -0
- package/src/services/MediaSourceManager.ts +333 -0
- package/src/transcoding/cache/CacheManager.ts +208 -0
- package/src/transcoding/cache/RequestDeduplicator.test.ts +170 -0
- package/src/transcoding/cache/RequestDeduplicator.ts +65 -0
- package/src/transcoding/types/index.ts +265 -0
- package/src/transcoding/utils/MediaUtils.ts +63 -0
- package/src/transcoding/utils/UrlGenerator.ts +68 -0
- package/src/transcoding/utils/constants.ts +36 -0
- package/src/utils/LRUCache.ts +153 -0
- package/test/EFVideo.framegen.browsertest.ts +38 -29
- package/test/__cache__/GET__api_v1_transcode_audio_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__32da3954ba60c96ad732020c65a08ebc/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_audio_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__32da3954ba60c96ad732020c65a08ebc/metadata.json +21 -0
- package/test/__cache__/GET__api_v1_transcode_audio_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__b0b2b07efcf607de8ee0f650328c32f7/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_audio_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__b0b2b07efcf607de8ee0f650328c32f7/metadata.json +21 -0
- package/test/__cache__/GET__api_v1_transcode_audio_3_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a75c2252b542e0c152c780e9a8d7b154/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_audio_3_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a75c2252b542e0c152c780e9a8d7b154/metadata.json +21 -0
- package/test/__cache__/GET__api_v1_transcode_audio_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a64ff1cfb1b52cae14df4b5dfa1e222b/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_audio_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a64ff1cfb1b52cae14df4b5dfa1e222b/metadata.json +21 -0
- package/test/__cache__/GET__api_v1_transcode_audio_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__91e8a522f950809b9f09f4173113b4b0/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_audio_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__91e8a522f950809b9f09f4173113b4b0/metadata.json +21 -0
- package/test/__cache__/GET__api_v1_transcode_audio_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__e66d2c831d951e74ad0aeaa6489795d0/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_audio_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__e66d2c831d951e74ad0aeaa6489795d0/metadata.json +21 -0
- package/test/__cache__/GET__api_v1_transcode_high_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__26197f6f7c46cacb0a71134131c3f775/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_high_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__26197f6f7c46cacb0a71134131c3f775/metadata.json +21 -0
- package/test/__cache__/GET__api_v1_transcode_high_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__4cb6774cd3650ccf59c8f8dc6678c0b9/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_high_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__4cb6774cd3650ccf59c8f8dc6678c0b9/metadata.json +21 -0
- package/test/__cache__/GET__api_v1_transcode_high_3_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__0b3b2b1c8933f7fcf8a9ecaa88d58b41/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_high_3_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__0b3b2b1c8933f7fcf8a9ecaa88d58b41/metadata.json +21 -0
- package/test/__cache__/GET__api_v1_transcode_high_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__0798c479b44aaeef850609a430f6e613/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_high_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__0798c479b44aaeef850609a430f6e613/metadata.json +21 -0
- package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/data.bin +1 -0
- package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/metadata.json +19 -0
- package/test/createJitTestClips.ts +320 -188
- package/test/recordReplayProxyPlugin.js +302 -0
- package/test/useAssetMSW.ts +1 -1
- package/test/useMSW.ts +35 -22
- package/types.json +1 -1
- package/dist/JitTranscodingClient.d.ts +0 -167
- package/dist/JitTranscodingClient.js +0 -373
- package/dist/ScrubTrackManager.js +0 -216
- package/dist/elements/printTaskStatus.js +0 -11
- package/src/elements/__screenshots__/EFMedia.browsertest.ts/EFMedia-JIT-audio-playback-audioBufferTask-should-work-in-JIT-mode-without-URL-errors-1.png +0 -0
- package/test/EFVideo.frame-tasks.browsertest.ts +0 -524
- /package/dist/{JitTranscodingClient.browsertest.d.ts → elements/EFMedia/AssetIdMediaEngine.test.d.ts} +0 -0
- /package/dist/{JitTranscodingClient.test.d.ts → elements/EFMedia/BaseMediaEngine.test.d.ts} +0 -0
- /package/dist/{ScrubTrackIntegration.test.d.ts → elements/EFMedia/BufferedSeekingInput.browsertest.d.ts} +0 -0
- /package/dist/{SegmentSwitchLoading.test.d.ts → elements/EFMedia/services/AudioElementFactory.browsertest.d.ts} +0 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MediaSourceManager,
|
|
3
|
+
type MediaSourceManagerOptions,
|
|
4
|
+
} from "../../../services/MediaSourceManager.js";
|
|
5
|
+
|
|
6
|
+
export interface MediaSourceServiceOptions {
|
|
7
|
+
onError?: (error: Error) => void;
|
|
8
|
+
onReady?: () => void;
|
|
9
|
+
onUpdateEnd?: () => void;
|
|
10
|
+
timeout?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Service for managing MediaSource lifecycle and audio element creation
|
|
15
|
+
* Extracted from EFMedia to improve separation of concerns and testability
|
|
16
|
+
*/
|
|
17
|
+
export class MediaSourceService {
|
|
18
|
+
private mediaSourceManager: MediaSourceManager | null = null;
|
|
19
|
+
private options: MediaSourceServiceOptions;
|
|
20
|
+
|
|
21
|
+
constructor(options: MediaSourceServiceOptions = {}) {
|
|
22
|
+
this.options = options;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Initialize MediaSource if not already initialized
|
|
27
|
+
*/
|
|
28
|
+
async ensureInitialized(): Promise<void> {
|
|
29
|
+
if (this.mediaSourceManager?.isReady()) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
await this.initialize();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Initialize fresh MediaSource
|
|
38
|
+
*/
|
|
39
|
+
async initialize(): Promise<void> {
|
|
40
|
+
// Clean up existing instance
|
|
41
|
+
this.cleanup();
|
|
42
|
+
|
|
43
|
+
// Create new MediaSourceManager
|
|
44
|
+
const managerOptions: MediaSourceManagerOptions = {
|
|
45
|
+
onError: this.options.onError,
|
|
46
|
+
onReady: this.options.onReady,
|
|
47
|
+
onUpdateEnd: this.options.onUpdateEnd,
|
|
48
|
+
timeout: this.options.timeout,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
this.mediaSourceManager = new MediaSourceManager(managerOptions);
|
|
52
|
+
await this.mediaSourceManager.initialize();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get audio element for MediaElementSource creation
|
|
57
|
+
*/
|
|
58
|
+
getAudioElement(): HTMLAudioElement | null {
|
|
59
|
+
return this.mediaSourceManager?.getAudioElement() || null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Feed audio segments to MediaSource
|
|
64
|
+
*/
|
|
65
|
+
async feedSegment(segmentBuffer: ArrayBuffer): Promise<void> {
|
|
66
|
+
await this.ensureInitialized();
|
|
67
|
+
if (this.mediaSourceManager) {
|
|
68
|
+
await this.mediaSourceManager.feedSegment(segmentBuffer);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Check if MediaSource is ready
|
|
74
|
+
*/
|
|
75
|
+
isReady(): boolean {
|
|
76
|
+
return this.mediaSourceManager?.isReady() ?? false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Get buffered time ranges
|
|
81
|
+
*/
|
|
82
|
+
getBuffered(): TimeRanges | null {
|
|
83
|
+
return this.mediaSourceManager?.getBuffered() || null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Set audio element current time
|
|
88
|
+
*/
|
|
89
|
+
setCurrentTime(timeMs: number): void {
|
|
90
|
+
this.mediaSourceManager?.setCurrentTime(timeMs);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Clean up MediaSource resources
|
|
95
|
+
*/
|
|
96
|
+
cleanup(): void {
|
|
97
|
+
if (this.mediaSourceManager) {
|
|
98
|
+
this.mediaSourceManager.cleanup();
|
|
99
|
+
this.mediaSourceManager = null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AudioSpan,
|
|
3
|
+
MediaEngine,
|
|
4
|
+
SegmentTimeRange,
|
|
5
|
+
} from "../../../transcoding/types";
|
|
6
|
+
import type { EFMedia } from "../../EFMedia";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Fetch audio segment data using MediaEngine
|
|
10
|
+
* Pure function with explicit dependencies
|
|
11
|
+
*/
|
|
12
|
+
const fetchAudioSegmentData = async (
|
|
13
|
+
segmentIds: number[],
|
|
14
|
+
mediaEngine: MediaEngine,
|
|
15
|
+
signal: AbortSignal,
|
|
16
|
+
): Promise<Map<number, ArrayBuffer>> => {
|
|
17
|
+
const audioRendition = mediaEngine.audioRendition;
|
|
18
|
+
if (!audioRendition) {
|
|
19
|
+
throw new Error("Audio rendition not available");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const segmentData = new Map<number, ArrayBuffer>();
|
|
23
|
+
|
|
24
|
+
// Fetch all segments - MediaEngine handles deduplication internally
|
|
25
|
+
const fetchPromises = segmentIds.map(async (segmentId) => {
|
|
26
|
+
const arrayBuffer = await mediaEngine.fetchMediaSegment(
|
|
27
|
+
segmentId,
|
|
28
|
+
audioRendition,
|
|
29
|
+
signal,
|
|
30
|
+
);
|
|
31
|
+
return [segmentId, arrayBuffer] as [number, ArrayBuffer];
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const fetchedSegments = await Promise.all(fetchPromises);
|
|
35
|
+
signal.throwIfAborted();
|
|
36
|
+
|
|
37
|
+
for (const [segmentId, arrayBuffer] of fetchedSegments) {
|
|
38
|
+
segmentData.set(segmentId, arrayBuffer);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return segmentData;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Create audio span blob from init segment and media segments
|
|
46
|
+
* Pure function for blob creation
|
|
47
|
+
*/
|
|
48
|
+
const createAudioSpanBlob = (
|
|
49
|
+
initSegment: ArrayBuffer,
|
|
50
|
+
mediaSegments: ArrayBuffer[],
|
|
51
|
+
): Blob => {
|
|
52
|
+
const chunks = [initSegment, ...mediaSegments];
|
|
53
|
+
return new Blob(chunks, { type: "audio/mp4" });
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Fetch audio spanning a time range
|
|
58
|
+
* Main function that orchestrates segment calculation, fetching, and blob creation
|
|
59
|
+
*/
|
|
60
|
+
export const fetchAudioSpanningTime = async (
|
|
61
|
+
host: EFMedia,
|
|
62
|
+
fromMs: number,
|
|
63
|
+
toMs: number,
|
|
64
|
+
signal: AbortSignal,
|
|
65
|
+
): Promise<AudioSpan> => {
|
|
66
|
+
// Validate inputs
|
|
67
|
+
if (fromMs >= toMs || fromMs < 0) {
|
|
68
|
+
throw new Error(`Invalid time range: fromMs=${fromMs}, toMs=${toMs}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Get dependencies from host
|
|
72
|
+
const mediaEngine = await host.mediaEngineTask.taskComplete;
|
|
73
|
+
const initSegment = await host.audioInitSegmentFetchTask.taskComplete;
|
|
74
|
+
|
|
75
|
+
if (!mediaEngine?.audioRendition) {
|
|
76
|
+
throw new Error("Audio rendition not available");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!initSegment) {
|
|
80
|
+
throw new Error("Audio init segment is not available");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Calculate segments needed using the media engine's method
|
|
84
|
+
const segmentRanges = mediaEngine.calculateAudioSegmentRange(
|
|
85
|
+
fromMs,
|
|
86
|
+
toMs,
|
|
87
|
+
mediaEngine.audioRendition,
|
|
88
|
+
host.intrinsicDurationMs || 10000,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
if (segmentRanges.length === 0) {
|
|
92
|
+
throw new Error(`No segments found for time range ${fromMs}-${toMs}ms`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Fetch segment data
|
|
96
|
+
const segmentIds = segmentRanges.map((r: SegmentTimeRange) => r.segmentId);
|
|
97
|
+
const segmentData = await fetchAudioSegmentData(
|
|
98
|
+
segmentIds,
|
|
99
|
+
mediaEngine,
|
|
100
|
+
signal,
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// Create ordered array of segments
|
|
104
|
+
const orderedSegments = segmentIds.map((id: number) => {
|
|
105
|
+
const segment = segmentData.get(id);
|
|
106
|
+
if (!segment) {
|
|
107
|
+
throw new Error(`Missing segment data for segment ID ${id}`);
|
|
108
|
+
}
|
|
109
|
+
return segment;
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Create blob
|
|
113
|
+
const blob = createAudioSpanBlob(initSegment, orderedSegments);
|
|
114
|
+
|
|
115
|
+
// Calculate actual time boundaries
|
|
116
|
+
const actualStartMs = Math.min(
|
|
117
|
+
...segmentRanges.map((r: SegmentTimeRange) => r.startMs),
|
|
118
|
+
);
|
|
119
|
+
const actualEndMs = Math.max(
|
|
120
|
+
...segmentRanges.map((r: SegmentTimeRange) => r.endMs),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
startMs: actualStartMs,
|
|
125
|
+
endMs: actualEndMs,
|
|
126
|
+
blob,
|
|
127
|
+
};
|
|
128
|
+
};
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AudioRendition,
|
|
3
|
+
VideoRendition,
|
|
4
|
+
} from "../../../transcoding/types";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* State interface for media buffering - generic for both audio and video
|
|
8
|
+
*/
|
|
9
|
+
export interface MediaBufferState {
|
|
10
|
+
currentSeekTimeMs: number;
|
|
11
|
+
activeRequests: Set<number>;
|
|
12
|
+
cachedSegments: Set<number>;
|
|
13
|
+
requestQueue: number[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Configuration interface for media buffering - generic for both audio and video
|
|
18
|
+
*/
|
|
19
|
+
export interface MediaBufferConfig {
|
|
20
|
+
bufferDurationMs: number;
|
|
21
|
+
maxParallelFetches: number;
|
|
22
|
+
enableBuffering: boolean;
|
|
23
|
+
enableContinuousBuffering?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Dependencies interface for media buffering - generic for both audio and video
|
|
28
|
+
*/
|
|
29
|
+
export interface MediaBufferDependencies<
|
|
30
|
+
T extends AudioRendition | VideoRendition,
|
|
31
|
+
> {
|
|
32
|
+
computeSegmentId: (
|
|
33
|
+
timeMs: number,
|
|
34
|
+
rendition: T,
|
|
35
|
+
) => Promise<number | undefined>;
|
|
36
|
+
fetchSegment: (segmentId: number, rendition: T) => Promise<ArrayBuffer>;
|
|
37
|
+
getRendition: () => Promise<T>;
|
|
38
|
+
logError: (message: string, error: any) => void;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Compute segment range for a time window
|
|
43
|
+
* Pure function - determines which segments are needed for a time range
|
|
44
|
+
*/
|
|
45
|
+
export const computeSegmentRange = <T extends AudioRendition | VideoRendition>(
|
|
46
|
+
startTimeMs: number,
|
|
47
|
+
endTimeMs: number,
|
|
48
|
+
rendition: T,
|
|
49
|
+
computeSegmentId: (timeMs: number, rendition: T) => number | undefined,
|
|
50
|
+
): number[] => {
|
|
51
|
+
const segments: number[] = [];
|
|
52
|
+
const segmentDurationMs = (rendition as any).segmentDurationMs || 1000;
|
|
53
|
+
|
|
54
|
+
// Calculate segment indices that overlap with [startTimeMs, endTimeMs]
|
|
55
|
+
const startSegmentIndex = Math.floor(startTimeMs / segmentDurationMs);
|
|
56
|
+
const endSegmentIndex = Math.floor(endTimeMs / segmentDurationMs);
|
|
57
|
+
|
|
58
|
+
for (let i = startSegmentIndex; i <= endSegmentIndex; i++) {
|
|
59
|
+
const segmentId = computeSegmentId(i * segmentDurationMs, rendition);
|
|
60
|
+
if (segmentId !== undefined) {
|
|
61
|
+
segments.push(segmentId);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return segments.filter((id, index, arr) => arr.indexOf(id) === index); // Remove duplicates
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Async version of computeSegmentRange for when computeSegmentId is async
|
|
70
|
+
*/
|
|
71
|
+
export const computeSegmentRangeAsync = async <
|
|
72
|
+
T extends AudioRendition | VideoRendition,
|
|
73
|
+
>(
|
|
74
|
+
startTimeMs: number,
|
|
75
|
+
endTimeMs: number,
|
|
76
|
+
durationMs: number,
|
|
77
|
+
rendition: T,
|
|
78
|
+
computeSegmentId: (
|
|
79
|
+
timeMs: number,
|
|
80
|
+
rendition: T,
|
|
81
|
+
) => Promise<number | undefined>,
|
|
82
|
+
): Promise<number[]> => {
|
|
83
|
+
const segments: number[] = [];
|
|
84
|
+
const segmentDurationMs = (rendition as any).segmentDurationMs || 1000;
|
|
85
|
+
|
|
86
|
+
// Calculate segment indices that overlap with [startTimeMs, endTimeMs]
|
|
87
|
+
const startSegmentIndex = Math.floor(startTimeMs / segmentDurationMs);
|
|
88
|
+
const endSegmentIndex = Math.floor(
|
|
89
|
+
Math.min(endTimeMs, durationMs) / segmentDurationMs,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
for (let i = startSegmentIndex; i <= endSegmentIndex; i++) {
|
|
93
|
+
const timeMs = i * segmentDurationMs;
|
|
94
|
+
if (timeMs < durationMs) {
|
|
95
|
+
const segmentId = await computeSegmentId(timeMs, rendition);
|
|
96
|
+
if (segmentId !== undefined) {
|
|
97
|
+
segments.push(segmentId);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return segments.filter((id, index, arr) => arr.indexOf(id) === index); // Remove duplicates
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Compute buffer queue based on current state and desired segments
|
|
107
|
+
* Pure function - determines what segments should be fetched
|
|
108
|
+
*/
|
|
109
|
+
export const computeBufferQueue = (
|
|
110
|
+
desiredSegments: number[],
|
|
111
|
+
activeRequests: Set<number>,
|
|
112
|
+
cachedSegments: Set<number>,
|
|
113
|
+
): number[] => {
|
|
114
|
+
return desiredSegments.filter(
|
|
115
|
+
(segmentId) =>
|
|
116
|
+
!activeRequests.has(segmentId) && !cachedSegments.has(segmentId),
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Handle seek time change and recompute buffer queue
|
|
122
|
+
* Pure function - computes new queue when seek time changes
|
|
123
|
+
*/
|
|
124
|
+
export const handleSeekTimeChange = <T extends AudioRendition | VideoRendition>(
|
|
125
|
+
newSeekTimeMs: number,
|
|
126
|
+
bufferDurationMs: number,
|
|
127
|
+
rendition: T,
|
|
128
|
+
currentState: MediaBufferState,
|
|
129
|
+
computeSegmentId: (timeMs: number, rendition: T) => number | undefined,
|
|
130
|
+
): { newQueue: number[]; overlappingRequests: number[] } => {
|
|
131
|
+
const endTimeMs = newSeekTimeMs + bufferDurationMs;
|
|
132
|
+
const desiredSegments = computeSegmentRange(
|
|
133
|
+
newSeekTimeMs,
|
|
134
|
+
endTimeMs,
|
|
135
|
+
rendition,
|
|
136
|
+
computeSegmentId,
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
// Find segments that are already being requested
|
|
140
|
+
const overlappingRequests = desiredSegments.filter((segmentId) =>
|
|
141
|
+
currentState.activeRequests.has(segmentId),
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const newQueue = computeBufferQueue(
|
|
145
|
+
desiredSegments,
|
|
146
|
+
currentState.activeRequests,
|
|
147
|
+
currentState.cachedSegments,
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
return { newQueue, overlappingRequests };
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Check if a specific segment is cached in the buffer
|
|
155
|
+
* Pure function for accessing buffer cache state
|
|
156
|
+
*/
|
|
157
|
+
export const getCachedSegment = (
|
|
158
|
+
segmentId: number,
|
|
159
|
+
bufferState: MediaBufferState | undefined,
|
|
160
|
+
): boolean => {
|
|
161
|
+
return bufferState?.cachedSegments.has(segmentId) ?? false;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get cached segments from a list of segment IDs
|
|
166
|
+
* Pure function that returns which segments are available in cache
|
|
167
|
+
*/
|
|
168
|
+
export const getCachedSegments = (
|
|
169
|
+
segmentIds: number[],
|
|
170
|
+
bufferState: MediaBufferState | undefined,
|
|
171
|
+
): Set<number> => {
|
|
172
|
+
if (!bufferState) {
|
|
173
|
+
return new Set();
|
|
174
|
+
}
|
|
175
|
+
return new Set(segmentIds.filter((id) => bufferState.cachedSegments.has(id)));
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get missing segments from a list of segment IDs
|
|
180
|
+
* Pure function that returns which segments need to be fetched
|
|
181
|
+
*/
|
|
182
|
+
export const getMissingSegments = (
|
|
183
|
+
segmentIds: number[],
|
|
184
|
+
bufferState: MediaBufferState | undefined,
|
|
185
|
+
): number[] => {
|
|
186
|
+
if (!bufferState) {
|
|
187
|
+
return segmentIds;
|
|
188
|
+
}
|
|
189
|
+
return segmentIds.filter((id) => !bufferState.cachedSegments.has(id));
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Core media buffering logic with explicit dependencies
|
|
194
|
+
* Generic implementation that works for both audio and video
|
|
195
|
+
*/
|
|
196
|
+
export const manageMediaBuffer = async <
|
|
197
|
+
T extends AudioRendition | VideoRendition,
|
|
198
|
+
>(
|
|
199
|
+
seekTimeMs: number,
|
|
200
|
+
config: MediaBufferConfig,
|
|
201
|
+
currentState: MediaBufferState,
|
|
202
|
+
durationMs: number,
|
|
203
|
+
signal: AbortSignal,
|
|
204
|
+
deps: MediaBufferDependencies<T>,
|
|
205
|
+
): Promise<MediaBufferState> => {
|
|
206
|
+
if (!config.enableBuffering) {
|
|
207
|
+
return currentState;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const rendition = await deps.getRendition();
|
|
211
|
+
const endTimeMs = seekTimeMs + config.bufferDurationMs;
|
|
212
|
+
|
|
213
|
+
const desiredSegments = await computeSegmentRangeAsync(
|
|
214
|
+
seekTimeMs,
|
|
215
|
+
endTimeMs,
|
|
216
|
+
durationMs,
|
|
217
|
+
rendition,
|
|
218
|
+
deps.computeSegmentId,
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
const newQueue = computeBufferQueue(
|
|
222
|
+
desiredSegments,
|
|
223
|
+
currentState.activeRequests,
|
|
224
|
+
currentState.cachedSegments,
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
// Start fetching segments up to maxParallelFetches limit
|
|
228
|
+
const segmentsToFetch = newQueue.slice(0, config.maxParallelFetches);
|
|
229
|
+
const newActiveRequests = new Set(currentState.activeRequests);
|
|
230
|
+
const newCachedSegments = new Set(currentState.cachedSegments);
|
|
231
|
+
|
|
232
|
+
// Function to start next individual segment when a slot becomes available
|
|
233
|
+
const startNextSegment = (remainingQueue: number[]): void => {
|
|
234
|
+
if (remainingQueue.length === 0 || signal.aborted) return;
|
|
235
|
+
|
|
236
|
+
const availableSlots = config.maxParallelFetches - newActiveRequests.size;
|
|
237
|
+
if (availableSlots <= 0) return;
|
|
238
|
+
|
|
239
|
+
const nextSegmentId = remainingQueue[0];
|
|
240
|
+
if (nextSegmentId === undefined) return;
|
|
241
|
+
|
|
242
|
+
if (
|
|
243
|
+
newActiveRequests.has(nextSegmentId) ||
|
|
244
|
+
newCachedSegments.has(nextSegmentId)
|
|
245
|
+
) {
|
|
246
|
+
// Skip this segment and try the next
|
|
247
|
+
startNextSegment(remainingQueue.slice(1));
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
newActiveRequests.add(nextSegmentId);
|
|
252
|
+
|
|
253
|
+
deps
|
|
254
|
+
.fetchSegment(nextSegmentId, rendition)
|
|
255
|
+
.then(() => {
|
|
256
|
+
if (signal.aborted) return;
|
|
257
|
+
newActiveRequests.delete(nextSegmentId);
|
|
258
|
+
newCachedSegments.add(nextSegmentId);
|
|
259
|
+
startNextSegment(remainingQueue.slice(1));
|
|
260
|
+
})
|
|
261
|
+
.catch((error) => {
|
|
262
|
+
if (signal.aborted) return;
|
|
263
|
+
newActiveRequests.delete(nextSegmentId);
|
|
264
|
+
deps.logError(`Failed to fetch segment ${nextSegmentId}`, error);
|
|
265
|
+
startNextSegment(remainingQueue.slice(1));
|
|
266
|
+
});
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
// Start fetch promises for new segments
|
|
270
|
+
for (const segmentId of segmentsToFetch) {
|
|
271
|
+
if (signal.aborted) break;
|
|
272
|
+
|
|
273
|
+
newActiveRequests.add(segmentId);
|
|
274
|
+
|
|
275
|
+
// Start fetch (don't await - let it run in background)
|
|
276
|
+
deps
|
|
277
|
+
.fetchSegment(segmentId, rendition)
|
|
278
|
+
.then(() => {
|
|
279
|
+
if (signal.aborted) return;
|
|
280
|
+
// On success, move from active to cached
|
|
281
|
+
newActiveRequests.delete(segmentId);
|
|
282
|
+
newCachedSegments.add(segmentId);
|
|
283
|
+
|
|
284
|
+
// Continue buffering if there are more segments needed and continuous buffering is enabled
|
|
285
|
+
if (config.enableContinuousBuffering ?? true) {
|
|
286
|
+
const remainingQueue = newQueue.slice(segmentsToFetch.length);
|
|
287
|
+
startNextSegment(remainingQueue);
|
|
288
|
+
}
|
|
289
|
+
})
|
|
290
|
+
.catch((error) => {
|
|
291
|
+
if (signal.aborted) return;
|
|
292
|
+
// On error, remove from active and continue
|
|
293
|
+
newActiveRequests.delete(segmentId);
|
|
294
|
+
deps.logError(`Failed to fetch segment ${segmentId}`, error);
|
|
295
|
+
|
|
296
|
+
// Continue buffering even after error if continuous buffering is enabled
|
|
297
|
+
if (config.enableContinuousBuffering ?? true) {
|
|
298
|
+
const remainingQueue = newQueue.slice(segmentsToFetch.length);
|
|
299
|
+
startNextSegment(remainingQueue);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return {
|
|
305
|
+
currentSeekTimeMs: seekTimeMs,
|
|
306
|
+
activeRequests: newActiveRequests,
|
|
307
|
+
cachedSegments: newCachedSegments,
|
|
308
|
+
requestQueue: newQueue.slice(segmentsToFetch.length), // Remaining queue
|
|
309
|
+
};
|
|
310
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Task } from "@lit/task";
|
|
2
|
+
import type {
|
|
3
|
+
AudioRendition,
|
|
4
|
+
MediaEngine,
|
|
5
|
+
VideoRendition,
|
|
6
|
+
} from "../../../transcoding/types";
|
|
7
|
+
import type { BufferedSeekingInput } from "../BufferedSeekingInput";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generic rendition type that can be either audio or video
|
|
11
|
+
*/
|
|
12
|
+
export type MediaRendition = AudioRendition | VideoRendition;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Generic task type for init segment fetch
|
|
16
|
+
*/
|
|
17
|
+
export type InitSegmentFetchTask = Task<
|
|
18
|
+
readonly [MediaEngine | undefined],
|
|
19
|
+
ArrayBuffer
|
|
20
|
+
>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Generic task type for segment ID calculation
|
|
24
|
+
*/
|
|
25
|
+
export type SegmentIdTask = Task<
|
|
26
|
+
readonly [MediaEngine | undefined, number],
|
|
27
|
+
number | undefined
|
|
28
|
+
>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Generic task type for segment fetch
|
|
32
|
+
*/
|
|
33
|
+
export type SegmentFetchTask = Task<
|
|
34
|
+
readonly [MediaEngine | undefined, number | undefined],
|
|
35
|
+
ArrayBuffer
|
|
36
|
+
>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Generic task type for input creation
|
|
40
|
+
*/
|
|
41
|
+
export type InputTask = Task<
|
|
42
|
+
readonly [ArrayBuffer, ArrayBuffer],
|
|
43
|
+
BufferedSeekingInput
|
|
44
|
+
>;
|