@mengine/medeo-tool 1.3.1-alpha.8 → 1.4.1-alpha.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 +26 -40
- package/dist/{entity-contract-Dm3AMEC9.d.mts → entity-contract-DHasvrhq.d.mts} +4 -4
- package/dist/index.d.mts +66 -142
- package/dist/index.mjs +369 -621
- package/dist/index.mjs.map +1 -1
- package/dist/sandbox-api.d.mts +43 -186
- package/dist/{script-session-C2uQHYt4.mjs → script-session-DTq_VPEA.mjs} +112 -33
- package/dist/script-session-DTq_VPEA.mjs.map +1 -0
- package/dist/worker-entry.d.mts +1 -1
- package/dist/worker-entry.mjs +13 -14
- package/dist/worker-entry.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/script-session-C2uQHYt4.mjs.map +0 -1
package/dist/sandbox-api.d.mts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
//#region src/sandbox/generated/entity-edit-sandbox-api.d.ts
|
|
2
2
|
/** @generated by gen:sandbox-dts. Entity-native editor contract; DO NOT EDIT. */
|
|
3
|
-
interface AudioMediaAssetFact {
|
|
4
|
-
readonly assetId: string;
|
|
5
|
-
readonly kind: 'audio';
|
|
6
|
-
readonly durationMs: number;
|
|
7
|
-
readonly storageKey: string;
|
|
8
|
-
}
|
|
9
3
|
interface BoundedDerivedSequencePayload extends JsonObject {
|
|
10
4
|
extent: {
|
|
11
5
|
kind: 'bounded';
|
|
@@ -25,6 +19,32 @@ interface BoundedNativeSequencePayload extends JsonObject {
|
|
|
25
19
|
sampling: 'native';
|
|
26
20
|
coordinateSpace: JsonValue;
|
|
27
21
|
}
|
|
22
|
+
/** Business editing surface. Infrastructure Assets are assembled by the host. */
|
|
23
|
+
interface BusinessEntityFacade {
|
|
24
|
+
list(): SandboxEntity[];
|
|
25
|
+
get(entityId: string): SandboxEntity | null;
|
|
26
|
+
readCaptionContent(entityId: string): ComposedScriptContent;
|
|
27
|
+
readPhoneticScriptContent(entityId: string): ComposedPhoneticContent;
|
|
28
|
+
create(input: Exclude<CreateEntityInput, {
|
|
29
|
+
entity_kind: 'asset';
|
|
30
|
+
}>): string;
|
|
31
|
+
update(input: UpdateEntityInput): void;
|
|
32
|
+
declareFields(input: UpdateEntityInput): void;
|
|
33
|
+
delete(input: DeleteEntityInput): void;
|
|
34
|
+
}
|
|
35
|
+
/** Physical Asset bindings are maintained outside the sandbox. */
|
|
36
|
+
interface BusinessRelationFacade {
|
|
37
|
+
list(): SandboxRelation[];
|
|
38
|
+
of(entityId: string, relationKind?: KnownRelationKind): SandboxRelation[];
|
|
39
|
+
link(input: Exclude<LinkRelationInput, {
|
|
40
|
+
relation_kind: 'physical-asset';
|
|
41
|
+
}>): string;
|
|
42
|
+
linkGenerated(input: LinkGeneratedRelationInput): string;
|
|
43
|
+
linkClipAnchor(input: LinkClipAnchorRelationInput): string;
|
|
44
|
+
linkPhoneticScriptRender(input: LinkPhoneticScriptRenderRelationInput): string;
|
|
45
|
+
linkAudioScriptSource(input: LinkAudioScriptSourceRelationInput): string;
|
|
46
|
+
unlink(input: UnlinkRelationInput): void;
|
|
47
|
+
}
|
|
28
48
|
interface CaptionFontDescriptor {
|
|
29
49
|
readonly system: 'font-library';
|
|
30
50
|
readonly key: string;
|
|
@@ -114,28 +134,6 @@ interface DeleteVoiceoverInput {
|
|
|
114
134
|
readonly voiceoverClipEntityIds: readonly string[];
|
|
115
135
|
}
|
|
116
136
|
type EmptyRelationKind = 'timeline-track' | 'track-clip' | 'clip-marker' | 'marker-content' | 'axvideo-marker' | 'marker-timeline' | 'audio-script-marker';
|
|
117
|
-
interface EntityFacade {
|
|
118
|
-
/** Read complete assembled fields; returned objects are snapshots. Use update to persist edits. */
|
|
119
|
-
list(): SandboxEntity[];
|
|
120
|
-
get(entityId: string): SandboxEntity | null;
|
|
121
|
-
/** Find document resources by external Memota asset id, including directly composed media variants. */
|
|
122
|
-
findByAssetId(assetId: string): SandboxEntity<ResourceEntityKind>[];
|
|
123
|
-
/** Assemble selected Caption text; missing composition is an error. */
|
|
124
|
-
readCaptionContent(entityId: string): ComposedScriptContent;
|
|
125
|
-
/** Assemble base text and pronunciation fields before generating Voice. */
|
|
126
|
-
readPhoneticScriptContent(entityId: string): ComposedPhoneticContent;
|
|
127
|
-
create(input: CreateEntityInput): string;
|
|
128
|
-
/** Patch assembled fields, routing inherited fields to their declaring entity. */
|
|
129
|
-
update(input: UpdateEntityInput): void;
|
|
130
|
-
/** Explicitly declare own fields, overriding unambiguous bases without modifying them. Ordinary edits use update. */
|
|
131
|
-
declareFields(input: UpdateEntityInput): void;
|
|
132
|
-
/** Delete an Entity only after all of its incident Relations have been explicitly unlinked. */
|
|
133
|
-
delete(input: DeleteEntityInput): void;
|
|
134
|
-
/** Get or create one typed Asset by factual external id and return its single content identity. Never creates a Clip. */
|
|
135
|
-
ensureMedia(fact: MediaAssetFact): {
|
|
136
|
-
contentEntityId: string;
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
137
|
type EntityId = string;
|
|
140
138
|
interface EntityPayloadByKind {
|
|
141
139
|
axvideo: BoundedDerivedSequencePayload;
|
|
@@ -145,12 +143,10 @@ interface EntityPayloadByKind {
|
|
|
145
143
|
role?: string;
|
|
146
144
|
};
|
|
147
145
|
clip: JsonObject;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
voice: BoundedNativeSequencePayload & MediaAssetPayload;
|
|
153
|
-
image: UnboundedConstantSequencePayload & MediaAssetPayload;
|
|
146
|
+
video: BoundedNativeSequencePayload;
|
|
147
|
+
audio: BoundedNativeSequencePayload;
|
|
148
|
+
voice: BoundedNativeSequencePayload;
|
|
149
|
+
image: UnboundedConstantSequencePayload;
|
|
154
150
|
'sequence-marker': JsonObject & {
|
|
155
151
|
sourceRange: {
|
|
156
152
|
start: number;
|
|
@@ -191,18 +187,18 @@ interface EntityPayloadByKind {
|
|
|
191
187
|
};
|
|
192
188
|
}
|
|
193
189
|
interface EntityStoreSnapshot {
|
|
190
|
+
/** Causal compiler baseline; required for publishing edits. */
|
|
191
|
+
loroSnapshot?: string;
|
|
194
192
|
revision: number;
|
|
193
|
+
/** Current AudioScript version attached to the project; initialized projects always attach a script, possibly empty. */
|
|
195
194
|
audioScriptEntityId: string | null;
|
|
196
195
|
entities: SandboxEntity[];
|
|
197
196
|
relations: SandboxRelation[];
|
|
198
197
|
}
|
|
199
|
-
interface ImageMediaAssetFact {
|
|
200
|
-
readonly assetId: string;
|
|
201
|
-
readonly kind: 'image';
|
|
202
|
-
readonly storageKey?: string;
|
|
203
|
-
}
|
|
204
198
|
interface InsertCaptionClipInput {
|
|
205
199
|
readonly timelineEntityId: string;
|
|
200
|
+
/** Existing generation identity for newly materialized Caption content, distinct from its Clip. */
|
|
201
|
+
readonly captionEntityId?: string;
|
|
206
202
|
/** Stable placed caption identity, distinct from the Caption content identity. */
|
|
207
203
|
readonly captionClipEntityId?: string;
|
|
208
204
|
/** Existing bases composed by this variant; includes an AudioScript text owner. */
|
|
@@ -223,21 +219,6 @@ interface InsertClipInput {
|
|
|
223
219
|
readonly targetRange?: SequenceRange<number>;
|
|
224
220
|
readonly clipPayload?: JsonObject;
|
|
225
221
|
}
|
|
226
|
-
interface InsertMediaClipInput {
|
|
227
|
-
readonly timelineEntityId: string;
|
|
228
|
-
readonly clipEntityId?: string;
|
|
229
|
-
readonly media: VisualMediaAssetFact;
|
|
230
|
-
/** Source/display window in whole milliseconds. Images use this as their finite display span. */
|
|
231
|
-
readonly sourceRange: SequenceRange<number>;
|
|
232
|
-
readonly placement: ClipPlacement;
|
|
233
|
-
readonly volume?: number;
|
|
234
|
-
}
|
|
235
|
-
interface InsertMediaClipsInput {
|
|
236
|
-
readonly timelineEntityId: string;
|
|
237
|
-
readonly clips: readonly ReplacementMediaClipInput[];
|
|
238
|
-
/** One placement decision for the whole input-ordered block. */
|
|
239
|
-
readonly insertion: MediaClipInsertion;
|
|
240
|
-
}
|
|
241
222
|
interface InsertPlacedClipInput {
|
|
242
223
|
readonly trackEntityId: string;
|
|
243
224
|
readonly contentEntityId: string;
|
|
@@ -253,8 +234,8 @@ interface JsonObject {
|
|
|
253
234
|
}
|
|
254
235
|
type JsonPrimitive = string | number | boolean | null;
|
|
255
236
|
type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
256
|
-
type KnownEntityKind = 'axvideo' | 'timeline' | 'track' | 'clip' | '
|
|
257
|
-
type KnownRelationKind = 'timeline-track' | 'track-clip' | 'clip-marker' | 'marker-content' | 'axvideo-marker' | 'marker-timeline' | '
|
|
237
|
+
type KnownEntityKind = 'axvideo' | 'timeline' | 'track' | 'clip' | 'video' | 'audio' | 'voice' | 'image' | 'sequence-marker' | 'viewport' | 'audio-script' | 'phonetic-script' | 'caption';
|
|
238
|
+
type KnownRelationKind = 'timeline-track' | 'track-clip' | 'clip-marker' | 'marker-content' | 'axvideo-marker' | 'marker-timeline' | 'generated' | 'caption-alignment' | 'clip-anchor' | 'phonetic-script-render' | 'audio-script-source' | 'audio-script-marker';
|
|
258
239
|
interface LinearClipSpeed {
|
|
259
240
|
readonly kind: 'linear';
|
|
260
241
|
readonly rate: number;
|
|
@@ -305,25 +286,6 @@ type LinkRelationInput = (LinkRelationBase & {
|
|
|
305
286
|
alignment: JsonValue;
|
|
306
287
|
};
|
|
307
288
|
});
|
|
308
|
-
/** Facts resolved from media storage. A trim window never substitutes for intrinsic duration. */
|
|
309
|
-
type MediaAssetFact = ImageMediaAssetFact | VideoMediaAssetFact | AudioMediaAssetFact | VoiceMediaAssetFact;
|
|
310
|
-
type MediaAssetPayload = JsonObject & {
|
|
311
|
-
external: {
|
|
312
|
-
system: 'memota' | 'memota-speech';
|
|
313
|
-
key: string;
|
|
314
|
-
};
|
|
315
|
-
storageKey?: string;
|
|
316
|
-
};
|
|
317
|
-
type MediaClipInsertion = {
|
|
318
|
-
readonly kind: 'before';
|
|
319
|
-
readonly clipEntityId: string;
|
|
320
|
-
} | {
|
|
321
|
-
readonly kind: 'after';
|
|
322
|
-
readonly clipEntityId: string;
|
|
323
|
-
} | {
|
|
324
|
-
readonly kind: 'firstStart';
|
|
325
|
-
readonly startMs: number;
|
|
326
|
-
};
|
|
327
289
|
interface MoveClipInput {
|
|
328
290
|
readonly clipEntityId: string;
|
|
329
291
|
readonly trackEntityId: string;
|
|
@@ -350,23 +312,6 @@ interface PatchCaptionStyleInput {
|
|
|
350
312
|
readonly timelineEntityId: string;
|
|
351
313
|
readonly style: CaptionStyleFields;
|
|
352
314
|
}
|
|
353
|
-
interface RelationFacade {
|
|
354
|
-
list(): SandboxRelation[];
|
|
355
|
-
/** Incident lookup is endpoint-agnostic; persisted endpoint positions stay unchanged. */
|
|
356
|
-
of(entityId: string, relationKind?: KnownRelationKind): SandboxRelation[];
|
|
357
|
-
/** Link existing entities through ordinary associations; variant bases are stored directly on the variant. */
|
|
358
|
-
link(input: LinkRelationInput): string;
|
|
359
|
-
/** Author ordered generated(output,input); generic link() deliberately rejects this kind. */
|
|
360
|
-
linkGenerated(input: LinkGeneratedRelationInput): string;
|
|
361
|
-
/** Author ordered clip-anchor(child,host) without positional endpoint ambiguity. */
|
|
362
|
-
linkClipAnchor(input: LinkClipAnchorRelationInput): string;
|
|
363
|
-
/** Author ordered phonetic-script-render(output,script) without positional endpoint ambiguity. */
|
|
364
|
-
linkPhoneticScriptRender(input: LinkPhoneticScriptRenderRelationInput): string;
|
|
365
|
-
/** Author ordered audio-script-source(script,source) without positional endpoint ambiguity. */
|
|
366
|
-
linkAudioScriptSource(input: LinkAudioScriptSourceRelationInput): string;
|
|
367
|
-
/** Remove a Relation by identity; endpoint replacement is an explicit unlink plus link. */
|
|
368
|
-
unlink(input: UnlinkRelationInput): void;
|
|
369
|
-
}
|
|
370
315
|
interface ReplaceClipContentInput {
|
|
371
316
|
readonly clipEntityId: string;
|
|
372
317
|
/** Existing Sequence media Entity id. Asset ids and URLs are not content ids. */
|
|
@@ -376,25 +321,6 @@ interface ReplaceClipContentInput {
|
|
|
376
321
|
readonly targetRange?: SequenceRange<number>;
|
|
377
322
|
readonly timeRemapping?: JsonValue;
|
|
378
323
|
}
|
|
379
|
-
interface ReplaceMediaClipInput {
|
|
380
|
-
readonly clipEntityId: string;
|
|
381
|
-
readonly media: VisualMediaAssetFact;
|
|
382
|
-
readonly sourceRange: SequenceRange<number>;
|
|
383
|
-
}
|
|
384
|
-
interface ReplaceSequentialClipsInput {
|
|
385
|
-
readonly timelineEntityId: string;
|
|
386
|
-
readonly oldClipEntityIds: readonly string[];
|
|
387
|
-
readonly newClips: readonly ReplacementMediaClipInput[];
|
|
388
|
-
readonly onAnchored: 'remap' | 'cascade';
|
|
389
|
-
}
|
|
390
|
-
interface ReplacementMediaClipInput {
|
|
391
|
-
readonly clipEntityId?: string;
|
|
392
|
-
readonly media: VisualMediaAssetFact;
|
|
393
|
-
readonly sourceRange: SequenceRange<number>;
|
|
394
|
-
readonly volume?: number;
|
|
395
|
-
}
|
|
396
|
-
/** Asset identity, either an old physical-only row or a directly composed media variant. */
|
|
397
|
-
type ResourceEntityKind = 'image' | 'video' | 'audio' | 'voice';
|
|
398
324
|
interface SandboxEntity<K extends KnownEntityKind = KnownEntityKind> {
|
|
399
325
|
entity_id: string;
|
|
400
326
|
entity_kind: K;
|
|
@@ -429,12 +355,6 @@ type SequentialClipAnchor = {
|
|
|
429
355
|
} | {
|
|
430
356
|
readonly position: 'trackStart';
|
|
431
357
|
};
|
|
432
|
-
interface SetBgmInput {
|
|
433
|
-
readonly timelineEntityId: string;
|
|
434
|
-
readonly bgmClipEntityId: string;
|
|
435
|
-
readonly media: AudioMediaAssetFact;
|
|
436
|
-
readonly volume: number;
|
|
437
|
-
}
|
|
438
358
|
interface SetCaptionVisibilityInput {
|
|
439
359
|
readonly timelineEntityId: string;
|
|
440
360
|
readonly hidden: boolean;
|
|
@@ -490,67 +410,8 @@ interface UpdateEntityInput {
|
|
|
490
410
|
entity_id: string;
|
|
491
411
|
payload: JsonObject;
|
|
492
412
|
}
|
|
493
|
-
interface VideoMediaAssetFact {
|
|
494
|
-
readonly assetId: string;
|
|
495
|
-
readonly kind: 'video';
|
|
496
|
-
readonly durationMs: number;
|
|
497
|
-
readonly storageKey?: string;
|
|
498
|
-
}
|
|
499
|
-
type VisualMediaAssetFact = ImageMediaAssetFact | VideoMediaAssetFact;
|
|
500
|
-
interface VoiceDescriptor {
|
|
501
|
-
readonly system: 'voice-library';
|
|
502
|
-
readonly key: string;
|
|
503
|
-
readonly name?: string;
|
|
504
|
-
}
|
|
505
|
-
interface VoiceMediaAssetFact {
|
|
506
|
-
/** Stable external speech result id, independent of the placed Clip id. */
|
|
507
|
-
readonly assetId: string;
|
|
508
|
-
readonly kind: 'voice';
|
|
509
|
-
readonly durationMs: number;
|
|
510
|
-
readonly storageKey: string;
|
|
511
|
-
/** Present for synthesized voice, absent for original recorded audio. */
|
|
512
|
-
readonly voice?: VoiceDescriptor;
|
|
513
|
-
}
|
|
514
|
-
interface VoiceoverCaptionFact {
|
|
515
|
-
/** Stable placed caption identity supplied by the materialized side effect. */
|
|
516
|
-
readonly captionClipEntityId: string;
|
|
517
|
-
/** Directly held bases; includes the AudioScript used by the Voice. */
|
|
518
|
-
readonly baseEntityIds: readonly string[];
|
|
519
|
-
/** Ordered selection of AudioScript segments; caption text is never passed inline. */
|
|
520
|
-
readonly selections: readonly CaptionSegmentSelection[];
|
|
521
|
-
readonly startMs: number;
|
|
522
|
-
readonly durationMs: number;
|
|
523
|
-
readonly style?: CaptionStyleFields;
|
|
524
|
-
}
|
|
525
|
-
type VoiceoverTakeInput = {
|
|
526
|
-
readonly timelineEntityId: string; /** Stable placed speech identity, distinct from media.assetId. */
|
|
527
|
-
readonly voiceoverClipEntityId: string;
|
|
528
|
-
readonly media: VoiceMediaAssetFact; /** Existing pronunciation variant; its composed AudioScript stays the text owner. */
|
|
529
|
-
readonly phoneticScriptEntityId: string;
|
|
530
|
-
readonly volume: number;
|
|
531
|
-
readonly captions: readonly VoiceoverCaptionFact[];
|
|
532
|
-
} & ({
|
|
533
|
-
readonly placement: ClipPlacement;
|
|
534
|
-
readonly hostClipEntityId?: never;
|
|
535
|
-
readonly anchorOffset?: never;
|
|
536
|
-
} | {
|
|
537
|
-
readonly placement?: never;
|
|
538
|
-
readonly hostClipEntityId: string;
|
|
539
|
-
readonly anchorOffset: number;
|
|
540
|
-
});
|
|
541
|
-
interface VoiceoverTakeResult {
|
|
542
|
-
readonly voiceoverClipEntityId: string;
|
|
543
|
-
readonly voiceEntityId: string;
|
|
544
|
-
/** The pronunciation variant the Voice was rendered from. */
|
|
545
|
-
readonly phoneticScriptEntityId: string;
|
|
546
|
-
/** The base-text owner resolved from the PhoneticScript baseEntityIds. */
|
|
547
|
-
readonly audioScriptEntityId: string;
|
|
548
|
-
readonly captionClipEntityIds: readonly string[];
|
|
549
|
-
}
|
|
550
413
|
/** Timeline writes accept existing media Entity ids, never Memota asset ids or URLs. */
|
|
551
414
|
interface EditApi {
|
|
552
|
-
/** Select the document AudioScript, or clear the optional association with null. */
|
|
553
|
-
setDocumentAudioScript(entityId: string | null): void;
|
|
554
415
|
insertClip(input: InsertClipInput): ClipEntityId;
|
|
555
416
|
insertPlacedClip(input: InsertPlacedClipInput): ClipEntityId;
|
|
556
417
|
updateClipMarker(input: UpdateClipMarkerInput): void;
|
|
@@ -558,39 +419,35 @@ interface EditApi {
|
|
|
558
419
|
moveSequentialClips(input: MoveSequentialClipsInput): void;
|
|
559
420
|
moveClip(input: MoveClipInput): void;
|
|
560
421
|
replaceClipContent(input: ReplaceClipContentInput): void;
|
|
561
|
-
insertMediaClip(input: InsertMediaClipInput): ClipEntityId;
|
|
562
|
-
insertMediaClips(input: InsertMediaClipsInput): readonly ClipEntityId[];
|
|
563
|
-
replaceMediaClip(input: ReplaceMediaClipInput): void;
|
|
564
422
|
setClipVolume(input: SetClipVolumeInput): void;
|
|
565
423
|
setClipSpeed(input: SetClipSpeedInput): void;
|
|
566
424
|
trimClip(input: TrimClipInput): void;
|
|
567
|
-
replaceSequentialClips(input: ReplaceSequentialClipsInput): readonly ClipEntityId[];
|
|
568
425
|
deleteClip(input: DeleteClipInput): void;
|
|
569
426
|
deleteClipTree(input: DeleteClipTreeInput): void;
|
|
570
427
|
updateClip(input: UpdateClipInput): void;
|
|
571
|
-
upsertVoiceoverTake(input: VoiceoverTakeInput): VoiceoverTakeResult;
|
|
572
428
|
moveVoiceover(input: MoveVoiceoverInput): void;
|
|
573
429
|
moveClipsToStarts(input: MoveClipsToStartsInput): void;
|
|
574
430
|
deleteVoiceover(input: DeleteVoiceoverInput): void;
|
|
575
|
-
setBgm(input: SetBgmInput): ClipEntityId;
|
|
576
431
|
deleteBgm(input: DeleteBgmInput): void;
|
|
577
432
|
setCaptionVisibility(input: SetCaptionVisibilityInput): void;
|
|
578
433
|
patchCaptionStyle(input: PatchCaptionStyleInput): void;
|
|
579
434
|
insertCaptionClip(input: InsertCaptionClipInput): ClipEntityId;
|
|
580
435
|
}
|
|
581
436
|
interface TimelineApi {
|
|
582
|
-
snapshot(): EntityStoreSnapshot
|
|
437
|
+
snapshot(): EntityStoreSnapshot & {
|
|
438
|
+
audioScriptEntityId: string;
|
|
439
|
+
};
|
|
583
440
|
}
|
|
584
441
|
interface SandboxCheckpoint {
|
|
585
442
|
readonly index: number;
|
|
586
443
|
}
|
|
587
444
|
declare const edit: EditApi;
|
|
588
445
|
declare const timeline: TimelineApi;
|
|
589
|
-
declare const entities:
|
|
590
|
-
declare const relations:
|
|
446
|
+
declare const entities: BusinessEntityFacade;
|
|
447
|
+
declare const relations: BusinessRelationFacade;
|
|
591
448
|
declare function checkpoint(): SandboxCheckpoint;
|
|
592
449
|
declare function rollbackTo(cp: SandboxCheckpoint): void;
|
|
593
450
|
declare const inputs: Readonly<Record<string, unknown>>;
|
|
594
451
|
//#endregion
|
|
595
|
-
export type {
|
|
452
|
+
export type { BoundedDerivedSequencePayload, BoundedNativeSequencePayload, BusinessEntityFacade, BusinessRelationFacade, CaptionFontDescriptor, CaptionSegmentSelection, CaptionStyleFields, CaptionTextRange, CaptionTextSelection, ClipEntityId, ClipPlacement, ComposedPhoneticContent, ComposedScriptContent, CreateEntityInput, DeleteBgmInput, DeleteClipInput, DeleteClipTreeInput, DeleteEntityInput, DeleteVoiceoverInput, EditApi, EmptyRelationKind, EntityId, EntityPayloadByKind, EntityStoreSnapshot, InsertCaptionClipInput, InsertClipInput, InsertPlacedClipInput, JsonObject, JsonPrimitive, JsonValue, KnownEntityKind, KnownRelationKind, LinearClipSpeed, LinkAudioScriptSourceRelationInput, LinkClipAnchorRelationInput, LinkGeneratedRelationInput, LinkPhoneticScriptRenderRelationInput, LinkRelationInput, MoveClipInput, MoveClipsToStartsInput, MoveSequentialClipsInput, MoveVoiceoverInput, PatchCaptionStyleInput, ReplaceClipContentInput, SandboxCheckpoint, SandboxEntity, SandboxRelation, ScriptTextSegment, SequenceDuration, SequenceRange, SequentialClipAnchor, SetCaptionVisibilityInput, SetClipPlacementInput, SetClipSpeedInput, SetClipVolumeInput, StoredEntityPayload, TimelineApi, TrimClipInput, UnboundedConstantSequencePayload, UnlinkRelationInput, UpdateClipInput, UpdateClipMarkerInput, UpdateEntityInput, checkpoint, edit, entities, inputs, relations, rollbackTo, timeline };
|
|
596
453
|
//# sourceMappingURL=sandbox-api.d.mts.map
|
|
@@ -183,7 +183,7 @@ function createId(value, label) {
|
|
|
183
183
|
//#region ../medeo-dsl/src/json-values.ts
|
|
184
184
|
const nativeObjectConstructorSource = Function.prototype.toString.call(Object);
|
|
185
185
|
function isJsonObject(value) {
|
|
186
|
-
return
|
|
186
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && isJsonValue(value, /* @__PURE__ */ new Set());
|
|
187
187
|
}
|
|
188
188
|
function isJsonValue(value, ancestors) {
|
|
189
189
|
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
@@ -422,9 +422,8 @@ function entityToRow(entity) {
|
|
|
422
422
|
//#region ../medeo-dsl/src/invariants.ts
|
|
423
423
|
/**
|
|
424
424
|
* Media variants own their Asset identity directly: a `physical-asset`
|
|
425
|
-
* Relation may not bind them. Caption
|
|
426
|
-
*
|
|
427
|
-
* open for future physical pipeline semantics.
|
|
425
|
+
* Relation may not bind them. Caption may associate with a physical text Asset
|
|
426
|
+
* independently of its AudioScript composition.
|
|
428
427
|
*/
|
|
429
428
|
function validateMediaAssetIdentity(entity, index) {
|
|
430
429
|
return [...index.relationsOf(entity)].filter((relation) => relation.kind === "physical-asset").map(() => ({
|
|
@@ -583,11 +582,6 @@ function validatePhoneticComposition(phonetic, index, entities = []) {
|
|
|
583
582
|
}
|
|
584
583
|
function validateVariantComposition(variant, index, entities, kind) {
|
|
585
584
|
const issues = [];
|
|
586
|
-
if (kind === "caption" && ofKind([...index.relationsOf(variant)], "physical-asset").length > 0) issues.push({
|
|
587
|
-
code: "caption_physical_asset_forbidden",
|
|
588
|
-
entityId: variant.entityId,
|
|
589
|
-
message: "Caption text is composed from its AudioScript; Caption must not bind a Physical Asset"
|
|
590
|
-
});
|
|
591
585
|
const rows = {
|
|
592
586
|
entities: collectRelatedEntities([...entities, variant], index).entities.map((ref) => entityToRow(ref.current())),
|
|
593
587
|
relations: []
|
|
@@ -1523,6 +1517,98 @@ function errorMessage(error) {
|
|
|
1523
1517
|
return error instanceof Error ? error.message : String(error);
|
|
1524
1518
|
}
|
|
1525
1519
|
//#endregion
|
|
1520
|
+
//#region src/sandbox/business-facades.ts
|
|
1521
|
+
/** Resource locators are host-owned even when stored on a typed media entity. */
|
|
1522
|
+
const infrastructureFields = new Set(["external", "storageKey"]);
|
|
1523
|
+
function businessEntity(entity) {
|
|
1524
|
+
return {
|
|
1525
|
+
...entity,
|
|
1526
|
+
payload: Object.fromEntries(Object.entries(entity.payload).filter(([key]) => !infrastructureFields.has(key)))
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
function businessState(state) {
|
|
1530
|
+
const assets = new Set(state.entities.filter((row) => row.entity_kind === "asset").map((row) => row.entity_id));
|
|
1531
|
+
return {
|
|
1532
|
+
revision: state.revision,
|
|
1533
|
+
audioScriptEntityId: state.audioScriptEntityId,
|
|
1534
|
+
entities: state.entities.filter((row) => !assets.has(row.entity_id)).map(businessEntity),
|
|
1535
|
+
relations: state.relations.filter((row) => row.relation_kind !== "physical-asset" && !assets.has(row.endpoint_0_entity_id) && !assets.has(row.endpoint_1_entity_id))
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1538
|
+
/** Keep infrastructure rows available to assembly without exposing their management to scripts. */
|
|
1539
|
+
function businessFacades(entities, relations) {
|
|
1540
|
+
const isAsset = (id) => entities.get(id)?.entity_kind === "asset";
|
|
1541
|
+
const assertBusiness = (id) => {
|
|
1542
|
+
if (isAsset(id)) throw new Error("Asset entities are managed by host assembly");
|
|
1543
|
+
};
|
|
1544
|
+
const assertBusinessPayload = (payload) => {
|
|
1545
|
+
for (const field of infrastructureFields) if (Object.hasOwn(payload, field)) throw new Error(`Field ${field} is managed by host assembly`);
|
|
1546
|
+
if (Array.isArray(payload.baseEntityIds)) {
|
|
1547
|
+
for (const id of payload.baseEntityIds) if (typeof id === "string") assertBusiness(id);
|
|
1548
|
+
}
|
|
1549
|
+
};
|
|
1550
|
+
const visibleRelation = (relation) => relation.relation_kind !== "physical-asset" && !isAsset(relation.endpoint_0_entity_id) && !isAsset(relation.endpoint_1_entity_id);
|
|
1551
|
+
return {
|
|
1552
|
+
entities: {
|
|
1553
|
+
list: () => entities.list().filter((entity) => entity.entity_kind !== "asset").map(businessEntity),
|
|
1554
|
+
get: (id) => {
|
|
1555
|
+
const entity = entities.get(id);
|
|
1556
|
+
return entity && !isAsset(id) ? businessEntity(entity) : null;
|
|
1557
|
+
},
|
|
1558
|
+
create: (input) => {
|
|
1559
|
+
if (input.entity_kind === "asset") throw new Error("Asset entities are managed by host assembly");
|
|
1560
|
+
assertBusinessPayload(input.payload);
|
|
1561
|
+
return entities.create(input);
|
|
1562
|
+
},
|
|
1563
|
+
update: (input) => {
|
|
1564
|
+
assertBusiness(input.entity_id);
|
|
1565
|
+
assertBusinessPayload(input.payload);
|
|
1566
|
+
entities.update(input);
|
|
1567
|
+
},
|
|
1568
|
+
declareFields: (input) => {
|
|
1569
|
+
assertBusiness(input.entity_id);
|
|
1570
|
+
assertBusinessPayload(input.payload);
|
|
1571
|
+
entities.declareFields(input);
|
|
1572
|
+
},
|
|
1573
|
+
delete: (input) => {
|
|
1574
|
+
assertBusiness(input.entity_id);
|
|
1575
|
+
const incident = relations.of(input.entity_id);
|
|
1576
|
+
if (incident.some(visibleRelation)) {
|
|
1577
|
+
entities.delete(input);
|
|
1578
|
+
return;
|
|
1579
|
+
}
|
|
1580
|
+
for (const relation of incident) relations.unlink({ relation_id: relation.relation_id });
|
|
1581
|
+
entities.delete(input);
|
|
1582
|
+
},
|
|
1583
|
+
readCaptionContent: (input) => entities.readCaptionContent(input),
|
|
1584
|
+
readPhoneticScriptContent: (input) => entities.readPhoneticScriptContent(input)
|
|
1585
|
+
},
|
|
1586
|
+
relations: {
|
|
1587
|
+
list: () => relations.list().filter(visibleRelation),
|
|
1588
|
+
of: (id, kind) => relations.of(id, kind).filter(visibleRelation),
|
|
1589
|
+
link: (input) => {
|
|
1590
|
+
if (input.relation_kind === "physical-asset") throw new Error("Asset bindings are managed by host assembly");
|
|
1591
|
+
assertBusiness(input.endpoint_0_entity_id);
|
|
1592
|
+
assertBusiness(input.endpoint_1_entity_id);
|
|
1593
|
+
return relations.link(input);
|
|
1594
|
+
},
|
|
1595
|
+
unlink: (input) => {
|
|
1596
|
+
const relation = relations.list().find((row) => row.relation_id === input.relation_id);
|
|
1597
|
+
if (relation && !visibleRelation(relation)) throw new Error("Asset bindings are managed by host assembly");
|
|
1598
|
+
relations.unlink(input);
|
|
1599
|
+
},
|
|
1600
|
+
linkGenerated: (input) => {
|
|
1601
|
+
assertBusiness(input.output_entity_id);
|
|
1602
|
+
assertBusiness(input.input_entity_id);
|
|
1603
|
+
return relations.linkGenerated(input);
|
|
1604
|
+
},
|
|
1605
|
+
linkClipAnchor: (input) => relations.linkClipAnchor(input),
|
|
1606
|
+
linkPhoneticScriptRender: (input) => relations.linkPhoneticScriptRender(input),
|
|
1607
|
+
linkAudioScriptSource: (input) => relations.linkAudioScriptSource(input)
|
|
1608
|
+
}
|
|
1609
|
+
};
|
|
1610
|
+
}
|
|
1611
|
+
//#endregion
|
|
1526
1612
|
//#region src/entity/entity-sandbox.ts
|
|
1527
1613
|
const ASSET_SOURCE_KEY = "external";
|
|
1528
1614
|
const MEMOTA_SYSTEM = "memota";
|
|
@@ -1560,16 +1646,11 @@ var EntitySandbox = class {
|
|
|
1560
1646
|
ensureFoundation(timelinePayload = {}) {
|
|
1561
1647
|
const foundation = ensureEditorFoundation(toDslRows(this.state), this.idFactory, timelinePayload);
|
|
1562
1648
|
this.appendResourceRows(foundation.rows);
|
|
1649
|
+
if (this.state.audioScriptEntityId === null) this.state.audioScriptEntityId = foundation.audioScriptEntityId;
|
|
1563
1650
|
}
|
|
1564
1651
|
get audioScriptEntityId() {
|
|
1565
1652
|
return this.state.audioScriptEntityId;
|
|
1566
1653
|
}
|
|
1567
|
-
setDocumentAudioScript(audioScriptEntityId) {
|
|
1568
|
-
this.record({
|
|
1569
|
-
kind: "set-document-audio-script",
|
|
1570
|
-
audioScriptEntityId
|
|
1571
|
-
});
|
|
1572
|
-
}
|
|
1573
1654
|
rollbackTo(index) {
|
|
1574
1655
|
if (!Number.isInteger(index) || index < 0 || index > this.commands.length) throw new Error(`rollbackTo: entity checkpoint index ${index} is past journal length ${this.commands.length}`);
|
|
1575
1656
|
const prefix = this.commands.slice(0, index);
|
|
@@ -1582,11 +1663,13 @@ var EntitySandbox = class {
|
|
|
1582
1663
|
buildPlan() {
|
|
1583
1664
|
const rows = toDslRows(this.state);
|
|
1584
1665
|
decodeEntityRelationRows(rows, numericMarkerComparators);
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1666
|
+
if (this.state.revision !== 0 || rows.entities.length !== 0 || this.commands.length !== 0) {
|
|
1667
|
+
assertCanonicalEditorResources(rows);
|
|
1668
|
+
readDocumentAudioScript({
|
|
1669
|
+
rows,
|
|
1670
|
+
audioScriptEntityId: this.state.audioScriptEntityId
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1590
1673
|
const currentEntityIds = new Set(this.state.entities.map((entity) => entity.entity_id));
|
|
1591
1674
|
const currentRelationIds = new Set(this.state.relations.map((relation) => relation.relation_id));
|
|
1592
1675
|
return {
|
|
@@ -1600,9 +1683,6 @@ var EntitySandbox = class {
|
|
|
1600
1683
|
renderPreview() {
|
|
1601
1684
|
const lines = [`Entity plan: base_revision=${this.original.revision} commands=${this.commands.length} entities=${this.state.entities.length} relations=${this.state.relations.length}`];
|
|
1602
1685
|
for (const command of this.commands) switch (command.kind) {
|
|
1603
|
-
case "set-document-audio-script":
|
|
1604
|
-
lines.push(`~ document audioScriptEntityId=${command.audioScriptEntityId}`);
|
|
1605
|
-
break;
|
|
1606
1686
|
case "create-entity":
|
|
1607
1687
|
lines.push(`+ entity ${command.entity.entity_id} kind=${command.entity.entity_kind}`);
|
|
1608
1688
|
break;
|
|
@@ -1722,6 +1802,10 @@ var EntitySandbox = class {
|
|
|
1722
1802
|
}
|
|
1723
1803
|
const entityId = input.entity_id ?? this.idFactory("entity");
|
|
1724
1804
|
assertTrimmed(entityId, "entity_id");
|
|
1805
|
+
if (input.entity_kind === "audio-script") {
|
|
1806
|
+
const existing = this.state.entities.find((entity) => entity.entity_kind === "audio-script");
|
|
1807
|
+
if (existing !== void 0 && existing.entity_id !== entityId) throw new Error(`Editor requires exactly one AudioScript; edit ${existing.entity_id} instead of creating ${entityId}`);
|
|
1808
|
+
}
|
|
1725
1809
|
const entity = {
|
|
1726
1810
|
entity_id: entityId,
|
|
1727
1811
|
entity_kind: input.entity_kind,
|
|
@@ -1949,18 +2033,13 @@ var EntitySandbox = class {
|
|
|
1949
2033
|
}
|
|
1950
2034
|
apply(command, enforceIdentity) {
|
|
1951
2035
|
switch (command.kind) {
|
|
1952
|
-
case "set-document-audio-script":
|
|
1953
|
-
readDocumentAudioScript({
|
|
1954
|
-
rows: toDslRows(this.state),
|
|
1955
|
-
audioScriptEntityId: command.audioScriptEntityId
|
|
1956
|
-
});
|
|
1957
|
-
this.state.audioScriptEntityId = command.audioScriptEntityId;
|
|
1958
|
-
return;
|
|
1959
2036
|
case "create-entity": {
|
|
2037
|
+
if (command.entity.entity_kind === "audio-script" && this.state.entities.some((entity) => entity.entity_kind === "audio-script")) throw new Error("The project AudioScript already exists; edit its segments instead");
|
|
1960
2038
|
if (enforceIdentity && this.state.entities.some((entity) => entity.entity_id === command.entity.entity_id)) throw new Error(`Entity id "${command.entity.entity_id}" already exists`);
|
|
1961
2039
|
const original = this.original.entities.find((entity) => entity.entity_id === command.entity.entity_id);
|
|
1962
2040
|
if (enforceIdentity && original != null && original.entity_kind !== command.entity.entity_kind) throw new Error(`Entity id "${command.entity.entity_id}" was originally kind "${original.entity_kind}" and cannot be recreated as "${command.entity.entity_kind}"`);
|
|
1963
2041
|
this.state.entities.push(clone(command.entity));
|
|
2042
|
+
if (command.entity.entity_kind === "audio-script" && this.state.audioScriptEntityId === null) this.state.audioScriptEntityId = command.entity.entity_id;
|
|
1964
2043
|
return;
|
|
1965
2044
|
}
|
|
1966
2045
|
case "update-entity": {
|
|
@@ -1975,7 +2054,7 @@ var EntitySandbox = class {
|
|
|
1975
2054
|
return;
|
|
1976
2055
|
}
|
|
1977
2056
|
case "delete-entity": {
|
|
1978
|
-
if (this.state.
|
|
2057
|
+
if (this.state.entities.find((entity) => entity.entity_id === command.entity_id)?.entity_kind === "audio-script") throw new Error("The document AudioScript is a fixed project identity and cannot be deleted");
|
|
1979
2058
|
const index = this.state.entities.findIndex((entity) => entity.entity_id === command.entity_id);
|
|
1980
2059
|
if (index < 0) throw new Error(`Entity id "${command.entity_id}" does not exist`);
|
|
1981
2060
|
const incidentRelationIds = this.state.relations.filter((relation) => relation.endpoint_0_entity_id === command.entity_id || relation.endpoint_1_entity_id === command.entity_id).map((relation) => relation.relation_id).sort();
|
|
@@ -2393,6 +2472,6 @@ function replayJournalSync(adapter, journal) {
|
|
|
2393
2472
|
}
|
|
2394
2473
|
}
|
|
2395
2474
|
//#endregion
|
|
2396
|
-
export {
|
|
2475
|
+
export { createEntityId as a, collectAffectedPartIds as c, businessState as i, renderPreview as l, EntitySandbox as n, createRelationId as o, businessFacades as r, isMediaAssetVariantKind as s, EditSandboxSession as t, renderCompactProjection as u };
|
|
2397
2476
|
|
|
2398
|
-
//# sourceMappingURL=script-session-
|
|
2477
|
+
//# sourceMappingURL=script-session-DTq_VPEA.mjs.map
|