@mengine/medeo-client 1.4.1-alpha.4 → 1.4.1-alpha.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/README.md CHANGED
@@ -80,7 +80,7 @@ with `assembleCaptionContent` or `assemblePhoneticScriptContent`. Broken composi
80
80
  fails explicitly. Same-name fields from different bases are rejected even for equal values and even if the variant declares that field. After base fields are unambiguous, explicit own fields may override them without mutating the bases. Recorded Audio/Video/Voice can be the ASR source via
81
81
  `audio-script-source`, without creating a synthesis variant.
82
82
 
83
- `insertCaptionClip` requires `baseEntityIds` and `selections`; its optional `captionEntityId` preserves a generation-provided business identity independently of `captionClipEntityId`. Each selection
83
+ `insertCaptionClip` requires `baseEntityIds` and one `selection` object; its optional `captionEntityId` preserves a generation-provided business identity independently of `captionClipEntityId`. The selection
84
84
  names a source `segmentId` and optionally a half-open Unicode code-point
85
85
  `textRange: {start, end}`. This permits display re-segmentation without rewriting
86
86
  the original script. `upsertVoiceoverTake` requires the real
@@ -1706,15 +1706,15 @@ function assembleCaptionContent(rows, captionEntityId) {
1706
1706
  requireEntityKind(rows, captionEntityId, "caption");
1707
1707
  const caption = assembleEntityContent(rows, captionEntityId);
1708
1708
  const script = findComposedAudioScript(rows, captionEntityId, "caption");
1709
- const segments = selectAudioScriptSegments({
1709
+ const segment = selectAudioScriptSegment({
1710
1710
  ...script,
1711
1711
  payload: caption.payload
1712
- }, captionSelections(caption));
1712
+ }, captionSelection(caption));
1713
1713
  return {
1714
1714
  caption,
1715
1715
  audioScript: script,
1716
- segments,
1717
- text: segments.map((segment) => segment.text).join("")
1716
+ segments: [segment],
1717
+ text: segment.text
1718
1718
  };
1719
1719
  }
1720
1720
  /**
@@ -1736,20 +1736,18 @@ function assemblePhoneticScriptContent(rows, phoneticScriptEntityId) {
1736
1736
  text: segments.map((segment) => segment.text).join("")
1737
1737
  };
1738
1738
  }
1739
- function captionSelections(caption) {
1740
- const selections = caption.payload.selections;
1741
- if (!Array.isArray(selections) || selections.length === 0) throw new ScriptCompositionError("empty_selection", caption.entityId, `Caption "${caption.entityId}" requires a non-empty segment selection into its AudioScript`);
1742
- if (!selections.every(isSegmentSelection)) throw new ScriptCompositionError("invalid_selection", caption.entityId, "Caption selections require a segmentId and optional textRange");
1743
- return selections;
1739
+ function captionSelection(caption) {
1740
+ if (Object.hasOwn(caption.payload, "selections") || !isSegmentSelection(caption.payload.selection)) throw new ScriptCompositionError("invalid_selection", caption.entityId, "Caption requires one selection object with segmentId and optional textRange; selections arrays are forbidden");
1741
+ return caption.payload.selection;
1744
1742
  }
1745
1743
  function isSegmentSelection(value) {
1746
1744
  return typeof value === "object" && value != null && !Array.isArray(value) && typeof value.segmentId === "string" && value.segmentId.trim() !== "" && Object.keys(value).every((key) => key === "segmentId" || key === "textRange");
1747
1745
  }
1748
1746
  /** Select source text without creating another authoritative text field. */
1749
- function selectAudioScriptSegments(script, selections) {
1750
- if (!Array.isArray(selections) || selections.length === 0 || !selections.every(isSegmentSelection) || new Set(selections.map((s) => s.segmentId)).size !== selections.length) throw new ScriptCompositionError("invalid_selection", script.entityId, "Caption selections must be non-empty and name unique source segments");
1747
+ function selectAudioScriptSegment(script, selection) {
1748
+ if (!isSegmentSelection(selection)) throw new ScriptCompositionError("invalid_selection", script.entityId, "Caption requires one selection object with segmentId and optional textRange");
1751
1749
  const bySegmentId = new Map(scriptSegments(script).map((segment) => [segment.segmentId, segment]));
1752
- const selected = selections.map((selection) => {
1750
+ const selected = (() => {
1753
1751
  const segment = bySegmentId.get(selection.segmentId);
1754
1752
  if (segment === void 0) throw new ScriptCompositionError("unknown_segment", script.entityId, `Caption selection "${selection.segmentId}" does not name a segment of AudioScript "${script.entityId}"`);
1755
1753
  if (selection.textRange === void 0) return segment;
@@ -1760,8 +1758,8 @@ function selectAudioScriptSegments(script, selections) {
1760
1758
  ...segment,
1761
1759
  text: points.slice(range.start, range.end).join("")
1762
1760
  };
1763
- });
1764
- if (!selected.map((segment) => segment.text).join("").trim()) throw new ScriptCompositionError("empty_selection", script.entityId, "Caption selection must contain visible source text");
1761
+ })();
1762
+ if (!selected.text.trim()) throw new ScriptCompositionError("empty_selection", script.entityId, "Caption selection must contain visible source text");
1765
1763
  return selected;
1766
1764
  }
1767
1765
  function requireEntityKind(rows, entityIdValue, entityKind) {
@@ -2233,25 +2231,15 @@ function validateVoicePayload(value, problems) {
2233
2231
  function validateCaptionPayload(value, problems) {
2234
2232
  validateExternalLocator(value, problems);
2235
2233
  if (value.segmentRanges !== void 0) validateSegmentRanges(value.segmentRanges, problems);
2236
- const selections = value.selections;
2237
- if (!Array.isArray(selections)) problems.push("selections must be a non-empty array of AudioScript segment selections");
2234
+ if (Object.hasOwn(value, "selections")) problems.push("selections is forbidden; Caption requires one selection object");
2235
+ const selection = value.selection;
2236
+ if (!isRecord(selection)) problems.push("selection must be one AudioScript segment selection object, not an array");
2238
2237
  else {
2239
- if (selections.length === 0) problems.push("selections must name at least one AudioScript segment");
2240
- const seen = /* @__PURE__ */ new Set();
2241
- for (const [index, selection] of selections.entries()) {
2242
- if (!isRecord(selection)) {
2243
- problems.push(`selections[${index}] must be an object`);
2244
- continue;
2245
- }
2246
- if (typeof selection.segmentId !== "string" || selection.segmentId.trim() === "") problems.push(`selections[${index}].segmentId must be a string`);
2247
- else if (seen.has(selection.segmentId)) problems.push(`selections[${index}].segmentId must be unique within the Caption`);
2248
- else seen.add(selection.segmentId);
2249
- if (Object.keys(selection).some((key) => key !== "segmentId" && key !== "textRange")) problems.push(`selections[${index}] may only contain segmentId and textRange`);
2250
- if (selection.textRange !== void 0) {
2251
- const range = selection.textRange;
2252
- if (!isRecord(range) || !Number.isSafeInteger(range.start) || !Number.isSafeInteger(range.end) || range.start < 0 || range.end <= range.start || Object.keys(range).some((key) => key !== "start" && key !== "end")) problems.push(`selections[${index}].textRange must be a non-empty half-open code-point range`);
2253
- }
2254
- }
2238
+ if (typeof selection.segmentId !== "string" || !selection.segmentId.trim()) problems.push("selection.segmentId must be a non-empty string");
2239
+ if (Object.keys(selection).some((key) => key !== "segmentId" && key !== "textRange")) problems.push("selection may only contain segmentId and textRange");
2240
+ const range = selection.textRange;
2241
+ if (range !== void 0 && (!isRecord(range) || !Number.isSafeInteger(range.start) || !Number.isSafeInteger(range.end) || range.start < 0 || range.end <= range.start || Object.keys(range).some((key) => key !== "start" && key !== "end"))) problems.push("selection.textRange must be a non-empty half-open code-point range");
2242
+ if (Array.isArray(value.segmentRanges) && (value.segmentRanges.length !== 1 || !isRecord(value.segmentRanges[0]) || value.segmentRanges[0].segmentId !== selection.segmentId)) problems.push("Caption segmentRanges must contain only the selected segment timing");
2255
2243
  }
2256
2244
  const style = value.style;
2257
2245
  if (style === void 0) return;
@@ -2375,7 +2363,7 @@ function isOwnedLocalEntityValuePath(entityKind, path) {
2375
2363
  if (entityKind === "asset" && /^(?:external\.(?:system|key)|storageKey)$/.test(path)) return true;
2376
2364
  if (isMediaAssetVariantKind(entityKind) && /^(?:external\.(?:system|key)|storageKey)$/.test(path)) return true;
2377
2365
  if (entityKind === "voice" && /^voice\.(?:system|key|name)$/.test(path)) return true;
2378
- if (entityKind === "caption" && (path.startsWith("style.") || /^selections\[\d+\]\.segmentId$/.test(path))) return true;
2366
+ if (entityKind === "caption" && (path.startsWith("style.") || path === "selection.segmentId")) return true;
2379
2367
  if ([
2380
2368
  "audio-script",
2381
2369
  "caption",
@@ -2390,7 +2378,7 @@ function isOwnedLocalIdPath(entityKind, path) {
2390
2378
  "caption",
2391
2379
  "phonetic-script"
2392
2380
  ].includes(entityKind) && /^segments\[\d+\]\.segmentId$/.test(path)) return true;
2393
- if (entityKind === "caption" && /^selections\[\d+\]\.segmentId$/.test(path)) return true;
2381
+ if (entityKind === "caption" && path === "selection.segmentId") return true;
2394
2382
  if ((entityKind === "sequence-marker" || entityKind === "caption") && /^segmentRanges\[\d+\]\.segmentId$/.test(path)) return true;
2395
2383
  if (entityKind === "asset" && /^(?:tracks\[\d+\]\.trackId|renditions\[\d+\]\.renditionId)$/.test(path)) return true;
2396
2384
  return false;
@@ -3344,13 +3332,13 @@ const atomicFields = new Set([
3344
3332
  "extent",
3345
3333
  "timeRemapping",
3346
3334
  "textRange",
3335
+ "selection",
3347
3336
  "external",
3348
3337
  "coordinateSpace"
3349
3338
  ]);
3350
3339
  const textFields = new Set(["text", "phonemeScript"]);
3351
3340
  const orderedFields = new Set([
3352
3341
  "segments",
3353
- "selections",
3354
3342
  "segmentRanges",
3355
3343
  "baseEntityIds"
3356
3344
  ]);
@@ -4078,8 +4066,8 @@ var LoroEntityDraft = class {
4078
4066
  }
4079
4067
  record(command) {
4080
4068
  if (command.type === "create") this.selectedRoots.add(command.row.entityId);
4081
- if (command.type === "write" && !equalJson(content(workspace(this.doc, command.root)).selections, command.payload.selections)) this.selectedRoots.add(command.root);
4082
- if (command.type === "field" && command.path[0] === "selections") this.selectedRoots.add(command.root);
4069
+ if (command.type === "write" && !equalJson(content(workspace(this.doc, command.root)).selection, command.payload.selection)) this.selectedRoots.add(command.root);
4070
+ if (command.type === "field" && command.path[0] === "selection") this.selectedRoots.add(command.root);
4083
4071
  apply(this.doc, command);
4084
4072
  this.commands.push(command);
4085
4073
  }
@@ -4195,17 +4183,14 @@ function writeBases(doc, map, ids) {
4195
4183
  /** Numeric sub-spans must not silently quote different text after a collaborative edit. */
4196
4184
  function selectionFingerprint(rows, id) {
4197
4185
  const row = rows.entities.find((row) => row.entityId === id);
4198
- if (row?.entityKind !== "caption" || !Array.isArray(row.payload.selections)) return void 0;
4199
- const ranged = row.payload.selections.filter((selection) => isJsonObject(selection) && selection.textRange !== void 0);
4200
- if (ranged.length === 0) return void 0;
4186
+ if (row?.entityKind !== "caption" || !isJsonObject(row.payload.selection)) return void 0;
4187
+ const selection = row.payload.selection;
4188
+ if (selection.textRange === void 0) return void 0;
4201
4189
  const segments = assembleEntityContent(rows, row.entityId).payload.segments;
4202
4190
  if (!Array.isArray(segments)) throw new Error("Caption text selection has no source segments");
4203
- return hash(ranged.map((selection) => {
4204
- if (!isJsonObject(selection)) throw new Error("Invalid Caption text selection");
4205
- const source = segments.find((segment) => isJsonObject(segment) && segment.segmentId === selection.segmentId);
4206
- if (!isJsonObject(source) || typeof source.text !== "string") throw new Error("Caption text selection source is missing");
4207
- return [selection, source.text];
4208
- }));
4191
+ const source = segments.find((segment) => isJsonObject(segment) && segment.segmentId === selection.segmentId);
4192
+ if (!isJsonObject(source) || typeof source.text !== "string") throw new Error("Caption text selection source is missing");
4193
+ return hash([selection, source.text]);
4209
4194
  }
4210
4195
  function assertState(state) {
4211
4196
  for (const row of state.rows.entities) assembleEntityContent(state.rows, row.entityId);
@@ -4549,4 +4534,4 @@ function createPlainMemoryAdapter(document, options) {
4549
4534
  return new PlainMemoryAdapter(document, options);
4550
4535
  }
4551
4536
  //#endregion
4552
- export { cascadeAfterVideoClipChanges as $, selectAudioScriptSegments as A, derivePositionFromAbs as B, decodeEntityRelationRows as C, assemblePhoneticScriptContent as D, assembleEntityContent as E, createRelationId as F, validateVideoDocument as G, toVideoDocument as H, hasSequence as I, LANE_KINDS_IN_STACK_ORDER as J, partUnionSchema as K, isMediaAssetVariantKind as L, variantBaseEntityIds as M, isJsonObject as N, assembleScriptText as O, createEntityId as P, solveVideoDocument as Q, buildInitialVideoDocument as R, EntityTimelineProjectionError as S, assembleCaptionContent as T, VideoDocumentValidationError as U, fromVideoDocument as V, assertValidVideoDocument as W, findLaneTrack as X, ensureLaneTrack as Y, laneTrackId as Z, assertFieldChanges as _, recordEntries as _t, applyEntityTimelineProjection as a, resolveSpeechOverlapByShiftingVideos as at, EntityProjectionGraph as b, bytesToBase64 as bt, writeVideoDocumentToDraft as c, isEmptyVideoClip as ct, LoroEntityDocument as d, DEFAULT_UNIT_TIME_MS as dt, arrangeMainTrackSeamlessly as et, LoroEntityDraft as f, ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION as ft, applyFieldChanges as g, partUnionToDraft as gt, equalJson as h, speedOf as ht, MirrorVideoDocumentAdapter as i, resolveAllSpeechOverlaps as it, updateEntityFields as j, findComposedAudioScript as k, readVideoDocumentFromDraft as l, partDurationMs as lt, entityOrderGroups as m, effectiveVideoClipDurationMs as mt, createPlainMemoryAdapter as n, reassignSpeechesToVideoClipsByTime as nt, createMirrorVideoDocument as o, syncAggregatedClipsTimePosition as ot, readEntityDocument as p, VIDEO_DOCUMENT_SCHEMA_VERSION as pt, videoDocumentSchema as q, generatePartId as r, recalculateTimelineDuration as rt, createMirrorVideoDocumentAdapter as s, TIMELINE_SKELETON_DURATION_MS as st, PlainMemoryAdapter as t, fillMainTrackTimeGaps as tt, LORO_ENTITY_SCHEMA as u, safeDurationMs as ut, resolveFieldPath as v, videoDocumentMirrorSchema as vt, ScriptCompositionError as w, resolveEntityTimelineLayout as x, projectEntityTimeline as y, base64ToBytes as yt, buildSpeechHostMap as z };
4537
+ export { cascadeAfterVideoClipChanges as $, selectAudioScriptSegment as A, derivePositionFromAbs as B, decodeEntityRelationRows as C, assemblePhoneticScriptContent as D, assembleEntityContent as E, createRelationId as F, validateVideoDocument as G, toVideoDocument as H, hasSequence as I, LANE_KINDS_IN_STACK_ORDER as J, partUnionSchema as K, isMediaAssetVariantKind as L, variantBaseEntityIds as M, isJsonObject as N, assembleScriptText as O, createEntityId as P, solveVideoDocument as Q, buildInitialVideoDocument as R, EntityTimelineProjectionError as S, assembleCaptionContent as T, VideoDocumentValidationError as U, fromVideoDocument as V, assertValidVideoDocument as W, findLaneTrack as X, ensureLaneTrack as Y, laneTrackId as Z, assertFieldChanges as _, recordEntries as _t, applyEntityTimelineProjection as a, resolveSpeechOverlapByShiftingVideos as at, EntityProjectionGraph as b, bytesToBase64 as bt, writeVideoDocumentToDraft as c, isEmptyVideoClip as ct, LoroEntityDocument as d, DEFAULT_UNIT_TIME_MS as dt, arrangeMainTrackSeamlessly as et, LoroEntityDraft as f, ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION as ft, applyFieldChanges as g, partUnionToDraft as gt, equalJson as h, speedOf as ht, MirrorVideoDocumentAdapter as i, resolveAllSpeechOverlaps as it, updateEntityFields as j, findComposedAudioScript as k, readVideoDocumentFromDraft as l, partDurationMs as lt, entityOrderGroups as m, effectiveVideoClipDurationMs as mt, createPlainMemoryAdapter as n, reassignSpeechesToVideoClipsByTime as nt, createMirrorVideoDocument as o, syncAggregatedClipsTimePosition as ot, readEntityDocument as p, VIDEO_DOCUMENT_SCHEMA_VERSION as pt, videoDocumentSchema as q, generatePartId as r, recalculateTimelineDuration as rt, createMirrorVideoDocumentAdapter as s, TIMELINE_SKELETON_DURATION_MS as st, PlainMemoryAdapter as t, fillMainTrackTimeGaps as tt, LORO_ENTITY_SCHEMA as u, safeDurationMs as ut, resolveFieldPath as v, videoDocumentMirrorSchema as vt, ScriptCompositionError as w, resolveEntityTimelineLayout as x, projectEntityTimeline as y, base64ToBytes as yt, buildSpeechHostMap as z };
@@ -919,7 +919,7 @@ interface CaptionTextRange extends JsonObject {
919
919
  readonly end: number;
920
920
  }
921
921
  /**
922
- * One ordered entry of the Caption's segment selection. `segmentId` quotes the
922
+ * The Caption's single text selection. `segmentId` quotes the
923
923
  * composed AudioScript's own stable segment identity — a local id quoted by the
924
924
  * variant, never a peer Entity reference. Text itself is never copied here;
925
925
  * complete Caption content is assembled through its direct baseEntityIds.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as index_d_exports } from "./index-CMa6ZCtX.js";
2
- import { $ as SequenceRange, A as generatePartId, At as VideoDraft, B as ResolvedEntityClipPlacement, Bt as Track$1, C as PlannedSemanticOpKind, Ct as TrackItemTimePosition, D as SnapshotReadable, Dt as VideoDocumentSchemaVersion, E as SchemaValidator, Et as VideoDocument, F as videoDocumentMirrorSchema, Ft as CaptionPart$1, G as EntityTimelineProjectionError, H as ResolvedEntityTrack, I as VideoDocumentValidationError, It as CaptionStyle, J as RelationRow, K as EntityRelationRows, L as assertValidVideoDocument, Lt as PartAggregation, M as TrackItemDraft, Mt as effectiveVideoClipDurationMs, N as VideoDocumentDraft, Nt as speedOf, O as ValidationError, Ot as VideoDocumentValidationIssue, P as VideoDocumentMirrorSchema, Pt as Attachment, Q as SequenceDuration, R as validateVideoDocument, Rt as SpeedShift, S as ImplementedSemanticOpKind, St as TrackItem, T as isImplementedSemanticOpKind, Tt as VideoClipPart, U as resolveEntityTimelineLayout, V as ResolvedEntityTimelineLayout, Vt as TrackItem$1, W as projectEntityTimeline, X as CaptionStyleFields, Y as CaptionSegmentSelection, Z as ScriptTextSegment, _ as SemanticEditor, _t as PartKind, a as PlainMemoryAdapter, at as buildInitialVideoDocument, b as TransactAudit, bt as Timeline, c as MirrorVideoDocumentAdapter, ct as buildSpeechHostMap, d as createMirrorVideoDocument, dt as toVideoDocument, et as VoiceDescriptor, f as createMirrorVideoDocumentAdapter, ft as BgmPart, g as SemanticDocumentAdapter, gt as ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION, h as OpActor, ht as DEFAULT_UNIT_TIME_MS, i as JournalEntry, it as InitialDocumentFacts, j as TrackDraft, jt as VideoDraftPartUnion, k as PartIdFactory, kt as VideoDocumentValidationIssueCode, l as MirrorVideoDocumentOptions, lt as derivePositionFromAbs, m as CommitOptions, mt as CaptionPart, n as videoDocumentSchema, nt as JsonValue, o as PlainMemoryAdapterOptions, ot as DerivedItemPosition, p as writeVideoDocumentToDraft, pt as CaptionDisplayCue, q as EntityRow, r as readVideoDocumentFromDraft, rt as EntityId, s as createPlainMemoryAdapter, st as SpeechHostMap, t as partUnionSchema, tt as JsonObject, u as applyEntityTimelineProjection, ut as fromVideoDocument, v as SemanticOpInput, vt as PartUnion, w as SemanticOpKind, wt as VIDEO_DOCUMENT_SCHEMA_VERSION, x as IMPLEMENTED_SEMANTIC_OP_KINDS, xt as Track, y as SemanticOpName, yt as SpeechPart, z as EntityTimelineTrackRole, zt as Timeline$1 } from "./index-D5XV4UPC.js";
2
+ import { $ as SequenceRange, A as generatePartId, At as VideoDraft, B as ResolvedEntityClipPlacement, Bt as Track$1, C as PlannedSemanticOpKind, Ct as TrackItemTimePosition, D as SnapshotReadable, Dt as VideoDocumentSchemaVersion, E as SchemaValidator, Et as VideoDocument, F as videoDocumentMirrorSchema, Ft as CaptionPart$1, G as EntityTimelineProjectionError, H as ResolvedEntityTrack, I as VideoDocumentValidationError, It as CaptionStyle, J as RelationRow, K as EntityRelationRows, L as assertValidVideoDocument, Lt as PartAggregation, M as TrackItemDraft, Mt as effectiveVideoClipDurationMs, N as VideoDocumentDraft, Nt as speedOf, O as ValidationError, Ot as VideoDocumentValidationIssue, P as VideoDocumentMirrorSchema, Pt as Attachment, Q as SequenceDuration, R as validateVideoDocument, Rt as SpeedShift, S as ImplementedSemanticOpKind, St as TrackItem, T as isImplementedSemanticOpKind, Tt as VideoClipPart, U as resolveEntityTimelineLayout, V as ResolvedEntityTimelineLayout, Vt as TrackItem$1, W as projectEntityTimeline, X as CaptionStyleFields, Y as CaptionSegmentSelection, Z as ScriptTextSegment, _ as SemanticEditor, _t as PartKind, a as PlainMemoryAdapter, at as buildInitialVideoDocument, b as TransactAudit, bt as Timeline, c as MirrorVideoDocumentAdapter, ct as buildSpeechHostMap, d as createMirrorVideoDocument, dt as toVideoDocument, et as VoiceDescriptor, f as createMirrorVideoDocumentAdapter, ft as BgmPart, g as SemanticDocumentAdapter, gt as ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION, h as OpActor, ht as DEFAULT_UNIT_TIME_MS, i as JournalEntry, it as InitialDocumentFacts, j as TrackDraft, jt as VideoDraftPartUnion, k as PartIdFactory, kt as VideoDocumentValidationIssueCode, l as MirrorVideoDocumentOptions, lt as derivePositionFromAbs, m as CommitOptions, mt as CaptionPart, n as videoDocumentSchema, nt as JsonValue, o as PlainMemoryAdapterOptions, ot as DerivedItemPosition, p as writeVideoDocumentToDraft, pt as CaptionDisplayCue, q as EntityRow, r as readVideoDocumentFromDraft, rt as EntityId, s as createPlainMemoryAdapter, st as SpeechHostMap, t as partUnionSchema, tt as JsonObject, u as applyEntityTimelineProjection, ut as fromVideoDocument, v as SemanticOpInput, vt as PartUnion, w as SemanticOpKind, wt as VIDEO_DOCUMENT_SCHEMA_VERSION, x as IMPLEMENTED_SEMANTIC_OP_KINDS, xt as Track, y as SemanticOpName, yt as SpeechPart, z as EntityTimelineTrackRole, zt as Timeline$1 } from "./index-B31KeDzA.js";
3
3
  import { LoroDoc, PeerID } from "loro-crdt";
4
4
  import { DocState } from "@mengine/sync";
5
5
  import { BaseDocStorage, Connection, DocDiff, DocPushReceipt, DocSnapshotRecord, DocStorage, DocStorageOptions, DocUpdate, DocUpdateRecord } from "@mengine/storage";
@@ -216,7 +216,7 @@ declare function assembleCaptionContent(rows: EntityRelationRows, captionEntityI
216
216
  */
217
217
  declare function assemblePhoneticScriptContent(rows: EntityRelationRows, phoneticScriptEntityId: EntityId): AssembledPhoneticScriptContent;
218
218
  /** Select source text without creating another authoritative text field. */
219
- declare function selectAudioScriptSegments(script: EntityRow<'audio-script'>, selections: readonly CaptionSegmentSelection[]): readonly ScriptTextSegment[];
219
+ declare function selectAudioScriptSegment(script: EntityRow<'audio-script'>, selection: CaptionSegmentSelection): ScriptTextSegment;
220
220
  //#endregion
221
221
  //#region src/entity-editor/entity-graph-http-client.d.ts
222
222
  /** One authenticated revision of the authoritative Medeo Entity graph. */
@@ -336,7 +336,7 @@ interface VoiceoverCaptionFact {
336
336
  /** Directly held bases; includes the AudioScript used by the Voice. */
337
337
  readonly baseEntityIds: readonly string[];
338
338
  /** Ordered selection of AudioScript segments; caption text is never passed inline. */
339
- readonly selections: readonly CaptionSegmentSelection[];
339
+ readonly selection: CaptionSegmentSelection;
340
340
  readonly startMs: number;
341
341
  readonly durationMs: number;
342
342
  readonly style?: CaptionStyleFields;
@@ -461,7 +461,7 @@ interface InsertCaptionClipInput {
461
461
  /** Existing bases composed by this variant; includes an AudioScript text owner. */
462
462
  readonly baseEntityIds: readonly string[];
463
463
  /** Ordered selection of the AudioScript segments this Caption displays. */
464
- readonly selections: readonly CaptionSegmentSelection[];
464
+ readonly selection: CaptionSegmentSelection;
465
465
  /** Intrinsic cue length of the Caption entity itself; display comes from the placement. */
466
466
  readonly durationMs: number;
467
467
  readonly style?: CaptionStyleFields;
@@ -656,7 +656,7 @@ interface CaptionContentInput {
656
656
  readonly contentEntityId: string;
657
657
  readonly audioScriptEntityId: string;
658
658
  readonly text: string;
659
- readonly selections?: readonly CaptionSegmentSelection[];
659
+ readonly selection?: CaptionSegmentSelection;
660
660
  readonly durationMs: number;
661
661
  }
662
662
  /** Author Caption content from semantic intent; callers never reconcile variant bases or assembled fields. */
@@ -1744,4 +1744,4 @@ declare function hostForAbsMs(ranges: MainClipRange[], absMs: number): MainClipR
1744
1744
  */
1745
1745
  declare function relativePositionForAbs(ranges: MainClipRange[], absMs: number): TrackItemTimePosition;
1746
1746
  //#endregion
1747
- export { type Aggregation, type AssembledCaptionContent, type AssembledPhoneticScriptContent, type Attachment, type AudioMediaAssetFact, type BgmPart, type CaptionContentInput, type CaptionDisplayCue, type CaptionPart, type CaptionSegmentSelection, type CaptionStyle, type ClipEntityId, type ClipPlacement, type CommitOptions, DEFAULT_UNIT_TIME_MS, type DeleteBgmInput, type DeleteClipInput, type DeleteClipTreeInput, type DeleteVoiceoverInput, type DerivedItemPosition, type DocStorageLike, type DocVersionMark, type DocumentAudioScript, type DocumentAudioScriptState, ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION, type EditorFoundation, EntityDocumentState, type EntityGraphCommitOptions, EntityGraphHttpClient, type EntityGraphState, EntityTimelineEditor, type EntityTimelineIdFactory, EntityTimelineProjectionError, type EntityTimelineTrackRole, type FieldChange, type FieldPath, IMPLEMENTED_SEMANTIC_OP_KINDS, type ImageMediaAssetFact, type ImplementedSemanticOpKind, type ImportedMediaAsset, type InitialDocumentFacts, type InsertCaptionClipInput, type InsertClipInput, type InsertMediaClipInput, type InsertMediaClipsInput, type InsertPlacedClipInput, type JournalEntry, LANE_KINDS_IN_STACK_ORDER, LORO_ENTITY_SCHEMA, type LaneKind, type LinearClipSpeed, LoroEntityDocument, LoroEntityDraft, type MainClipRange, type MakeEmptyPart, ManualSyncDoc, type ManualSyncDocOptions, MedeoHttpDocStorage, type MedeoHttpDocStorageOptions, type MediaAssetFact, type MediaClipInsertion, MemoryDocStorage, MengineAckFailedError, type MengineAuditEntry, type MengineAuditResponse, MengineDocSession, type MengineDocSessionOptions, type MengineDocSessionUpdateEvent, type MengineDocumentVersion, type MengineEventStreamOptions, MengineHttpClient, type MengineHttpClientOptions, MengineHttpRequestError, MenginePushRejectedError, type MenginePushResponse, type MenginePushUpdateResponse, type MengineRejectedResponse, type MengineSnapshotResponse, type MengineSseUpdateEvent, type MengineSyncResponse, type MengineUpdateMeta, MirrorVideoDocumentAdapter, type MirrorVideoDocumentOptions, type MoveClipInput, type MoveClipsToStartsInput, type MoveSequentialClipsInput, type MoveVoiceoverInput, type OpActor, type PartAggregation, type PartIdFactory, type PartKind, type PartUnion, type PatchCaptionStyleInput, PlainMemoryAdapter, type PlainMemoryAdapterOptions, type PlannedSemanticOpKind, type PullFailureReason, type PullResult, type PushOutcome, type PushOutcomeKind, type PushResult, type PushResultKind, type ReplaceClipContentInput, type ReplaceMediaClipInput, type ReplaceSequentialClipsInput, type ReplacementMediaClipInput, type ResolvedEntityClipPlacement, type ResolvedEntityTimelineLayout, type ResolvedEntityTrack, SchemaValidator, ScriptCompositionError, type SemanticDocumentAdapter, SemanticEditor, type SemanticOpInput, type SemanticOpKind, type SemanticOpName, type SequentialClipAnchor, type SetBgmInput, type SetCaptionVisibilityInput, type SetClipPlacementInput, type SetClipSpeedInput, type SetClipVolumeInput, type SnapshotReadable, type SolvedVideoDocument, type SpeechHostMap, type SpeechPart, type SpeedShift, TIMELINE_SKELETON_DURATION_MS, type Timeline, type TimelineDoc, type TimelineItem, type Track, type TrackDraft, type TrackItem, type TrackItemDraft, type TrackItemTimePosition, type TransactAudit, type TrimClipInput, type UpdateClipInput, type UpdateClipMarkerInput, VIDEO_DOCUMENT_SCHEMA_VERSION, ValidationError, type VideoClipPart, type VideoDocument, type VideoDocumentDraft, type VideoDocumentMirrorSchema, type VideoDocumentSchemaVersion, VideoDocumentValidationError, type VideoDocumentValidationIssue, type VideoDocumentValidationIssueCode, type VideoDraft, type CaptionPart$1 as VideoDraftCaptionPart, type VideoDraftPartUnion, type Timeline$1 as VideoDraftTimeline, type Track$1 as VideoDraftTrack, type TrackItem$1 as VideoDraftTrackItem, type VideoMediaAssetFact, type VisualMediaAssetFact, type VoiceMediaAssetFact, type VoiceoverCaptionFact, type VoiceoverTakeInput, type VoiceoverTakeResult, type WaitForServerAckOptions, applyEntityRows, applyEntityTimelineProjection, applyFieldChanges, arrangeMainTrackSeamlessly, assembleCaptionContent, assembleEntityContent, assemblePhoneticScriptContent, assembleScriptText, assertCanonicalEditorResources, assertEntityProjectionPreservesLegacy, assertFieldChanges, assertMediaAssetWritePolicy, assertValidVideoDocument, base64ToBytes, buildInitialVideoDocument, buildSpeechHostMap, bytesToBase64, cascadeAfterVideoClipChanges, compileEntityRows, createEditSandbox, createMirrorVideoDocument, createMirrorVideoDocumentAdapter, createPlainMemoryAdapter, decodeDocVersionMark, derivePositionFromAbs, effectiveVideoClipDurationMs, encodeDocVersionMark, ensureEditorFoundation, ensureLaneTrack, fillMainTrackTimeGaps, findComposedAudioScript, findLaneTrack, fromVideoDocument, generatePartId, getAt, hostForAbsMs, importMediaAsset, isEmptyVideoClip, isImplementedSemanticOpKind, isMap, laneTrackId, mainTrackRanges, migrateLegacyTimelineToEntities, partDurationMs, partUnionSchema, prepareCaptionContent, projectEntityTimeline, readDocumentAudioScript, readEntityDocument, readMainTrackItems, readMengineEventStream, readPart, readPartDurationMs, readVideoDocumentFromDraft, reassignSpeechesToVideoClipsByTime, recalculateTimelineDuration, relativePositionForAbs, replayJournal, resolveAllSpeechOverlaps, resolveEntityTimelineLayout, resolveFieldPath, resolveSpeechOverlapByShiftingVideos, safeDurationMs, index_d_exports as schemas, selectAudioScriptSegments, snapshotToPlain, solveVideoDocument, speedOf, syncAggregatedClipsTimePosition, toVideoDocument, validateVideoDocument, videoDocumentMirrorSchema, videoDocumentSchema, writeVideoDocumentToDraft };
1747
+ export { type Aggregation, type AssembledCaptionContent, type AssembledPhoneticScriptContent, type Attachment, type AudioMediaAssetFact, type BgmPart, type CaptionContentInput, type CaptionDisplayCue, type CaptionPart, type CaptionSegmentSelection, type CaptionStyle, type ClipEntityId, type ClipPlacement, type CommitOptions, DEFAULT_UNIT_TIME_MS, type DeleteBgmInput, type DeleteClipInput, type DeleteClipTreeInput, type DeleteVoiceoverInput, type DerivedItemPosition, type DocStorageLike, type DocVersionMark, type DocumentAudioScript, type DocumentAudioScriptState, ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION, type EditorFoundation, EntityDocumentState, type EntityGraphCommitOptions, EntityGraphHttpClient, type EntityGraphState, EntityTimelineEditor, type EntityTimelineIdFactory, EntityTimelineProjectionError, type EntityTimelineTrackRole, type FieldChange, type FieldPath, IMPLEMENTED_SEMANTIC_OP_KINDS, type ImageMediaAssetFact, type ImplementedSemanticOpKind, type ImportedMediaAsset, type InitialDocumentFacts, type InsertCaptionClipInput, type InsertClipInput, type InsertMediaClipInput, type InsertMediaClipsInput, type InsertPlacedClipInput, type JournalEntry, LANE_KINDS_IN_STACK_ORDER, LORO_ENTITY_SCHEMA, type LaneKind, type LinearClipSpeed, LoroEntityDocument, LoroEntityDraft, type MainClipRange, type MakeEmptyPart, ManualSyncDoc, type ManualSyncDocOptions, MedeoHttpDocStorage, type MedeoHttpDocStorageOptions, type MediaAssetFact, type MediaClipInsertion, MemoryDocStorage, MengineAckFailedError, type MengineAuditEntry, type MengineAuditResponse, MengineDocSession, type MengineDocSessionOptions, type MengineDocSessionUpdateEvent, type MengineDocumentVersion, type MengineEventStreamOptions, MengineHttpClient, type MengineHttpClientOptions, MengineHttpRequestError, MenginePushRejectedError, type MenginePushResponse, type MenginePushUpdateResponse, type MengineRejectedResponse, type MengineSnapshotResponse, type MengineSseUpdateEvent, type MengineSyncResponse, type MengineUpdateMeta, MirrorVideoDocumentAdapter, type MirrorVideoDocumentOptions, type MoveClipInput, type MoveClipsToStartsInput, type MoveSequentialClipsInput, type MoveVoiceoverInput, type OpActor, type PartAggregation, type PartIdFactory, type PartKind, type PartUnion, type PatchCaptionStyleInput, PlainMemoryAdapter, type PlainMemoryAdapterOptions, type PlannedSemanticOpKind, type PullFailureReason, type PullResult, type PushOutcome, type PushOutcomeKind, type PushResult, type PushResultKind, type ReplaceClipContentInput, type ReplaceMediaClipInput, type ReplaceSequentialClipsInput, type ReplacementMediaClipInput, type ResolvedEntityClipPlacement, type ResolvedEntityTimelineLayout, type ResolvedEntityTrack, SchemaValidator, ScriptCompositionError, type SemanticDocumentAdapter, SemanticEditor, type SemanticOpInput, type SemanticOpKind, type SemanticOpName, type SequentialClipAnchor, type SetBgmInput, type SetCaptionVisibilityInput, type SetClipPlacementInput, type SetClipSpeedInput, type SetClipVolumeInput, type SnapshotReadable, type SolvedVideoDocument, type SpeechHostMap, type SpeechPart, type SpeedShift, TIMELINE_SKELETON_DURATION_MS, type Timeline, type TimelineDoc, type TimelineItem, type Track, type TrackDraft, type TrackItem, type TrackItemDraft, type TrackItemTimePosition, type TransactAudit, type TrimClipInput, type UpdateClipInput, type UpdateClipMarkerInput, VIDEO_DOCUMENT_SCHEMA_VERSION, ValidationError, type VideoClipPart, type VideoDocument, type VideoDocumentDraft, type VideoDocumentMirrorSchema, type VideoDocumentSchemaVersion, VideoDocumentValidationError, type VideoDocumentValidationIssue, type VideoDocumentValidationIssueCode, type VideoDraft, type CaptionPart$1 as VideoDraftCaptionPart, type VideoDraftPartUnion, type Timeline$1 as VideoDraftTimeline, type Track$1 as VideoDraftTrack, type TrackItem$1 as VideoDraftTrackItem, type VideoMediaAssetFact, type VisualMediaAssetFact, type VoiceMediaAssetFact, type VoiceoverCaptionFact, type VoiceoverTakeInput, type VoiceoverTakeResult, type WaitForServerAckOptions, applyEntityRows, applyEntityTimelineProjection, applyFieldChanges, arrangeMainTrackSeamlessly, assembleCaptionContent, assembleEntityContent, assemblePhoneticScriptContent, assembleScriptText, assertCanonicalEditorResources, assertEntityProjectionPreservesLegacy, assertFieldChanges, assertMediaAssetWritePolicy, assertValidVideoDocument, base64ToBytes, buildInitialVideoDocument, buildSpeechHostMap, bytesToBase64, cascadeAfterVideoClipChanges, compileEntityRows, createEditSandbox, createMirrorVideoDocument, createMirrorVideoDocumentAdapter, createPlainMemoryAdapter, decodeDocVersionMark, derivePositionFromAbs, effectiveVideoClipDurationMs, encodeDocVersionMark, ensureEditorFoundation, ensureLaneTrack, fillMainTrackTimeGaps, findComposedAudioScript, findLaneTrack, fromVideoDocument, generatePartId, getAt, hostForAbsMs, importMediaAsset, isEmptyVideoClip, isImplementedSemanticOpKind, isMap, laneTrackId, mainTrackRanges, migrateLegacyTimelineToEntities, partDurationMs, partUnionSchema, prepareCaptionContent, projectEntityTimeline, readDocumentAudioScript, readEntityDocument, readMainTrackItems, readMengineEventStream, readPart, readPartDurationMs, readVideoDocumentFromDraft, reassignSpeechesToVideoClipsByTime, recalculateTimelineDuration, relativePositionForAbs, replayJournal, resolveAllSpeechOverlaps, resolveEntityTimelineLayout, resolveFieldPath, resolveSpeechOverlapByShiftingVideos, safeDurationMs, index_d_exports as schemas, selectAudioScriptSegment, snapshotToPlain, solveVideoDocument, speedOf, syncAggregatedClipsTimePosition, toVideoDocument, validateVideoDocument, videoDocumentMirrorSchema, videoDocumentSchema, writeVideoDocumentToDraft };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as cascadeAfterVideoClipChanges, A as selectAudioScriptSegments, B as derivePositionFromAbs, C as decodeEntityRelationRows, D as assemblePhoneticScriptContent, E as assembleEntityContent, F as createRelationId, G as validateVideoDocument, H as toVideoDocument, I as hasSequence, J as LANE_KINDS_IN_STACK_ORDER, K as partUnionSchema, L as isMediaAssetVariantKind, M as variantBaseEntityIds, N as isJsonObject, O as assembleScriptText, P as createEntityId, Q as solveVideoDocument, R as buildInitialVideoDocument, S as EntityTimelineProjectionError, T as assembleCaptionContent, U as VideoDocumentValidationError, V as fromVideoDocument, W as assertValidVideoDocument, X as findLaneTrack, Y as ensureLaneTrack, Z as laneTrackId, _ as assertFieldChanges, _t as recordEntries, a as applyEntityTimelineProjection, at as resolveSpeechOverlapByShiftingVideos, b as EntityProjectionGraph, bt as bytesToBase64, c as writeVideoDocumentToDraft, ct as isEmptyVideoClip, d as LoroEntityDocument, dt as DEFAULT_UNIT_TIME_MS, et as arrangeMainTrackSeamlessly, f as LoroEntityDraft, ft as ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION, g as applyFieldChanges, gt as partUnionToDraft, h as equalJson, ht as speedOf, i as MirrorVideoDocumentAdapter, it as resolveAllSpeechOverlaps, j as updateEntityFields, k as findComposedAudioScript, l as readVideoDocumentFromDraft, lt as partDurationMs, m as entityOrderGroups, mt as effectiveVideoClipDurationMs, n as createPlainMemoryAdapter, nt as reassignSpeechesToVideoClipsByTime, o as createMirrorVideoDocument, ot as syncAggregatedClipsTimePosition, p as readEntityDocument, pt as VIDEO_DOCUMENT_SCHEMA_VERSION, q as videoDocumentSchema, r as generatePartId, rt as recalculateTimelineDuration, s as createMirrorVideoDocumentAdapter, st as TIMELINE_SKELETON_DURATION_MS, t as PlainMemoryAdapter, tt as fillMainTrackTimeGaps, u as LORO_ENTITY_SCHEMA, ut as safeDurationMs, v as resolveFieldPath, vt as videoDocumentMirrorSchema, w as ScriptCompositionError, x as resolveEntityTimelineLayout, y as projectEntityTimeline, yt as base64ToBytes, z as buildSpeechHostMap } from "./document-BLm4ABAb.js";
1
+ import { $ as cascadeAfterVideoClipChanges, A as selectAudioScriptSegment, B as derivePositionFromAbs, C as decodeEntityRelationRows, D as assemblePhoneticScriptContent, E as assembleEntityContent, F as createRelationId, G as validateVideoDocument, H as toVideoDocument, I as hasSequence, J as LANE_KINDS_IN_STACK_ORDER, K as partUnionSchema, L as isMediaAssetVariantKind, M as variantBaseEntityIds, N as isJsonObject, O as assembleScriptText, P as createEntityId, Q as solveVideoDocument, R as buildInitialVideoDocument, S as EntityTimelineProjectionError, T as assembleCaptionContent, U as VideoDocumentValidationError, V as fromVideoDocument, W as assertValidVideoDocument, X as findLaneTrack, Y as ensureLaneTrack, Z as laneTrackId, _ as assertFieldChanges, _t as recordEntries, a as applyEntityTimelineProjection, at as resolveSpeechOverlapByShiftingVideos, b as EntityProjectionGraph, bt as bytesToBase64, c as writeVideoDocumentToDraft, ct as isEmptyVideoClip, d as LoroEntityDocument, dt as DEFAULT_UNIT_TIME_MS, et as arrangeMainTrackSeamlessly, f as LoroEntityDraft, ft as ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION, g as applyFieldChanges, gt as partUnionToDraft, h as equalJson, ht as speedOf, i as MirrorVideoDocumentAdapter, it as resolveAllSpeechOverlaps, j as updateEntityFields, k as findComposedAudioScript, l as readVideoDocumentFromDraft, lt as partDurationMs, m as entityOrderGroups, mt as effectiveVideoClipDurationMs, n as createPlainMemoryAdapter, nt as reassignSpeechesToVideoClipsByTime, o as createMirrorVideoDocument, ot as syncAggregatedClipsTimePosition, p as readEntityDocument, pt as VIDEO_DOCUMENT_SCHEMA_VERSION, q as videoDocumentSchema, r as generatePartId, rt as recalculateTimelineDuration, s as createMirrorVideoDocumentAdapter, st as TIMELINE_SKELETON_DURATION_MS, t as PlainMemoryAdapter, tt as fillMainTrackTimeGaps, u as LORO_ENTITY_SCHEMA, ut as safeDurationMs, v as resolveFieldPath, vt as videoDocumentMirrorSchema, w as ScriptCompositionError, x as resolveEntityTimelineLayout, y as projectEntityTimeline, yt as base64ToBytes, z as buildSpeechHostMap } from "./document-BSAUud6c.js";
2
2
  import { addSpeechesInputSchema, addVideoClipsInputSchema, adjustBgmVolumeInputSchema, adjustSpeechVolumeInputSchema, adjustVideoClipDurationInputSchema, adjustVideoClipVolumeInputSchema, changeSpeechScriptInputSchema, changeSpeechVoiceInputSchema, deleteBgmInputSchema, deleteSpeechesInputSchema, deleteVideoClipsInputSchema, moveSpeechesInputSchema, moveVideoClipsByAnchorInputSchema, moveVideoClipsInputSchema, replaceVideoClipContentInputSchema, replaceVideoClipSequenceInputSchema, setBgmInputSchema, setCaptionStyleInputSchema, setCaptionVisibilityInputSchema, setVideoClipSpeedShiftInputSchema, t as schemas_exports } from "./schemas.js";
3
3
  import { LoroDoc, VersionVector } from "loro-crdt";
4
4
  import { ClientServerSynchronizer, DocManager } from "@mengine/sync";
@@ -682,8 +682,8 @@ function sameVoice(left, right) {
682
682
  function requireComposedAudioScript(rows, phoneticScriptEntityId) {
683
683
  return assemblePhoneticScriptContent(rows, phoneticScriptEntityId).audioScript.entityId;
684
684
  }
685
- function captionSelections(selections) {
686
- return structuredClone(selections);
685
+ function captionSelection(selection) {
686
+ return structuredClone(selection);
687
687
  }
688
688
  function captionBaseIds(ids) {
689
689
  if (!Array.isArray(ids) || ids.length === 0) throw new Error("Caption requires non-empty baseEntityIds");
@@ -1377,7 +1377,7 @@ var EntityTimelineEditor = class {
1377
1377
  insertCaptionClip(input) {
1378
1378
  return this.transact((draft) => {
1379
1379
  const durationMs = finitePositive(input.durationMs, "Caption durationMs");
1380
- const selections = captionSelections(input.selections);
1380
+ const selection = captionSelection(input.selection);
1381
1381
  const track = this.ensureRoleTrack(draft, input.timelineEntityId, "caption");
1382
1382
  const content = {
1383
1383
  entityId: input.captionEntityId === void 0 ? this.mintEntityId(draft) : requireAvailableEntityId(draft, input.captionEntityId),
@@ -1391,7 +1391,7 @@ var EntityTimelineEditor = class {
1391
1391
  sampling: "native",
1392
1392
  coordinateSpace: "milliseconds",
1393
1393
  baseEntityIds: captionBaseIds(input.baseEntityIds),
1394
- selections,
1394
+ selection,
1395
1395
  ...input.style === void 0 ? {} : { style: cloneJsonObject(input.style, "Caption style") }
1396
1396
  }
1397
1397
  };
@@ -1500,7 +1500,7 @@ var EntityTimelineEditor = class {
1500
1500
  for (const caption of captions) {
1501
1501
  const startMs = finiteNonNegative(caption.startMs, "Caption startMs");
1502
1502
  const durationMs = finitePositive(caption.durationMs, "Caption durationMs");
1503
- const selections = captionSelections(caption.selections);
1503
+ const selection = captionSelection(caption.selection);
1504
1504
  const baseEntityIds = captionBaseIds(caption.baseEntityIds);
1505
1505
  if (draft.entities.find((entity) => entity.entityId === caption.captionClipEntityId) === void 0) {
1506
1506
  const content = {
@@ -1515,7 +1515,7 @@ var EntityTimelineEditor = class {
1515
1515
  sampling: "native",
1516
1516
  coordinateSpace: "milliseconds",
1517
1517
  baseEntityIds,
1518
- selections,
1518
+ selection,
1519
1519
  ...caption.style === void 0 ? {} : { style: cloneJsonObject(caption.style, "Caption style") }
1520
1520
  }
1521
1521
  };
@@ -1557,7 +1557,7 @@ var EntityTimelineEditor = class {
1557
1557
  payload: {
1558
1558
  ...content.payload,
1559
1559
  baseEntityIds,
1560
- selections,
1560
+ selection,
1561
1561
  ...Object.keys(style).length === 0 ? {} : { style }
1562
1562
  }
1563
1563
  });
@@ -2149,14 +2149,14 @@ function migrateLegacyTimelineToEntities(legacy, assetFacts, initial = {
2149
2149
  const sourceText = scriptText(script);
2150
2150
  const captionText = caption.text;
2151
2151
  const offset = sourceText.indexOf(captionText);
2152
- if (!captionText.trim() || offset < 0 || sourceText.indexOf(captionText, offset + 1) >= 0) fail("Legacy Caption needs explicit unambiguous AudioScript selections before cutover");
2153
- const selections = [{
2152
+ if (!captionText.trim() || offset < 0 || sourceText.indexOf(captionText, offset + 1) >= 0) fail("Legacy Caption needs explicit unambiguous AudioScript selection before cutover");
2153
+ const selection = {
2154
2154
  segmentId: "segment-0",
2155
2155
  ...sourceText === captionText ? {} : { textRange: {
2156
2156
  start: Array.from(sourceText.slice(0, offset)).length,
2157
2157
  end: Array.from(sourceText.slice(0, offset + captionText.length)).length
2158
2158
  } }
2159
- }];
2159
+ };
2160
2160
  content = addEntity("caption", {
2161
2161
  extent: {
2162
2162
  kind: "bounded",
@@ -2166,7 +2166,7 @@ function migrateLegacyTimelineToEntities(legacy, assetFacts, initial = {
2166
2166
  sampling: "native",
2167
2167
  coordinateSpace: "milliseconds",
2168
2168
  baseEntityIds: [script.entityId],
2169
- selections,
2169
+ selection,
2170
2170
  ...caption.style === void 0 ? {} : { style: toEntityCaptionStyle(caption.style) }
2171
2171
  });
2172
2172
  link("caption-alignment", content, voice, { alignment: {
@@ -2680,7 +2680,7 @@ function prepareCaptionContent(rows, input) {
2680
2680
  ...candidate,
2681
2681
  payload: {
2682
2682
  ...candidate.payload,
2683
- selections: structuredClone(input.selections ?? selectCaptionText(textSource, input.text))
2683
+ selection: structuredClone(input.selection ?? selectCaptionText(textSource, input.text))
2684
2684
  }
2685
2685
  };
2686
2686
  if (assembleCaptionContent({
@@ -2691,10 +2691,7 @@ function prepareCaptionContent(rows, input) {
2691
2691
  }
2692
2692
  function selectCaptionText(script, text) {
2693
2693
  if (!text.trim()) throw new Error("Caption text selection must not be blank");
2694
- const source = script;
2695
- const fullText = assembleScriptText(source);
2696
- const segments = source.payload.segments;
2697
- if (text === fullText) return segments.map((segment) => ({ segmentId: segment.segmentId }));
2694
+ const segments = script.payload.segments;
2698
2695
  const matches = [];
2699
2696
  for (const segment of segments) {
2700
2697
  let offset = segment.text.indexOf(text);
@@ -2710,8 +2707,8 @@ function selectCaptionText(script, text) {
2710
2707
  offset = segment.text.indexOf(text, offset + 1);
2711
2708
  }
2712
2709
  }
2713
- if (matches.length !== 1) throw new Error("Caption text must select a unique AudioScript range; provide explicit selections");
2714
- return matches;
2710
+ if (matches.length !== 1) throw new Error("Caption text must select a unique AudioScript range; provide explicit selection");
2711
+ return matches[0];
2715
2712
  }
2716
2713
  //#endregion
2717
2714
  //#region src/editor/snapshot-utils.ts
@@ -4852,4 +4849,4 @@ function serverCovers(serverVV, target) {
4852
4849
  return covers(server, target);
4853
4850
  }
4854
4851
  //#endregion
4855
- export { DEFAULT_UNIT_TIME_MS, ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION, EntityGraphHttpClient, EntityTimelineEditor, EntityTimelineProjectionError, IMPLEMENTED_SEMANTIC_OP_KINDS, LANE_KINDS_IN_STACK_ORDER, LORO_ENTITY_SCHEMA, LoroEntityDocument, LoroEntityDraft, ManualSyncDoc, MedeoHttpDocStorage, MemoryDocStorage, MengineAckFailedError, MengineDocSession, MengineHttpClient, MengineHttpRequestError, MenginePushRejectedError, MirrorVideoDocumentAdapter, PlainMemoryAdapter, SchemaValidator, ScriptCompositionError, SemanticEditor, TIMELINE_SKELETON_DURATION_MS, VIDEO_DOCUMENT_SCHEMA_VERSION, ValidationError, VideoDocumentValidationError, applyEntityRows, applyEntityTimelineProjection, applyFieldChanges, arrangeMainTrackSeamlessly, assembleCaptionContent, assembleEntityContent, assemblePhoneticScriptContent, assembleScriptText, assertCanonicalEditorResources, assertEntityProjectionPreservesLegacy, assertFieldChanges, assertMediaAssetWritePolicy, assertValidVideoDocument, base64ToBytes, buildInitialVideoDocument, buildSpeechHostMap, bytesToBase64, cascadeAfterVideoClipChanges, compileEntityRows, createEditSandbox, createMirrorVideoDocument, createMirrorVideoDocumentAdapter, createPlainMemoryAdapter, decodeDocVersionMark, derivePositionFromAbs, effectiveVideoClipDurationMs, encodeDocVersionMark, ensureEditorFoundation, ensureLaneTrack, fillMainTrackTimeGaps, findComposedAudioScript, findLaneTrack, fromVideoDocument, generatePartId, getAt, hostForAbsMs, importMediaAsset, isEmptyVideoClip, isImplementedSemanticOpKind, isMap, laneTrackId, mainTrackRanges, migrateLegacyTimelineToEntities, partDurationMs, partUnionSchema, prepareCaptionContent, projectEntityTimeline, readDocumentAudioScript, readEntityDocument, readMainTrackItems, readMengineEventStream, readPart, readPartDurationMs, readVideoDocumentFromDraft, reassignSpeechesToVideoClipsByTime, recalculateTimelineDuration, relativePositionForAbs, replayJournal, resolveAllSpeechOverlaps, resolveEntityTimelineLayout, resolveFieldPath, resolveSpeechOverlapByShiftingVideos, safeDurationMs, schemas_exports as schemas, selectAudioScriptSegments, snapshotToPlain, solveVideoDocument, speedOf, syncAggregatedClipsTimePosition, toVideoDocument, validateVideoDocument, videoDocumentMirrorSchema, videoDocumentSchema, writeVideoDocumentToDraft };
4852
+ export { DEFAULT_UNIT_TIME_MS, ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION, EntityGraphHttpClient, EntityTimelineEditor, EntityTimelineProjectionError, IMPLEMENTED_SEMANTIC_OP_KINDS, LANE_KINDS_IN_STACK_ORDER, LORO_ENTITY_SCHEMA, LoroEntityDocument, LoroEntityDraft, ManualSyncDoc, MedeoHttpDocStorage, MemoryDocStorage, MengineAckFailedError, MengineDocSession, MengineHttpClient, MengineHttpRequestError, MenginePushRejectedError, MirrorVideoDocumentAdapter, PlainMemoryAdapter, SchemaValidator, ScriptCompositionError, SemanticEditor, TIMELINE_SKELETON_DURATION_MS, VIDEO_DOCUMENT_SCHEMA_VERSION, ValidationError, VideoDocumentValidationError, applyEntityRows, applyEntityTimelineProjection, applyFieldChanges, arrangeMainTrackSeamlessly, assembleCaptionContent, assembleEntityContent, assemblePhoneticScriptContent, assembleScriptText, assertCanonicalEditorResources, assertEntityProjectionPreservesLegacy, assertFieldChanges, assertMediaAssetWritePolicy, assertValidVideoDocument, base64ToBytes, buildInitialVideoDocument, buildSpeechHostMap, bytesToBase64, cascadeAfterVideoClipChanges, compileEntityRows, createEditSandbox, createMirrorVideoDocument, createMirrorVideoDocumentAdapter, createPlainMemoryAdapter, decodeDocVersionMark, derivePositionFromAbs, effectiveVideoClipDurationMs, encodeDocVersionMark, ensureEditorFoundation, ensureLaneTrack, fillMainTrackTimeGaps, findComposedAudioScript, findLaneTrack, fromVideoDocument, generatePartId, getAt, hostForAbsMs, importMediaAsset, isEmptyVideoClip, isImplementedSemanticOpKind, isMap, laneTrackId, mainTrackRanges, migrateLegacyTimelineToEntities, partDurationMs, partUnionSchema, prepareCaptionContent, projectEntityTimeline, readDocumentAudioScript, readEntityDocument, readMainTrackItems, readMengineEventStream, readPart, readPartDurationMs, readVideoDocumentFromDraft, reassignSpeechesToVideoClipsByTime, recalculateTimelineDuration, relativePositionForAbs, replayJournal, resolveAllSpeechOverlaps, resolveEntityTimelineLayout, resolveFieldPath, resolveSpeechOverlapByShiftingVideos, safeDurationMs, schemas_exports as schemas, selectAudioScriptSegment, snapshotToPlain, solveVideoDocument, speedOf, syncAggregatedClipsTimePosition, toVideoDocument, validateVideoDocument, videoDocumentMirrorSchema, videoDocumentSchema, writeVideoDocumentToDraft };
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { At as VideoDraft, c as MirrorVideoDocumentAdapter } from "./index-D5XV4UPC.js";
1
+ import { At as VideoDraft, c as MirrorVideoDocumentAdapter } from "./index-B31KeDzA.js";
2
2
 
3
3
  //#region src/testing/in-memory-mengine-server.d.ts
4
4
  /**
package/dist/testing.js CHANGED
@@ -1,4 +1,4 @@
1
- import { bt as bytesToBase64, pt as VIDEO_DOCUMENT_SCHEMA_VERSION, s as createMirrorVideoDocumentAdapter, yt as base64ToBytes } from "./document-BLm4ABAb.js";
1
+ import { bt as bytesToBase64, pt as VIDEO_DOCUMENT_SCHEMA_VERSION, s as createMirrorVideoDocumentAdapter, yt as base64ToBytes } from "./document-BSAUud6c.js";
2
2
  import { t as classifyUpdate } from "./loro-relay-doc-ssdYpuef.js";
3
3
  import { LoroDoc, VersionVector, encodeFrontiers } from "loro-crdt";
4
4
  //#region src/testing/in-memory-mengine-server.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mengine/medeo-client",
3
- "version": "1.4.1-alpha.4",
3
+ "version": "1.4.1-alpha.5",
4
4
  "license": "UNLICENSED",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,9 +28,9 @@
28
28
  "immer": "^10.2.0",
29
29
  "loro-mirror": "^2.2.0",
30
30
  "zod": "^4.4.3",
31
- "@mengine/storage": "1.4.1-alpha.4",
32
- "@mengine/sync": "1.4.1-alpha.4",
33
- "@mengine/utils": "1.4.1-alpha.4"
31
+ "@mengine/utils": "1.4.1-alpha.5",
32
+ "@mengine/sync": "1.4.1-alpha.5",
33
+ "@mengine/storage": "1.4.1-alpha.5"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^25.9.1",