@editframe/elements 0.18.3-beta.0 → 0.18.7-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.
Files changed (107) hide show
  1. package/dist/elements/EFMedia/AssetMediaEngine.browsertest.d.ts +0 -0
  2. package/dist/elements/EFMedia/AssetMediaEngine.d.ts +2 -4
  3. package/dist/elements/EFMedia/AssetMediaEngine.js +22 -3
  4. package/dist/elements/EFMedia/BaseMediaEngine.js +20 -1
  5. package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +5 -5
  6. package/dist/elements/EFMedia/BufferedSeekingInput.js +27 -7
  7. package/dist/elements/EFMedia/JitMediaEngine.d.ts +1 -1
  8. package/dist/elements/EFMedia/JitMediaEngine.js +22 -3
  9. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +4 -1
  10. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +11 -3
  11. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.d.ts +0 -0
  12. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +10 -2
  13. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +11 -1
  14. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +3 -2
  15. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +4 -1
  16. package/dist/elements/EFMedia/shared/PrecisionUtils.d.ts +28 -0
  17. package/dist/elements/EFMedia/shared/PrecisionUtils.js +29 -0
  18. package/dist/elements/EFMedia/videoTasks/makeVideoSeekTask.js +11 -2
  19. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.js +11 -1
  20. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.js +3 -2
  21. package/dist/elements/EFMedia.d.ts +0 -12
  22. package/dist/elements/EFMedia.js +4 -30
  23. package/dist/elements/EFTimegroup.js +12 -17
  24. package/dist/elements/EFVideo.d.ts +0 -9
  25. package/dist/elements/EFVideo.js +0 -7
  26. package/dist/elements/SampleBuffer.js +6 -6
  27. package/dist/getRenderInfo.d.ts +2 -2
  28. package/dist/gui/ContextMixin.js +71 -17
  29. package/dist/gui/TWMixin.js +1 -1
  30. package/dist/style.css +1 -1
  31. package/dist/transcoding/types/index.d.ts +9 -9
  32. package/package.json +2 -3
  33. package/src/elements/EFAudio.browsertest.ts +7 -7
  34. package/src/elements/EFMedia/AssetMediaEngine.browsertest.ts +100 -0
  35. package/src/elements/EFMedia/AssetMediaEngine.ts +52 -7
  36. package/src/elements/EFMedia/BaseMediaEngine.ts +50 -1
  37. package/src/elements/EFMedia/BufferedSeekingInput.browsertest.ts +135 -54
  38. package/src/elements/EFMedia/BufferedSeekingInput.ts +74 -17
  39. package/src/elements/EFMedia/JitMediaEngine.ts +58 -2
  40. package/src/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.ts +10 -1
  41. package/src/elements/EFMedia/audioTasks/makeAudioInputTask.ts +16 -8
  42. package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.ts +199 -0
  43. package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.ts +25 -3
  44. package/src/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.ts +12 -1
  45. package/src/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.ts +3 -2
  46. package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +10 -1
  47. package/src/elements/EFMedia/shared/PrecisionUtils.ts +46 -0
  48. package/src/elements/EFMedia/videoTasks/makeVideoSeekTask.ts +27 -3
  49. package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.ts +12 -1
  50. package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.ts +3 -2
  51. package/src/elements/EFMedia.browsertest.ts +73 -33
  52. package/src/elements/EFMedia.ts +11 -54
  53. package/src/elements/EFTimegroup.ts +21 -26
  54. package/src/elements/EFVideo.browsertest.ts +895 -162
  55. package/src/elements/EFVideo.ts +0 -16
  56. package/src/elements/SampleBuffer.ts +8 -10
  57. package/src/gui/ContextMixin.ts +104 -26
  58. package/src/transcoding/types/index.ts +10 -6
  59. package/test/EFVideo.framegen.browsertest.ts +1 -1
  60. package/test/__cache__/GET__api_v1_transcode_audio_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__32da3954ba60c96ad732020c65a08ebc/metadata.json +3 -3
  61. package/test/__cache__/GET__api_v1_transcode_audio_1_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__9ed2d25c675aa6bb6ff5b3ae23887c71/data.bin +0 -0
  62. package/test/__cache__/GET__api_v1_transcode_audio_1_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__9ed2d25c675aa6bb6ff5b3ae23887c71/metadata.json +22 -0
  63. package/test/__cache__/GET__api_v1_transcode_audio_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__b0b2b07efcf607de8ee0f650328c32f7/metadata.json +3 -3
  64. package/test/__cache__/GET__api_v1_transcode_audio_2_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__d5a3309a2bf756dd6e304807eb402f56/data.bin +0 -0
  65. package/test/__cache__/GET__api_v1_transcode_audio_2_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__d5a3309a2bf756dd6e304807eb402f56/metadata.json +22 -0
  66. package/test/__cache__/GET__api_v1_transcode_audio_3_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a75c2252b542e0c152c780e9a8d7b154/metadata.json +3 -3
  67. package/test/__cache__/GET__api_v1_transcode_audio_3_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__773254bb671e3466fca8677139fb239e/data.bin +0 -0
  68. package/test/__cache__/GET__api_v1_transcode_audio_3_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__773254bb671e3466fca8677139fb239e/metadata.json +22 -0
  69. package/test/__cache__/GET__api_v1_transcode_audio_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a64ff1cfb1b52cae14df4b5dfa1e222b/metadata.json +3 -3
  70. package/test/__cache__/GET__api_v1_transcode_audio_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__e66d2c831d951e74ad0aeaa6489795d0/metadata.json +3 -3
  71. package/test/__cache__/GET__api_v1_transcode_high_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__26197f6f7c46cacb0a71134131c3f775/metadata.json +3 -3
  72. package/test/__cache__/GET__api_v1_transcode_high_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__4cb6774cd3650ccf59c8f8dc6678c0b9/metadata.json +3 -3
  73. package/test/__cache__/GET__api_v1_transcode_high_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a6fb05a22b18d850f7f2950bbcdbdeed/data.bin +0 -0
  74. package/test/__cache__/GET__api_v1_transcode_high_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a6fb05a22b18d850f7f2950bbcdbdeed/metadata.json +21 -0
  75. package/test/__cache__/GET__api_v1_transcode_high_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a50058c7c3602e90879fe3428ed891f4/data.bin +0 -0
  76. package/test/__cache__/GET__api_v1_transcode_high_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a50058c7c3602e90879fe3428ed891f4/metadata.json +21 -0
  77. package/test/__cache__/GET__api_v1_transcode_high_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__0798c479b44aaeef850609a430f6e613/metadata.json +3 -3
  78. package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/data.bin +1 -1
  79. package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/metadata.json +4 -4
  80. package/test/recordReplayProxyPlugin.js +50 -0
  81. package/types.json +1 -1
  82. package/dist/DecoderResetFrequency.test.d.ts +0 -1
  83. package/dist/DecoderResetRecovery.test.d.ts +0 -1
  84. package/dist/ScrubTrackManager.d.ts +0 -96
  85. package/dist/elements/EFMedia/services/AudioElementFactory.browsertest.d.ts +0 -1
  86. package/dist/elements/EFMedia/services/AudioElementFactory.d.ts +0 -22
  87. package/dist/elements/EFMedia/services/AudioElementFactory.js +0 -72
  88. package/dist/elements/EFMedia/services/MediaSourceService.browsertest.d.ts +0 -1
  89. package/dist/elements/EFMedia/services/MediaSourceService.d.ts +0 -47
  90. package/dist/elements/EFMedia/services/MediaSourceService.js +0 -73
  91. package/dist/gui/services/ElementConnectionManager.browsertest.d.ts +0 -1
  92. package/dist/gui/services/ElementConnectionManager.d.ts +0 -59
  93. package/dist/gui/services/ElementConnectionManager.js +0 -128
  94. package/dist/gui/services/PlaybackController.browsertest.d.ts +0 -1
  95. package/dist/gui/services/PlaybackController.d.ts +0 -103
  96. package/dist/gui/services/PlaybackController.js +0 -290
  97. package/dist/services/MediaSourceManager.d.ts +0 -62
  98. package/dist/services/MediaSourceManager.js +0 -211
  99. package/src/elements/EFMedia/services/AudioElementFactory.browsertest.ts +0 -325
  100. package/src/elements/EFMedia/services/AudioElementFactory.ts +0 -119
  101. package/src/elements/EFMedia/services/MediaSourceService.browsertest.ts +0 -257
  102. package/src/elements/EFMedia/services/MediaSourceService.ts +0 -102
  103. package/src/gui/services/ElementConnectionManager.browsertest.ts +0 -263
  104. package/src/gui/services/ElementConnectionManager.ts +0 -224
  105. package/src/gui/services/PlaybackController.browsertest.ts +0 -437
  106. package/src/gui/services/PlaybackController.ts +0 -521
  107. package/src/services/MediaSourceManager.ts +0 -333
@@ -1,333 +0,0 @@
1
- export interface MediaSourceManagerOptions {
2
- onError?: (error: Error) => void;
3
- onReady?: () => void;
4
- onUpdateEnd?: () => void;
5
- timeout?: number;
6
- }
7
-
8
- /**
9
- * Manages MediaSource for audio streaming
10
- */
11
- export class MediaSourceManager {
12
- private mediaSource: MediaSource | null = null;
13
- private audioElement: HTMLAudioElement | null = null;
14
- private sourceBuffer: SourceBuffer | null = null;
15
- private mediaSourceReady = false;
16
- private pendingSegments: ArrayBuffer[] = [];
17
- private options: MediaSourceManagerOptions;
18
-
19
- constructor(options: MediaSourceManagerOptions = {}) {
20
- this.options = {
21
- timeout: 10000,
22
- ...options,
23
- };
24
- }
25
-
26
- /**
27
- * Initialize MediaSource for audio streaming
28
- */
29
- async initialize(): Promise<void> {
30
- this.cleanup(true);
31
-
32
- this.mediaSource = new MediaSource();
33
- this.audioElement = document.createElement("audio");
34
-
35
- // Add error event listeners to the audio element
36
- this.audioElement.addEventListener("error", (event) => {
37
- const error = this.audioElement?.error;
38
- console.error("🎵 [AUDIO_ELEMENT_ERROR] Audio element error:", {
39
- code: error?.code,
40
- message: error?.message,
41
- event,
42
- });
43
-
44
- if (this.options.onError) {
45
- this.options.onError(
46
- new Error(`Audio element error: ${error?.message}`),
47
- );
48
- }
49
- });
50
-
51
- this.audioElement.src = URL.createObjectURL(this.mediaSource);
52
-
53
- return new Promise((resolve, reject) => {
54
- this.mediaSource?.addEventListener("sourceopen", () => {
55
- try {
56
- const sourceBuffer = this.createSourceBuffer();
57
- if (!sourceBuffer) {
58
- throw new Error(
59
- "Failed to create SourceBuffer with any supported codec",
60
- );
61
- }
62
-
63
- this.sourceBuffer = sourceBuffer;
64
- this.setupSourceBufferListeners();
65
-
66
- this.mediaSourceReady = true;
67
-
68
- if (this.options.onReady) {
69
- this.options.onReady();
70
- }
71
-
72
- resolve();
73
- } catch (error) {
74
- console.error(
75
- "🎵 [MEDIA_SOURCE_ERROR] Failed to create SourceBuffer:",
76
- error,
77
- );
78
- reject(error);
79
- }
80
- });
81
-
82
- this.mediaSource?.addEventListener("error", (error) => {
83
- console.error("🎵 [MEDIA_SOURCE_ERROR] MediaSource error:", error);
84
- reject(error);
85
- });
86
-
87
- // Add timeout for MediaSource opening
88
- setTimeout(() => {
89
- if (!this.mediaSourceReady) {
90
- const timeoutError = new Error(
91
- "MediaSource failed to open within timeout",
92
- );
93
- console.error(
94
- "🎵 [MEDIA_SOURCE_TIMEOUT] MediaSource initialization timeout",
95
- );
96
- reject(timeoutError);
97
- }
98
- }, 4000);
99
- });
100
- }
101
-
102
- /**
103
- * Create SourceBuffer with codec fallback
104
- */
105
- private createSourceBuffer(): SourceBuffer | undefined {
106
- const codecOptions = [
107
- 'audio/mp4; codecs="mp4a.40.2"', // AAC-LC (most common)
108
- 'audio/mp4; codecs="mp4a.40.5"', // AAC-HE
109
- "audio/mp4", // Generic MP4 audio
110
- ];
111
-
112
- let sourceBuffer: SourceBuffer | undefined;
113
- let lastError: Error | undefined;
114
-
115
- for (const codec of codecOptions) {
116
- try {
117
- if (MediaSource.isTypeSupported(codec)) {
118
- sourceBuffer = this.mediaSource?.addSourceBuffer(codec);
119
- break;
120
- }
121
- } catch (error) {
122
- console.error(
123
- `🎵 [CODEC_ERROR] Failed to create SourceBuffer with ${codec}:`,
124
- error,
125
- );
126
- lastError = error as Error;
127
- }
128
- }
129
-
130
- if (!sourceBuffer && lastError) {
131
- throw new Error(
132
- `Failed to create SourceBuffer with any supported codec. Last error: ${lastError.message}`,
133
- );
134
- }
135
-
136
- return sourceBuffer;
137
- }
138
-
139
- /**
140
- * Setup SourceBuffer event listeners
141
- */
142
- private setupSourceBufferListeners(): void {
143
- if (!this.sourceBuffer) return;
144
-
145
- this.sourceBuffer.addEventListener("updateend", () => {
146
- this.processPendingSegments();
147
-
148
- if (this.options.onUpdateEnd) {
149
- this.options.onUpdateEnd();
150
- }
151
- });
152
-
153
- this.sourceBuffer.addEventListener("error", (event) => {
154
- console.error(
155
- "🎵 [SOURCE_BUFFER_EVENT_ERROR] SourceBuffer error event:",
156
- event,
157
- );
158
-
159
- if (this.options.onError) {
160
- this.options.onError(new Error("SourceBuffer error"));
161
- }
162
- });
163
- }
164
-
165
- /**
166
- * Feed audio segments directly to MediaSource SourceBuffer
167
- */
168
- async feedSegment(segmentBuffer: ArrayBuffer): Promise<void> {
169
- if (!this.mediaSourceReady || !this.sourceBuffer) {
170
- this.pendingSegments.push(segmentBuffer);
171
- return;
172
- }
173
-
174
- if (this.sourceBuffer.updating) {
175
- this.pendingSegments.push(segmentBuffer);
176
- return;
177
- }
178
-
179
- // Check for HTMLMediaElement errors before appending
180
- if (this.audioElement?.error) {
181
- const error = this.audioElement.error;
182
- console.error(
183
- "🎵 [MEDIA_ELEMENT_ERROR] HTMLMediaElement error detected:",
184
- {
185
- code: error.code,
186
- message: error.message,
187
- MEDIA_ERR_ABORTED: error.code === MediaError.MEDIA_ERR_ABORTED,
188
- MEDIA_ERR_NETWORK: error.code === MediaError.MEDIA_ERR_NETWORK,
189
- MEDIA_ERR_DECODE: error.code === MediaError.MEDIA_ERR_DECODE,
190
- MEDIA_ERR_SRC_NOT_SUPPORTED:
191
- error.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED,
192
- },
193
- );
194
-
195
- // Reset the audio element to try to recover
196
- this.audioElement.load();
197
- return;
198
- }
199
-
200
- try {
201
- this.sourceBuffer.appendBuffer(segmentBuffer);
202
- } catch (error) {
203
- console.error(
204
- "🎵 [SOURCE_BUFFER_ERROR] Failed to append segment:",
205
- error,
206
- );
207
- this.logDebugInfo();
208
- this.pendingSegments.push(segmentBuffer);
209
- }
210
- }
211
-
212
- /**
213
- * Process any queued segments when SourceBuffer becomes available
214
- */
215
- private processPendingSegments(): void {
216
- if (
217
- !this.sourceBuffer ||
218
- this.sourceBuffer.updating ||
219
- this.pendingSegments.length === 0
220
- ) {
221
- return;
222
- }
223
-
224
- const nextSegment = this.pendingSegments.shift();
225
- if (nextSegment) {
226
- this.feedSegment(nextSegment);
227
- }
228
- }
229
-
230
- /**
231
- * Log debug information for troubleshooting
232
- */
233
- private logDebugInfo(): void {
234
- console.error("🎵 [SOURCE_BUFFER_DEBUG] SourceBuffer state:", {
235
- updating: this.sourceBuffer?.updating,
236
- buffered: this.sourceBuffer?.buffered
237
- ? Array.from(
238
- { length: this.sourceBuffer.buffered.length },
239
- (_, i) =>
240
- `${this.sourceBuffer?.buffered.start(i)}-${this.sourceBuffer?.buffered.end(i)}`,
241
- )
242
- : [],
243
- mode: this.sourceBuffer?.mode,
244
- timestampOffset: this.sourceBuffer?.timestampOffset,
245
- });
246
-
247
- console.error("🎵 [MEDIA_SOURCE_DEBUG] MediaSource state:", {
248
- readyState: this.mediaSource?.readyState,
249
- sourceBuffers: this.mediaSource?.sourceBuffers.length,
250
- duration: this.mediaSource?.duration,
251
- });
252
-
253
- console.error("🎵 [AUDIO_ELEMENT_DEBUG] Audio element state:", {
254
- readyState: this.audioElement?.readyState,
255
- networkState: this.audioElement?.networkState,
256
- error: this.audioElement?.error?.code,
257
- src: `${this.audioElement?.src.substring(0, 50)}...`,
258
- });
259
- }
260
-
261
- /**
262
- * Set audio element current time
263
- */
264
- setCurrentTime(timeMs: number): void {
265
- if (this.audioElement) {
266
- this.audioElement.currentTime = timeMs / 1000;
267
- }
268
- }
269
-
270
- /**
271
- * Get the audio element for MediaElementSource
272
- */
273
- getAudioElement(): HTMLAudioElement | null {
274
- return this.audioElement;
275
- }
276
-
277
- /**
278
- * Check if MediaSource is ready
279
- */
280
- isReady(): boolean {
281
- return this.mediaSourceReady;
282
- }
283
-
284
- /**
285
- * Get buffered time ranges
286
- */
287
- getBuffered(): TimeRanges | null {
288
- return this.sourceBuffer?.buffered || null;
289
- }
290
-
291
- /**
292
- * Clean up MediaSource resources
293
- */
294
- cleanup(_preserveCache = false): void {
295
- // Clean up existing MediaSource
296
- if (
297
- this.sourceBuffer &&
298
- this.mediaSource &&
299
- this.mediaSource.readyState === "open"
300
- ) {
301
- try {
302
- this.mediaSource.removeSourceBuffer(this.sourceBuffer);
303
- } catch (error) {
304
- console.warn("🎵 [CLEANUP_ERROR] Error removing SourceBuffer:", error);
305
- }
306
- }
307
-
308
- if (this.mediaSource) {
309
- try {
310
- if (this.mediaSource.readyState === "open") {
311
- this.mediaSource.endOfStream();
312
- }
313
- } catch (error) {
314
- console.warn("🎵 [CLEANUP_ERROR] Error ending MediaSource:", error);
315
- }
316
- }
317
-
318
- if (this.audioElement) {
319
- try {
320
- URL.revokeObjectURL(this.audioElement.src);
321
- } catch (error) {
322
- console.warn("🎵 [CLEANUP_ERROR] Error revoking URL:", error);
323
- }
324
- }
325
-
326
- // Reset state
327
- this.mediaSource = null;
328
- this.audioElement = null;
329
- this.sourceBuffer = null;
330
- this.mediaSourceReady = false;
331
- this.pendingSegments = [];
332
- }
333
- }