@meframe/core 0.3.6 → 0.3.7
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/orchestrator/ExportScheduler.d.ts +9 -7
- package/dist/orchestrator/ExportScheduler.d.ts.map +1 -1
- package/dist/orchestrator/ExportScheduler.js +182 -80
- package/dist/orchestrator/ExportScheduler.js.map +1 -1
- package/dist/orchestrator/Orchestrator.js +22 -22
- package/dist/orchestrator/Orchestrator.js.map +1 -1
- package/dist/orchestrator/VideoWindowDecodeSession.d.ts.map +1 -1
- package/dist/orchestrator/VideoWindowDecodeSession.js +15 -3
- package/dist/orchestrator/VideoWindowDecodeSession.js.map +1 -1
- package/dist/stages/compose/VideoComposer.d.ts +2 -0
- package/dist/stages/compose/VideoComposer.d.ts.map +1 -1
- package/dist/stages/compose/VideoComposer.js +41 -2
- package/dist/stages/compose/VideoComposer.js.map +1 -1
- package/dist/stages/decode/video-decoder.d.ts.map +1 -1
- package/dist/stages/decode/video-decoder.js +5 -3
- package/dist/stages/decode/video-decoder.js.map +1 -1
- package/dist/utils/time-utils.d.ts +15 -0
- package/dist/utils/time-utils.d.ts.map +1 -1
- package/dist/utils/time-utils.js +33 -0
- package/dist/utils/time-utils.js.map +1 -0
- package/dist/worker/WorkerChannel.d.ts.map +1 -1
- package/dist/worker/WorkerChannel.js +3 -15
- package/dist/worker/WorkerChannel.js.map +1 -1
- package/dist/worker/WorkerPool.d.ts.map +1 -1
- package/dist/worker/WorkerPool.js +4 -12
- package/dist/worker/WorkerPool.js.map +1 -1
- package/dist/worker/types.d.ts +1 -1
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/types.js.map +1 -1
- package/dist/worker/worker-event-whitelist.d.ts.map +1 -1
- package/dist/workers/stages/{compose/video-compose.worker.KMZjuJuY.js → export/export.worker.BYttrqTQ.js} +872 -217
- package/dist/workers/stages/export/export.worker.BYttrqTQ.js.map +1 -0
- package/dist/workers/worker-manifest.json +1 -3
- package/package.json +1 -1
- package/dist/orchestrator/VideoClipSession.d.ts +0 -80
- package/dist/orchestrator/VideoClipSession.d.ts.map +0 -1
- package/dist/orchestrator/VideoClipSession.js +0 -361
- package/dist/orchestrator/VideoClipSession.js.map +0 -1
- package/dist/workers/WorkerChannel.DQK8rAab.js +0 -528
- package/dist/workers/WorkerChannel.DQK8rAab.js.map +0 -1
- package/dist/workers/stages/compose/audio-compose.worker.B4Io5w9i.js +0 -1063
- package/dist/workers/stages/compose/audio-compose.worker.B4Io5w9i.js.map +0 -1
- package/dist/workers/stages/compose/video-compose.worker.KMZjuJuY.js.map +0 -1
- package/dist/workers/stages/encode/video-encode.worker.D6aB_rF9.js +0 -334
- package/dist/workers/stages/encode/video-encode.worker.D6aB_rF9.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getRecommendedHardwareAcceleration } from "../../utils/platform-utils.js";
|
|
2
|
-
function
|
|
2
|
+
function isDecodeError(error) {
|
|
3
3
|
return error instanceof Error && error.message === "Decoding error.";
|
|
4
4
|
}
|
|
5
5
|
async function decodeChunksForScrub(chunks, config, targetTimeUs, options = {}) {
|
|
@@ -7,7 +7,8 @@ async function decodeChunksForScrub(chunks, config, targetTimeUs, options = {})
|
|
|
7
7
|
try {
|
|
8
8
|
return await _decodeForScrub(chunks, config, targetTimeUs, options, hwAccel);
|
|
9
9
|
} catch (error) {
|
|
10
|
-
|
|
10
|
+
console.warn("[decodeChunksForScrub] decode error:", error, " hwAccel:", hwAccel);
|
|
11
|
+
if (hwAccel !== "prefer-software" && isDecodeError(error)) {
|
|
11
12
|
console.warn("[VideoDecoder] Hardware decode failed, falling back to software decode");
|
|
12
13
|
return _decodeForScrub(chunks, config, targetTimeUs, options, "prefer-software");
|
|
13
14
|
}
|
|
@@ -145,7 +146,8 @@ async function decodeChunksWithoutFlush(chunks, config, options = {}) {
|
|
|
145
146
|
try {
|
|
146
147
|
return await _decodeWithoutFlush(chunks, config, options, hwAccel);
|
|
147
148
|
} catch (error) {
|
|
148
|
-
|
|
149
|
+
console.warn("[decodeChunksWithoutFlush]decode error:", error, " hwAccel:", hwAccel);
|
|
150
|
+
if (hwAccel !== "prefer-software" && isDecodeError(error)) {
|
|
149
151
|
console.warn("[VideoDecoder] Hardware decode failed, falling back to software decode");
|
|
150
152
|
return _decodeWithoutFlush(chunks, config, options, "prefer-software");
|
|
151
153
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video-decoder.js","sources":["../../../src/stages/decode/video-decoder.ts"],"sourcesContent":["import { getRecommendedHardwareAcceleration } from '../../utils/platform-utils';\n\nfunction isHwDecodeError(error: unknown): boolean {\n return error instanceof Error && error.message === 'Decoding error.';\n}\n\nexport interface DecodeResult {\n frames: VideoFrame[];\n stats: {\n inputChunks: number;\n outputFrames: number;\n durationMs: number;\n };\n}\n\nexport interface VideoDecoderConfig {\n codec: string;\n width: number;\n height: number;\n description?: ArrayBuffer;\n hardwareAcceleration?: HardwareAcceleration;\n}\n\nexport interface DecodeOptions {\n timeoutMs?: number;\n pollIntervalMs?: number;\n}\n\nexport interface DecodeScrubResult {\n before: VideoFrame | null;\n after: VideoFrame | null;\n stats: {\n inputChunks: number;\n outputFrames: number;\n durationMs: number;\n };\n}\n\nexport interface DecodeScrubOptions {\n timeoutMs?: number;\n /**\n * Backpressure: keep decodeQueueSize small so we don't decode far past target.\n */\n maxQueueSize?: number;\n /**\n * Optional cooperative abort hook (e.g., session cancelled by a newer seek).\n */\n shouldAbort?: () => boolean;\n}\n\n/**\n * Scrub decode: feed chunks in order, stop as soon as output crosses targetTimeUs.\n *\n * Why this lives in helpers:\n * - Centralize VideoDecoder quirks (no-await flush, HW accel defaults)\n * - Keep on-demand session focused on IO/demux/cache, not decode control flow\n */\nexport async function decodeChunksForScrub(\n chunks: EncodedVideoChunk[],\n config: VideoDecoderConfig,\n targetTimeUs: number,\n options: DecodeScrubOptions = {}\n): Promise<DecodeScrubResult> {\n const hwAccel = config.hardwareAcceleration ?? getRecommendedHardwareAcceleration();\n\n try {\n return await _decodeForScrub(chunks, config, targetTimeUs, options, hwAccel);\n } catch (error) {\n if (hwAccel !== 'prefer-software' && isHwDecodeError(error)) {\n console.warn('[VideoDecoder] Hardware decode failed, falling back to software decode');\n return _decodeForScrub(chunks, config, targetTimeUs, options, 'prefer-software');\n }\n throw error;\n }\n}\n\nasync function _decodeForScrub(\n chunks: EncodedVideoChunk[],\n config: VideoDecoderConfig,\n targetTimeUs: number,\n options: DecodeScrubOptions,\n hwAccel: HardwareAcceleration\n): Promise<DecodeScrubResult> {\n const { timeoutMs = 2000, maxQueueSize = 2, shouldAbort } = options;\n const startTime = performance.now();\n let outputFrames = 0;\n\n // Keep at most two frames: last <= target and first > target.\n let before: VideoFrame | null = null;\n let after: VideoFrame | null = null;\n\n return await new Promise<DecodeScrubResult>((resolve, reject) => {\n let settled = false;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const cleanup = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n const settle = (ok: boolean, err?: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n\n const stats = {\n inputChunks: chunks.length,\n outputFrames,\n durationMs: performance.now() - startTime,\n };\n\n if (!ok) {\n if (before) before.close();\n if (after) after.close();\n reject(err instanceof Error ? err : new Error(String(err ?? 'Scrub decode failed')));\n return;\n }\n\n resolve({ before, after, stats });\n };\n\n const decoder = new VideoDecoder({\n output: (frame) => {\n outputFrames += 1;\n\n if (settled) {\n frame.close();\n return;\n }\n\n const ts = frame.timestamp ?? 0;\n if (ts <= targetTimeUs) {\n if (before) before.close();\n before = frame;\n return;\n }\n\n if (!after) {\n after = frame;\n // We have both sides (or at least the first after); stop as soon as possible.\n try {\n decoder.close();\n } catch {\n // ignore\n }\n settle(true);\n return;\n }\n\n frame.close();\n },\n error: (e) => {\n try {\n decoder.close();\n } catch {\n /* noop */\n }\n settle(false, e);\n },\n });\n\n try {\n decoder.configure({\n codec: config.codec,\n codedWidth: config.width,\n codedHeight: config.height,\n hardwareAcceleration: hwAccel,\n optimizeForLatency: true,\n ...(config.description && { description: config.description }),\n });\n } catch (e) {\n settle(false, e);\n return;\n }\n\n timeoutId = setTimeout(() => {\n try {\n decoder.close();\n } catch {\n // ignore\n }\n // Best-effort: if we got at least one frame, still treat as success.\n if (before || after) {\n settle(true);\n } else {\n settle(false, new Error(`Scrub decode timeout after ${timeoutMs}ms`));\n }\n }, timeoutMs);\n\n const feed = async () => {\n try {\n for (const chunk of chunks) {\n if (settled) break;\n if (shouldAbort?.()) break;\n\n // Backpressure: keep queue small so we don't decode far past target.\n while (!settled && !shouldAbort?.() && decoder.decodeQueueSize > maxQueueSize) {\n await new Promise((r) => setTimeout(r, 0));\n }\n\n if (settled) break;\n if (shouldAbort?.()) break;\n decoder.decode(chunk);\n }\n\n // If we already settled (found target), we're done.\n if (settled) return;\n if (shouldAbort?.()) {\n // If cancelled, resolve best-effort if any output exists; otherwise fail.\n if (before || after) {\n try {\n decoder.close();\n } catch {\n // ignore\n }\n settle(true);\n return;\n }\n try {\n decoder.close();\n } catch {\n // ignore\n }\n settle(false, new Error('Scrub decode aborted'));\n return;\n }\n\n // We may have hit end-of-input without seeing a frame after target (e.g., target at end).\n // Trigger flush (do not await) and give output a chance before timeout.\n decoder.flush().catch(() => {});\n } catch (e) {\n settle(false, e);\n }\n };\n\n void feed();\n });\n}\n\n/**\n * Decode chunks using native VideoDecoder without awaiting flush\n * This avoids Windows hardware acceleration flush hang bug\n *\n * Strategy:\n * - Feed all chunks to decoder\n * - Call flush() but don't await (may hang on Windows HW)\n * - Poll decodeQueueSize to detect completion\n * - Timeout fallback ensures no infinite hang\n */\nexport async function decodeChunksWithoutFlush(\n chunks: EncodedVideoChunk[],\n config: VideoDecoderConfig,\n options: DecodeOptions = {}\n): Promise<DecodeResult> {\n const hwAccel = config.hardwareAcceleration ?? getRecommendedHardwareAcceleration();\n\n try {\n return await _decodeWithoutFlush(chunks, config, options, hwAccel);\n } catch (error) {\n if (hwAccel !== 'prefer-software' && isHwDecodeError(error)) {\n console.warn('[VideoDecoder] Hardware decode failed, falling back to software decode');\n return _decodeWithoutFlush(chunks, config, options, 'prefer-software');\n }\n throw error;\n }\n}\n\nfunction _decodeWithoutFlush(\n chunks: EncodedVideoChunk[],\n config: VideoDecoderConfig,\n options: DecodeOptions,\n hwAccel: HardwareAcceleration\n): Promise<DecodeResult> {\n const { timeoutMs = 2000, pollIntervalMs = 10 } = options;\n const startTime = performance.now();\n const frames: VideoFrame[] = [];\n\n return new Promise((resolve, reject) => {\n let isSettled = false;\n let pollTimer: ReturnType<typeof setInterval> | null = null;\n let timeoutTimer: ReturnType<typeof setTimeout> | null = null;\n\n const cleanup = () => {\n if (pollTimer !== null) {\n clearInterval(pollTimer);\n pollTimer = null;\n }\n if (timeoutTimer !== null) {\n clearTimeout(timeoutTimer);\n timeoutTimer = null;\n }\n };\n\n const settle = (success: boolean, errorMsg?: string) => {\n if (isSettled) return;\n isSettled = true;\n cleanup();\n\n const stats = {\n inputChunks: chunks.length,\n outputFrames: frames.length,\n durationMs: performance.now() - startTime,\n };\n\n if (success && frames.length > 0) {\n resolve({ frames, stats });\n } else {\n reject(new Error(errorMsg || 'Decode failed'));\n }\n };\n\n const decoder = new VideoDecoder({\n output: (frame) => {\n frames.push(frame);\n },\n error: (error) => {\n for (const f of frames) {\n try {\n f.close();\n } catch {\n /* noop */\n }\n }\n try {\n decoder.close();\n } catch {\n /* noop */\n }\n settle(false, error.message);\n },\n });\n\n decoder.configure({\n codec: config.codec,\n codedWidth: config.width,\n codedHeight: config.height,\n hardwareAcceleration: hwAccel,\n optimizeForLatency: true,\n ...(config.description && { description: config.description }),\n });\n\n // Feed all chunks\n for (const chunk of chunks) {\n decoder.decode(chunk);\n }\n\n // Call flush but don't await (may hang on Windows HW acceleration)\n decoder.flush().catch(() => {\n // Flush errors are non-critical\n });\n\n // Poll decode queue to detect completion\n pollTimer = setInterval(() => {\n if (decoder.decodeQueueSize === 0 && frames.length > 0) {\n decoder.close();\n settle(true);\n }\n }, pollIntervalMs);\n\n // Timeout fallback\n timeoutTimer = setTimeout(() => {\n decoder.close();\n settle(frames.length > 0, `Decode timeout after ${timeoutMs}ms`);\n }, timeoutMs);\n });\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"video-decoder.js","sources":["../../../src/stages/decode/video-decoder.ts"],"sourcesContent":["import { getRecommendedHardwareAcceleration } from '../../utils/platform-utils';\n\nfunction isDecodeError(error: unknown): boolean {\n return error instanceof Error && error.message === 'Decoding error.';\n}\n\nexport interface DecodeResult {\n frames: VideoFrame[];\n stats: {\n inputChunks: number;\n outputFrames: number;\n durationMs: number;\n };\n}\n\nexport interface VideoDecoderConfig {\n codec: string;\n width: number;\n height: number;\n description?: ArrayBuffer;\n hardwareAcceleration?: HardwareAcceleration;\n}\n\nexport interface DecodeOptions {\n timeoutMs?: number;\n pollIntervalMs?: number;\n}\n\nexport interface DecodeScrubResult {\n before: VideoFrame | null;\n after: VideoFrame | null;\n stats: {\n inputChunks: number;\n outputFrames: number;\n durationMs: number;\n };\n}\n\nexport interface DecodeScrubOptions {\n timeoutMs?: number;\n /**\n * Backpressure: keep decodeQueueSize small so we don't decode far past target.\n */\n maxQueueSize?: number;\n /**\n * Optional cooperative abort hook (e.g., session cancelled by a newer seek).\n */\n shouldAbort?: () => boolean;\n}\n\n/**\n * Scrub decode: feed chunks in order, stop as soon as output crosses targetTimeUs.\n *\n * Why this lives in helpers:\n * - Centralize VideoDecoder quirks (no-await flush, HW accel defaults)\n * - Keep on-demand session focused on IO/demux/cache, not decode control flow\n */\nexport async function decodeChunksForScrub(\n chunks: EncodedVideoChunk[],\n config: VideoDecoderConfig,\n targetTimeUs: number,\n options: DecodeScrubOptions = {}\n): Promise<DecodeScrubResult> {\n const hwAccel = config.hardwareAcceleration ?? getRecommendedHardwareAcceleration();\n\n try {\n return await _decodeForScrub(chunks, config, targetTimeUs, options, hwAccel);\n } catch (error) {\n console.warn('[decodeChunksForScrub] decode error:', error, ' hwAccel:', hwAccel);\n if (hwAccel !== 'prefer-software' && isDecodeError(error)) {\n console.warn('[VideoDecoder] Hardware decode failed, falling back to software decode');\n return _decodeForScrub(chunks, config, targetTimeUs, options, 'prefer-software');\n }\n throw error;\n }\n}\n\nasync function _decodeForScrub(\n chunks: EncodedVideoChunk[],\n config: VideoDecoderConfig,\n targetTimeUs: number,\n options: DecodeScrubOptions,\n hwAccel: HardwareAcceleration\n): Promise<DecodeScrubResult> {\n const { timeoutMs = 2000, maxQueueSize = 2, shouldAbort } = options;\n const startTime = performance.now();\n let outputFrames = 0;\n\n // Keep at most two frames: last <= target and first > target.\n let before: VideoFrame | null = null;\n let after: VideoFrame | null = null;\n\n return await new Promise<DecodeScrubResult>((resolve, reject) => {\n let settled = false;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const cleanup = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n const settle = (ok: boolean, err?: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n\n const stats = {\n inputChunks: chunks.length,\n outputFrames,\n durationMs: performance.now() - startTime,\n };\n\n if (!ok) {\n if (before) before.close();\n if (after) after.close();\n reject(err instanceof Error ? err : new Error(String(err ?? 'Scrub decode failed')));\n return;\n }\n\n resolve({ before, after, stats });\n };\n\n const decoder = new VideoDecoder({\n output: (frame) => {\n outputFrames += 1;\n\n if (settled) {\n frame.close();\n return;\n }\n\n const ts = frame.timestamp ?? 0;\n if (ts <= targetTimeUs) {\n if (before) before.close();\n before = frame;\n return;\n }\n\n if (!after) {\n after = frame;\n // We have both sides (or at least the first after); stop as soon as possible.\n try {\n decoder.close();\n } catch {\n // ignore\n }\n settle(true);\n return;\n }\n\n frame.close();\n },\n error: (e) => {\n try {\n decoder.close();\n } catch {\n /* noop */\n }\n settle(false, e);\n },\n });\n\n try {\n decoder.configure({\n codec: config.codec,\n codedWidth: config.width,\n codedHeight: config.height,\n hardwareAcceleration: hwAccel,\n optimizeForLatency: true,\n ...(config.description && { description: config.description }),\n });\n } catch (e) {\n settle(false, e);\n return;\n }\n\n timeoutId = setTimeout(() => {\n try {\n decoder.close();\n } catch {\n // ignore\n }\n // Best-effort: if we got at least one frame, still treat as success.\n if (before || after) {\n settle(true);\n } else {\n settle(false, new Error(`Scrub decode timeout after ${timeoutMs}ms`));\n }\n }, timeoutMs);\n\n const feed = async () => {\n try {\n for (const chunk of chunks) {\n if (settled) break;\n if (shouldAbort?.()) break;\n\n // Backpressure: keep queue small so we don't decode far past target.\n while (!settled && !shouldAbort?.() && decoder.decodeQueueSize > maxQueueSize) {\n await new Promise((r) => setTimeout(r, 0));\n }\n\n if (settled) break;\n if (shouldAbort?.()) break;\n decoder.decode(chunk);\n }\n\n // If we already settled (found target), we're done.\n if (settled) return;\n if (shouldAbort?.()) {\n // If cancelled, resolve best-effort if any output exists; otherwise fail.\n if (before || after) {\n try {\n decoder.close();\n } catch {\n // ignore\n }\n settle(true);\n return;\n }\n try {\n decoder.close();\n } catch {\n // ignore\n }\n settle(false, new Error('Scrub decode aborted'));\n return;\n }\n\n // We may have hit end-of-input without seeing a frame after target (e.g., target at end).\n // Trigger flush (do not await) and give output a chance before timeout.\n decoder.flush().catch(() => {});\n } catch (e) {\n settle(false, e);\n }\n };\n\n void feed();\n });\n}\n\n/**\n * Decode chunks using native VideoDecoder without awaiting flush\n * This avoids Windows hardware acceleration flush hang bug\n *\n * Strategy:\n * - Feed all chunks to decoder\n * - Call flush() but don't await (may hang on Windows HW)\n * - Poll decodeQueueSize to detect completion\n * - Timeout fallback ensures no infinite hang\n */\nexport async function decodeChunksWithoutFlush(\n chunks: EncodedVideoChunk[],\n config: VideoDecoderConfig,\n options: DecodeOptions = {}\n): Promise<DecodeResult> {\n const hwAccel = config.hardwareAcceleration ?? getRecommendedHardwareAcceleration();\n\n try {\n return await _decodeWithoutFlush(chunks, config, options, hwAccel);\n } catch (error) {\n console.warn('[decodeChunksWithoutFlush]decode error:', error, ' hwAccel:', hwAccel);\n if (hwAccel !== 'prefer-software' && isDecodeError(error)) {\n console.warn('[VideoDecoder] Hardware decode failed, falling back to software decode');\n return _decodeWithoutFlush(chunks, config, options, 'prefer-software');\n }\n throw error;\n }\n}\n\nfunction _decodeWithoutFlush(\n chunks: EncodedVideoChunk[],\n config: VideoDecoderConfig,\n options: DecodeOptions,\n hwAccel: HardwareAcceleration\n): Promise<DecodeResult> {\n const { timeoutMs = 2000, pollIntervalMs = 10 } = options;\n const startTime = performance.now();\n const frames: VideoFrame[] = [];\n\n return new Promise((resolve, reject) => {\n let isSettled = false;\n let pollTimer: ReturnType<typeof setInterval> | null = null;\n let timeoutTimer: ReturnType<typeof setTimeout> | null = null;\n\n const cleanup = () => {\n if (pollTimer !== null) {\n clearInterval(pollTimer);\n pollTimer = null;\n }\n if (timeoutTimer !== null) {\n clearTimeout(timeoutTimer);\n timeoutTimer = null;\n }\n };\n\n const settle = (success: boolean, errorMsg?: string) => {\n if (isSettled) return;\n isSettled = true;\n cleanup();\n\n const stats = {\n inputChunks: chunks.length,\n outputFrames: frames.length,\n durationMs: performance.now() - startTime,\n };\n\n if (success && frames.length > 0) {\n resolve({ frames, stats });\n } else {\n reject(new Error(errorMsg || 'Decode failed'));\n }\n };\n\n const decoder = new VideoDecoder({\n output: (frame) => {\n frames.push(frame);\n },\n error: (error) => {\n for (const f of frames) {\n try {\n f.close();\n } catch {\n /* noop */\n }\n }\n try {\n decoder.close();\n } catch {\n /* noop */\n }\n settle(false, error.message);\n },\n });\n\n decoder.configure({\n codec: config.codec,\n codedWidth: config.width,\n codedHeight: config.height,\n hardwareAcceleration: hwAccel,\n optimizeForLatency: true,\n ...(config.description && { description: config.description }),\n });\n\n // Feed all chunks\n for (const chunk of chunks) {\n decoder.decode(chunk);\n }\n\n // Call flush but don't await (may hang on Windows HW acceleration)\n decoder.flush().catch(() => {\n // Flush errors are non-critical\n });\n\n // Poll decode queue to detect completion\n pollTimer = setInterval(() => {\n if (decoder.decodeQueueSize === 0 && frames.length > 0) {\n decoder.close();\n settle(true);\n }\n }, pollIntervalMs);\n\n // Timeout fallback\n timeoutTimer = setTimeout(() => {\n decoder.close();\n settle(frames.length > 0, `Decode timeout after ${timeoutMs}ms`);\n }, timeoutMs);\n });\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -7,5 +7,20 @@ export declare function frameDurationFromFps(fps?: number): TimeUs;
|
|
|
7
7
|
export declare function frameIndexFromTimestamp(baseTimestampUs: TimeUs, timestampUs: TimeUs, fps?: number, strategy?: QuantizeStrategy): number;
|
|
8
8
|
export declare function quantizeTimestampToFrame(timestampUs: TimeUs, baseTimestampUs: TimeUs, fps?: number, strategy?: QuantizeStrategy): TimeUs;
|
|
9
9
|
export declare function isTimestampWithinFrame(targetTimeUs: TimeUs, frameTimestampUs: TimeUs, frameDurationUs: TimeUs, toleranceUs?: TimeUs): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Group consecutive GOPs into windows that respect maxDurationUs.
|
|
12
|
+
* First window starts at trimStartUs (may not align with GOP);
|
|
13
|
+
* subsequent windows start at GOP boundaries (zero leading-GOP overhead).
|
|
14
|
+
*/
|
|
15
|
+
export declare function computeGOPAlignedWindows(gopIndex: readonly {
|
|
16
|
+
startTimeUs: number;
|
|
17
|
+
}[], trimStartUs: TimeUs, trimEndUs: TimeUs, maxDurationUs: TimeUs): {
|
|
18
|
+
startUs: TimeUs;
|
|
19
|
+
endUs: TimeUs;
|
|
20
|
+
}[];
|
|
21
|
+
export declare function computeFixedWindows(trimStartUs: TimeUs, trimEndUs: TimeUs, windowDurationUs: TimeUs): {
|
|
22
|
+
startUs: TimeUs;
|
|
23
|
+
endUs: TimeUs;
|
|
24
|
+
}[];
|
|
10
25
|
export {};
|
|
11
26
|
//# sourceMappingURL=time-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-utils.d.ts","sourceRoot":"","sources":["../../src/utils/time-utils.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAC5D,KAAK,MAAM,GAAG,MAAM,CAAC;AACrB,eAAO,MAAM,uBAAuB,UAAY,CAAC;AAIjD,eAAO,MAAM,0BAA0B,EAAE,MAAe,CAAC;AAEzD,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,wBAAgB,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,MAAM,EACvB,WAAW,EAAE,MAAM,EACnB,GAAG,CAAC,EAAE,MAAM,EACZ,QAAQ,GAAE,gBAA4B,GACrC,MAAM,CAqBR;AAED,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EACvB,GAAG,CAAC,EAAE,MAAM,EACZ,QAAQ,GAAE,gBAA4B,GACrC,MAAM,CAIR;AAED,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,EACxB,eAAe,EAAE,MAAM,EACvB,WAAW,GAAE,MAAmC,GAC/C,OAAO,CAeT"}
|
|
1
|
+
{"version":3,"file":"time-utils.d.ts","sourceRoot":"","sources":["../../src/utils/time-utils.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAC5D,KAAK,MAAM,GAAG,MAAM,CAAC;AACrB,eAAO,MAAM,uBAAuB,UAAY,CAAC;AAIjD,eAAO,MAAM,0BAA0B,EAAE,MAAe,CAAC;AAEzD,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,wBAAgB,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,MAAM,EACvB,WAAW,EAAE,MAAM,EACnB,GAAG,CAAC,EAAE,MAAM,EACZ,QAAQ,GAAE,gBAA4B,GACrC,MAAM,CAqBR;AAED,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EACvB,GAAG,CAAC,EAAE,MAAM,EACZ,QAAQ,GAAE,gBAA4B,GACrC,MAAM,CAIR;AAED,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,EACxB,eAAe,EAAE,MAAM,EACvB,WAAW,GAAE,MAAmC,GAC/C,OAAO,CAeT;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,SAAS;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,EAAE,EAC5C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GACpB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAwBtC;AAED,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,MAAM,GACvB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAMtC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
function computeGOPAlignedWindows(gopIndex, trimStartUs, trimEndUs, maxDurationUs) {
|
|
2
|
+
const windows = [];
|
|
3
|
+
const gopBoundaries = [];
|
|
4
|
+
for (const gop of gopIndex) {
|
|
5
|
+
if (gop.startTimeUs > trimStartUs && gop.startTimeUs < trimEndUs) {
|
|
6
|
+
gopBoundaries.push(gop.startTimeUs);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
gopBoundaries.push(trimEndUs);
|
|
10
|
+
let windowStart = trimStartUs;
|
|
11
|
+
for (const boundary of gopBoundaries) {
|
|
12
|
+
if (boundary - windowStart >= maxDurationUs) {
|
|
13
|
+
windows.push({ startUs: windowStart, endUs: boundary });
|
|
14
|
+
windowStart = boundary;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
if (windowStart < trimEndUs) {
|
|
18
|
+
windows.push({ startUs: windowStart, endUs: trimEndUs });
|
|
19
|
+
}
|
|
20
|
+
return windows;
|
|
21
|
+
}
|
|
22
|
+
function computeFixedWindows(trimStartUs, trimEndUs, windowDurationUs) {
|
|
23
|
+
const windows = [];
|
|
24
|
+
for (let ws = trimStartUs; ws < trimEndUs; ws += windowDurationUs) {
|
|
25
|
+
windows.push({ startUs: ws, endUs: Math.min(ws + windowDurationUs, trimEndUs) });
|
|
26
|
+
}
|
|
27
|
+
return windows;
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
computeFixedWindows,
|
|
31
|
+
computeGOPAlignedWindows
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=time-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-utils.js","sources":["../../src/utils/time-utils.ts"],"sourcesContent":["export type QuantizeStrategy = 'nearest' | 'floor' | 'ceil';\ntype TimeUs = number;\nexport const MICROSECONDS_PER_SECOND = 1_000_000;\n\nconst DEFAULT_FPS = 30;\n\nexport const DEFAULT_FRAME_TOLERANCE_US: TimeUs = 33_333;\n\nexport function normalizeFps(value?: number): number {\n if (!Number.isFinite(value) || (value as number) <= 0) {\n return DEFAULT_FPS;\n }\n return value as number;\n}\n\nexport function frameDurationFromFps(fps?: number): TimeUs {\n const normalized = normalizeFps(fps);\n const duration = MICROSECONDS_PER_SECOND / normalized;\n return Math.max(Math.round(duration), 1);\n}\n\nexport function frameIndexFromTimestamp(\n baseTimestampUs: TimeUs,\n timestampUs: TimeUs,\n fps?: number,\n strategy: QuantizeStrategy = 'nearest'\n): number {\n const frameDurationUs = frameDurationFromFps(fps);\n if (frameDurationUs <= 0) {\n return 0;\n }\n\n const delta = timestampUs - baseTimestampUs;\n const rawIndex = delta / frameDurationUs;\n\n if (!Number.isFinite(rawIndex)) {\n return 0;\n }\n\n switch (strategy) {\n case 'floor':\n return Math.floor(rawIndex);\n case 'ceil':\n return Math.ceil(rawIndex);\n default:\n return Math.round(rawIndex);\n }\n}\n\nexport function quantizeTimestampToFrame(\n timestampUs: TimeUs,\n baseTimestampUs: TimeUs,\n fps?: number,\n strategy: QuantizeStrategy = 'nearest'\n): TimeUs {\n const frameDurationUs = frameDurationFromFps(fps);\n const index = frameIndexFromTimestamp(baseTimestampUs, timestampUs, fps, strategy);\n return baseTimestampUs + index * frameDurationUs;\n}\n\nexport function isTimestampWithinFrame(\n targetTimeUs: TimeUs,\n frameTimestampUs: TimeUs,\n frameDurationUs: TimeUs,\n toleranceUs: TimeUs = DEFAULT_FRAME_TOLERANCE_US\n): boolean {\n if (!Number.isFinite(frameTimestampUs)) {\n return false;\n }\n\n const delta = Math.abs(targetTimeUs - frameTimestampUs);\n if (delta <= toleranceUs) {\n return true;\n }\n\n if (frameDurationUs > 0 && frameTimestampUs <= targetTimeUs) {\n return targetTimeUs < frameTimestampUs + frameDurationUs;\n }\n\n return false;\n}\n\n/**\n * Group consecutive GOPs into windows that respect maxDurationUs.\n * First window starts at trimStartUs (may not align with GOP);\n * subsequent windows start at GOP boundaries (zero leading-GOP overhead).\n */\nexport function computeGOPAlignedWindows(\n gopIndex: readonly { startTimeUs: number }[],\n trimStartUs: TimeUs,\n trimEndUs: TimeUs,\n maxDurationUs: TimeUs\n): { startUs: TimeUs; endUs: TimeUs }[] {\n const windows: { startUs: TimeUs; endUs: TimeUs }[] = [];\n\n const gopBoundaries: TimeUs[] = [];\n for (const gop of gopIndex) {\n if (gop.startTimeUs > trimStartUs && gop.startTimeUs < trimEndUs) {\n gopBoundaries.push(gop.startTimeUs);\n }\n }\n gopBoundaries.push(trimEndUs);\n\n let windowStart = trimStartUs;\n for (const boundary of gopBoundaries) {\n if (boundary - windowStart >= maxDurationUs) {\n windows.push({ startUs: windowStart, endUs: boundary });\n windowStart = boundary;\n }\n }\n\n if (windowStart < trimEndUs) {\n windows.push({ startUs: windowStart, endUs: trimEndUs });\n }\n\n return windows;\n}\n\nexport function computeFixedWindows(\n trimStartUs: TimeUs,\n trimEndUs: TimeUs,\n windowDurationUs: TimeUs\n): { startUs: TimeUs; endUs: TimeUs }[] {\n const windows: { startUs: TimeUs; endUs: TimeUs }[] = [];\n for (let ws = trimStartUs; ws < trimEndUs; ws += windowDurationUs) {\n windows.push({ startUs: ws, endUs: Math.min(ws + windowDurationUs, trimEndUs) });\n }\n return windows;\n}\n"],"names":[],"mappings":"AAuFO,SAAS,yBACd,UACA,aACA,WACA,eACsC;AACtC,QAAM,UAAgD,CAAA;AAEtD,QAAM,gBAA0B,CAAA;AAChC,aAAW,OAAO,UAAU;AAC1B,QAAI,IAAI,cAAc,eAAe,IAAI,cAAc,WAAW;AAChE,oBAAc,KAAK,IAAI,WAAW;AAAA,IACpC;AAAA,EACF;AACA,gBAAc,KAAK,SAAS;AAE5B,MAAI,cAAc;AAClB,aAAW,YAAY,eAAe;AACpC,QAAI,WAAW,eAAe,eAAe;AAC3C,cAAQ,KAAK,EAAE,SAAS,aAAa,OAAO,UAAU;AACtD,oBAAc;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,cAAc,WAAW;AAC3B,YAAQ,KAAK,EAAE,SAAS,aAAa,OAAO,WAAW;AAAA,EACzD;AAEA,SAAO;AACT;AAEO,SAAS,oBACd,aACA,WACA,kBACsC;AACtC,QAAM,UAAgD,CAAA;AACtD,WAAS,KAAK,aAAa,KAAK,WAAW,MAAM,kBAAkB;AACjE,YAAQ,KAAK,EAAE,SAAS,IAAI,OAAO,KAAK,IAAI,KAAK,kBAAkB,SAAS,EAAA,CAAG;AAAA,EACjF;AACA,SAAO;AACT;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkerChannel.d.ts","sourceRoot":"","sources":["../../src/worker/WorkerChannel.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"WorkerChannel.d.ts","sourceRoot":"","sources":["../../src/worker/WorkerChannel.ts"],"names":[],"mappings":"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"}
|
|
@@ -259,10 +259,7 @@ class WorkerChannel {
|
|
|
259
259
|
while (true) {
|
|
260
260
|
const { done, value } = await reader.read();
|
|
261
261
|
if (done) {
|
|
262
|
-
this.post("stream_end", {
|
|
263
|
-
streamId,
|
|
264
|
-
...metadata
|
|
265
|
-
});
|
|
262
|
+
this.post("stream_end", { streamId });
|
|
266
263
|
break;
|
|
267
264
|
}
|
|
268
265
|
const transfer = [];
|
|
@@ -287,15 +284,7 @@ class WorkerChannel {
|
|
|
287
284
|
const extracted = extractTransferables(value);
|
|
288
285
|
transfer.push(...extracted);
|
|
289
286
|
}
|
|
290
|
-
this.post(
|
|
291
|
-
"stream_chunk",
|
|
292
|
-
{
|
|
293
|
-
streamId,
|
|
294
|
-
chunk: chunkValue,
|
|
295
|
-
...metadata
|
|
296
|
-
},
|
|
297
|
-
transfer
|
|
298
|
-
);
|
|
287
|
+
this.post("stream_chunk", { streamId, chunk: chunkValue }, transfer);
|
|
299
288
|
for (const t of transfer) {
|
|
300
289
|
if (typeof VideoFrame !== "undefined" && t instanceof VideoFrame) {
|
|
301
290
|
try {
|
|
@@ -315,8 +304,7 @@ class WorkerChannel {
|
|
|
315
304
|
} catch (error) {
|
|
316
305
|
this.post("stream_error", {
|
|
317
306
|
streamId,
|
|
318
|
-
error: error instanceof Error ? error.message : String(error)
|
|
319
|
-
...metadata
|
|
307
|
+
error: error instanceof Error ? error.message : String(error)
|
|
320
308
|
});
|
|
321
309
|
throw error;
|
|
322
310
|
} finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkerChannel.js","sources":["../../src/worker/WorkerChannel.ts"],"sourcesContent":["/**\n * WorkerChannel - MessageChannel wrapper for worker communication\n * Provides type-safe message passing with automatic serialization/deserialization\n */\n\nimport {\n WorkerMessage,\n WorkerResponse,\n WorkerError,\n WorkerMessageType,\n PendingRequest,\n MessageHandler,\n MessageHandlers,\n WorkerState,\n PortLike,\n} from './types';\nimport { withRetry, RetryConfig, defaultRetryConfig } from './worker-retry';\nimport {\n isTransferable,\n extractTransferables,\n encodedVideoChunkToTransferable,\n encodedAudioChunkToTransferable,\n} from './transferable-helper';\n\nexport interface WorkerChannelConfig {\n name: string;\n timeout?: number; // Default timeout in milliseconds\n maxRetries?: number; // Default max retries\n}\n\nexport class WorkerChannel {\n name: string;\n port: PortLike;\n pendingRequests = new Map<string, PendingRequest>();\n messageHandlers: MessageHandlers = {};\n state: WorkerState = WorkerState.Idle;\n defaultTimeout: number;\n defaultMaxRetries: number;\n\n constructor(port: PortLike, config: WorkerChannelConfig) {\n this.name = config.name;\n this.port = port;\n this.defaultTimeout = config.timeout ?? 30000; // 30 seconds default\n this.defaultMaxRetries = config.maxRetries ?? 3;\n\n this.setupMessageHandler();\n this.state = WorkerState.Ready;\n }\n\n /**\n * Send a message and wait for response with retry support\n */\n async send<T = any, R = any>(\n type: WorkerMessageType,\n payload?: T,\n options?: {\n timeout?: number;\n maxRetries?: number;\n transfer?: Transferable[];\n retryConfig?: Partial<RetryConfig>;\n }\n ): Promise<R> {\n const maxRetries = options?.maxRetries ?? this.defaultMaxRetries;\n\n // Create retry config\n const retryConfig: RetryConfig = {\n ...defaultRetryConfig,\n maxRetries,\n ...options?.retryConfig,\n };\n\n // Wrap send logic for retry\n return withRetry(() => this.sendOnce<T, R>(type, payload, options), retryConfig);\n }\n\n /**\n * Send a message once (without retry)\n */\n private async sendOnce<T = any, R = any>(\n type: WorkerMessageType,\n payload?: T,\n options?: {\n timeout?: number;\n transfer?: Transferable[];\n }\n ): Promise<R> {\n const id = this.generateMessageId();\n const timeout = options?.timeout ?? this.defaultTimeout;\n\n const message: WorkerMessage<T> = {\n type,\n id,\n payload,\n timestamp: Date.now(),\n };\n\n return new Promise((resolve, reject) => {\n const request: PendingRequest = {\n id,\n type,\n timestamp: Date.now(),\n timeout,\n resolve,\n reject,\n };\n\n this.pendingRequests.set(id, request);\n\n // Set timeout\n const timeoutId = setTimeout(() => {\n const pending = this.pendingRequests.get(id);\n if (pending) {\n this.pendingRequests.delete(id);\n const error = new Error(`Request timeout: ${id} ${type} (${timeout}ms)`);\n (error as any).code = 'TIMEOUT';\n pending.reject(error);\n }\n }, timeout);\n\n // Store timeout ID for cleanup\n (request as any).timeoutId = timeoutId;\n // Send message\n if (options?.transfer) {\n this.port.postMessage(message, options.transfer);\n } else {\n this.port.postMessage(message);\n }\n });\n }\n\n /**\n * Send a message without waiting for response\n */\n post<T = any>(type: WorkerMessageType, payload?: T, transfer?: Transferable[]): void {\n const message: WorkerMessage<T> = {\n type,\n id: this.generateMessageId(),\n payload,\n timestamp: Date.now(),\n };\n\n if (transfer) {\n this.port.postMessage(message, transfer);\n } else {\n this.port.postMessage(message);\n }\n }\n\n /**\n * Register a message handler\n */\n on<T = any, R = any>(type: WorkerMessageType, handler: MessageHandler<T, R>): void {\n this.messageHandlers[type] = handler;\n }\n\n /**\n * Unregister a message handler\n */\n off(type: WorkerMessageType): void {\n delete this.messageHandlers[type];\n }\n\n /**\n * Dispose the channel\n */\n dispose(): void {\n this.state = WorkerState.Disposed;\n\n // Clear all pending requests\n for (const [, request] of this.pendingRequests) {\n if ((request as any).timeoutId) {\n clearTimeout((request as any).timeoutId);\n }\n request.reject(new Error('Channel disposed'));\n }\n this.pendingRequests.clear();\n\n // Remove message handler\n this.port.onmessage = null;\n }\n\n /**\n * Setup message handler for incoming messages\n */\n private setupMessageHandler(): void {\n this.port.onmessage = async (event: MessageEvent) => {\n const data = event.data;\n\n // Handle response messages\n if (this.isResponse(data)) {\n this.handleResponse(data as WorkerResponse);\n return;\n }\n\n // Handle request messages\n if (this.isRequest(data)) {\n await this.handleRequest(data as WorkerMessage);\n return;\n }\n };\n }\n\n /**\n * Handle incoming request\n */\n private async handleRequest(message: WorkerMessage): Promise<void> {\n const handler = this.messageHandlers[message.type];\n\n if (!handler) {\n // Send error response if no handler registered\n this.sendResponse(message.id, false, null, {\n code: 'NO_HANDLER',\n message: `No handler registered for message type: ${message.type}`,\n });\n return;\n }\n\n this.state = WorkerState.Processing;\n\n // Handler execution with error handling at framework level\n Promise.resolve()\n .then(() => handler(message.payload, message.transfer))\n .then((result) => {\n this.sendResponse(message.id, true, result);\n this.state = WorkerState.Ready;\n })\n .catch((error) => {\n const workerError: WorkerError = {\n code: 'HANDLER_ERROR',\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n };\n this.sendResponse(message.id, false, null, workerError);\n this.state = WorkerState.Ready;\n });\n }\n\n /**\n * Handle incoming response\n */\n private handleResponse(response: WorkerResponse): void {\n const request = this.pendingRequests.get(response.id);\n if (!request) {\n return; // Response for unknown request\n }\n\n this.pendingRequests.delete(response.id);\n\n // Clear timeout\n if ((request as any).timeoutId) {\n clearTimeout((request as any).timeoutId);\n }\n\n if (response.success) {\n request.resolve(response.result);\n } else {\n const error = new Error(response.error?.message || 'Unknown error');\n if (response.error) {\n Object.assign(error, response.error);\n }\n request.reject(error);\n }\n }\n\n /**\n * Send a response message\n */\n private sendResponse(id: string, success: boolean, result?: any, error?: WorkerError): void {\n let transfer: Transferable[] = [];\n if (isTransferable(result)) {\n // Still include reference so caller can access the transferred object\n transfer.push(result);\n }\n const response: WorkerResponse = {\n id,\n success,\n result,\n error,\n timestamp: Date.now(),\n };\n\n this.port.postMessage(response, transfer);\n }\n\n /**\n * Check if message is a response\n */\n private isResponse(data: any): boolean {\n return (\n data && typeof data === 'object' && 'id' in data && 'success' in data && !('type' in data)\n );\n }\n\n /**\n * Check if message is a request\n */\n private isRequest(data: any): boolean {\n return data && typeof data === 'object' && 'id' in data && 'type' in data;\n }\n\n /**\n * Generate unique message ID\n */\n private generateMessageId(): string {\n return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n }\n\n /**\n * Send a notification message without waiting for response\n * Alias for post() method for compatibility\n */\n notify<T = any>(type: WorkerMessageType | string, payload?: T, transfer?: Transferable[]): void {\n this.post(type as WorkerMessageType, payload, transfer);\n }\n\n /**\n * Register a message handler\n * Alias for on() method for compatibility\n */\n registerHandler<T = any, R = any>(\n type: WorkerMessageType | string,\n handler: MessageHandler<T, R>\n ): void {\n this.on(type as WorkerMessageType, handler);\n }\n\n /**\n * Send a ReadableStream to another worker\n * Automatically handles transferable streams vs chunk-by-chunk fallback\n */\n async sendStream<T = Uint8Array>(\n stream: ReadableStream<T>,\n metadata?: {\n type?: string;\n url?: string;\n streamId?: string;\n streamType?: string;\n forceChunkTransfer?: boolean;\n [key: string]: any;\n }\n ): Promise<void> {\n const streamId = metadata?.streamId || this.generateMessageId();\n const forceChunkTransfer =\n metadata?.forceChunkTransfer === true ||\n metadata?.streamType === 'video' ||\n metadata?.streamType === 'audio';\n // Check if streams are transferable in this environment\n if (!forceChunkTransfer && isTransferable(stream)) {\n // Direct stream transfer (preferred)\n this.port.postMessage(\n {\n type: 'stream_transfer',\n ...metadata,\n stream,\n streamId,\n },\n [stream] // Transfer ownership\n );\n } else {\n // Fallback: chunk-by-chunk transfer\n await this.streamChunks(stream, streamId, metadata);\n }\n }\n\n /**\n * Stream chunks from a ReadableStream (fallback when transfer is not supported)\n */\n private async streamChunks<T = Uint8Array>(\n stream: ReadableStream<T>,\n streamId: string,\n metadata?: Record<string, any>\n ): Promise<void> {\n const reader = stream.getReader();\n\n // Send stream start notification\n this.post('stream_start' as WorkerMessageType, {\n streamId,\n ...metadata,\n mode: 'chunk_transfer',\n });\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n // Send stream end notification\n this.post('stream_end' as WorkerMessageType, {\n streamId,\n ...metadata,\n });\n break;\n }\n\n // Send chunk with transfer - use extractTransferables for complex objects\n const transfer: Transferable[] = [];\n let chunkValue: T = value;\n\n if (value instanceof ArrayBuffer) {\n transfer.push(value);\n } else if (value instanceof Uint8Array) {\n transfer.push(value.buffer);\n } else if (typeof AudioData !== 'undefined' && value instanceof AudioData) {\n transfer.push(value as unknown as Transferable);\n } else if (typeof VideoFrame !== 'undefined' && value instanceof VideoFrame) {\n transfer.push(value as unknown as Transferable);\n } else if (typeof EncodedVideoChunk !== 'undefined' && value instanceof EncodedVideoChunk) {\n // EncodedVideoChunk is not transferable by itself\n // But its constructor supports transfer parameter for the underlying ArrayBuffer\n // We serialize it to a plain object and transfer the ArrayBuffer\n const serialized = encodedVideoChunkToTransferable(value);\n transfer.push(serialized.data); // Transfer the ArrayBuffer\n chunkValue = serialized as T;\n } else if (typeof EncodedAudioChunk !== 'undefined' && value instanceof EncodedAudioChunk) {\n // EncodedAudioChunk is not transferable by itself\n // We serialize it to a plain object and transfer the ArrayBuffer\n const serialized = encodedAudioChunkToTransferable(value);\n transfer.push(serialized.data); // Transfer the ArrayBuffer\n chunkValue = serialized as T;\n } else if (typeof value === 'object' && value !== null) {\n // For wrapped objects (e.g., {frame: VideoFrame, metadata...}), extract transferables\n const extracted = extractTransferables(value);\n transfer.push(...extracted);\n }\n\n this.post(\n 'stream_chunk' as WorkerMessageType,\n {\n streamId,\n chunk: chunkValue,\n ...metadata,\n },\n transfer\n );\n\n // If we transferred ownership of WebCodecs resources, close them on the sender side.\n // Otherwise they may be GC'd without explicit close(), triggering browser warnings.\n for (const t of transfer) {\n if (typeof VideoFrame !== 'undefined' && t instanceof VideoFrame) {\n try {\n t.close();\n } catch {\n // ignore\n }\n continue;\n }\n if (typeof AudioData !== 'undefined' && t instanceof AudioData) {\n try {\n t.close();\n } catch {\n // ignore\n }\n }\n }\n }\n } catch (error) {\n // Send error notification\n this.post('stream_error' as WorkerMessageType, {\n streamId,\n error: error instanceof Error ? error.message : String(error),\n ...metadata,\n });\n throw error;\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Receive a stream from another worker\n * Handles both transferable streams and chunk-by-chunk reconstruction\n */\n async receiveStream<T = Uint8Array>(\n onStream: (stream: ReadableStream<T>, metadata?: Record<string, any>) => void\n ): Promise<void> {\n const chunkedStreams = new Map<\n string,\n {\n controller: ReadableStreamDefaultController<T>;\n metadata?: Record<string, any>;\n }\n >();\n\n // Intercept stream messages via onmessage to avoid extra event plumbing\n const prev = this.port.onmessage as any;\n // Use function assignment with explicit type to satisfy esbuild parser\n const handler: (event: MessageEvent) => void = (event) => {\n const raw = (event as any).data;\n const envelopeType = raw?.type;\n const hasPayload = raw && typeof raw === 'object' && 'payload' in raw;\n const payload = hasPayload ? (raw as any).payload : raw;\n\n if (envelopeType === 'stream_transfer' && (payload as any)?.stream) {\n onStream((payload as any).stream, payload);\n return;\n }\n if (envelopeType === 'stream_start' && (payload as any)?.streamId) {\n const stream = new ReadableStream<T>({\n start(controller) {\n chunkedStreams.set((payload as any).streamId, { controller, metadata: payload });\n },\n });\n onStream(stream, payload);\n return;\n }\n if (\n envelopeType === 'stream_chunk' &&\n (payload as any)?.streamId &&\n chunkedStreams.has((payload as any).streamId)\n ) {\n const s = chunkedStreams.get((payload as any).streamId);\n if (s) s.controller.enqueue((payload as any).chunk as T);\n return;\n }\n if (\n envelopeType === 'stream_end' &&\n (payload as any)?.streamId &&\n chunkedStreams.has((payload as any).streamId)\n ) {\n const s = chunkedStreams.get((payload as any).streamId);\n if (s) {\n s.controller.close();\n chunkedStreams.delete((payload as any).streamId);\n }\n return;\n }\n if (\n envelopeType === 'stream_error' &&\n (payload as any)?.streamId &&\n chunkedStreams.has((payload as any).streamId)\n ) {\n const s = chunkedStreams.get((payload as any).streamId);\n if (s) {\n s.controller.error(new Error(String((payload as any).error || 'stream error')));\n chunkedStreams.delete((payload as any).streamId);\n }\n return;\n }\n\n // Delegate non-stream messages to previous handler\n if (typeof prev === 'function') prev.call(this.port, event);\n };\n this.port.onmessage = handler as any;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WorkerChannel.js","sources":["../../src/worker/WorkerChannel.ts"],"sourcesContent":["/**\n * WorkerChannel - MessageChannel wrapper for worker communication\n * Provides type-safe message passing with automatic serialization/deserialization\n */\n\nimport {\n WorkerMessage,\n WorkerResponse,\n WorkerError,\n WorkerMessageType,\n PendingRequest,\n MessageHandler,\n MessageHandlers,\n WorkerState,\n PortLike,\n} from './types';\nimport { withRetry, RetryConfig, defaultRetryConfig } from './worker-retry';\nimport {\n isTransferable,\n extractTransferables,\n encodedVideoChunkToTransferable,\n encodedAudioChunkToTransferable,\n} from './transferable-helper';\n\nexport interface WorkerChannelConfig {\n name: string;\n timeout?: number; // Default timeout in milliseconds\n maxRetries?: number; // Default max retries\n}\n\nexport class WorkerChannel {\n name: string;\n port: PortLike;\n pendingRequests = new Map<string, PendingRequest>();\n messageHandlers: MessageHandlers = {};\n state: WorkerState = WorkerState.Idle;\n defaultTimeout: number;\n defaultMaxRetries: number;\n\n constructor(port: PortLike, config: WorkerChannelConfig) {\n this.name = config.name;\n this.port = port;\n this.defaultTimeout = config.timeout ?? 30000; // 30 seconds default\n this.defaultMaxRetries = config.maxRetries ?? 3;\n\n this.setupMessageHandler();\n this.state = WorkerState.Ready;\n }\n\n /**\n * Send a message and wait for response with retry support\n */\n async send<T = any, R = any>(\n type: WorkerMessageType,\n payload?: T,\n options?: {\n timeout?: number;\n maxRetries?: number;\n transfer?: Transferable[];\n retryConfig?: Partial<RetryConfig>;\n }\n ): Promise<R> {\n const maxRetries = options?.maxRetries ?? this.defaultMaxRetries;\n\n // Create retry config\n const retryConfig: RetryConfig = {\n ...defaultRetryConfig,\n maxRetries,\n ...options?.retryConfig,\n };\n\n // Wrap send logic for retry\n return withRetry(() => this.sendOnce<T, R>(type, payload, options), retryConfig);\n }\n\n /**\n * Send a message once (without retry)\n */\n private async sendOnce<T = any, R = any>(\n type: WorkerMessageType,\n payload?: T,\n options?: {\n timeout?: number;\n transfer?: Transferable[];\n }\n ): Promise<R> {\n const id = this.generateMessageId();\n const timeout = options?.timeout ?? this.defaultTimeout;\n\n const message: WorkerMessage<T> = {\n type,\n id,\n payload,\n timestamp: Date.now(),\n };\n\n return new Promise((resolve, reject) => {\n const request: PendingRequest = {\n id,\n type,\n timestamp: Date.now(),\n timeout,\n resolve,\n reject,\n };\n\n this.pendingRequests.set(id, request);\n\n // Set timeout\n const timeoutId = setTimeout(() => {\n const pending = this.pendingRequests.get(id);\n if (pending) {\n this.pendingRequests.delete(id);\n const error = new Error(`Request timeout: ${id} ${type} (${timeout}ms)`);\n (error as any).code = 'TIMEOUT';\n pending.reject(error);\n }\n }, timeout);\n\n // Store timeout ID for cleanup\n (request as any).timeoutId = timeoutId;\n // Send message\n if (options?.transfer) {\n this.port.postMessage(message, options.transfer);\n } else {\n this.port.postMessage(message);\n }\n });\n }\n\n /**\n * Send a message without waiting for response\n */\n post<T = any>(type: WorkerMessageType, payload?: T, transfer?: Transferable[]): void {\n const message: WorkerMessage<T> = {\n type,\n id: this.generateMessageId(),\n payload,\n timestamp: Date.now(),\n };\n\n if (transfer) {\n this.port.postMessage(message, transfer);\n } else {\n this.port.postMessage(message);\n }\n }\n\n /**\n * Register a message handler\n */\n on<T = any, R = any>(type: WorkerMessageType, handler: MessageHandler<T, R>): void {\n this.messageHandlers[type] = handler;\n }\n\n /**\n * Unregister a message handler\n */\n off(type: WorkerMessageType): void {\n delete this.messageHandlers[type];\n }\n\n /**\n * Dispose the channel\n */\n dispose(): void {\n this.state = WorkerState.Disposed;\n\n // Clear all pending requests\n for (const [, request] of this.pendingRequests) {\n if ((request as any).timeoutId) {\n clearTimeout((request as any).timeoutId);\n }\n request.reject(new Error('Channel disposed'));\n }\n this.pendingRequests.clear();\n\n // Remove message handler\n this.port.onmessage = null;\n }\n\n /**\n * Setup message handler for incoming messages\n */\n private setupMessageHandler(): void {\n this.port.onmessage = async (event: MessageEvent) => {\n const data = event.data;\n\n // Handle response messages\n if (this.isResponse(data)) {\n this.handleResponse(data as WorkerResponse);\n return;\n }\n\n // Handle request messages\n if (this.isRequest(data)) {\n await this.handleRequest(data as WorkerMessage);\n return;\n }\n };\n }\n\n /**\n * Handle incoming request\n */\n private async handleRequest(message: WorkerMessage): Promise<void> {\n const handler = this.messageHandlers[message.type];\n\n if (!handler) {\n // Send error response if no handler registered\n this.sendResponse(message.id, false, null, {\n code: 'NO_HANDLER',\n message: `No handler registered for message type: ${message.type}`,\n });\n return;\n }\n\n this.state = WorkerState.Processing;\n\n // Handler execution with error handling at framework level\n Promise.resolve()\n .then(() => handler(message.payload, message.transfer))\n .then((result) => {\n this.sendResponse(message.id, true, result);\n this.state = WorkerState.Ready;\n })\n .catch((error) => {\n const workerError: WorkerError = {\n code: 'HANDLER_ERROR',\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n };\n this.sendResponse(message.id, false, null, workerError);\n this.state = WorkerState.Ready;\n });\n }\n\n /**\n * Handle incoming response\n */\n private handleResponse(response: WorkerResponse): void {\n const request = this.pendingRequests.get(response.id);\n if (!request) {\n return; // Response for unknown request\n }\n\n this.pendingRequests.delete(response.id);\n\n // Clear timeout\n if ((request as any).timeoutId) {\n clearTimeout((request as any).timeoutId);\n }\n\n if (response.success) {\n request.resolve(response.result);\n } else {\n const error = new Error(response.error?.message || 'Unknown error');\n if (response.error) {\n Object.assign(error, response.error);\n }\n request.reject(error);\n }\n }\n\n /**\n * Send a response message\n */\n private sendResponse(id: string, success: boolean, result?: any, error?: WorkerError): void {\n let transfer: Transferable[] = [];\n if (isTransferable(result)) {\n // Still include reference so caller can access the transferred object\n transfer.push(result);\n }\n const response: WorkerResponse = {\n id,\n success,\n result,\n error,\n timestamp: Date.now(),\n };\n\n this.port.postMessage(response, transfer);\n }\n\n /**\n * Check if message is a response\n */\n private isResponse(data: any): boolean {\n return (\n data && typeof data === 'object' && 'id' in data && 'success' in data && !('type' in data)\n );\n }\n\n /**\n * Check if message is a request\n */\n private isRequest(data: any): boolean {\n return data && typeof data === 'object' && 'id' in data && 'type' in data;\n }\n\n /**\n * Generate unique message ID\n */\n private generateMessageId(): string {\n return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n }\n\n /**\n * Send a notification message without waiting for response\n * Alias for post() method for compatibility\n */\n notify<T = any>(type: WorkerMessageType | string, payload?: T, transfer?: Transferable[]): void {\n this.post(type as WorkerMessageType, payload, transfer);\n }\n\n /**\n * Register a message handler\n * Alias for on() method for compatibility\n */\n registerHandler<T = any, R = any>(\n type: WorkerMessageType | string,\n handler: MessageHandler<T, R>\n ): void {\n this.on(type as WorkerMessageType, handler);\n }\n\n /**\n * Send a ReadableStream to another worker\n * Automatically handles transferable streams vs chunk-by-chunk fallback\n */\n async sendStream<T = Uint8Array>(\n stream: ReadableStream<T>,\n metadata?: {\n type?: string;\n url?: string;\n streamId?: string;\n streamType?: string;\n forceChunkTransfer?: boolean;\n [key: string]: any;\n }\n ): Promise<void> {\n const streamId = metadata?.streamId || this.generateMessageId();\n const forceChunkTransfer =\n metadata?.forceChunkTransfer === true ||\n metadata?.streamType === 'video' ||\n metadata?.streamType === 'audio';\n // Check if streams are transferable in this environment\n if (!forceChunkTransfer && isTransferable(stream)) {\n // Direct stream transfer (preferred)\n this.port.postMessage(\n {\n type: 'stream_transfer',\n ...metadata,\n stream,\n streamId,\n },\n [stream] // Transfer ownership\n );\n } else {\n // Fallback: chunk-by-chunk transfer\n await this.streamChunks(stream, streamId, metadata);\n }\n }\n\n /**\n * Stream chunks from a ReadableStream (fallback when transfer is not supported)\n */\n private async streamChunks<T = Uint8Array>(\n stream: ReadableStream<T>,\n streamId: string,\n metadata?: Record<string, any>\n ): Promise<void> {\n const reader = stream.getReader();\n\n // Send stream start notification\n this.post('stream_start' as WorkerMessageType, {\n streamId,\n ...metadata,\n mode: 'chunk_transfer',\n });\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n this.post('stream_end' as WorkerMessageType, { streamId });\n break;\n }\n\n // Send chunk with transfer - use extractTransferables for complex objects\n const transfer: Transferable[] = [];\n let chunkValue: T = value;\n\n if (value instanceof ArrayBuffer) {\n transfer.push(value);\n } else if (value instanceof Uint8Array) {\n transfer.push(value.buffer);\n } else if (typeof AudioData !== 'undefined' && value instanceof AudioData) {\n transfer.push(value as unknown as Transferable);\n } else if (typeof VideoFrame !== 'undefined' && value instanceof VideoFrame) {\n transfer.push(value as unknown as Transferable);\n } else if (typeof EncodedVideoChunk !== 'undefined' && value instanceof EncodedVideoChunk) {\n // EncodedVideoChunk is not transferable by itself\n // But its constructor supports transfer parameter for the underlying ArrayBuffer\n // We serialize it to a plain object and transfer the ArrayBuffer\n const serialized = encodedVideoChunkToTransferable(value);\n transfer.push(serialized.data); // Transfer the ArrayBuffer\n chunkValue = serialized as T;\n } else if (typeof EncodedAudioChunk !== 'undefined' && value instanceof EncodedAudioChunk) {\n // EncodedAudioChunk is not transferable by itself\n // We serialize it to a plain object and transfer the ArrayBuffer\n const serialized = encodedAudioChunkToTransferable(value);\n transfer.push(serialized.data); // Transfer the ArrayBuffer\n chunkValue = serialized as T;\n } else if (typeof value === 'object' && value !== null) {\n // For wrapped objects (e.g., {frame: VideoFrame, metadata...}), extract transferables\n const extracted = extractTransferables(value);\n transfer.push(...extracted);\n }\n\n this.post('stream_chunk' as WorkerMessageType, { streamId, chunk: chunkValue }, transfer);\n\n // If we transferred ownership of WebCodecs resources, close them on the sender side.\n // Otherwise they may be GC'd without explicit close(), triggering browser warnings.\n for (const t of transfer) {\n if (typeof VideoFrame !== 'undefined' && t instanceof VideoFrame) {\n try {\n t.close();\n } catch {\n // ignore\n }\n continue;\n }\n if (typeof AudioData !== 'undefined' && t instanceof AudioData) {\n try {\n t.close();\n } catch {\n // ignore\n }\n }\n }\n }\n } catch (error) {\n // Send error notification\n this.post('stream_error' as WorkerMessageType, {\n streamId,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Receive a stream from another worker\n * Handles both transferable streams and chunk-by-chunk reconstruction\n */\n async receiveStream<T = Uint8Array>(\n onStream: (stream: ReadableStream<T>, metadata?: Record<string, any>) => void\n ): Promise<void> {\n const chunkedStreams = new Map<\n string,\n {\n controller: ReadableStreamDefaultController<T>;\n metadata?: Record<string, any>;\n }\n >();\n\n // Intercept stream messages via onmessage to avoid extra event plumbing\n const prev = this.port.onmessage as any;\n // Use function assignment with explicit type to satisfy esbuild parser\n const handler: (event: MessageEvent) => void = (event) => {\n const raw = (event as any).data;\n const envelopeType = raw?.type;\n const hasPayload = raw && typeof raw === 'object' && 'payload' in raw;\n const payload = hasPayload ? (raw as any).payload : raw;\n\n if (envelopeType === 'stream_transfer' && (payload as any)?.stream) {\n onStream((payload as any).stream, payload);\n return;\n }\n if (envelopeType === 'stream_start' && (payload as any)?.streamId) {\n const stream = new ReadableStream<T>({\n start(controller) {\n chunkedStreams.set((payload as any).streamId, { controller, metadata: payload });\n },\n });\n onStream(stream, payload);\n return;\n }\n if (\n envelopeType === 'stream_chunk' &&\n (payload as any)?.streamId &&\n chunkedStreams.has((payload as any).streamId)\n ) {\n const s = chunkedStreams.get((payload as any).streamId);\n if (s) s.controller.enqueue((payload as any).chunk as T);\n return;\n }\n if (\n envelopeType === 'stream_end' &&\n (payload as any)?.streamId &&\n chunkedStreams.has((payload as any).streamId)\n ) {\n const s = chunkedStreams.get((payload as any).streamId);\n if (s) {\n s.controller.close();\n chunkedStreams.delete((payload as any).streamId);\n }\n return;\n }\n if (\n envelopeType === 'stream_error' &&\n (payload as any)?.streamId &&\n chunkedStreams.has((payload as any).streamId)\n ) {\n const s = chunkedStreams.get((payload as any).streamId);\n if (s) {\n s.controller.error(new Error(String((payload as any).error || 'stream error')));\n chunkedStreams.delete((payload as any).streamId);\n }\n return;\n }\n\n // Delegate non-stream messages to previous handler\n if (typeof prev === 'function') prev.call(this.port, event);\n };\n this.port.onmessage = handler as any;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkerPool.d.ts","sourceRoot":"","sources":["../../src/worker/WorkerPool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAA0B,MAAM,SAAS,CAAC;AAEhF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACxC,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;
|
|
1
|
+
{"version":3,"file":"WorkerPool.d.ts","sourceRoot":"","sources":["../../src/worker/WorkerPool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAA0B,MAAM,SAAS,CAAC;AAEhF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACxC,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAUD,qBAAa,UAAU;IACrB,OAAO,CAAC,IAAI,CAAiC;IAC7C,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,eAAe,CAA+C;gBAE1D,MAAM,EAAE,gBAAgB;IAOpC;;OAEG;YACW,YAAY;IAyC1B,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAK1D;;;;;;OAMG;IACG,WAAW,CACf,IAAI,EAAE,UAAU,EAChB,EAAE,CAAC,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3B,OAAO,CAAC,UAAU,CAAC;IAsChB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB7D;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAU9C;;OAEG;IACH,YAAY,IAAI,IAAI;IAOpB;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC,CAQrD;IAED;;OAEG;IACH,IAAI,aAAa,IAAI,MAAM,EAAE,CAE5B;IAED;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;CAI5C"}
|
|
@@ -2,11 +2,8 @@ import { BaseWorker } from "./BaseWorker.js";
|
|
|
2
2
|
import { WorkerMessageType } from "./types.js";
|
|
3
3
|
import { loadWorkerManifest } from "./worker-manifest.js";
|
|
4
4
|
const WORKER_FILE_NAMES = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
videoCompose: "video-compose",
|
|
8
|
-
audioCompose: "audio-compose",
|
|
9
|
-
videoEncode: "video-encode"
|
|
5
|
+
videoExport: "export",
|
|
6
|
+
audioCompose: "audio-compose"
|
|
10
7
|
};
|
|
11
8
|
class WorkerPool {
|
|
12
9
|
pool = /* @__PURE__ */ new Map();
|
|
@@ -30,13 +27,8 @@ class WorkerPool {
|
|
|
30
27
|
throw new Error(`[WorkerPool] Worker type '${type}' is deprecated or not supported`);
|
|
31
28
|
}
|
|
32
29
|
const stageMap = {
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
decode: "decode",
|
|
36
|
-
"video-compose": "compose",
|
|
37
|
-
"audio-compose": "compose",
|
|
38
|
-
"video-encode": "encode",
|
|
39
|
-
encode: "encode"
|
|
30
|
+
export: "export",
|
|
31
|
+
"audio-compose": "compose"
|
|
40
32
|
};
|
|
41
33
|
const stage = stageMap[fileName];
|
|
42
34
|
if (this.workerExtension === ".ts") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkerPool.js","sources":["../../src/worker/WorkerPool.ts"],"sourcesContent":["/**\n * WorkerPool: Manages worker instances with key-based access\n * Provides lazy creation and unified management of workers\n */\n\nimport { BaseWorker } from './BaseWorker';\nimport type { WorkerType, WorkerStatus, WorkerConfigurePayload } from './types';\nimport { WorkerMessageType } from './types';\nimport type { EventBus } from '../event/EventBus';\nimport type { EventPayloadMap } from '../event/events';\nimport { loadWorkerManifest, type WorkerManifest } from './worker-manifest';\n\nexport interface WorkerPoolConfig {\n eventBus: EventBus<EventPayloadMap>;\n workerConfigs?: Record<WorkerType, any>;\n /** Worker files base path (default: '/meframe-workers') */\n workerPath?: string;\n workerExtension?: string;\n}\n\n/**\n * Worker name mapping (worker type -> file name)\n */\nconst WORKER_FILE_NAMES: Partial<Record<WorkerType, string>> = {\n
|
|
1
|
+
{"version":3,"file":"WorkerPool.js","sources":["../../src/worker/WorkerPool.ts"],"sourcesContent":["/**\n * WorkerPool: Manages worker instances with key-based access\n * Provides lazy creation and unified management of workers\n */\n\nimport { BaseWorker } from './BaseWorker';\nimport type { WorkerType, WorkerStatus, WorkerConfigurePayload } from './types';\nimport { WorkerMessageType } from './types';\nimport type { EventBus } from '../event/EventBus';\nimport type { EventPayloadMap } from '../event/events';\nimport { loadWorkerManifest, type WorkerManifest } from './worker-manifest';\n\nexport interface WorkerPoolConfig {\n eventBus: EventBus<EventPayloadMap>;\n workerConfigs?: Record<WorkerType, any>;\n /** Worker files base path (default: '/meframe-workers') */\n workerPath?: string;\n workerExtension?: string;\n}\n\n/**\n * Worker name mapping (worker type -> file name)\n */\nconst WORKER_FILE_NAMES: Partial<Record<WorkerType, string>> = {\n videoExport: 'export',\n audioCompose: 'audio-compose',\n};\n\nexport class WorkerPool {\n private pool = new Map<string, BaseWorker>();\n private eventBus: EventBus<EventPayloadMap>;\n private workerConfigs: Record<string, any>;\n private workerPath: string;\n private workerExtension: string;\n private manifestPromise: Promise<WorkerManifest | null> | null = null;\n\n constructor(config: WorkerPoolConfig) {\n this.eventBus = config.eventBus;\n this.workerConfigs = config.workerConfigs || {};\n this.workerPath = config.workerPath || '/meframe-workers';\n this.workerExtension = config.workerExtension || '.js';\n }\n\n /**\n * Get worker URL for a specific worker type\n */\n private async getWorkerUrl(type: WorkerType): Promise<string> {\n const fileName = WORKER_FILE_NAMES[type];\n\n if (!fileName) {\n throw new Error(`[WorkerPool] Worker type '${type}' is deprecated or not supported`);\n }\n\n // Map worker type to its stage directory\n const stageMap: Record<string, string> = {\n export: 'export',\n 'audio-compose': 'compose',\n };\n const stage = stageMap[fileName];\n\n // Dev mode: use .ts source files directly (no manifest needed)\n if (this.workerExtension === '.ts') {\n return `${this.workerPath}/stages/${stage}/${fileName}.worker.ts`;\n }\n\n // Production mode: try to load manifest for hashed filenames\n if (!this.manifestPromise) {\n this.manifestPromise = loadWorkerManifest(this.workerPath);\n }\n\n const manifest = await this.manifestPromise;\n\n if (manifest) {\n // Use hashed filename from manifest\n const manifestKey = `${fileName}.worker`;\n const hashedPath = manifest[manifestKey];\n\n if (hashedPath) {\n // Manifest contains full relative path from workers directory\n return `${this.workerPath}/${hashedPath}`;\n }\n }\n\n // Fallback: use non-hashed filename (backward compatibility)\n return `${this.workerPath}/stages/${stage}/${fileName}.worker.js`;\n }\n\n get(type: WorkerType, id?: string): BaseWorker | undefined {\n const key = id ? `${type}#${id}` : type;\n return this.pool.get(key) ?? undefined;\n }\n\n /**\n * Get or create a worker instance\n * @param type - Worker type\n * @param id - Optional ID for per-resource or per-clip workers\n * @param options - Optional configuration\n * - lazy: If true, skip initial configure (default: false)\n */\n async getOrCreate(\n type: WorkerType,\n id?: string,\n options?: { lazy?: boolean }\n ): Promise<BaseWorker> {\n const key = id ? `${type}#${id}` : type;\n\n const existing = this.pool.get(key);\n if (!existing) {\n // Generate worker URL based on worker path and type\n const url = await this.getWorkerUrl(type);\n\n const worker = new BaseWorker({\n type,\n url,\n eventBus: this.eventBus,\n clipId: id,\n });\n\n // Only initialize if not in lazy mode\n if (!options?.lazy) {\n const config = this.workerConfigs[type];\n await worker.initialize(config);\n }\n\n this.pool.set(key, worker);\n return worker;\n }\n\n if (!options?.lazy) {\n const config = this.workerConfigs[type];\n if (config) {\n await existing.send(WorkerMessageType.Configure, {\n config,\n initial: false,\n } as WorkerConfigurePayload);\n }\n }\n\n return existing;\n }\n\n async setConfig(type: WorkerType, config: any): Promise<void> {\n const existing = this.workerConfigs[type] || {};\n const mergedConfig = { ...existing, ...config };\n\n this.workerConfigs[type] = mergedConfig;\n\n for (const [key, worker] of this.pool.entries()) {\n if (key === type || key.startsWith(`${type}#`)) {\n await worker.send(WorkerMessageType.Configure, {\n config: mergedConfig,\n initial: false,\n } as WorkerConfigurePayload);\n }\n }\n }\n\n /**\n * Terminate a specific worker\n */\n terminate(type: WorkerType, id?: string): void {\n const key = id ? `${type}#${id}` : type;\n const worker = this.pool.get(key);\n\n if (worker) {\n worker.terminate();\n this.pool.delete(key);\n }\n }\n\n /**\n * Terminate all workers\n */\n terminateAll(): void {\n for (const worker of this.pool.values()) {\n worker.terminate();\n }\n this.pool.clear();\n }\n\n /**\n * Get status of all workers\n */\n get status(): Record<string, WorkerStatus[WorkerType]> {\n const result: Record<string, WorkerStatus[WorkerType]> = {};\n\n for (const [key, worker] of this.pool.entries()) {\n result[key] = worker.status;\n }\n\n return result;\n }\n\n /**\n * Get list of active worker keys\n */\n get activeWorkers(): string[] {\n return Array.from(this.pool.keys());\n }\n\n /**\n * Check if a worker exists\n */\n has(type: WorkerType, id?: string): boolean {\n const key = id ? `${type}#${id}` : type;\n return this.pool.has(key);\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/worker/types.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type PortLike = MessagePort | DedicatedWorkerGlobalScope | Worker;
|
|
|
6
6
|
/**
|
|
7
7
|
* Worker types in the pipeline
|
|
8
8
|
*/
|
|
9
|
-
export type WorkerType = '
|
|
9
|
+
export type WorkerType = 'videoExport' | 'audioCompose';
|
|
10
10
|
export interface WorkerConfigurePayload<T = any> {
|
|
11
11
|
config: T;
|
|
12
12
|
initial: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/worker/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,0BAA0B,GAAG,MAAM,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/worker/types.ts"],"names":[],"mappings":"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"}
|
package/dist/worker/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sources":["../../src/worker/types.ts"],"sourcesContent":["/**\n * Worker Communication Protocol Types\n * Define standard message types and protocols for worker communication\n */\n\n// A port-like object that supports postMessage/onmessage used by WorkerChannel\nexport type PortLike = MessagePort | DedicatedWorkerGlobalScope | Worker;\n\n/**\n * Worker types in the pipeline\n */\nexport type WorkerType =\n // | 'videoDemux' // DEPRECATED: Replaced by IndexedVideoSource (main-thread GOP-based streaming)\n // | 'audioDemux' // DEPRECATED: Replaced by main-thread parsing + AudioSampleCache\n // | 'videoDecode' // DEPRECATED: Replaced by VideoWindowDecodeSession (main-thread decoding)\n // | 'audioDecode' // DEPRECATED: Replaced by AudioWindowPreparer (main-thread decoding)\n 'videoCompose'
|
|
1
|
+
{"version":3,"file":"types.js","sources":["../../src/worker/types.ts"],"sourcesContent":["/**\n * Worker Communication Protocol Types\n * Define standard message types and protocols for worker communication\n */\n\n// A port-like object that supports postMessage/onmessage used by WorkerChannel\nexport type PortLike = MessagePort | DedicatedWorkerGlobalScope | Worker;\n\n/**\n * Worker types in the pipeline\n */\nexport type WorkerType =\n // | 'videoDemux' // DEPRECATED: Replaced by IndexedVideoSource (main-thread GOP-based streaming)\n // | 'audioDemux' // DEPRECATED: Replaced by main-thread parsing + AudioSampleCache\n // | 'videoDecode' // DEPRECATED: Replaced by VideoWindowDecodeSession (main-thread decoding)\n // | 'audioDecode' // DEPRECATED: Replaced by AudioWindowPreparer (main-thread decoding)\n // | 'videoCompose' // DEPRECATED: Merged into 'videoExport'\n // | 'videoEncode' // DEPRECATED: Merged into 'videoExport'\n 'videoExport' | 'audioCompose';\n\nexport interface WorkerConfigurePayload<T = any> {\n config: T;\n initial: boolean;\n}\n\n/**\n * Worker state definition\n */\nexport interface WorkerStateInfo {\n state: 'idle' | 'busy' | 'error' | 'terminated';\n taskCount: number;\n lastError?: string;\n}\n\n/**\n * Worker status for all workers\n */\nexport type WorkerStatus = Record<WorkerType, WorkerStateInfo>;\n\n/**\n * Worker wrapper interface\n */\nexport interface IWorker {\n readonly type: WorkerType;\n readonly state: WorkerStateInfo;\n\n initialize(): Promise<void>;\n terminate(): Promise<void>;\n restart(): Promise<void>;\n\n postMessage(message: any, transfer?: Transferable[]): void;\n on(event: string, handler: (data: any) => void): void;\n off(event: string, handler: (data: any) => void): void;\n}\n\n// Message types for different workers\nexport enum WorkerMessageType {\n // Init = 'init', // configure, { initial: true }\n Ready = 'ready',\n Error = 'error',\n Dispose = 'dispose',\n Configure = 'configure',\n LoadResource = 'load_resource',\n ResourceLoaded = 'resource_loaded',\n ResourceProgress = 'resource_progress',\n ConfigureDemux = 'configure_demux',\n AppendBuffer = 'append_buffer',\n DemuxSamples = 'demux_samples',\n FlushDemux = 'flush_demux',\n ConfigureDecode = 'configure_decode',\n DecodeChunk = 'decode_chunk',\n DecodedFrame = 'decoded_frame',\n SeekGop = 'seek_gop',\n SetComposition = 'set_composition',\n ApplyPatch = 'apply_patch',\n RenderFrame = 'render_frame',\n ComposeFrameReady = 'compose_frame_ready',\n ConfigureEncode = 'configure_encode',\n EncodeFrame = 'encode_frame',\n EncodeAudio = 'encode_audio',\n EncodedChunk = 'encoded_chunk',\n FlushEncode = 'flush_encode',\n AddChunk = 'add_chunk',\n PerformanceStats = 'performance_stats',\n RenderWindow = 'renderWindow',\n AudioTrackAdd = 'audio_track:add',\n AudioTrackRemove = 'audio_track:remove',\n AudioTrackUpdate = 'audio_track:update',\n}\n\n// Base message structure\nexport interface WorkerMessage<T = any> {\n type: WorkerMessageType;\n id: string; // Unique message ID for request-response pairing\n payload?: T;\n transfer?: Transferable[]; // Objects to transfer ownership\n timestamp: number;\n}\n\n// Response message structure\nexport interface WorkerResponse<T = any> {\n id: string; // Matches request ID\n success: boolean;\n result?: T;\n error?: WorkerError;\n timestamp: number;\n}\n\n// Error structure\nexport interface WorkerError {\n code: string;\n message: string;\n details?: any;\n stack?: string;\n}\n\n// Worker configuration\nexport interface WorkerConfig {\n name: string;\n workerUrl?: string;\n capabilities?: string[];\n maxRetries?: number;\n timeout?: number;\n}\n\n// Message handler type\nexport type MessageHandler<T = any, R = any> = (\n payload: T,\n transfer?: Transferable[]\n) => Promise<R> | R;\n\n// Message handler registry\nexport interface MessageHandlers {\n [key: string]: MessageHandler;\n}\n\n/**\n * Unified stream connection message for the data plane\n * Used by the stream-pipeline refactor to reduce message surface\n */\nexport interface ConnectMsg {\n direction: 'upstream';\n port: MessagePort;\n streamType: 'video' | 'audio' | 'frame' | 'chunk';\n clipId?: string;\n trackId?: string;\n}\n\n// Transferable types used in workers\nexport interface TransferableFrame {\n frame: VideoFrame;\n timestamp: number;\n duration?: number;\n}\n\nexport interface TransferableChunk {\n chunk: EncodedVideoChunk | EncodedAudioChunk;\n timestamp: number;\n duration?: number;\n trackId: string;\n}\n\nexport interface TransferableBuffer {\n buffer: ArrayBuffer;\n offset?: number;\n length?: number;\n}\n\n// Worker state\nexport enum WorkerState {\n Idle = 'idle',\n Initializing = 'initializing',\n Ready = 'ready',\n Processing = 'processing',\n Error = 'error',\n Disposed = 'disposed',\n}\n\n// Performance metrics\nexport interface WorkerPerformanceStats {\n workerId: string;\n workerName: string;\n messagesProcessed: number;\n averageProcessingTime: number;\n maxProcessingTime: number;\n errorCount: number;\n queueSize: number;\n memoryUsage?: number;\n}\n\n// Request tracking\nexport interface PendingRequest {\n id: string;\n type: WorkerMessageType;\n timestamp: number;\n timeout?: number;\n resolve: (value: any) => void;\n reject: (error: any) => void;\n retryCount?: number;\n maxRetries?: number;\n}\n\n// Stream support\nexport interface StreamConfig {\n highWaterMark?: number;\n strategy?: QueuingStrategy;\n}\n\n// Worker pool settings\nexport interface WorkerPoolSettings {\n maxWorkers?: number;\n workerIdleTimeout?: number;\n enableSharedArrayBuffer?: boolean;\n enableOffscreenCanvas?: boolean;\n}\n\n// Message priority levels\nexport enum MessagePriority {\n Low = 0,\n Normal = 1,\n High = 2,\n Critical = 3,\n}\n\n// Priority message\nexport interface PriorityMessage<T = any> extends WorkerMessage<T> {\n priority: MessagePriority;\n}\n"],"names":["WorkerMessageType","WorkerState"],"mappings":"AAwDO,IAAK,sCAAAA,uBAAL;AAELA,qBAAA,OAAA,IAAQ;AACRA,qBAAA,OAAA,IAAQ;AACRA,qBAAA,SAAA,IAAU;AACVA,qBAAA,WAAA,IAAY;AACZA,qBAAA,cAAA,IAAe;AACfA,qBAAA,gBAAA,IAAiB;AACjBA,qBAAA,kBAAA,IAAmB;AACnBA,qBAAA,gBAAA,IAAiB;AACjBA,qBAAA,cAAA,IAAe;AACfA,qBAAA,cAAA,IAAe;AACfA,qBAAA,YAAA,IAAa;AACbA,qBAAA,iBAAA,IAAkB;AAClBA,qBAAA,aAAA,IAAc;AACdA,qBAAA,cAAA,IAAe;AACfA,qBAAA,SAAA,IAAU;AACVA,qBAAA,gBAAA,IAAiB;AACjBA,qBAAA,YAAA,IAAa;AACbA,qBAAA,aAAA,IAAc;AACdA,qBAAA,mBAAA,IAAoB;AACpBA,qBAAA,iBAAA,IAAkB;AAClBA,qBAAA,aAAA,IAAc;AACdA,qBAAA,aAAA,IAAc;AACdA,qBAAA,cAAA,IAAe;AACfA,qBAAA,aAAA,IAAc;AACdA,qBAAA,UAAA,IAAW;AACXA,qBAAA,kBAAA,IAAmB;AACnBA,qBAAA,cAAA,IAAe;AACfA,qBAAA,eAAA,IAAgB;AAChBA,qBAAA,kBAAA,IAAmB;AACnBA,qBAAA,kBAAA,IAAmB;AA/BT,SAAAA;AAAA,GAAA,qBAAA,CAAA,CAAA;AAiHL,IAAK,gCAAAC,iBAAL;AACLA,eAAA,MAAA,IAAO;AACPA,eAAA,cAAA,IAAe;AACfA,eAAA,OAAA,IAAQ;AACRA,eAAA,YAAA,IAAa;AACbA,eAAA,OAAA,IAAQ;AACRA,eAAA,UAAA,IAAW;AAND,SAAAA;AAAA,GAAA,eAAA,CAAA,CAAA;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-event-whitelist.d.ts","sourceRoot":"","sources":["../../src/worker/worker-event-whitelist.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,UAAU,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"worker-event-whitelist.d.ts","sourceRoot":"","sources":["../../src/worker/worker-event-whitelist.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,UAAU,EAAE,YAAY,EAAE,CAmCrE,CAAC;AAEF;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAGvF;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAKlE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAGhE,CAAC"}
|