@mengine/medeo-client 2.0.1-alpha.20 → 2.0.1-alpha.21

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.
@@ -1177,7 +1177,8 @@ function toAuthoritativePartLibrary(partLibrary) {
1177
1177
  if (typeof part !== "object" || part == null) continue;
1178
1178
  if (part.video_clip != null) out[partId] = { video_clip: withTrimWindowFromDuration(part.video_clip) };
1179
1179
  else if (part.speech != null) {
1180
- const { duration_ms, rest } = splitDurationMs(part.speech);
1180
+ const { origin_asset_system: _originAssetSystem, ...readSpeech } = part.speech;
1181
+ const { duration_ms, rest } = splitDurationMs(readSpeech);
1181
1182
  out[partId] = { speech: {
1182
1183
  ...rest,
1183
1184
  media_duration_ms: rest.media_duration_ms ?? duration_ms
@@ -3035,7 +3036,7 @@ function resolveGraphLayout(graph) {
3035
3036
  if (clip.entityKind !== "clip" || graph.adjacent(clip.entityId, "track-clip").length !== 1) fail(`Clip ${clip.entityId} must belong to exactly one Track`);
3036
3037
  const marker = graph.one(clip.entityId, "clip-marker", "sequence-marker");
3037
3038
  const content = graph.one(marker.entityId, "marker-content");
3038
- if (!(typedRole === "video_clip" ? ["image", "video"] : typedRole === "speech" ? ["voiceover"] : typedRole === "caption" ? ["caption"] : ["audio"]).includes(content.entityKind)) fail(`unsupported compatibility content kind ${content.entityKind} on ${typedRole} Track`);
3039
+ assertTrackContent(graph, typedRole, content);
3039
3040
  const source = range(marker.payload.sourceRange, "sourceRange");
3040
3041
  const durationFact = marker.payload.duration;
3041
3042
  if (!object(durationFact)) fail(`Marker ${marker.entityId} requires duration`);
@@ -3154,6 +3155,32 @@ function resolveGraphLayout(graph) {
3154
3155
  }))
3155
3156
  };
3156
3157
  }
3158
+ function assertTrackContent(graph, role, content) {
3159
+ if (role === "speech") {
3160
+ assertSpeechContent(graph, content);
3161
+ return;
3162
+ }
3163
+ if (!(role === "video_clip" ? ["image", "video"] : role === "caption" ? ["caption"] : ["audio"]).includes(content.entityKind)) fail(`unsupported compatibility content kind ${content.entityKind} on ${role} Track`);
3164
+ }
3165
+ function assertSpeechContent(graph, content) {
3166
+ const assetLinks = graph.rows.relations.filter((relation) => relation.relationKind === "from-asset" && (relation.endpoint0EntityId === content.entityId || relation.endpoint1EntityId === content.entityId));
3167
+ if (assetLinks.length !== 1 || assetLinks[0].endpoint0EntityId !== content.entityId) fail("Speech content requires one ordered from-asset binding");
3168
+ const asset = graph.entity(assetLinks[0].endpoint1EntityId, "asset");
3169
+ if (content.entityKind === "voiceover") {
3170
+ const renders = graph.rows.relations.filter((relation) => relation.relationKind === "phonetic-script-render" && (relation.endpoint0EntityId === content.entityId || relation.endpoint1EntityId === content.entityId));
3171
+ if (renders.length !== 1 || renders[0].endpoint0EntityId !== content.entityId || graph.entity(renders[0].endpoint1EntityId).entityKind !== "phonetic-script") fail("Synthesized Speech Voiceover requires one ordered PhoneticScript render");
3172
+ if (asset.payload.system !== "memota-speech") fail("Synthesized Speech Voiceover requires an explicit memota-speech key");
3173
+ return;
3174
+ }
3175
+ if (content.entityKind === "audio") {
3176
+ const sources = graph.rows.relations.filter((relation) => relation.relationKind === "audio-script-source" && (relation.endpoint0EntityId === content.entityId || relation.endpoint1EntityId === content.entityId));
3177
+ if (sources.length > 1) fail("Recorded speech has an ambiguous AudioScript source receipt");
3178
+ if (sources.length === 1 && (sources[0].endpoint1EntityId !== content.entityId || graph.entity(sources[0].endpoint0EntityId).entityKind !== "audio-script")) fail("Recorded Speech AudioScript source must use ordered endpoints");
3179
+ if (asset.payload.system !== "memota") fail("Recorded Speech Audio requires an explicit memota key");
3180
+ return;
3181
+ }
3182
+ fail(`unsupported compatibility content kind ${content.entityKind} on speech Track`);
3183
+ }
3157
3184
  //#endregion
3158
3185
  //#region src/document/entity-projection.ts
3159
3186
  /**
@@ -3195,20 +3222,21 @@ function projectEntityTimeline(rows) {
3195
3222
  } else if (track.role === "speech") {
3196
3223
  const asset = mediaAssetFacts(graph, content);
3197
3224
  requireUntrimmedAudio(content, marker, placement);
3198
- const external = externalLocator(asset, "memota-speech");
3199
- const renderEdges = graph.adjacent(content.entityId, "phonetic-script-render");
3200
3225
  const timbreEdges = graph.adjacent(content.entityId, "voice-timbre");
3201
- const assembled = renderEdges.length > 0 || timbreEdges.length > 0 ? assemblePhoneticScriptContent(rows, graph.one(content.entityId, "phonetic-script-render", "phonetic-script").entityId) : void 0;
3226
+ const isSynthesized = content.entityKind === "voiceover";
3227
+ const external = externalLocator(asset, isSynthesized ? "memota-speech" : "memota");
3228
+ const assembled = isSynthesized ? assemblePhoneticScriptContent(rows, graph.one(content.entityId, "phonetic-script-render", "phonetic-script").entityId) : void 0;
3202
3229
  if (timbreEdges.length > 1) fail("A voiceover resolves at most one Voice identity");
3203
3230
  const voice = timbreEdges.length === 0 ? void 0 : graph.one(content.entityId, "voice-timbre", "voice").payload.voice;
3204
3231
  if (voice !== void 0 && (!object(voice) || voice.system !== "voice-library" || typeof voice.key !== "string")) fail("Voice must use an explicit voice-library locator");
3205
3232
  const captionIds = layout.tracks.flatMap((candidate) => candidate.role === "caption" ? candidate.clips.filter((caption) => caption.anchorClipEntityId === clip.entityId).map((caption) => caption.clipEntityId) : []);
3206
- parts[clip.entityId] = { speech: {
3233
+ const speech = {
3207
3234
  id: clip.entityId,
3208
3235
  kind: "speech",
3209
3236
  media_duration_ms: placement.duration,
3210
3237
  audio_storage_key: storageKey(asset),
3211
3238
  origin_speech_id: external.key,
3239
+ origin_asset_system: external.system,
3212
3240
  audio_script: assembled?.text ?? (graph.adjacent(content.entityId, "audio-script-source").length > 0 ? assembleScriptText(graph.one(content.entityId, "audio-script-source", "audio-script")) : ""),
3213
3241
  volume: volume.data,
3214
3242
  voice: object(voice) ? {
@@ -3216,7 +3244,8 @@ function projectEntityTimeline(rows) {
3216
3244
  name: typeof voice.name === "string" ? voice.name : void 0
3217
3245
  } : void 0,
3218
3246
  caption_ids: captionIds
3219
- } };
3247
+ };
3248
+ parts[clip.entityId] = { speech };
3220
3249
  } else if (track.role === "caption") {
3221
3250
  const assembled = assembleCaptionContent(rows, content.entityId);
3222
3251
  const text = assembled.text;
@@ -3296,7 +3325,10 @@ function storageKey(asset) {
3296
3325
  function externalLocator(asset, system) {
3297
3326
  const { system: found, key } = asset.payload;
3298
3327
  if (found !== system || typeof key !== "string" || key.trim() === "") fail("Asset " + asset.entityId + " requires an explicit " + system + " key");
3299
- return { key };
3328
+ return {
3329
+ key,
3330
+ system
3331
+ };
3300
3332
  }
3301
3333
  function captionStyle(value) {
3302
3334
  if (value === void 0) return void 0;
@@ -3940,6 +3972,25 @@ var LoroEntityDocument = class LoroEntityDocument {
3940
3972
  if (id === void 0) return [];
3941
3973
  return this.snapshot().rows.relations.filter((row) => row.endpoint0EntityId === id || row.endpoint1EntityId === id);
3942
3974
  }
3975
+ /** Read unlinked Relation records for durable effect receipts; never part of the current semantic graph. */
3976
+ tombstonedRelations() {
3977
+ const result = [];
3978
+ for (const key of section(this.doc, "relations").keys().sort((a, b) => a < b ? -1 : a > b ? 1 : 0)) {
3979
+ const map = section(this.doc, "relations").get(key);
3980
+ if (!(map instanceof LoroMap) || map.get("deleted") !== true) continue;
3981
+ const identity = map.get("identity");
3982
+ if (!identity || identity.endpoints.length !== 2) throw new Error(`Invalid tombstoned Relation ${key}`);
3983
+ result.push({
3984
+ relationId: createRelationId(key),
3985
+ relationKind: identity.kind,
3986
+ endpoint0EntityId: createEntityId(identity.endpoints[0]),
3987
+ endpoint1EntityId: createEntityId(identity.endpoints[1]),
3988
+ metadata: requireMap(map, "metadata").toJSON(),
3989
+ trace: requireMap(map, "trace").toJSON()
3990
+ });
3991
+ }
3992
+ return result;
3993
+ }
3943
3994
  /** Resolve a queued edit target through its native identity without changing history. */
3944
3995
  resolveCurrentEntityId(id) {
3945
3996
  return currentId(this.doc, id);
@@ -4727,4 +4778,4 @@ function createPlainMemoryAdapter(document, options) {
4727
4778
  return new PlainMemoryAdapter(document, options);
4728
4779
  }
4729
4780
  //#endregion
4730
- export { partUnionSchema as $, decodeEntityRelationRows as A, isJsonObject as B, applyFieldChanges as C, recordEntries as Ct, EntityProjectionGraph as D, projectEntityTimeline as E, bytesToBase64 as Et, assembleScriptText as F, buildInitialVideoDocument as G, createRelationId as H, findComposedAudioScript as I, fromVideoDocument as J, buildSpeechHostMap as K, selectAudioScriptSegment as L, assembleCaptionContent as M, assembleEntityContent as N, resolveEntityTimelineLayout as O, assemblePhoneticScriptContent as P, validateVideoDocument as Q, updateEntityFields as R, equalJson as S, partUnionToDraft as St, resolveFieldPath as T, base64ToBytes as Tt, hasSequence as U, createEntityId as V, isMediaAssetVariantKind as W, VideoDocumentValidationError as X, toVideoDocument as Y, assertValidVideoDocument as Z, audioScriptAssetOf as _, partDurationMs as _t, createMirrorVideoDocument as a, laneTrackId as at, phoneticScriptAssetOf as b, effectiveVideoClipDurationMs as bt, DocumentMutationGuard as c, arrangeMainTrackSeamlessly as ct, LoroEntityDraft as d, recalculateTimelineDuration as dt, videoDocumentSchema as et, readEntityDocument as f, resolveAllSpeechOverlaps as ft, audioScriptAssetHash as g, isEmptyVideoClip as gt, audioScriptAssetFields as h, TIMELINE_SKELETON_DURATION_MS as ht, MirrorVideoDocumentAdapter as i, hasResolvedPlacement as it, ScriptCompositionError as j, EntityTimelineProjectionError as k, LORO_ENTITY_SCHEMA as l, fillMainTrackTimeGaps as lt, audioScriptAssetContent as m, syncAggregatedClipsTimePosition as mt, createPlainMemoryAdapter as n, ensureLaneTrack as nt, createMirrorVideoDocumentAdapter as o, solveVideoDocument as ot, entityOrderGroups as p, resolveSpeechOverlapByShiftingVideos as pt, derivePositionFromAbs as q, generatePartId as r, findLaneTrack as rt, readVideoDocumentFromDraft as s, cascadeAfterVideoClipChanges as st, PlainMemoryAdapter as t, LANE_KINDS_IN_STACK_ORDER as tt, LoroEntityDocument as u, reassignSpeechesToVideoClipsByTime as ut, phoneticScriptAssetContent as v, safeDurationMs as vt, assertFieldChanges as w, videoDocumentMirrorSchema as wt, scriptSourceAssetOf as x, speedOf as xt, phoneticScriptAssetHash as y, DEFAULT_UNIT_TIME_MS as yt, variantBaseEntityIds as z };
4781
+ export { validateVideoDocument as $, EntityTimelineProjectionError as A, variantBaseEntityIds as B, equalJson as C, partUnionToDraft as Ct, projectEntityTimeline as D, bytesToBase64 as Dt, resolveFieldPath as E, base64ToBytes as Et, assemblePhoneticScriptContent as F, isMediaAssetVariantKind as G, createEntityId as H, assembleScriptText as I, derivePositionFromAbs as J, buildInitialVideoDocument as K, findComposedAudioScript as L, ScriptCompositionError as M, assembleCaptionContent as N, EntityProjectionGraph as O, assembleEntityContent as P, assertValidVideoDocument as Q, selectAudioScriptSegment as R, canonicalJson as S, speedOf as St, assertFieldChanges as T, videoDocumentMirrorSchema as Tt, createRelationId as U, isJsonObject as V, hasSequence as W, toVideoDocument as X, fromVideoDocument as Y, VideoDocumentValidationError as Z, audioScriptAssetOf as _, isEmptyVideoClip as _t, createMirrorVideoDocument as a, hasResolvedPlacement as at, phoneticScriptAssetOf as b, DEFAULT_UNIT_TIME_MS as bt, DocumentMutationGuard as c, cascadeAfterVideoClipChanges as ct, LoroEntityDraft as d, reassignSpeechesToVideoClipsByTime as dt, partUnionSchema as et, readEntityDocument as f, recalculateTimelineDuration as ft, audioScriptAssetHash as g, TIMELINE_SKELETON_DURATION_MS as gt, audioScriptAssetFields as h, syncAggregatedClipsTimePosition as ht, MirrorVideoDocumentAdapter as i, findLaneTrack as it, decodeEntityRelationRows as j, resolveEntityTimelineLayout as k, LORO_ENTITY_SCHEMA as l, arrangeMainTrackSeamlessly as lt, audioScriptAssetContent as m, resolveSpeechOverlapByShiftingVideos as mt, createPlainMemoryAdapter as n, LANE_KINDS_IN_STACK_ORDER as nt, createMirrorVideoDocumentAdapter as o, laneTrackId as ot, entityOrderGroups as p, resolveAllSpeechOverlaps as pt, buildSpeechHostMap as q, generatePartId as r, ensureLaneTrack as rt, readVideoDocumentFromDraft as s, solveVideoDocument as st, PlainMemoryAdapter as t, videoDocumentSchema as tt, LoroEntityDocument as u, fillMainTrackTimeGaps as ut, phoneticScriptAssetContent as v, partDurationMs as vt, applyFieldChanges as w, recordEntries as wt, scriptSourceAssetOf as x, effectiveVideoClipDurationMs as xt, phoneticScriptAssetHash as y, safeDurationMs as yt, updateEntityFields as z };
@@ -473,6 +473,8 @@ type VideoClipPart = Omit<VideoClipPart$1, 'duration_ms'>;
473
473
  type SpeechPart = Omit<SpeechPart$1, 'duration_ms'> & {
474
474
  media_duration_ms?: number | undefined;
475
475
  };
476
+ /** Asset namespace exposed only by the legacy read view; never an authoritative Speech fact. */
477
+ type SpeechOriginAssetSystem = 'memota' | 'memota-speech';
476
478
  /**
477
479
  * Authoritative caption part. The IDL `CaptionPart` carries `duration_ms` (the
478
480
  * effective display length, a derived read-view value); the authoritative store
@@ -621,7 +623,8 @@ type VideoDraftPartUnion = {
621
623
  } | {
622
624
  video_clip?: never;
623
625
  speech: SpeechPart & {
624
- duration_ms?: number;
626
+ duration_ms?: number; /** Absent only on historical drafts created before this read-view discriminator. */
627
+ origin_asset_system?: SpeechOriginAssetSystem;
625
628
  };
626
629
  caption?: never;
627
630
  bgm?: never;
@@ -669,6 +672,7 @@ type VideoDraftContentPartUnion = {
669
672
  video_clip?: never;
670
673
  speech: SpeechPart & {
671
674
  duration_ms: number | undefined;
675
+ origin_asset_system?: SpeechOriginAssetSystem;
672
676
  };
673
677
  caption?: never;
674
678
  bgm?: never;
@@ -1143,12 +1147,26 @@ declare class EntityTimelineProjectionError extends Error {
1143
1147
  }
1144
1148
  //#endregion
1145
1149
  //#region src/document/entity-projection.d.ts
1150
+ type EntityTimelineProjectionPart = Exclude<PartUnion, {
1151
+ speech: SpeechPart;
1152
+ }> | {
1153
+ video_clip?: never;
1154
+ speech: SpeechPart & {
1155
+ origin_asset_system: SpeechOriginAssetSystem;
1156
+ };
1157
+ caption?: never;
1158
+ bgm?: never;
1159
+ };
1160
+ /** Ephemeral compatibility document; the origin discriminator is never stored in Loro. */
1161
+ type EntityTimelineProjectionDocument = Omit<VideoDocument, 'part_library'> & {
1162
+ part_library: Record<string, EntityTimelineProjectionPart>;
1163
+ };
1146
1164
  /**
1147
1165
  * One-way compatibility view over the Entity graph. A legacy part is never
1148
1166
  * consulted as an editing fact. Peer IDs appear only in this derived read
1149
1167
  * contract, reconstructed from relations; they are not stored in payloads.
1150
1168
  */
1151
- declare function projectEntityTimeline(rows: EntityRelationRows): VideoDocument;
1169
+ declare function projectEntityTimeline(rows: EntityRelationRows): EntityTimelineProjectionDocument;
1152
1170
  //#endregion
1153
1171
  //#region src/document/entity-timeline-layout.d.ts
1154
1172
  type EntityTimelineTrackRole = 'video_clip' | 'speech' | 'caption' | 'bgm';
@@ -1870,4 +1888,4 @@ declare const videoDocumentSchema: z.ZodObject<{
1870
1888
  }, z.core.$loose>]>>>;
1871
1889
  }, z.core.$loose>;
1872
1890
  //#endregion
1873
- export { SpeechHostMap as $, assertValidVideoDocument as A, VideoDocumentValidationIssueCode as At, EntityRow as B, SpeedShift as Bt, isImplementedSemanticOpKind as C, Timeline as Ct, PartIdFactory as D, VideoClipPart as Dt, ValidationError as E, TrackItemTimePosition as Et, ResolvedEntityTrack as F, speedOf as Ft, SequenceDuration as G, CaptionSegmentSelection as H, Track$1 as Ht, resolveEntityTimelineLayout as I, Attachment as It, JsonObject as J, SequenceRange as K, projectEntityTimeline as L, CaptionPart$1 as Lt, EntityTimelineTrackRole as M, VideoDraftContent as Mt, ResolvedEntityClipPlacement as N, VideoDraftPartUnion as Nt, generatePartId as O, VideoDocument as Ot, ResolvedEntityTimelineLayout as P, effectiveVideoClipDurationMs as Pt, DerivedItemPosition as Q, EntityTimelineProjectionError as R, CaptionStyle as Rt, SemanticOpKind as S, SpeechPart as St, SnapshotReadable as T, TrackItem as Tt, CaptionStyleFields as U, TrackItem$1 as Ut, RelationRow as V, Timeline$1 as Vt, ScriptTextSegment as W, EntityId as X, JsonValue as Y, buildInitialVideoDocument as Z, SemanticOpName as _, CaptionDisplayCue as _t, PlainMemoryAdapter as a, LaneKind as at, ImplementedSemanticOpKind as b, PartKind as bt, MirrorVideoDocumentAdapter as c, findLaneTrack as ct, createMirrorVideoDocumentAdapter as d, TrackDraft as dt, buildSpeechHostMap as et, CommitOptions as f, TrackItemDraft as ft, SemanticOpInput as g, BgmPart as gt, SemanticEditor as h, videoDocumentMirrorSchema as ht, JournalEntry as i, LANE_KINDS_IN_STACK_ORDER as it, validateVideoDocument as j, VideoDraft as jt, VideoDocumentValidationError as k, VideoDocumentValidationIssue as kt, MirrorVideoDocumentOptions as l, laneTrackId as lt, SemanticDocumentAdapter as m, VideoDocumentMirrorSchema as mt, videoDocumentSchema as n, fromVideoDocument as nt, PlainMemoryAdapterOptions as o, SolvedVideoDocument as ot, OpActor as p, VideoDocumentDraft as pt, VoiceDescriptor as q, readVideoDocumentFromDraft as r, toVideoDocument as rt, createPlainMemoryAdapter as s, ensureLaneTrack as st, partUnionSchema as t, derivePositionFromAbs as tt, createMirrorVideoDocument as u, solveVideoDocument as ut, TransactAudit as v, CaptionPart as vt, SchemaValidator as w, Track as wt, PlannedSemanticOpKind as x, PartUnion as xt, IMPLEMENTED_SEMANTIC_OP_KINDS as y, DEFAULT_UNIT_TIME_MS as yt, EntityRelationRows as z, PartAggregation as zt };
1891
+ export { DerivedItemPosition as $, assertValidVideoDocument as A, VideoDocument as At, EntityRelationRows as B, CaptionStyle as Bt, isImplementedSemanticOpKind as C, SpeechOriginAssetSystem as Ct, PartIdFactory as D, TrackItem as Dt, ValidationError as E, Track as Et, ResolvedEntityTrack as F, VideoDraftPartUnion as Ft, ScriptTextSegment as G, TrackItem$1 as Gt, RelationRow as H, SpeedShift as Ht, resolveEntityTimelineLayout as I, effectiveVideoClipDurationMs as It, VoiceDescriptor as J, SequenceDuration as K, EntityTimelineProjectionDocument as L, speedOf as Lt, EntityTimelineTrackRole as M, VideoDocumentValidationIssueCode as Mt, ResolvedEntityClipPlacement as N, VideoDraft as Nt, generatePartId as O, TrackItemTimePosition as Ot, ResolvedEntityTimelineLayout as P, VideoDraftContent as Pt, buildInitialVideoDocument as Q, projectEntityTimeline as R, Attachment as Rt, SemanticOpKind as S, PartUnion as St, SnapshotReadable as T, Timeline as Tt, CaptionSegmentSelection as U, Timeline$1 as Ut, EntityRow as V, PartAggregation as Vt, CaptionStyleFields as W, Track$1 as Wt, JsonValue as X, JsonObject as Y, EntityId as Z, SemanticOpName as _, BgmPart as _t, PlainMemoryAdapter as a, LANE_KINDS_IN_STACK_ORDER as at, ImplementedSemanticOpKind as b, DEFAULT_UNIT_TIME_MS as bt, MirrorVideoDocumentAdapter as c, ensureLaneTrack as ct, createMirrorVideoDocumentAdapter as d, solveVideoDocument as dt, SpeechHostMap as et, CommitOptions as f, TrackDraft as ft, SemanticOpInput as g, videoDocumentMirrorSchema as gt, SemanticEditor as h, VideoDocumentMirrorSchema as ht, JournalEntry as i, toVideoDocument as it, validateVideoDocument as j, VideoDocumentValidationIssue as jt, VideoDocumentValidationError as k, VideoClipPart as kt, MirrorVideoDocumentOptions as l, findLaneTrack as lt, SemanticDocumentAdapter as m, VideoDocumentDraft as mt, videoDocumentSchema as n, derivePositionFromAbs as nt, PlainMemoryAdapterOptions as o, LaneKind as ot, OpActor as p, TrackItemDraft as pt, SequenceRange as q, readVideoDocumentFromDraft as r, fromVideoDocument as rt, createPlainMemoryAdapter as s, SolvedVideoDocument as st, partUnionSchema as t, buildSpeechHostMap as tt, createMirrorVideoDocument as u, laneTrackId as ut, TransactAudit as v, CaptionDisplayCue as vt, SchemaValidator as w, SpeechPart as wt, PlannedSemanticOpKind as x, PartKind as xt, IMPLEMENTED_SEMANTIC_OP_KINDS as y, CaptionPart as yt, EntityTimelineProjectionError as z, CaptionPart$1 as zt };