@meframe/server 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cjs/ServerExporterBase.js +41 -4
- package/dist/cjs/ServerExporterBase.js.map +1 -1
- package/dist/cjs/utils/http-cors.js +24 -0
- package/dist/cjs/utils/http-cors.js.map +1 -0
- package/dist/cjs/utils/local-spool-server.js +19 -28
- package/dist/cjs/utils/local-spool-server.js.map +1 -1
- package/dist/cjs/utils/local-worker-server.js +93 -0
- package/dist/cjs/utils/local-worker-server.js.map +1 -0
- package/dist/cjs/utils/resolve-core-workers.js +51 -0
- package/dist/cjs/utils/resolve-core-workers.js.map +1 -0
- package/dist/esm/ServerExporterBase.d.ts.map +1 -1
- package/dist/esm/ServerExporterBase.js +41 -4
- package/dist/esm/ServerExporterBase.js.map +1 -1
- package/dist/esm/types.d.ts +33 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/utils/http-cors.d.ts +8 -0
- package/dist/esm/utils/http-cors.d.ts.map +1 -0
- package/dist/esm/utils/http-cors.js +21 -0
- package/dist/esm/utils/http-cors.js.map +1 -0
- package/dist/esm/utils/local-spool-server.d.ts.map +1 -1
- package/dist/esm/utils/local-spool-server.js +19 -28
- package/dist/esm/utils/local-spool-server.js.map +1 -1
- package/dist/esm/utils/local-worker-server.d.ts +15 -0
- package/dist/esm/utils/local-worker-server.d.ts.map +1 -0
- package/dist/esm/utils/local-worker-server.js +87 -0
- package/dist/esm/utils/local-worker-server.js.map +1 -0
- package/dist/esm/utils/resolve-core-workers.d.ts +2 -0
- package/dist/esm/utils/resolve-core-workers.d.ts.map +1 -0
- package/dist/esm/utils/resolve-core-workers.js +12 -0
- package/dist/esm/utils/resolve-core-workers.js.map +1 -0
- package/dist/runner-browser/runner.mjs +88 -85
- package/docs/INTEGRATION.md +7 -0
- package/package.json +2 -2
|
@@ -1296,7 +1296,7 @@ class Qs {
|
|
|
1296
1296
|
this.port.onmessage = h;
|
|
1297
1297
|
}
|
|
1298
1298
|
}
|
|
1299
|
-
var
|
|
1299
|
+
var O = /* @__PURE__ */ ((a) => (a.ModelSet = "model:set", a.ResourceAdd = "resource:add", a.ResourceUpdate = "resource:update", a.ResourceRemove = "resource:remove", a.ResourceStageChange = "resource:state", a.ResourceFirstFrameReady = "resource:firstFrameReady", a.LoadStart = "load:start", a.LoadProgress = "load:progress", a.LoadComplete = "load:complete", a.LoadError = "load:error", a.DemuxStart = "demux:start", a.DemuxProgress = "demux:progress", a.DemuxComplete = "demux:complete", a.DemuxError = "demux:error", a.DecodeStart = "decode:start", a.DecodeProgress = "decode:progress", a.DecodeComplete = "decode:complete", a.DecodeError = "decode:error", a.ComposeStart = "compose:start", a.ComposeProgress = "compose:progress", a.ComposeComplete = "compose:complete", a.ComposeFrameReady = "compose:frameReady", a.ComposeFrameDropped = "compose:frameDropped", a.EncodeChunkReady = "encode:chunkReady", a.EncodeChunkError = "encode:chunkError", a.CacheHit = "cache:hit", a.CacheMiss = "cache:miss", a.CacheEvict = "cache:evict", a.CacheWrite = "cache:write", a.CacheCover = "cache:cover", a.ExportPreparing = "export:preparing", a.ExportStart = "export:start", a.ExportProgress = "export:progress", a.ExportComplete = "export:complete", a.ExportError = "export:error", a.CompositionUpdated = "composition:updated", a.PatchApplied = "patch:applied", a.Ready = "ready", a.WorkerStarted = "worker:started", a.WorkerReady = "worker:ready", a.WorkerError = "worker:error", a.WorkerRestarted = "worker:restarted", a.PlaybackBuffering = "playback:buffering", a.PlaybackPlay = "playback:play", a.PlaybackPause = "playback:pause", a.PlaybackStop = "playback:stop", a.PlaybackSeek = "playback:seek", a.PlaybackEnded = "playback:ended", a.PlaybackTimeUpdate = "playback:timeupdate", a.PlaybackRateChange = "playback:ratechange", a.PlaybackVolumeChange = "playback:volumechange", a.PlaybackError = "playback:error", a.PlaybackStarted = "playback:started", a.PlaybackPaused = "playback:paused", a.PlaybackSeeked = "playback:seeked", a.Error = "error", a.PluginLoaded = "plugin:loaded", a.PluginError = "plugin:error", a.PluginUnloaded = "plugin:unloaded", a.ClipActivated = "clip:activated", a.ClipDeactivated = "clip:deactivated", a))(O || {});
|
|
1300
1300
|
class Xs {
|
|
1301
1301
|
worker;
|
|
1302
1302
|
channel;
|
|
@@ -1314,7 +1314,7 @@ class Xs {
|
|
|
1314
1314
|
}
|
|
1315
1315
|
setupErrorHandling() {
|
|
1316
1316
|
this.worker.onerror = (e) => {
|
|
1317
|
-
this.state = "error", this.lastError = new Error(e.message || "Worker error"), this.onError?.(this.lastError), this.eventBus.emit(
|
|
1317
|
+
this.state = "error", this.lastError = new Error(e.message || "Worker error"), this.onError?.(this.lastError), this.eventBus.emit(O.WorkerError, {
|
|
1318
1318
|
type: this.type,
|
|
1319
1319
|
workerId: this.getWorkerId(),
|
|
1320
1320
|
error: this.lastError
|
|
@@ -1322,13 +1322,13 @@ class Xs {
|
|
|
1322
1322
|
};
|
|
1323
1323
|
}
|
|
1324
1324
|
async initialize(e) {
|
|
1325
|
-
this.eventBus.emit(
|
|
1325
|
+
this.eventBus.emit(O.WorkerStarted, {
|
|
1326
1326
|
type: this.type,
|
|
1327
1327
|
workerId: this.getWorkerId()
|
|
1328
1328
|
}), await this.channel.send(mt.Configure, {
|
|
1329
1329
|
config: e,
|
|
1330
1330
|
initial: !0
|
|
1331
|
-
}), this.eventBus.emit(
|
|
1331
|
+
}), this.eventBus.emit(O.WorkerReady, {
|
|
1332
1332
|
type: this.type,
|
|
1333
1333
|
workerId: this.getWorkerId()
|
|
1334
1334
|
});
|
|
@@ -6166,7 +6166,7 @@ class Ir {
|
|
|
6166
6166
|
const l = new kr(), u = h ? this.shouldExtractCover(h) : !1, o = await l.parseFromStream(s, {
|
|
6167
6167
|
resourceId: r,
|
|
6168
6168
|
onFirstFrameReady: u ? async (p, m) => {
|
|
6169
|
-
p.resourceId = r, this.cacheManager.mp4IndexCache.set(r, p), this.eventBus?.emit(
|
|
6169
|
+
p.resourceId = r, this.cacheManager.mp4IndexCache.set(r, p), this.eventBus?.emit(O.ResourceFirstFrameReady, {
|
|
6170
6170
|
resourceId: r,
|
|
6171
6171
|
clipId: h,
|
|
6172
6172
|
index: p,
|
|
@@ -6224,8 +6224,8 @@ class Ir {
|
|
|
6224
6224
|
const h = this.model?.resources.get(e);
|
|
6225
6225
|
if (h) {
|
|
6226
6226
|
const l = h.state;
|
|
6227
|
-
h.state = s, s === "error" ? h.error = r : h.error = void 0, this.eventBus?.emit(
|
|
6228
|
-
type:
|
|
6227
|
+
h.state = s, s === "error" ? h.error = r : h.error = void 0, this.eventBus?.emit(O.ResourceStageChange, {
|
|
6228
|
+
type: O.ResourceStageChange,
|
|
6229
6229
|
resourceId: e,
|
|
6230
6230
|
oldState: l,
|
|
6231
6231
|
newState: s
|
|
@@ -7365,12 +7365,12 @@ class Nr {
|
|
|
7365
7365
|
*/
|
|
7366
7366
|
addFrame(e, s, r, h, l) {
|
|
7367
7367
|
const u = this.videoL1Cache.addFrame(e, s, r, h, l), o = e.timestamp ?? 0;
|
|
7368
|
-
return this.checkAndNotifyClipReady(s, o), l === 0 && this.eventBus?.emit(
|
|
7368
|
+
return this.checkAndNotifyClipReady(s, o), l === 0 && this.eventBus?.emit(O.CacheCover, {
|
|
7369
7369
|
timeUs: l,
|
|
7370
7370
|
clipId: s,
|
|
7371
7371
|
level: "L1",
|
|
7372
7372
|
size: u.sizeEstimate ?? 0
|
|
7373
|
-
}), this.eventBus?.emit(
|
|
7373
|
+
}), this.eventBus?.emit(O.ComposeFrameReady, {
|
|
7374
7374
|
timeUs: l,
|
|
7375
7375
|
frameNumber: Math.floor(l / r),
|
|
7376
7376
|
renderTimeMs: 0,
|
|
@@ -8448,7 +8448,7 @@ class vn {
|
|
|
8448
8448
|
if (!ei(u))
|
|
8449
8449
|
throw new Error(`Clip ${u.id} in audio track is not an audio clip`);
|
|
8450
8450
|
if (this.deps.cacheManager.audioSampleCache.has(u.resourceId)) {
|
|
8451
|
-
this.activeClips.add(u.id), this.deps.eventBus.emit(
|
|
8451
|
+
this.activeClips.add(u.id), this.deps.eventBus.emit(O.ClipActivated, { clipId: u.id });
|
|
8452
8452
|
continue;
|
|
8453
8453
|
}
|
|
8454
8454
|
try {
|
|
@@ -8462,7 +8462,7 @@ class vn {
|
|
|
8462
8462
|
continue;
|
|
8463
8463
|
throw o;
|
|
8464
8464
|
}
|
|
8465
|
-
this.activeClips.add(u.id), this.deps.eventBus.emit(
|
|
8465
|
+
this.activeClips.add(u.id), this.deps.eventBus.emit(O.ClipActivated, { clipId: u.id });
|
|
8466
8466
|
}
|
|
8467
8467
|
}
|
|
8468
8468
|
}
|
|
@@ -11442,7 +11442,7 @@ class zo {
|
|
|
11442
11442
|
await new Promise((T) => setTimeout(T, 100));
|
|
11443
11443
|
}
|
|
11444
11444
|
}, x = s.width || e.renderConfig?.width || 720, C = s.height || e.renderConfig?.height || 1280, v = s.fps || e.fps || 30;
|
|
11445
|
-
l.emit(
|
|
11445
|
+
l.emit(O.ExportStart, {
|
|
11446
11446
|
format: s.format || "mp4",
|
|
11447
11447
|
width: x,
|
|
11448
11448
|
height: C,
|
|
@@ -11456,7 +11456,7 @@ class zo {
|
|
|
11456
11456
|
requestedFormat: s.format ?? "mp4",
|
|
11457
11457
|
requestedAudioCodec: s.audioCodec ?? "aac"
|
|
11458
11458
|
});
|
|
11459
|
-
n && l.emit(
|
|
11459
|
+
n && l.emit(O.ExportProgress, {
|
|
11460
11460
|
progress: 0.4,
|
|
11461
11461
|
stage: "encoding",
|
|
11462
11462
|
message: n
|
|
@@ -11481,7 +11481,7 @@ class zo {
|
|
|
11481
11481
|
try {
|
|
11482
11482
|
await f;
|
|
11483
11483
|
} catch (y) {
|
|
11484
|
-
l.emit(
|
|
11484
|
+
l.emit(O.ExportProgress, {
|
|
11485
11485
|
progress: 0.95,
|
|
11486
11486
|
stage: "encoding",
|
|
11487
11487
|
message: `Audio skipped (runtime failure): ${y instanceof Error ? y.message : String(y)}`
|
|
@@ -11492,16 +11492,16 @@ class zo {
|
|
|
11492
11492
|
if (await h.finalizeExportAudio(), o?.aborted)
|
|
11493
11493
|
throw new DOMException("Export aborted", "AbortError");
|
|
11494
11494
|
const d = await r.finalize();
|
|
11495
|
-
return l.emit(
|
|
11495
|
+
return l.emit(O.ExportComplete, {
|
|
11496
11496
|
size: d?.size ?? g,
|
|
11497
11497
|
durationMs: e.durationUs / 1e3,
|
|
11498
11498
|
format: s.format || "mp4"
|
|
11499
|
-
}), l.emit(
|
|
11499
|
+
}), l.emit(O.ExportProgress, {
|
|
11500
11500
|
progress: 1,
|
|
11501
11501
|
stage: "muxing"
|
|
11502
11502
|
}), d;
|
|
11503
11503
|
} catch (T) {
|
|
11504
|
-
throw l.emit(
|
|
11504
|
+
throw l.emit(O.ExportError, {
|
|
11505
11505
|
error: T instanceof Error ? T : new Error(String(T)),
|
|
11506
11506
|
stage: "export"
|
|
11507
11507
|
}), T;
|
|
@@ -11513,7 +11513,7 @@ class zo {
|
|
|
11513
11513
|
* Preload all resources (0-40% progress)
|
|
11514
11514
|
*/
|
|
11515
11515
|
async preloadResources(e, s, r, h) {
|
|
11516
|
-
r.emit(
|
|
11516
|
+
r.emit(O.ExportProgress, {
|
|
11517
11517
|
progress: 0,
|
|
11518
11518
|
stage: "preparing",
|
|
11519
11519
|
message: "Loading and parsing resources..."
|
|
@@ -11538,7 +11538,7 @@ class zo {
|
|
|
11538
11538
|
}
|
|
11539
11539
|
g++;
|
|
11540
11540
|
const C = m > 0 ? g / m * 0.4 : 0.4;
|
|
11541
|
-
r.emit(
|
|
11541
|
+
r.emit(O.ExportProgress, {
|
|
11542
11542
|
progress: C,
|
|
11543
11543
|
stage: "preparing",
|
|
11544
11544
|
message: `Loading resources... (${g}/${m})`
|
|
@@ -11601,7 +11601,7 @@ class zo {
|
|
|
11601
11601
|
});
|
|
11602
11602
|
s.writeVideoChunk(U, y), u = k + _;
|
|
11603
11603
|
const I = 0.4 + k / r.durationUs * 0.6;
|
|
11604
|
-
this.deps.eventBus.emit(
|
|
11604
|
+
this.deps.eventBus.emit(O.ExportProgress, {
|
|
11605
11605
|
progress: Math.min(1, I),
|
|
11606
11606
|
stage: "encoding",
|
|
11607
11607
|
timeUs: k
|
|
@@ -11709,7 +11709,7 @@ class Oo {
|
|
|
11709
11709
|
}), this.setupResourceFirstFrameHandler();
|
|
11710
11710
|
}
|
|
11711
11711
|
setupResourceFirstFrameHandler() {
|
|
11712
|
-
this.eventBus.on(
|
|
11712
|
+
this.eventBus.on(O.ResourceFirstFrameReady, async (e) => {
|
|
11713
11713
|
const { resourceId: s, clipId: r, index: h, chunks: l } = e;
|
|
11714
11714
|
if (!this.compositionModel) return;
|
|
11715
11715
|
const u = this.compositionModel.findClip(r);
|
|
@@ -11745,7 +11745,7 @@ class Oo {
|
|
|
11745
11745
|
async setCompositionModel(e) {
|
|
11746
11746
|
this.cacheManager.clear(), this.cancelActiveDecoding(), this.audio.preview.stopPlayback(), this.audio.preview.invalidatePreviewMixCache(), this.modelToken++, this.compositionModel = e, this.planner.setModel(e);
|
|
11747
11747
|
const s = this.resourceLoader.setModel(e);
|
|
11748
|
-
this.audio.prepare.setModel(e), await s, this.eventBus.emit(
|
|
11748
|
+
this.audio.prepare.setModel(e), await s, this.eventBus.emit(O.ModelSet, e), this.eventBus.emit(O.CompositionUpdated, {
|
|
11749
11749
|
trackCount: e.tracks.length,
|
|
11750
11750
|
clipCount: e.tracks.reduce((r, h) => r + h.clips.length, 0),
|
|
11751
11751
|
durationUs: e.durationUs
|
|
@@ -11755,7 +11755,7 @@ class Oo {
|
|
|
11755
11755
|
if (!this.compositionModel)
|
|
11756
11756
|
throw new Error("No composition model set");
|
|
11757
11757
|
const s = tr(this.compositionModel, e);
|
|
11758
|
-
this.planner.applyPatch(e, s), this.eventBus.emit(
|
|
11758
|
+
this.planner.applyPatch(e, s), this.eventBus.emit(O.PatchApplied, {
|
|
11759
11759
|
operations: e.operations.length,
|
|
11760
11760
|
affectedClips: Array.from(s)
|
|
11761
11761
|
});
|
|
@@ -12083,7 +12083,7 @@ class Oo {
|
|
|
12083
12083
|
return l;
|
|
12084
12084
|
}
|
|
12085
12085
|
}
|
|
12086
|
-
var
|
|
12086
|
+
var z = /* @__PURE__ */ ((a) => (a.Idle = "idle", a.Buffering = "buffering", a.Playing = "playing", a.Paused = "paused", a.Seeking = "seeking", a.Ended = "ended", a))(z || {});
|
|
12087
12087
|
const j = {
|
|
12088
12088
|
Play: "play",
|
|
12089
12089
|
Pause: "pause",
|
|
@@ -13282,7 +13282,7 @@ class Jo {
|
|
|
13282
13282
|
}
|
|
13283
13283
|
}
|
|
13284
13284
|
class ea {
|
|
13285
|
-
state =
|
|
13285
|
+
state = z.Idle;
|
|
13286
13286
|
wantsPlay = !1;
|
|
13287
13287
|
frozenTimeUs = null;
|
|
13288
13288
|
token = 0;
|
|
@@ -13309,13 +13309,13 @@ class ea {
|
|
|
13309
13309
|
};
|
|
13310
13310
|
switch (e.type) {
|
|
13311
13311
|
case j.ModelSet:
|
|
13312
|
-
return h(), r.push({ type: P.CancelRaf }), r.push({ type: P.StopAudio }), r.push({ type: P.SetLastAudioScheduleTime, timeUs: 0 }), o(null), (this.state ===
|
|
13312
|
+
return h(), r.push({ type: P.CancelRaf }), r.push({ type: P.StopAudio }), r.push({ type: P.SetLastAudioScheduleTime, timeUs: 0 }), o(null), (this.state === z.Playing || this.state === z.Buffering || this.state === z.Seeking) && l(z.Paused), { token: this.token, commands: r };
|
|
13313
13313
|
case j.Play: {
|
|
13314
13314
|
const g = h(), w = this.state;
|
|
13315
|
-
if (u(!0), this.state ===
|
|
13315
|
+
if (u(!0), this.state === z.Ended && p(0), this.state === z.Playing)
|
|
13316
13316
|
return { token: g, commands: r };
|
|
13317
|
-
l(
|
|
13318
|
-
const x = w ===
|
|
13317
|
+
l(z.Playing), o(null), r.push({ type: P.SetLastAudioScheduleTime, timeUs: 0 }), r.push({ type: P.CancelRaf });
|
|
13318
|
+
const x = w === z.Idle || w === z.Ended ? z.Idle : z.Paused;
|
|
13319
13319
|
return r.push({
|
|
13320
13320
|
type: P.Try,
|
|
13321
13321
|
logPrefix: "[PlaybackController] Failed to start playback:",
|
|
@@ -13335,7 +13335,7 @@ class ea {
|
|
|
13335
13335
|
{ type: P.StartAudioPlayback, timeUs: s.currentTimeUs },
|
|
13336
13336
|
{ type: P.SyncTimeBaseToAudioClock, timeUs: s.currentTimeUs },
|
|
13337
13337
|
{ type: P.StartRafLoop },
|
|
13338
|
-
{ type: P.Emit, event:
|
|
13338
|
+
{ type: P.Emit, event: O.PlaybackPlay }
|
|
13339
13339
|
]
|
|
13340
13340
|
}
|
|
13341
13341
|
}), { token: g, commands: r };
|
|
@@ -13343,13 +13343,13 @@ class ea {
|
|
|
13343
13343
|
case j.Pause: {
|
|
13344
13344
|
h();
|
|
13345
13345
|
const g = this.state;
|
|
13346
|
-
return u(!1), o(null), r.push({ type: P.CancelRaf }), r.push({ type: P.StopAudio }), g !==
|
|
13346
|
+
return u(!1), o(null), r.push({ type: P.CancelRaf }), r.push({ type: P.StopAudio }), g !== z.Idle && g !== z.Ended && l(z.Paused), (g === z.Playing || g === z.Buffering || g === z.Seeking) && r.push({ type: P.Emit, event: O.PlaybackPause }), { token: this.token, commands: r };
|
|
13347
13347
|
}
|
|
13348
13348
|
case j.Stop:
|
|
13349
|
-
return h(), u(!1), o(null), l(
|
|
13349
|
+
return h(), u(!1), o(null), l(z.Idle), p(0), r.push({ type: P.CancelRaf }), r.push({ type: P.StopAudio }), r.push({ type: P.ClearCanvas }), r.push({ type: P.ResetAudioSession }), r.push({ type: P.ResetAudioPlaybackStates }), r.push({ type: P.SetLastAudioScheduleTime, timeUs: 0 }), r.push({ type: P.Emit, event: O.PlaybackStop }), { token: this.token, commands: r };
|
|
13350
13350
|
case j.Seek: {
|
|
13351
13351
|
const g = h(), w = this.state, x = m(e.timeUs, e.durationUs);
|
|
13352
|
-
return p(x), o(x), l(
|
|
13352
|
+
return p(x), o(x), l(z.Seeking), r.push({ type: P.CancelRaf }), r.push({ type: P.StopAudio }), r.push({ type: P.SetLastAudioScheduleTime, timeUs: 0 }), r.push({
|
|
13353
13353
|
type: P.Try,
|
|
13354
13354
|
logPrefix: "[PlaybackController] Seek error:",
|
|
13355
13355
|
emitPlaybackError: !0,
|
|
@@ -13380,7 +13380,7 @@ class ea {
|
|
|
13380
13380
|
}), { token: g, commands: r };
|
|
13381
13381
|
}
|
|
13382
13382
|
case j.EnterBuffering:
|
|
13383
|
-
return (e.bumpToken ?? !1) && h(), this.state !==
|
|
13383
|
+
return (e.bumpToken ?? !1) && h(), this.state !== z.Playing ? { token: this.token, commands: r } : (o(e.timeUs), l(z.Buffering), r.push({ type: P.Emit, event: O.PlaybackBuffering }), r.push({ type: P.CancelRaf }), r.push({ type: P.StopAudio }), r.push({
|
|
13384
13384
|
type: P.Try,
|
|
13385
13385
|
logPrefix: "[PlaybackController] Buffering error:",
|
|
13386
13386
|
emitPlaybackError: !0,
|
|
@@ -13409,11 +13409,11 @@ class ea {
|
|
|
13409
13409
|
}
|
|
13410
13410
|
}), { token: this.token, commands: r });
|
|
13411
13411
|
case j.BufferingResolved:
|
|
13412
|
-
return this.state !==
|
|
13412
|
+
return this.state !== z.Buffering ? { token: this.token, commands: r } : (o(null), this.wantsPlay ? (l(z.Playing), r.push({
|
|
13413
13413
|
type: P.Try,
|
|
13414
13414
|
logPrefix: "[PlaybackController] Failed to start playback:",
|
|
13415
13415
|
emitPlaybackError: !0,
|
|
13416
|
-
onError: { type: j.StartFailed, fallbackState:
|
|
13416
|
+
onError: { type: j.StartFailed, fallbackState: z.Paused },
|
|
13417
13417
|
command: {
|
|
13418
13418
|
type: P.Seq,
|
|
13419
13419
|
commands: [
|
|
@@ -13422,20 +13422,20 @@ class ea {
|
|
|
13422
13422
|
{ type: P.StartAudioPlayback, timeUs: e.timeUs },
|
|
13423
13423
|
{ type: P.SyncTimeBaseToAudioClock, timeUs: e.timeUs },
|
|
13424
13424
|
{ type: P.StartRafLoop },
|
|
13425
|
-
{ type: P.Emit, event:
|
|
13425
|
+
{ type: P.Emit, event: O.PlaybackPlay }
|
|
13426
13426
|
]
|
|
13427
13427
|
}
|
|
13428
|
-
})) : l(
|
|
13428
|
+
})) : l(z.Paused), { token: this.token, commands: r });
|
|
13429
13429
|
case j.SeekResolved:
|
|
13430
|
-
return this.state !==
|
|
13430
|
+
return this.state !== z.Seeking ? { token: this.token, commands: r } : (o(null), r.push({
|
|
13431
13431
|
type: P.Emit,
|
|
13432
|
-
event:
|
|
13432
|
+
event: O.PlaybackSeek,
|
|
13433
13433
|
payload: { timeUs: s.currentTimeUs }
|
|
13434
|
-
}), this.wantsPlay ? (l(
|
|
13434
|
+
}), this.wantsPlay ? (l(z.Playing), r.push({
|
|
13435
13435
|
type: P.Try,
|
|
13436
13436
|
logPrefix: "[PlaybackController] Failed to start playback:",
|
|
13437
13437
|
emitPlaybackError: !0,
|
|
13438
|
-
onError: { type: j.StartFailed, fallbackState:
|
|
13438
|
+
onError: { type: j.StartFailed, fallbackState: z.Paused },
|
|
13439
13439
|
command: {
|
|
13440
13440
|
type: P.Seq,
|
|
13441
13441
|
commands: [
|
|
@@ -13448,16 +13448,16 @@ class ea {
|
|
|
13448
13448
|
{ type: P.StartAudioPlayback, timeUs: s.currentTimeUs },
|
|
13449
13449
|
{ type: P.SyncTimeBaseToAudioClock, timeUs: s.currentTimeUs },
|
|
13450
13450
|
{ type: P.StartRafLoop },
|
|
13451
|
-
{ type: P.Emit, event:
|
|
13451
|
+
{ type: P.Emit, event: O.PlaybackPlay }
|
|
13452
13452
|
]
|
|
13453
13453
|
}
|
|
13454
13454
|
})) : l(
|
|
13455
|
-
e.previousState ===
|
|
13455
|
+
e.previousState === z.Idle ? z.Idle : z.Paused
|
|
13456
13456
|
), { token: this.token, commands: r });
|
|
13457
13457
|
case j.StartFailed:
|
|
13458
13458
|
return u(!1), o(null), l(e.fallbackState), r.push({ type: P.CancelRaf }), r.push({ type: P.StopAudio }), r.push({ type: P.SetLastAudioScheduleTime, timeUs: 0 }), { token: this.token, commands: r };
|
|
13459
13459
|
case j.ClockTick: {
|
|
13460
|
-
if (this.state !==
|
|
13460
|
+
if (this.state !== z.Playing)
|
|
13461
13461
|
return { token: this.token, commands: r };
|
|
13462
13462
|
if (this.frozenTimeUs !== null)
|
|
13463
13463
|
return { token: this.token, commands: r };
|
|
@@ -13465,13 +13465,13 @@ class ea {
|
|
|
13465
13465
|
return g >= e.durationUs ? (e.loop ? (p(0), r.push({
|
|
13466
13466
|
type: P.SetStartTimeBase,
|
|
13467
13467
|
startTimeUs: e.audioNowUs
|
|
13468
|
-
}), r.push({ type: P.ResetAudioPlaybackStates }), r.push({ type: P.SetLastAudioScheduleTime, timeUs: 0 }), r.push({ type: P.InitWindow, timeUs: 0 })) : (u(!1), l(
|
|
13468
|
+
}), r.push({ type: P.ResetAudioPlaybackStates }), r.push({ type: P.SetLastAudioScheduleTime, timeUs: 0 }), r.push({ type: P.InitWindow, timeUs: 0 })) : (u(!1), l(z.Ended), r.push({ type: P.CancelRaf }), r.push({ type: P.StopAudio }), p(0), r.push({
|
|
13469
13469
|
type: P.Emit,
|
|
13470
|
-
event:
|
|
13470
|
+
event: O.PlaybackEnded,
|
|
13471
13471
|
payload: { timeUs: e.durationUs }
|
|
13472
13472
|
})), { token: this.token, commands: r }) : (p(g), r.push({
|
|
13473
13473
|
type: P.Emit,
|
|
13474
|
-
event:
|
|
13474
|
+
event: O.PlaybackTimeUpdate,
|
|
13475
13475
|
payload: { timeUs: g }
|
|
13476
13476
|
}), { token: this.token, commands: r });
|
|
13477
13477
|
}
|
|
@@ -13511,8 +13511,11 @@ class ta {
|
|
|
13511
13511
|
seekFlushRafId = null;
|
|
13512
13512
|
seekInFlight = null;
|
|
13513
13513
|
// If user drags far away while a seek is decoding, cancel it to avoid visible lag.
|
|
13514
|
-
SEEK_CANCEL_DISTANCE_US =
|
|
13515
|
-
//
|
|
13514
|
+
SEEK_CANCEL_DISTANCE_US = 5e6;
|
|
13515
|
+
// 5s
|
|
13516
|
+
isSeekActive() {
|
|
13517
|
+
return this.pendingSeekTimeUs !== null || this.seekInFlight !== null || this.fsm.snapshot.state === z.Seeking;
|
|
13518
|
+
}
|
|
13516
13519
|
// Unified window management for both video and audio
|
|
13517
13520
|
windowEnd = 0;
|
|
13518
13521
|
WINDOW_DURATION = 3e6;
|
|
@@ -13575,25 +13578,25 @@ class ta {
|
|
|
13575
13578
|
this.seekInFlight = { targetUs: e, done: s }, s.finally(() => {
|
|
13576
13579
|
const r = this.pendingSeekWaiters;
|
|
13577
13580
|
this.pendingSeekWaiters = [];
|
|
13578
|
-
for (const
|
|
13579
|
-
this.seekInFlight?.targetUs === e && (this.seekInFlight = null), this.pendingSeekTimeUs === null && !this.orchestrator.cacheManager.isExporting && this.preheatNextWindow(), this.pendingSeekTimeUs !== null && this.seekFlushRafId === null && (this.seekFlushRafId = requestAnimationFrame(() => {
|
|
13581
|
+
for (const l of r) l();
|
|
13582
|
+
this.seekInFlight?.targetUs === e && (this.seekInFlight = null), this.pendingSeekTimeUs === null && !this.orchestrator.cacheManager.isExporting && this.fsm.snapshot.state === z.Playing && this.preheatNextWindow(), this.pendingSeekTimeUs !== null && this.seekFlushRafId === null && (this.seekFlushRafId = requestAnimationFrame(() => {
|
|
13580
13583
|
this.seekFlushRafId = null, this.flushCoalescedSeek();
|
|
13581
13584
|
}));
|
|
13582
13585
|
});
|
|
13583
13586
|
}
|
|
13584
13587
|
setRate(e) {
|
|
13585
13588
|
const s = this.currentTimeUs;
|
|
13586
|
-
this.playbackRate = e, this.startTimeUs = this.audioContext.currentTime * 1e6 - s / e, this.audioSession.setPlaybackRate(this.playbackRate), this.eventBus.emit(
|
|
13589
|
+
this.playbackRate = e, this.startTimeUs = this.audioContext.currentTime * 1e6 - s / e, this.audioSession.setPlaybackRate(this.playbackRate), this.eventBus.emit(O.PlaybackRateChange, { rate: e });
|
|
13587
13590
|
}
|
|
13588
13591
|
setVolume(e) {
|
|
13589
|
-
this.volume = Math.max(0, Math.min(1, e)), this.audioSession.setVolume(this.volume), this.eventBus.emit(
|
|
13592
|
+
this.volume = Math.max(0, Math.min(1, e)), this.audioSession.setVolume(this.volume), this.eventBus.emit(O.PlaybackVolumeChange, { volume: this.volume });
|
|
13590
13593
|
}
|
|
13591
13594
|
setMute(e) {
|
|
13592
13595
|
if (e) {
|
|
13593
13596
|
this.audioSession.stopPlayback();
|
|
13594
13597
|
return;
|
|
13595
13598
|
}
|
|
13596
|
-
this.fsm.snapshot.state ===
|
|
13599
|
+
this.fsm.snapshot.state === z.Playing && this.audioSession.startPlayback(this.currentTimeUs, this.audioContext);
|
|
13597
13600
|
}
|
|
13598
13601
|
setLoop(e) {
|
|
13599
13602
|
this.loop = e;
|
|
@@ -13602,7 +13605,7 @@ class ta {
|
|
|
13602
13605
|
return this.orchestrator.compositionModel?.durationUs ?? 0;
|
|
13603
13606
|
}
|
|
13604
13607
|
get isPlaying() {
|
|
13605
|
-
return this.fsm.snapshot.state ===
|
|
13608
|
+
return this.fsm.snapshot.state === z.Playing;
|
|
13606
13609
|
}
|
|
13607
13610
|
resume() {
|
|
13608
13611
|
this.play();
|
|
@@ -13657,7 +13660,7 @@ class ta {
|
|
|
13657
13660
|
p instanceof Nt || // Missing moov may be caused by incomplete/corrupted cache and can be retried via recovery.
|
|
13658
13661
|
p instanceof Le
|
|
13659
13662
|
);
|
|
13660
|
-
this.eventBus.emit(
|
|
13663
|
+
this.eventBus.emit(O.PlaybackError, p), this.eventBus.emit(O.Error, {
|
|
13661
13664
|
source: "playback",
|
|
13662
13665
|
error: p,
|
|
13663
13666
|
context: {
|
|
@@ -13764,7 +13767,7 @@ class ta {
|
|
|
13764
13767
|
return;
|
|
13765
13768
|
}
|
|
13766
13769
|
case P.StartRafLoop: {
|
|
13767
|
-
this.startPlaybackLoop(s);
|
|
13770
|
+
this.startPlaybackLoop(s), !this.orchestrator.cacheManager.isExporting && this.fsm.snapshot.state === z.Playing && this.preheatNextWindow();
|
|
13768
13771
|
return;
|
|
13769
13772
|
}
|
|
13770
13773
|
}
|
|
@@ -13781,7 +13784,7 @@ class ta {
|
|
|
13781
13784
|
});
|
|
13782
13785
|
}
|
|
13783
13786
|
async onRafTick(e) {
|
|
13784
|
-
if (!this.isCurrentToken(e) || this.fsm.snapshot.state !==
|
|
13787
|
+
if (!this.isCurrentToken(e) || this.fsm.snapshot.state !== z.Playing)
|
|
13785
13788
|
return;
|
|
13786
13789
|
const s = (this.audioContext.currentTime * 1e6 - this.startTimeUs) * this.playbackRate;
|
|
13787
13790
|
if (this.dispatch({
|
|
@@ -13790,7 +13793,7 @@ class ta {
|
|
|
13790
13793
|
durationUs: this.duration,
|
|
13791
13794
|
loop: this.loop,
|
|
13792
13795
|
audioNowUs: this.audioContext.currentTime * 1e6
|
|
13793
|
-
}), !this.isCurrentToken(e) || this.fsm.snapshot.state !==
|
|
13796
|
+
}), !this.isCurrentToken(e) || this.fsm.snapshot.state !== z.Playing)
|
|
13794
13797
|
return;
|
|
13795
13798
|
if (this.currentTimeUs - this.lastAudioScheduleTime >= this.AUDIO_SCHEDULE_INTERVAL && (this.audioSession.scheduleAudio(this.currentTimeUs, this.audioContext), this.lastAudioScheduleTime = this.currentTimeUs), this.audioSession.shouldEnterBufferingForUpcomingPreviewAudio(this.currentTimeUs)) {
|
|
13796
13799
|
this.audioSession.ensureAudioForTime(this.currentTimeUs, { mode: "probe" }), this.dispatch({
|
|
@@ -13803,7 +13806,7 @@ class ta {
|
|
|
13803
13806
|
const r = await this.orchestrator.getRenderState(this.currentTimeUs, {
|
|
13804
13807
|
mode: "probe"
|
|
13805
13808
|
});
|
|
13806
|
-
if (!(!this.isCurrentToken(e) || this.fsm.snapshot.state !==
|
|
13809
|
+
if (!(!this.isCurrentToken(e) || this.fsm.snapshot.state !== z.Playing)) {
|
|
13807
13810
|
if (!r) {
|
|
13808
13811
|
if (this.isTerminalVideoErrorAtTime(this.currentTimeUs)) {
|
|
13809
13812
|
this.clearCanvas(), this.finalizeFrameAndContinue(e);
|
|
@@ -13812,11 +13815,11 @@ class ta {
|
|
|
13812
13815
|
this.dispatch({ type: j.EnterBuffering, timeUs: this.currentTimeUs });
|
|
13813
13816
|
return;
|
|
13814
13817
|
}
|
|
13815
|
-
await this.compose(this.currentTimeUs, r), !(!this.isCurrentToken(e) || this.fsm.snapshot.state !==
|
|
13818
|
+
await this.compose(this.currentTimeUs, r), !(!this.isCurrentToken(e) || this.fsm.snapshot.state !== z.Playing) && this.finalizeFrameAndContinue(e);
|
|
13816
13819
|
}
|
|
13817
13820
|
}
|
|
13818
13821
|
finalizeFrameAndContinue(e) {
|
|
13819
|
-
this.updateFps(), this.frameCount++, this.orchestrator.cacheManager.setWindow(this.currentTimeUs), this.checkAndPreheatWindow(), !(!this.isCurrentToken(e) || this.fsm.snapshot.state !==
|
|
13822
|
+
this.updateFps(), this.frameCount++, this.orchestrator.cacheManager.setWindow(this.currentTimeUs), this.checkAndPreheatWindow(), !(!this.isCurrentToken(e) || this.fsm.snapshot.state !== z.Playing) && this.startPlaybackLoop(e);
|
|
13820
13823
|
}
|
|
13821
13824
|
updateFps() {
|
|
13822
13825
|
const e = performance.now();
|
|
@@ -13830,30 +13833,30 @@ class ta {
|
|
|
13830
13833
|
this.windowEnd = e + this.WINDOW_DURATION, this.preheatInProgress = !1, this.orchestrator.cacheManager.setWindow(e);
|
|
13831
13834
|
}
|
|
13832
13835
|
checkAndPreheatWindow() {
|
|
13833
|
-
|
|
13834
|
-
|
|
13835
|
-
const e = this.windowEnd - this.currentTimeUs;
|
|
13836
|
-
if (e < 0) {
|
|
13836
|
+
const e = this.orchestrator.cacheManager.isExporting, s = this.preheatInProgress, r = this.fsm.snapshot.state === z.Playing, h = this.windowEnd - this.currentTimeUs;
|
|
13837
|
+
if (h < 0) {
|
|
13837
13838
|
this.initWindow(this.currentTimeUs);
|
|
13838
13839
|
return;
|
|
13839
13840
|
}
|
|
13840
|
-
|
|
13841
|
+
const l = h > 0 && h <= this.PREHEAT_DISTANCE;
|
|
13842
|
+
e || s || !r || !l || this.isSeekActive() || this.preheatNextWindow();
|
|
13841
13843
|
}
|
|
13842
13844
|
async preheatNextWindow() {
|
|
13843
|
-
|
|
13845
|
+
const e = this.orchestrator.cacheManager.isExporting, s = this.preheatInProgress;
|
|
13846
|
+
if (!(e || s || this.isSeekActive())) {
|
|
13844
13847
|
this.preheatInProgress = !0;
|
|
13845
13848
|
try {
|
|
13846
|
-
const
|
|
13847
|
-
for (const
|
|
13848
|
-
if (!Ut(
|
|
13849
|
-
const
|
|
13850
|
-
|
|
13851
|
-
this.orchestrator.preheatClipWindow(
|
|
13849
|
+
const h = this.currentTimeUs, l = h + this.WINDOW_DURATION, u = this.orchestrator.compositionModel?.getClipsInRange(h, l) ?? [], o = [];
|
|
13850
|
+
for (const p of u) {
|
|
13851
|
+
if (!Ut(p)) continue;
|
|
13852
|
+
const m = Math.max(0, h - p.startUs), g = Math.min(p.durationUs, l - p.startUs);
|
|
13853
|
+
m >= g || o.push(
|
|
13854
|
+
this.orchestrator.preheatClipWindow(p.id, m, g, h)
|
|
13852
13855
|
);
|
|
13853
13856
|
}
|
|
13854
|
-
await Promise.all(
|
|
13855
|
-
} catch (
|
|
13856
|
-
console.warn("[PlaybackController] Preheat failed:",
|
|
13857
|
+
await Promise.all(o), this.windowEnd = l;
|
|
13858
|
+
} catch (h) {
|
|
13859
|
+
console.warn("[PlaybackController] Preheat failed:", h);
|
|
13857
13860
|
} finally {
|
|
13858
13861
|
this.preheatInProgress = !1;
|
|
13859
13862
|
}
|
|
@@ -13891,10 +13894,10 @@ class ta {
|
|
|
13891
13894
|
const e = this.pendingSeekWaiters;
|
|
13892
13895
|
this.pendingSeekWaiters = [];
|
|
13893
13896
|
for (const s of e) s();
|
|
13894
|
-
this.eventBus.off(
|
|
13897
|
+
this.eventBus.off(O.CacheCover, this.onCacheCover), this.eventBus.off(O.ModelSet, this.onModelSet), this.videoComposer && (this.videoComposer.dispose(), this.videoComposer = null);
|
|
13895
13898
|
}
|
|
13896
13899
|
onCacheCover = () => {
|
|
13897
|
-
this.fsm.snapshot.state ===
|
|
13900
|
+
this.fsm.snapshot.state === z.Idle && this.currentTimeUs === 0 && this.renderCurrentFrame(0, { mode: "blocking" });
|
|
13898
13901
|
};
|
|
13899
13902
|
onModelSet = () => {
|
|
13900
13903
|
if (!this.videoComposer || !this.orchestrator.compositionModel) return;
|
|
@@ -13908,7 +13911,7 @@ class ta {
|
|
|
13908
13911
|
}), this.orchestrator.cacheManager.isExporting || this.audioSession.ensureAudioForTime(this.currentTimeUs, { mode: "probe" }), this.renderCurrentFrame(this.currentTimeUs, { mode: "blocking" });
|
|
13909
13912
|
};
|
|
13910
13913
|
setupEventListeners() {
|
|
13911
|
-
this.eventBus.on(
|
|
13914
|
+
this.eventBus.on(O.CacheCover, this.onCacheCover), this.eventBus.on(O.ModelSet, this.onModelSet);
|
|
13912
13915
|
}
|
|
13913
13916
|
isVideoResourceReadyAtTime(e) {
|
|
13914
13917
|
const s = this.orchestrator.compositionModel;
|
|
@@ -14081,7 +14084,7 @@ class ki {
|
|
|
14081
14084
|
async setCompositionModel(e) {
|
|
14082
14085
|
this.ensureNotDestroyed(), this.playbackController?.pause();
|
|
14083
14086
|
const s = e instanceof Ui ? e : new Ui(e);
|
|
14084
|
-
await this.orchestrator.setCompositionModel(s), this.model = s, this.setState("ready"), this.eventBus.emit(
|
|
14087
|
+
await this.orchestrator.setCompositionModel(s), this.model = s, this.setState("ready"), this.eventBus.emit(O.Ready, {
|
|
14085
14088
|
trackCount: e.tracks.length,
|
|
14086
14089
|
clipCount: e.tracks.reduce(
|
|
14087
14090
|
(r, h) => r + h.clips?.length || 0,
|
|
@@ -14322,13 +14325,13 @@ async function ra() {
|
|
|
14322
14325
|
}
|
|
14323
14326
|
};
|
|
14324
14327
|
let _ = 0;
|
|
14325
|
-
if (o.events.on(
|
|
14328
|
+
if (o.events.on(O.ExportProgress, (b) => {
|
|
14326
14329
|
window.runnerReportProgress(b);
|
|
14327
14330
|
const U = Date.now();
|
|
14328
14331
|
U - _ >= 1e3 && (_ = U, console.log("[meframe-runner] progress", b));
|
|
14329
|
-
}), o.events.on(
|
|
14332
|
+
}), o.events.on(O.ExportStart, (b) => {
|
|
14330
14333
|
console.log("[meframe-runner] export:start", b);
|
|
14331
|
-
}), o.events.on(
|
|
14334
|
+
}), o.events.on(O.ExportComplete, (b) => {
|
|
14332
14335
|
console.log("[meframe-runner] export:complete", b);
|
|
14333
14336
|
}), console.log("[meframe-runner] export()..."), await o.export({
|
|
14334
14337
|
...s,
|
package/docs/INTEGRATION.md
CHANGED
|
@@ -71,6 +71,13 @@ WebCodecs 等 API 需要 secure/trustworthy origin。`exportToStore({ pageUrl })
|
|
|
71
71
|
|
|
72
72
|
> 核心原则:`CompositionModelData.resources[*].uri`、`workerPath` 指向的文件,都必须能在 Chromium 里直接 `fetch()`/加载到。
|
|
73
73
|
|
|
74
|
+
新增(默认行为):
|
|
75
|
+
|
|
76
|
+
- 若 `exportToStore({ workerPath })` **未提供**,`@meframe/server` 会临时启动一个本地 HTTP 服务,
|
|
77
|
+
自动托管 `@meframe/core/dist/workers` 并把它的 base URL 作为 `workerPath` 注入到 runner。
|
|
78
|
+
- 你可以通过 `ServerExporterOptions.workerServer.enabled = false` 关闭该行为,或用
|
|
79
|
+
`ServerExporterOptions.workerServer.workerDir` 指向自定义目录。
|
|
80
|
+
|
|
74
81
|
#### 2.4 音频(AAC)能力说明(强烈建议阅读)
|
|
75
82
|
|
|
76
83
|
当前 `mp4` 输出的音频轨 **只能是 AAC**(对应 WebCodecs `AudioEncoder` 的 `codec: 'mp4a.40.2'`)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meframe/server",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Server-side exporter for @meframe/core (browser-driven, multipart upload via injected store)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/esm/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"puppeteer-core": "^23.5.0",
|
|
23
|
-
"@meframe/core": "0.3.
|
|
23
|
+
"@meframe/core": "0.3.2"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@aws-sdk/client-s3": "^3.758.0",
|