@meframe/core 0.2.3 → 0.2.5
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/Meframe.d.ts +7 -1
- package/dist/Meframe.d.ts.map +1 -1
- package/dist/Meframe.js +7 -27
- package/dist/Meframe.js.map +1 -1
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +9 -2
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/storage/opfs/OPFSManager.d.ts.map +1 -1
- package/dist/cache/storage/opfs/OPFSManager.js +11 -7
- package/dist/cache/storage/opfs/OPFSManager.js.map +1 -1
- package/dist/controllers/ExportController.d.ts +7 -1
- package/dist/controllers/ExportController.d.ts.map +1 -1
- package/dist/controllers/ExportController.js.map +1 -1
- package/dist/controllers/PlaybackController.d.ts.map +1 -1
- package/dist/controllers/PlaybackController.js +6 -0
- package/dist/controllers/PlaybackController.js.map +1 -1
- package/dist/node_modules/.pnpm/mp4-muxer@5.2.2/node_modules/mp4-muxer/build/mp4-muxer.js.map +1 -0
- package/dist/{medeo-fe/node_modules → node_modules}/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js +2 -2
- package/dist/node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js.map +1 -0
- package/dist/orchestrator/AudioExportSession.d.ts +3 -1
- package/dist/orchestrator/AudioExportSession.d.ts.map +1 -1
- package/dist/orchestrator/AudioExportSession.js +28 -20
- package/dist/orchestrator/AudioExportSession.js.map +1 -1
- package/dist/orchestrator/ExportScheduler.d.ts +5 -1
- package/dist/orchestrator/ExportScheduler.d.ts.map +1 -1
- package/dist/orchestrator/ExportScheduler.js +20 -2
- package/dist/orchestrator/ExportScheduler.js.map +1 -1
- package/dist/orchestrator/OnDemandVideoSession.d.ts +1 -0
- package/dist/orchestrator/OnDemandVideoSession.d.ts.map +1 -1
- package/dist/orchestrator/OnDemandVideoSession.js +28 -17
- package/dist/orchestrator/OnDemandVideoSession.js.map +1 -1
- package/dist/orchestrator/Orchestrator.d.ts +1 -1
- package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/Orchestrator.js.map +1 -1
- package/dist/orchestrator/types.d.ts +1 -1
- package/dist/orchestrator/types.d.ts.map +1 -1
- package/dist/stages/compose/FrameRateConverter.d.ts +6 -2
- package/dist/stages/compose/FrameRateConverter.d.ts.map +1 -1
- package/dist/stages/compose/OfflineAudioMixer.d.ts.map +1 -1
- package/dist/stages/compose/OfflineAudioMixer.js +8 -0
- package/dist/stages/compose/OfflineAudioMixer.js.map +1 -1
- package/dist/stages/load/ResourceLoader.d.ts.map +1 -1
- package/dist/stages/load/ResourceLoader.js +34 -8
- package/dist/stages/load/ResourceLoader.js.map +1 -1
- package/dist/stages/mux/MP4Muxer.d.ts +11 -2
- package/dist/stages/mux/MP4Muxer.d.ts.map +1 -1
- package/dist/stages/mux/MP4Muxer.js +32 -6
- package/dist/stages/mux/MP4Muxer.js.map +1 -1
- package/dist/stages/mux/MuxManager.d.ts +5 -1
- package/dist/stages/mux/MuxManager.d.ts.map +1 -1
- package/dist/stages/mux/MuxManager.js +15 -7
- package/dist/stages/mux/MuxManager.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/errors.d.ts +1 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +5 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/mp4box.js +1 -1
- package/dist/workers/MP4Demuxer.DfWiwyjB.js.map +1 -1
- package/dist/workers/stages/compose/{video-compose.worker.CA2_Kpg-.js → video-compose.worker.KMZjuJuY.js} +47 -4
- package/dist/workers/stages/compose/video-compose.worker.KMZjuJuY.js.map +1 -0
- package/dist/workers/worker-manifest.json +1 -1
- package/package.json +1 -1
- package/dist/medeo-fe/node_modules/.pnpm/mp4-muxer@5.2.2/node_modules/mp4-muxer/build/mp4-muxer.js.map +0 -1
- package/dist/medeo-fe/node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js.map +0 -1
- package/dist/workers/stages/compose/video-compose.worker.CA2_Kpg-.js.map +0 -1
- /package/dist/{medeo-fe/node_modules → node_modules}/.pnpm/mp4-muxer@5.2.2/node_modules/mp4-muxer/build/mp4-muxer.js +0 -0
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export type MuxOutputConfig = {
|
|
2
|
+
kind: 'blob';
|
|
3
|
+
} | {
|
|
4
|
+
kind: 'stream';
|
|
5
|
+
onData: (data: Uint8Array, position: number) => void;
|
|
6
|
+
chunked?: boolean;
|
|
7
|
+
chunkSize?: number;
|
|
8
|
+
};
|
|
1
9
|
/**
|
|
2
10
|
* MP4Muxer - MP4 container multiplexer using mp4-muxer library
|
|
3
11
|
* Supports video and audio track export
|
|
@@ -8,6 +16,7 @@ export declare class MP4Muxer {
|
|
|
8
16
|
private firstAudioChunk;
|
|
9
17
|
private videoChunkMeta;
|
|
10
18
|
private audioChunkMeta;
|
|
19
|
+
private lastAudioDurationUs;
|
|
11
20
|
constructor(config: {
|
|
12
21
|
width: number;
|
|
13
22
|
height: number;
|
|
@@ -15,11 +24,11 @@ export declare class MP4Muxer {
|
|
|
15
24
|
fastStart?: false | 'in-memory' | 'fragmented';
|
|
16
25
|
videoChunkMeta?: any;
|
|
17
26
|
audioChunkMeta?: any;
|
|
18
|
-
});
|
|
27
|
+
}, output?: MuxOutputConfig);
|
|
19
28
|
private videoChunkCount;
|
|
20
29
|
writeVideoChunk(chunk: EncodedVideoChunk, metadata?: EncodedVideoChunkMetadata): void;
|
|
21
30
|
private audioChunkCount;
|
|
22
31
|
writeAudioChunk(chunk: EncodedAudioChunk, metadata?: EncodedAudioChunkMetadata): void;
|
|
23
|
-
finalize(): Blob;
|
|
32
|
+
finalize(): Blob | null;
|
|
24
33
|
}
|
|
25
34
|
//# sourceMappingURL=MP4Muxer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MP4Muxer.d.ts","sourceRoot":"","sources":["../../../src/stages/mux/MP4Muxer.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"MP4Muxer.d.ts","sourceRoot":"","sources":["../../../src/stages/mux/MP4Muxer.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEN;;;GAGG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAA0C;IACvD,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,mBAAmB,CAAuB;gBAGhD,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,CAAC,EAAE,KAAK,GAAG,WAAW,GAAG,YAAY,CAAC;QAC/C,cAAc,CAAC,EAAE,GAAG,CAAC;QACrB,cAAc,CAAC,EAAE,GAAG,CAAC;KACtB,EACD,MAAM,GAAE,eAAkC;IAqD5C,OAAO,CAAC,eAAe,CAAK;IAE5B,eAAe,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,CAAC,EAAE,yBAAyB,GAAG,IAAI;IAwBrF,OAAO,CAAC,eAAe,CAAK;IAE5B,eAAe,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,CAAC,EAAE,yBAAyB,GAAG,IAAI;IAmDrF,QAAQ,IAAI,IAAI,GAAG,IAAI;CASxB"}
|
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
import { ArrayBufferTarget, Muxer } from "../../
|
|
1
|
+
import { StreamTarget, ArrayBufferTarget, Muxer } from "../../node_modules/.pnpm/mp4-muxer@5.2.2/node_modules/mp4-muxer/build/mp4-muxer.js";
|
|
2
2
|
class MP4Muxer {
|
|
3
3
|
muxer;
|
|
4
4
|
firstVideoChunk = true;
|
|
5
5
|
firstAudioChunk = true;
|
|
6
6
|
videoChunkMeta = null;
|
|
7
7
|
audioChunkMeta = null;
|
|
8
|
-
|
|
8
|
+
lastAudioDurationUs = null;
|
|
9
|
+
constructor(config, output = { kind: "blob" }) {
|
|
9
10
|
this.videoChunkMeta = config.videoChunkMeta;
|
|
10
11
|
this.audioChunkMeta = config.audioChunkMeta;
|
|
12
|
+
const target = output.kind === "stream" ? new StreamTarget({
|
|
13
|
+
onData: output.onData,
|
|
14
|
+
chunked: output.chunked ?? true,
|
|
15
|
+
chunkSize: output.chunkSize ?? 16 * 1024 * 1024
|
|
16
|
+
// 16 MiB default to reduce writes
|
|
17
|
+
}) : new ArrayBufferTarget();
|
|
11
18
|
const muxerConfig = {
|
|
12
|
-
target
|
|
19
|
+
target,
|
|
13
20
|
video: {
|
|
14
21
|
codec: "avc",
|
|
15
22
|
width: config.width,
|
|
@@ -46,7 +53,7 @@ class MP4Muxer {
|
|
|
46
53
|
}
|
|
47
54
|
audioChunkCount = 0;
|
|
48
55
|
writeAudioChunk(chunk, metadata) {
|
|
49
|
-
if (chunk.byteLength <= 16) {
|
|
56
|
+
if (chunk.byteLength <= 16 && (!chunk.duration || chunk.duration <= 0)) {
|
|
50
57
|
return;
|
|
51
58
|
}
|
|
52
59
|
let meta;
|
|
@@ -59,13 +66,32 @@ class MP4Muxer {
|
|
|
59
66
|
}
|
|
60
67
|
this.firstAudioChunk = false;
|
|
61
68
|
}
|
|
69
|
+
const hasValidDuration = !!chunk.duration && chunk.duration > 0;
|
|
70
|
+
if (!hasValidDuration) {
|
|
71
|
+
const sampleRate = metadata?.decoderConfig?.sampleRate ?? this.audioChunkMeta?.sampleRate ?? 48e3;
|
|
72
|
+
const inferredDurationUs = this.lastAudioDurationUs ?? Math.max(1, Math.round(1024 / sampleRate * 1e6));
|
|
73
|
+
const buffer = new ArrayBuffer(chunk.byteLength);
|
|
74
|
+
chunk.copyTo(buffer);
|
|
75
|
+
chunk = new EncodedAudioChunk({
|
|
76
|
+
type: chunk.type,
|
|
77
|
+
timestamp: chunk.timestamp,
|
|
78
|
+
duration: inferredDurationUs,
|
|
79
|
+
data: buffer
|
|
80
|
+
});
|
|
81
|
+
this.lastAudioDurationUs = inferredDurationUs;
|
|
82
|
+
} else {
|
|
83
|
+
this.lastAudioDurationUs = chunk.duration;
|
|
84
|
+
}
|
|
62
85
|
this.audioChunkCount++;
|
|
63
86
|
this.muxer.addAudioChunk(chunk, meta);
|
|
64
87
|
}
|
|
65
88
|
finalize() {
|
|
66
89
|
this.muxer.finalize();
|
|
67
|
-
|
|
68
|
-
|
|
90
|
+
if (this.muxer.target instanceof ArrayBufferTarget) {
|
|
91
|
+
const buffer = this.muxer.target.buffer;
|
|
92
|
+
return new Blob([buffer], { type: "video/mp4" });
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
69
95
|
}
|
|
70
96
|
}
|
|
71
97
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MP4Muxer.js","sources":["../../../src/stages/mux/MP4Muxer.ts"],"sourcesContent":["import { Muxer, ArrayBufferTarget } from 'mp4-muxer';\n\n/**\n * MP4Muxer - MP4 container multiplexer using mp4-muxer library\n * Supports video and audio track export\n */\nexport class MP4Muxer {\n private muxer: Muxer<ArrayBufferTarget>;\n private firstVideoChunk = true;\n private firstAudioChunk = true;\n private videoChunkMeta: any = null;\n private audioChunkMeta: any = null;\n\n constructor(config: {\n
|
|
1
|
+
{"version":3,"file":"MP4Muxer.js","sources":["../../../src/stages/mux/MP4Muxer.ts"],"sourcesContent":["import { Muxer, ArrayBufferTarget, StreamTarget } from 'mp4-muxer';\n\nexport type MuxOutputConfig =\n | { kind: 'blob' }\n | {\n kind: 'stream';\n onData: (data: Uint8Array, position: number) => void;\n chunked?: boolean;\n chunkSize?: number;\n };\n\n/**\n * MP4Muxer - MP4 container multiplexer using mp4-muxer library\n * Supports video and audio track export\n */\nexport class MP4Muxer {\n private muxer: Muxer<ArrayBufferTarget | StreamTarget>;\n private firstVideoChunk = true;\n private firstAudioChunk = true;\n private videoChunkMeta: any = null;\n private audioChunkMeta: any = null;\n private lastAudioDurationUs: number | null = null;\n\n constructor(\n config: {\n width: number;\n height: number;\n fps: number;\n fastStart?: false | 'in-memory' | 'fragmented';\n videoChunkMeta?: any;\n audioChunkMeta?: any;\n },\n output: MuxOutputConfig = { kind: 'blob' }\n ) {\n this.videoChunkMeta = config.videoChunkMeta;\n this.audioChunkMeta = config.audioChunkMeta;\n\n const target =\n output.kind === 'stream'\n ? new StreamTarget({\n onData: output.onData,\n chunked: output.chunked ?? true,\n chunkSize: output.chunkSize ?? 16 * 1024 * 1024, // 16 MiB default to reduce writes\n })\n : new ArrayBufferTarget();\n\n const muxerConfig: any = {\n target,\n video: {\n codec: 'avc',\n width: config.width,\n height: config.height,\n frameRate: config.fps,\n },\n fastStart: config.fastStart ?? 'in-memory',\n firstTimestampBehavior: 'offset',\n };\n\n // Add audio configuration if provided\n // If not provided initially, we assume AAC (standard for web)\n // but mp4-muxer might need it.\n // Actually mp4-muxer allows adding track configuration later?\n // No, it requires it in constructor or inferred?\n // If audioChunkMeta is missing, we can't configure audio fully here.\n // But mp4-muxer docs say: \"If you don't provide options.audio, no audio track will be created.\"\n // So we MUST provide options.audio if we want audio.\n // If we don't have meta yet, we guess?\n // Or we rely on audio export always providing AAC 48k?\n // Let's assume AAC 48k 2ch as default if we want audio support.\n // Or better: if audioChunkMeta is null, we enable audio with defaults.\n\n // However, for robustness, we should probably wait for first chunk to configure muxer?\n // But MuxManager calls `start` then `writeVideoChunk` then `writeAudioChunk`.\n // Audio might come later.\n //\n // Let's assume we always want audio track capability.\n muxerConfig.audio = {\n codec: 'aac',\n sampleRate: this.audioChunkMeta?.sampleRate || 48000,\n numberOfChannels: this.audioChunkMeta?.numberOfChannels || 2,\n };\n\n this.muxer = new Muxer(muxerConfig);\n }\n\n private videoChunkCount = 0;\n\n writeVideoChunk(chunk: EncodedVideoChunk, metadata?: EncodedVideoChunkMetadata): void {\n let meta: EncodedVideoChunkMetadata | undefined;\n\n if (this.firstVideoChunk) {\n if (metadata && metadata.decoderConfig) {\n this.videoChunkMeta = metadata.decoderConfig;\n }\n\n if (this.videoChunkMeta) {\n meta = { decoderConfig: this.videoChunkMeta };\n }\n\n // Ensure we have metadata for first chunk if it's a keyframe\n if (chunk.type === 'key' && !meta) {\n console.warn('[MP4Muxer] First video chunk is keyframe but missing decoderConfig');\n }\n\n this.firstVideoChunk = false;\n }\n\n this.videoChunkCount++;\n this.muxer.addVideoChunk(chunk, meta);\n }\n\n private audioChunkCount = 0;\n\n writeAudioChunk(chunk: EncodedAudioChunk, metadata?: EncodedAudioChunkMetadata): void {\n // Safari (and sometimes Chromium) may emit tiny (e.g. 6 bytes) \"audio\" chunks that are not valid AAC frames.\n // mp4-muxer treats durations as authoritative; dropping *valid* small chunks can collapse silence gaps and cause stutter.\n // So only drop tiny chunks when they are clearly invalid (duration missing/<=0).\n if (chunk.byteLength <= 16 && (!chunk.duration || chunk.duration <= 0)) {\n return;\n }\n\n let meta: EncodedAudioChunkMetadata | undefined;\n\n if (this.firstAudioChunk) {\n if (metadata && metadata.decoderConfig) {\n this.audioChunkMeta = metadata.decoderConfig;\n }\n\n if (this.audioChunkMeta) {\n meta = { decoderConfig: this.audioChunkMeta };\n }\n\n this.firstAudioChunk = false;\n }\n\n // Some platforms output duration=0/undefined for audio chunks.\n // mp4-muxer uses duration to build the timeline; 0 duration can collapse time and remove intended gaps.\n // Try to synthesize a sane duration:\n // - Prefer the chunk's own duration when >0\n // - Otherwise use AAC-LC frame duration (1024 samples) inferred from decoderConfig sampleRate if known\n const hasValidDuration = !!chunk.duration && chunk.duration > 0;\n if (!hasValidDuration) {\n const sampleRate =\n (metadata as any)?.decoderConfig?.sampleRate ?? this.audioChunkMeta?.sampleRate ?? 48_000;\n const inferredDurationUs =\n this.lastAudioDurationUs ?? Math.max(1, Math.round((1024 / sampleRate) * 1_000_000));\n\n const buffer = new ArrayBuffer(chunk.byteLength);\n chunk.copyTo(buffer);\n chunk = new EncodedAudioChunk({\n type: chunk.type,\n timestamp: chunk.timestamp,\n duration: inferredDurationUs,\n data: buffer,\n });\n this.lastAudioDurationUs = inferredDurationUs;\n } else {\n this.lastAudioDurationUs = chunk.duration!;\n }\n\n this.audioChunkCount++;\n this.muxer.addAudioChunk(chunk, meta);\n }\n\n finalize(): Blob | null {\n this.muxer.finalize();\n if (this.muxer.target instanceof ArrayBufferTarget) {\n const buffer = this.muxer.target.buffer;\n return new Blob([buffer], { type: 'video/mp4' });\n }\n // Stream target has already delivered data via onData callback.\n return null;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
import { MuxOutputConfig } from './MP4Muxer';
|
|
2
|
+
|
|
1
3
|
export declare class MuxManager {
|
|
2
4
|
private muxer;
|
|
5
|
+
private output;
|
|
3
6
|
constructor();
|
|
4
7
|
start(config: {
|
|
5
8
|
width: number;
|
|
6
9
|
height: number;
|
|
7
10
|
fps: number;
|
|
11
|
+
output?: MuxOutputConfig;
|
|
8
12
|
}): void;
|
|
9
13
|
writeVideoChunk(chunk: EncodedVideoChunk, metadata?: EncodedVideoChunkMetadata): void;
|
|
10
14
|
writeAudioChunk(chunk: EncodedAudioChunk, metadata?: EncodedAudioChunkMetadata): void;
|
|
11
|
-
finalize(): Blob;
|
|
15
|
+
finalize(): Blob | null;
|
|
12
16
|
}
|
|
13
17
|
//# sourceMappingURL=MuxManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MuxManager.d.ts","sourceRoot":"","sources":["../../../src/stages/mux/MuxManager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MuxManager.d.ts","sourceRoot":"","sources":["../../../src/stages/mux/MuxManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAE5D,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,MAAM,CAAgC;;IAI9C,KAAK,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,eAAe,CAAA;KAAE;IAgBtF,eAAe,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,CAAC,EAAE,yBAAyB;IAK9E,eAAe,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,CAAC,EAAE,yBAAyB;IAS9E,QAAQ,IAAI,IAAI,GAAG,IAAI;CAOxB"}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { MP4Muxer } from "./MP4Muxer.js";
|
|
2
2
|
class MuxManager {
|
|
3
3
|
muxer = null;
|
|
4
|
+
output = null;
|
|
4
5
|
constructor() {
|
|
5
6
|
}
|
|
6
7
|
start(config) {
|
|
7
|
-
this.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
this.output = config.output ?? { kind: "blob" };
|
|
9
|
+
this.muxer = new MP4Muxer(
|
|
10
|
+
{
|
|
11
|
+
width: config.width,
|
|
12
|
+
height: config.height,
|
|
13
|
+
fps: config.fps,
|
|
14
|
+
// For blob output, prefer fast start by keeping chunks in memory.
|
|
15
|
+
// For stream output, prefer minimal memory usage: metadata at end (non-fMP4).
|
|
16
|
+
fastStart: this.output.kind === "stream" ? false : "in-memory"
|
|
17
|
+
// Metadata will be handled by first chunks
|
|
18
|
+
},
|
|
19
|
+
this.output
|
|
20
|
+
);
|
|
14
21
|
}
|
|
15
22
|
writeVideoChunk(chunk, metadata) {
|
|
16
23
|
if (!this.muxer) throw new Error("Muxer not started");
|
|
@@ -27,6 +34,7 @@ class MuxManager {
|
|
|
27
34
|
if (!this.muxer) throw new Error("Muxer not started");
|
|
28
35
|
const blob = this.muxer.finalize();
|
|
29
36
|
this.muxer = null;
|
|
37
|
+
this.output = null;
|
|
30
38
|
return blob;
|
|
31
39
|
}
|
|
32
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MuxManager.js","sources":["../../../src/stages/mux/MuxManager.ts"],"sourcesContent":["import { MP4Muxer } from './MP4Muxer';\n\nexport class MuxManager {\n private muxer: MP4Muxer | null = null;\n\n constructor() {}\n\n start(config: { width: number; height: number; fps: number }) {\n this.muxer = new MP4Muxer({\n
|
|
1
|
+
{"version":3,"file":"MuxManager.js","sources":["../../../src/stages/mux/MuxManager.ts"],"sourcesContent":["import { MP4Muxer, type MuxOutputConfig } from './MP4Muxer';\n\nexport class MuxManager {\n private muxer: MP4Muxer | null = null;\n private output: MuxOutputConfig | null = null;\n\n constructor() {}\n\n start(config: { width: number; height: number; fps: number; output?: MuxOutputConfig }) {\n this.output = config.output ?? { kind: 'blob' };\n this.muxer = new MP4Muxer(\n {\n width: config.width,\n height: config.height,\n fps: config.fps,\n // For blob output, prefer fast start by keeping chunks in memory.\n // For stream output, prefer minimal memory usage: metadata at end (non-fMP4).\n fastStart: this.output.kind === 'stream' ? false : 'in-memory',\n // Metadata will be handled by first chunks\n },\n this.output\n );\n }\n\n writeVideoChunk(chunk: EncodedVideoChunk, metadata?: EncodedVideoChunkMetadata) {\n if (!this.muxer) throw new Error('Muxer not started');\n this.muxer.writeVideoChunk(chunk, metadata);\n }\n\n writeAudioChunk(chunk: EncodedAudioChunk, metadata?: EncodedAudioChunkMetadata) {\n // Check if muxer is available (it might have been finalized already if audio is late)\n if (!this.muxer) {\n console.warn('[MuxManager] writeAudioChunk called after finalization, dropping chunk');\n return;\n }\n this.muxer.writeAudioChunk(chunk, metadata);\n }\n\n finalize(): Blob | null {\n if (!this.muxer) throw new Error('Muxer not started');\n const blob = this.muxer.finalize();\n this.muxer = null;\n this.output = null;\n return blob;\n }\n}\n"],"names":[],"mappings":";AAEO,MAAM,WAAW;AAAA,EACd,QAAyB;AAAA,EACzB,SAAiC;AAAA,EAEzC,cAAc;AAAA,EAAC;AAAA,EAEf,MAAM,QAAkF;AACtF,SAAK,SAAS,OAAO,UAAU,EAAE,MAAM,OAAA;AACvC,SAAK,QAAQ,IAAI;AAAA,MACf;AAAA,QACE,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,KAAK,OAAO;AAAA;AAAA;AAAA,QAGZ,WAAW,KAAK,OAAO,SAAS,WAAW,QAAQ;AAAA;AAAA,MAAA;AAAA,MAGrD,KAAK;AAAA,IAAA;AAAA,EAET;AAAA,EAEA,gBAAgB,OAA0B,UAAsC;AAC9E,QAAI,CAAC,KAAK,MAAO,OAAM,IAAI,MAAM,mBAAmB;AACpD,SAAK,MAAM,gBAAgB,OAAO,QAAQ;AAAA,EAC5C;AAAA,EAEA,gBAAgB,OAA0B,UAAsC;AAE9E,QAAI,CAAC,KAAK,OAAO;AACf,cAAQ,KAAK,wEAAwE;AACrF;AAAA,IACF;AACA,SAAK,MAAM,gBAAgB,OAAO,QAAQ;AAAA,EAC5C;AAAA,EAEA,WAAwB;AACtB,QAAI,CAAC,KAAK,MAAO,OAAM,IAAI,MAAM,mBAAmB;AACpD,UAAM,OAAO,KAAK,MAAM,SAAA;AACxB,SAAK,QAAQ;AACb,SAAK,SAAS;AACd,WAAO;AAAA,EACT;AACF;"}
|
package/dist/types.d.ts
CHANGED
|
@@ -21,5 +21,13 @@ export interface ExportOptions {
|
|
|
21
21
|
fps?: number;
|
|
22
22
|
/** Quality preset */
|
|
23
23
|
quality?: 'low' | 'medium' | 'high' | 'highest';
|
|
24
|
+
/** Export output mode (default blob). */
|
|
25
|
+
exportMode?: 'blob' | 'stream';
|
|
26
|
+
/** Streaming mux callback, required when exportMode is 'stream'. */
|
|
27
|
+
onMuxData?: (data: Uint8Array, position: number) => void;
|
|
28
|
+
/** Optional chunk sizing hint for streaming mux output. */
|
|
29
|
+
muxChunkSizeBytes?: number;
|
|
30
|
+
/** Whether to enable mp4-muxer chunked StreamTarget (default true). */
|
|
31
|
+
muxChunked?: boolean;
|
|
24
32
|
}
|
|
25
33
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEpE,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,SAAS,GACT,OAAO,GACP,SAAS,GACT,QAAQ,GACR,WAAW,GACX,OAAO,GACP,WAAW,CAAC;AAEhB,MAAM,WAAW,aAAa;IAC5B,oBAAoB;IACpB,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAExB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;IAE7C,kBAAkB;IAClB,UAAU,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAE5B,2BAA2B;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,2BAA2B;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,iBAAiB;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,qBAAqB;IACrB,OAAO,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEpE,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,SAAS,GACT,OAAO,GACP,SAAS,GACT,QAAQ,GACR,WAAW,GACX,OAAO,GACP,WAAW,CAAC;AAEhB,MAAM,WAAW,aAAa;IAC5B,oBAAoB;IACpB,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAExB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;IAE7C,kBAAkB;IAClB,UAAU,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAE5B,2BAA2B;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,2BAA2B;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,iBAAiB;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,qBAAqB;IACrB,OAAO,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IAEhD,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC/B,oEAAoE;IACpE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
|
package/dist/utils/errors.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;aAChB,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;CAI3C;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;aAEvB,UAAU,EAAE,MAAM;aAClB,UAAU,EAAE,MAAM;gBADlB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM;CAQrC;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,UAAU,EAAE,MAAM;aAClB,MAAM,EAAE,MAAM;gBADd,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM;CAKjC;AAED;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,SAAS,EAAE,MAAM;aACjB,MAAM,EAAE,MAAM;aACd,SAAS,EAAE,OAAO;gBAFlB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,OAAO;CAQrC;AAED;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;aAEhC,aAAa,EAAE;QAC7B,kBAAkB,EAAE,OAAO,CAAC;QAC5B,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,WAAW,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC;KACrE;gBALe,aAAa,EAAE;QAC7B,kBAAkB,EAAE,OAAO,CAAC;QAC5B,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,WAAW,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC;KACrE;CAYJ"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;aAChB,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;CAI3C;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;aAEvB,UAAU,EAAE,MAAM;aAClB,UAAU,EAAE,MAAM;gBADlB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM;CAQrC;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,UAAU,EAAE,MAAM;aAClB,MAAM,EAAE,MAAM;gBADd,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM;CAKjC;AAED;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,SAAS,EAAE,MAAM;aACjB,MAAM,EAAE,MAAM;aACd,SAAS,EAAE,OAAO;gBAFlB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,OAAO;CAQrC;AAED;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;aAEhC,aAAa,EAAE;QAC7B,kBAAkB,EAAE,OAAO,CAAC;QAC5B,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,WAAW,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC;KACrE;gBALe,aAAa,EAAE;QAC7B,kBAAkB,EAAE,OAAO,CAAC;QAC5B,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,WAAW,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC;KACrE;CAYJ;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpE"}
|
package/dist/utils/errors.js
CHANGED
|
@@ -44,11 +44,15 @@ class BrowserCompatibilityError extends Error {
|
|
|
44
44
|
this.name = "BrowserCompatibilityError";
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
function isDOMException(error, name) {
|
|
48
|
+
return error instanceof Error && "name" in error && error.name === name;
|
|
49
|
+
}
|
|
47
50
|
export {
|
|
48
51
|
BrowserCompatibilityError,
|
|
49
52
|
EmptyStreamError,
|
|
50
53
|
OPFSQuotaExceededError,
|
|
51
54
|
ResourceCorruptedError,
|
|
52
|
-
WaiterReplacedError
|
|
55
|
+
WaiterReplacedError,
|
|
56
|
+
isDOMException
|
|
53
57
|
};
|
|
54
58
|
//# sourceMappingURL=errors.js.map
|
package/dist/utils/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sources":["../../src/utils/errors.ts"],"sourcesContent":["/**\n * Custom error types for Meframe\n */\n\n/**\n * Error thrown when a clip ready waiter is replaced by a newer one\n * This happens during rapid seeks and should be ignored by callers\n */\nexport class WaiterReplacedError extends Error {\n constructor(public readonly clipId: string) {\n super(`Waiter for clip ${clipId} was replaced by a newer waiter`);\n this.name = 'WaiterReplacedError';\n }\n}\n\n/**\n * Error thrown when reading an empty or incomplete OPFS file\n * Usually indicates a race condition between write and read operations\n */\nexport class EmptyStreamError extends Error {\n constructor(\n public readonly resourceId: string,\n public readonly fileOffset: number\n ) {\n super(\n `Empty stream received for resource ${resourceId}. ` +\n `File offset: ${fileOffset}. This indicates the file is being written or is corrupted.`\n );\n this.name = 'EmptyStreamError';\n }\n}\n\n/**\n * Error thrown when a cached resource file is corrupted or incomplete\n */\nexport class ResourceCorruptedError extends Error {\n constructor(\n public readonly resourceId: string,\n public readonly reason: string\n ) {\n super(`Resource ${resourceId} is corrupted: ${reason}`);\n this.name = 'ResourceCorruptedError';\n }\n}\n\n/**\n * Error thrown when OPFS quota is exceeded\n * Used for project-level LRU eviction coordination\n */\nexport class OPFSQuotaExceededError extends Error {\n constructor(\n public readonly projectId: string,\n public readonly prefix: string,\n public readonly retryable: boolean\n ) {\n super(\n `OPFS quota exceeded for ${prefix}-${projectId}. ` +\n (retryable ? 'Old projects evicted, please retry.' : 'No space available.')\n );\n this.name = 'OPFSQuotaExceededError';\n }\n}\n\n/**\n * Error thrown when browser doesn't meet minimum requirements\n */\nexport class BrowserCompatibilityError extends Error {\n constructor(\n public readonly compatibility: {\n webCodecsAvailable: boolean;\n opfsAvailable: boolean;\n missingFeatures: string[];\n browserInfo: { name: string; version: string; recommended: string };\n }\n ) {\n const { browserInfo, missingFeatures } = compatibility;\n\n super(\n `Browser not supported: ${browserInfo.name} ${browserInfo.version}. ` +\n `Required: ${browserInfo.recommended}. ` +\n `Missing: ${missingFeatures.join(', ')}`\n );\n\n this.name = 'BrowserCompatibilityError';\n }\n}\n"],"names":[],"mappings":"AAQO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YAA4B,QAAgB;AAC1C,UAAM,mBAAmB,MAAM,iCAAiC;AADtC,SAAA,SAAA;AAE1B,SAAK,OAAO;AAAA,EACd;AACF;AAMO,MAAM,yBAAyB,MAAM;AAAA,EAC1C,YACkB,YACA,YAChB;AACA;AAAA,MACE,sCAAsC,UAAU,kBAC9B,UAAU;AAAA,IAAA;AALd,SAAA,aAAA;AACA,SAAA,aAAA;AAMhB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,MAAM,+BAA+B,MAAM;AAAA,EAChD,YACkB,YACA,QAChB;AACA,UAAM,YAAY,UAAU,kBAAkB,MAAM,EAAE;AAHtC,SAAA,aAAA;AACA,SAAA,SAAA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAMO,MAAM,+BAA+B,MAAM;AAAA,EAChD,YACkB,WACA,QACA,WAChB;AACA;AAAA,MACE,2BAA2B,MAAM,IAAI,SAAS,QAC3C,YAAY,wCAAwC;AAAA,IAAA;AANzC,SAAA,YAAA;AACA,SAAA,SAAA;AACA,SAAA,YAAA;AAMhB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,MAAM,kCAAkC,MAAM;AAAA,EACnD,YACkB,eAMhB;AACA,UAAM,EAAE,aAAa,gBAAA,IAAoB;AAEzC;AAAA,MACE,0BAA0B,YAAY,IAAI,IAAI,YAAY,OAAO,eAClD,YAAY,WAAW,cACxB,gBAAgB,KAAK,IAAI,CAAC;AAAA,IAAA;AAZ1B,SAAA,gBAAA;AAehB,SAAK,OAAO;AAAA,EACd;AACF;"}
|
|
1
|
+
{"version":3,"file":"errors.js","sources":["../../src/utils/errors.ts"],"sourcesContent":["/**\n * Custom error types for Meframe\n */\n\n/**\n * Error thrown when a clip ready waiter is replaced by a newer one\n * This happens during rapid seeks and should be ignored by callers\n */\nexport class WaiterReplacedError extends Error {\n constructor(public readonly clipId: string) {\n super(`Waiter for clip ${clipId} was replaced by a newer waiter`);\n this.name = 'WaiterReplacedError';\n }\n}\n\n/**\n * Error thrown when reading an empty or incomplete OPFS file\n * Usually indicates a race condition between write and read operations\n */\nexport class EmptyStreamError extends Error {\n constructor(\n public readonly resourceId: string,\n public readonly fileOffset: number\n ) {\n super(\n `Empty stream received for resource ${resourceId}. ` +\n `File offset: ${fileOffset}. This indicates the file is being written or is corrupted.`\n );\n this.name = 'EmptyStreamError';\n }\n}\n\n/**\n * Error thrown when a cached resource file is corrupted or incomplete\n */\nexport class ResourceCorruptedError extends Error {\n constructor(\n public readonly resourceId: string,\n public readonly reason: string\n ) {\n super(`Resource ${resourceId} is corrupted: ${reason}`);\n this.name = 'ResourceCorruptedError';\n }\n}\n\n/**\n * Error thrown when OPFS quota is exceeded\n * Used for project-level LRU eviction coordination\n */\nexport class OPFSQuotaExceededError extends Error {\n constructor(\n public readonly projectId: string,\n public readonly prefix: string,\n public readonly retryable: boolean\n ) {\n super(\n `OPFS quota exceeded for ${prefix}-${projectId}. ` +\n (retryable ? 'Old projects evicted, please retry.' : 'No space available.')\n );\n this.name = 'OPFSQuotaExceededError';\n }\n}\n\n/**\n * Error thrown when browser doesn't meet minimum requirements\n */\nexport class BrowserCompatibilityError extends Error {\n constructor(\n public readonly compatibility: {\n webCodecsAvailable: boolean;\n opfsAvailable: boolean;\n missingFeatures: string[];\n browserInfo: { name: string; version: string; recommended: string };\n }\n ) {\n const { browserInfo, missingFeatures } = compatibility;\n\n super(\n `Browser not supported: ${browserInfo.name} ${browserInfo.version}. ` +\n `Required: ${browserInfo.recommended}. ` +\n `Missing: ${missingFeatures.join(', ')}`\n );\n\n this.name = 'BrowserCompatibilityError';\n }\n}\n\nexport function isDOMException(error: unknown, name: string): boolean {\n return error instanceof Error && 'name' in error && error.name === name;\n}\n"],"names":[],"mappings":"AAQO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YAA4B,QAAgB;AAC1C,UAAM,mBAAmB,MAAM,iCAAiC;AADtC,SAAA,SAAA;AAE1B,SAAK,OAAO;AAAA,EACd;AACF;AAMO,MAAM,yBAAyB,MAAM;AAAA,EAC1C,YACkB,YACA,YAChB;AACA;AAAA,MACE,sCAAsC,UAAU,kBAC9B,UAAU;AAAA,IAAA;AALd,SAAA,aAAA;AACA,SAAA,aAAA;AAMhB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,MAAM,+BAA+B,MAAM;AAAA,EAChD,YACkB,YACA,QAChB;AACA,UAAM,YAAY,UAAU,kBAAkB,MAAM,EAAE;AAHtC,SAAA,aAAA;AACA,SAAA,SAAA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAMO,MAAM,+BAA+B,MAAM;AAAA,EAChD,YACkB,WACA,QACA,WAChB;AACA;AAAA,MACE,2BAA2B,MAAM,IAAI,SAAS,QAC3C,YAAY,wCAAwC;AAAA,IAAA;AANzC,SAAA,YAAA;AACA,SAAA,SAAA;AACA,SAAA,YAAA;AAMhB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,MAAM,kCAAkC,MAAM;AAAA,EACnD,YACkB,eAMhB;AACA,UAAM,EAAE,aAAa,gBAAA,IAAoB;AAEzC;AAAA,MACE,0BAA0B,YAAY,IAAI,IAAI,YAAY,OAAO,eAClD,YAAY,WAAW,cACxB,gBAAgB,KAAK,IAAI,CAAC;AAAA,IAAA;AAZ1B,SAAA,gBAAA;AAehB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,SAAS,eAAe,OAAgB,MAAuB;AACpE,SAAO,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS;AACrE;"}
|
package/dist/utils/mp4box.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as mp4box_all from "../
|
|
1
|
+
import * as mp4box_all from "../node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js";
|
|
2
2
|
const lib = mp4box_all;
|
|
3
3
|
const MP4Box = lib.default && typeof lib.default.createFile === "function" ? lib.default : lib;
|
|
4
4
|
if (typeof MP4Box.createFile !== "function") {
|