@pixerate/editor 0.240.0 → 0.242.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.
Files changed (67) hide show
  1. package/dist/animation-editor/controller.d.cts +10 -0
  2. package/dist/animation-editor/controller.d.ts +10 -0
  3. package/dist/animation-editor/effects.d.cts +1 -1
  4. package/dist/animation-editor/effects.d.ts +1 -1
  5. package/dist/animation-editor/index.cjs +195 -146
  6. package/dist/animation-editor/index.js +63 -14
  7. package/dist/{brushstrokeRender-WB67GMUP.js → brushstrokeRender-MOYGEXOC.js} +2 -2
  8. package/dist/{brushstrokeRender-MPOM7BFW.cjs → brushstrokeRender-UKADOV5D.cjs} +5 -5
  9. package/dist/canvas/index.cjs +15 -15
  10. package/dist/canvas/index.js +2 -2
  11. package/dist/{chunk-NKTNLJUJ.cjs → chunk-5BR7LC24.cjs} +99 -11
  12. package/dist/{chunk-ZXNO3ZOX.cjs → chunk-7F4G74UQ.cjs} +35 -35
  13. package/dist/{chunk-A7PQNIBX.cjs → chunk-7V7QMFTI.cjs} +14 -14
  14. package/dist/{chunk-AD7GA3TL.cjs → chunk-AFLMXITL.cjs} +23 -23
  15. package/dist/{chunk-JAOSL334.cjs → chunk-GHCSC2WP.cjs} +38 -16
  16. package/dist/{chunk-PP6BXVRL.cjs → chunk-HGGJ36HR.cjs} +1 -1
  17. package/dist/{chunk-BBUE3UJL.cjs → chunk-HW72ABGR.cjs} +86 -86
  18. package/dist/{chunk-7YGBSFC6.js → chunk-ILM6GYAX.js} +1 -1
  19. package/dist/{chunk-JWCKJNDR.cjs → chunk-K5DS2JTA.cjs} +6 -6
  20. package/dist/{chunk-THXFU3JB.cjs → chunk-KCMV2534.cjs} +2 -2
  21. package/dist/{chunk-WDDUPWVG.js → chunk-L3JFOTBQ.js} +1 -1
  22. package/dist/{chunk-3E36VDMJ.js → chunk-NE6OOKWJ.js} +1 -1
  23. package/dist/{chunk-SIK3LT6M.js → chunk-OFH6Q67U.js} +28 -6
  24. package/dist/{chunk-RV5DKZHU.js → chunk-QP2B3MID.js} +1 -1
  25. package/dist/{chunk-G3RUKJ5C.js → chunk-RXZL4NG5.js} +1 -1
  26. package/dist/{chunk-UUBO6RB5.js → chunk-UDBDYZET.js} +1 -1
  27. package/dist/{chunk-TEFQISBY.js → chunk-X3ZINLIP.js} +1 -1
  28. package/dist/{chunk-PJYG6FCF.js → chunk-XBZK47LV.js} +98 -10
  29. package/dist/{chunk-ZQIWBJGH.cjs → chunk-XNZFVYC2.cjs} +7 -7
  30. package/dist/{chunk-XK4SST43.js → chunk-ZDPLZDTT.js} +1 -1
  31. package/dist/effects/fake.d.cts +4 -0
  32. package/dist/effects/fake.d.ts +4 -0
  33. package/dist/effects/helpers.d.cts +6 -0
  34. package/dist/effects/helpers.d.ts +6 -0
  35. package/dist/effects/index.cjs +222 -94
  36. package/dist/effects/index.js +131 -3
  37. package/dist/effects/types.d.cts +31 -0
  38. package/dist/effects/types.d.ts +31 -0
  39. package/dist/image-editor/index.cjs +788 -788
  40. package/dist/image-editor/index.js +5 -5
  41. package/dist/paint-editor/controller.d.cts +67 -0
  42. package/dist/paint-editor/controller.d.ts +67 -0
  43. package/dist/paint-editor/effect-paint.d.cts +60 -3
  44. package/dist/paint-editor/effect-paint.d.ts +60 -3
  45. package/dist/paint-editor/index.cjs +682 -436
  46. package/dist/paint-editor/index.js +284 -38
  47. package/dist/paint-editor/stickers.d.cts +6 -0
  48. package/dist/paint-editor/stickers.d.ts +6 -0
  49. package/dist/paint-editor/thick.d.cts +4 -0
  50. package/dist/paint-editor/thick.d.ts +4 -0
  51. package/dist/paint-editor/wet.d.cts +8 -0
  52. package/dist/paint-editor/wet.d.ts +8 -0
  53. package/dist/vector/index.cjs +968 -968
  54. package/dist/vector/index.js +5 -5
  55. package/dist/video-editor/controller.d.cts +49 -1
  56. package/dist/video-editor/controller.d.ts +49 -1
  57. package/dist/video-editor/effect-path.d.cts +66 -0
  58. package/dist/video-editor/effect-path.d.ts +66 -0
  59. package/dist/video-editor/index.cjs +616 -427
  60. package/dist/video-editor/index.d.cts +1 -0
  61. package/dist/video-editor/index.d.ts +1 -0
  62. package/dist/video-editor/index.js +193 -4
  63. package/package.json +1 -1
  64. package/skills/pixerate-animation-editor/SKILL.md +1 -1
  65. package/skills/pixerate-paint-editor/SKILL.md +17 -21
  66. package/skills/pixerate-paint-editor/references/effect-paint.md +25 -0
  67. package/skills/pixerate-video-editor/SKILL.md +9 -2
@@ -1,6 +1,6 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8;
2
2
 
3
- var _chunkA7PQNIBXcjs = require('../chunk-A7PQNIBX.cjs');
3
+ var _chunk7V7QMFTIcjs = require('../chunk-7V7QMFTI.cjs');
4
4
 
5
5
 
6
6
 
@@ -149,7 +149,7 @@ var _chunkA7PQNIBXcjs = require('../chunk-A7PQNIBX.cjs');
149
149
 
150
150
 
151
151
 
152
- var _chunkZQIWBJGHcjs = require('../chunk-ZQIWBJGH.cjs');
152
+ var _chunkXNZFVYC2cjs = require('../chunk-XNZFVYC2.cjs');
153
153
 
154
154
 
155
155
  var _chunkDGWOGQJ5cjs = require('../chunk-DGWOGQJ5.cjs');
@@ -159,7 +159,7 @@ var _chunkDGWOGQJ5cjs = require('../chunk-DGWOGQJ5.cjs');
159
159
 
160
160
 
161
161
 
162
- var _chunkJWCKJNDRcjs = require('../chunk-JWCKJNDR.cjs');
162
+ var _chunkK5DS2JTAcjs = require('../chunk-K5DS2JTA.cjs');
163
163
  require('../chunk-PY4GWSE2.cjs');
164
164
 
165
165
 
@@ -170,7 +170,8 @@ require('../chunk-PY4GWSE2.cjs');
170
170
 
171
171
 
172
172
 
173
- var _chunkJAOSL334cjs = require('../chunk-JAOSL334.cjs');
173
+
174
+ var _chunkGHCSC2WPcjs = require('../chunk-GHCSC2WP.cjs');
174
175
  require('../chunk-WOFXZ3XU.cjs');
175
176
 
176
177
 
@@ -230,7 +231,7 @@ function parseVideoEase(v, path) {
230
231
  if (v[0] < 0 || v[0] > 1 || v[2] < 0 || v[2] > 1) fail(path, "must have x1 and x2 between 0 and 1");
231
232
  return [v[0], v[1], v[2], v[3]];
232
233
  }
233
- return oneOf(v, _chunkZQIWBJGHcjs.VIDEO_EASE_NAMES, path);
234
+ return oneOf(v, _chunkXNZFVYC2cjs.VIDEO_EASE_NAMES, path);
234
235
  }
235
236
  function parseVideoKeyframes(v, path, { min, max } = {}) {
236
237
  if (!isObject(v)) return fail(path, "must be a number or keyframes { keys: [{ t, v, ease }] }");
@@ -272,7 +273,7 @@ function parseVideoTimeRemap(v, speed, path) {
272
273
  if (speed !== void 0 && speed !== 1) fail(path, 'cannot be used with a speed; a ramp sets the speed itself (remove "speed")');
273
274
  for (let i = 1; i < remap.keys.length; i++) if (remap.keys[i].t === remap.keys[i - 1].t) fail(`${path}.keys[${i}].t`, `must be later than the key before (${remap.keys[i - 1].t} ms); a speed ramp has one key per time`);
274
275
  try {
275
- _chunkZQIWBJGHcjs.checkVideoTimeRemap.call(void 0, remap, path);
276
+ _chunkXNZFVYC2cjs.checkVideoTimeRemap.call(void 0, remap, path);
276
277
  } catch (e) {
277
278
  throw new Error(e.message.replace(/\.?$/, "."));
278
279
  }
@@ -282,17 +283,17 @@ function parseVideoClipAnimation(v, path) {
282
283
  if (v === void 0) return void 0;
283
284
  if (!isObject(v)) return fail(path, "must be an object { effect, duration }");
284
285
  return compact({
285
- effect: oneOf(v.effect, _chunkZQIWBJGHcjs.VIDEO_CLIP_ANIMATION_EFFECTS, `${path}.effect`, false),
286
+ effect: oneOf(v.effect, _chunkXNZFVYC2cjs.VIDEO_CLIP_ANIMATION_EFFECTS, `${path}.effect`, false),
286
287
  duration: num(v.duration, `${path}.duration`, { optional: true, positive: true })
287
288
  });
288
289
  }
289
290
  function parseVideoGrade(v, path) {
290
291
  if (v === void 0) return void 0;
291
292
  if (!isObject(v)) return fail(path, "must be an object such as { exposure, contrast, saturation }");
292
- const known = /* @__PURE__ */ new Set([..._chunkZQIWBJGHcjs.VIDEO_GRADE_CONTROLS.map((c) => c.key), "lut"]);
293
+ const known = /* @__PURE__ */ new Set([..._chunkXNZFVYC2cjs.VIDEO_GRADE_CONTROLS.map((c) => c.key), "lut"]);
293
294
  const unknown = Object.keys(v).find((k) => !known.has(k));
294
295
  if (unknown) fail(`${path}.${unknown}`, `is not a grade setting; use ${[...known].join(", ")}`);
295
- return compact({ ...Object.fromEntries(_chunkZQIWBJGHcjs.VIDEO_GRADE_CONTROLS.map((c) => [c.key, num(v[c.key], `${path}.${c.key}`, { optional: true, min: c.min, max: c.max })])), lut: parseVideoGradeLut(v.lut, `${path}.lut`) });
296
+ return compact({ ...Object.fromEntries(_chunkXNZFVYC2cjs.VIDEO_GRADE_CONTROLS.map((c) => [c.key, num(v[c.key], `${path}.${c.key}`, { optional: true, min: c.min, max: c.max })])), lut: parseVideoGradeLut(v.lut, `${path}.lut`) });
296
297
  }
297
298
  function parseVideoGradeLut(v, path) {
298
299
  if (v === void 0) return void 0;
@@ -307,7 +308,7 @@ function parseVideoClipMask(v, path) {
307
308
  if (!isObject(v)) return fail(path, 'must be an object such as { shape: "ellipse", x: 0.5, y: 0.5, width: 0.4, height: 0.6, feather: 20 }');
308
309
  const unknown = Object.keys(v).find((k) => !MASK_KEYS.includes(k));
309
310
  if (unknown) fail(`${path}.${unknown}`, `is not a mask setting; use ${MASK_KEYS.join(", ")}`);
310
- const shape = oneOf(v.shape, _chunkZQIWBJGHcjs.VIDEO_MASK_SHAPES, `${path}.shape`, false);
311
+ const shape = oneOf(v.shape, _chunkXNZFVYC2cjs.VIDEO_MASK_SHAPES, `${path}.shape`, false);
311
312
  let points;
312
313
  if (v.points !== void 0) {
313
314
  if (shape !== "polygon") fail(`${path}.points`, "is only for polygon masks");
@@ -333,15 +334,15 @@ function parseVideoClipMask(v, path) {
333
334
  function parseVideoTransition(v, path) {
334
335
  if (v === void 0) return void 0;
335
336
  if (!isObject(v)) return fail(path, "must be an object { type, duration }");
336
- const type = oneOf(v.type, _chunkZQIWBJGHcjs.VIDEO_TRANSITION_TYPES, `${path}.type`, false);
337
+ const type = oneOf(v.type, _chunkXNZFVYC2cjs.VIDEO_TRANSITION_TYPES, `${path}.type`, false);
337
338
  if (type === "effect" && v.effect === void 0) fail(`${path}.effect`, 'is required for an effect transition: { effect: "<effect id>", values }');
338
339
  if (type !== "effect" && v.effect !== void 0) fail(`${path}.effect`, 'is only for transitions of type "effect"');
339
340
  return compact({
340
341
  type,
341
342
  duration: num(v.duration, `${path}.duration`, { positive: true }),
342
343
  color: str(v.color, `${path}.color`, true),
343
- direction: oneOf(v.direction, _chunkZQIWBJGHcjs.VIDEO_WIPE_DIRECTIONS, `${path}.direction`),
344
- audioCurve: oneOf(v.audioCurve, _chunkZQIWBJGHcjs.VIDEO_FADE_CURVES, `${path}.audioCurve`),
344
+ direction: oneOf(v.direction, _chunkXNZFVYC2cjs.VIDEO_WIPE_DIRECTIONS, `${path}.direction`),
345
+ audioCurve: oneOf(v.audioCurve, _chunkXNZFVYC2cjs.VIDEO_FADE_CURVES, `${path}.audioCurve`),
345
346
  effect: v.effect === void 0 ? void 0 : parseVideoEffectRef(v.effect, `${path}.effect`, false)
346
347
  });
347
348
  }
@@ -470,7 +471,7 @@ function parseVideoClipCamera(v, path) {
470
471
  }
471
472
  function parseVideoClip(v, path = "clip") {
472
473
  if (!isObject(v)) return fail(path, "must be an object");
473
- const type = oneOf(_nullishCoalesce(v.type, () => ( "media")), _chunkZQIWBJGHcjs.VIDEO_CLIP_TYPES, `${path}.type`, false);
474
+ const type = oneOf(_nullishCoalesce(v.type, () => ( "media")), _chunkXNZFVYC2cjs.VIDEO_CLIP_TYPES, `${path}.type`, false);
474
475
  const base = {
475
476
  id: str(v.id, `${path}.id`),
476
477
  name: str(v.name, `${path}.name`, true),
@@ -478,8 +479,8 @@ function parseVideoClip(v, path = "clip") {
478
479
  duration: num(v.duration, `${path}.duration`, { positive: true }),
479
480
  opacity: parseVideoAnimatable(v.opacity, `${path}.opacity`, { optional: true, min: 0, max: 1 }),
480
481
  transform: parseVideoTransform(v.transform, `${path}.transform`),
481
- fit: oneOf(v.fit, _chunkZQIWBJGHcjs.VIDEO_FITS, `${path}.fit`),
482
- blend: oneOf(v.blend, _chunkZQIWBJGHcjs.VIDEO_BLEND_MODES, `${path}.blend`),
482
+ fit: oneOf(v.fit, _chunkXNZFVYC2cjs.VIDEO_FITS, `${path}.fit`),
483
+ blend: oneOf(v.blend, _chunkXNZFVYC2cjs.VIDEO_BLEND_MODES, `${path}.blend`),
483
484
  grade: parseVideoGrade(v.grade, `${path}.grade`),
484
485
  animateIn: parseVideoClipAnimation(v.animateIn, `${path}.animateIn`),
485
486
  animateOut: parseVideoClipAnimation(v.animateOut, `${path}.animateOut`),
@@ -500,8 +501,8 @@ function parseVideoClip(v, path = "clip") {
500
501
  volume: parseVideoAnimatable(v.volume, `${path}.volume`, { optional: true, min: 0, max: 4 }),
501
502
  muted: bool(v.muted, `${path}.muted`),
502
503
  timeRemap: parseVideoTimeRemap(v.timeRemap, v.speed, `${path}.timeRemap`),
503
- fadeInCurve: oneOf(v.fadeInCurve, _chunkZQIWBJGHcjs.VIDEO_FADE_CURVES, `${path}.fadeInCurve`),
504
- fadeOutCurve: oneOf(v.fadeOutCurve, _chunkZQIWBJGHcjs.VIDEO_FADE_CURVES, `${path}.fadeOutCurve`)
504
+ fadeInCurve: oneOf(v.fadeInCurve, _chunkXNZFVYC2cjs.VIDEO_FADE_CURVES, `${path}.fadeInCurve`),
505
+ fadeOutCurve: oneOf(v.fadeOutCurve, _chunkXNZFVYC2cjs.VIDEO_FADE_CURVES, `${path}.fadeOutCurve`)
505
506
  });
506
507
  if (type === "sequence") {
507
508
  for (const key of ["speed", "timeRemap"])
@@ -513,8 +514,8 @@ function parseVideoClip(v, path = "clip") {
513
514
  in: num(v.in, `${path}.in`, { optional: true, min: 0 }),
514
515
  volume: parseVideoAnimatable(v.volume, `${path}.volume`, { optional: true, min: 0, max: 4 }),
515
516
  muted: bool(v.muted, `${path}.muted`),
516
- fadeInCurve: oneOf(v.fadeInCurve, _chunkZQIWBJGHcjs.VIDEO_FADE_CURVES, `${path}.fadeInCurve`),
517
- fadeOutCurve: oneOf(v.fadeOutCurve, _chunkZQIWBJGHcjs.VIDEO_FADE_CURVES, `${path}.fadeOutCurve`)
517
+ fadeInCurve: oneOf(v.fadeInCurve, _chunkXNZFVYC2cjs.VIDEO_FADE_CURVES, `${path}.fadeInCurve`),
518
+ fadeOutCurve: oneOf(v.fadeOutCurve, _chunkXNZFVYC2cjs.VIDEO_FADE_CURVES, `${path}.fadeOutCurve`)
518
519
  });
519
520
  }
520
521
  if (type === "text")
@@ -529,7 +530,7 @@ function parseVideoClip(v, path = "clip") {
529
530
  background: str(v.background, `${path}.background`, true)
530
531
  });
531
532
  if (type === "adjustment") {
532
- const scope = oneOf(v.scope, _chunkZQIWBJGHcjs.VIDEO_ADJUSTMENT_SCOPES, `${path}.scope`);
533
+ const scope = oneOf(v.scope, _chunkXNZFVYC2cjs.VIDEO_ADJUSTMENT_SCOPES, `${path}.scope`);
533
534
  const targetTrack = str(v.targetTrack, `${path}.targetTrack`, true);
534
535
  if (scope === "track" && !targetTrack) fail(`${path}.targetTrack`, 'is required when scope is "track": the id of the track whose pictures the adjustment changes');
535
536
  if (targetTrack !== void 0 && scope !== "track") fail(`${path}.targetTrack`, 'is only for scope "track"');
@@ -632,9 +633,9 @@ function createVideoProject(options = {}) {
632
633
  // src/video-editor/check.ts
633
634
  function videoClipKeyframes(clip) {
634
635
  const out = [
635
- { property: "opacity", keys: _chunkZQIWBJGHcjs.videoKeysOf.call(void 0, clip.opacity) },
636
- { property: "volume", keys: clip.type === "media" || clip.type === "sequence" ? _chunkZQIWBJGHcjs.videoKeysOf.call(void 0, clip.volume) : [] },
637
- ..._chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES.map((p) => ({ property: p, keys: _chunkZQIWBJGHcjs.videoKeysOf.call(void 0, _optionalChain([clip, 'access', _2 => _2.transform, 'optionalAccess', _3 => _3[p]])) }))
636
+ { property: "opacity", keys: _chunkXNZFVYC2cjs.videoKeysOf.call(void 0, clip.opacity) },
637
+ { property: "volume", keys: clip.type === "media" || clip.type === "sequence" ? _chunkXNZFVYC2cjs.videoKeysOf.call(void 0, clip.volume) : [] },
638
+ ..._chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES.map((p) => ({ property: p, keys: _chunkXNZFVYC2cjs.videoKeysOf.call(void 0, _optionalChain([clip, 'access', _2 => _2.transform, 'optionalAccess', _3 => _3[p]])) }))
638
639
  ];
639
640
  return out.filter((o) => o.keys.length);
640
641
  }
@@ -663,8 +664,8 @@ var VIDEO_ISSUE_CODES = [
663
664
  var videoIssueKey = (i) => [i.code, _nullishCoalesce(i.sequence, () => ( "")), _nullishCoalesce(i.track, () => ( "")), _nullishCoalesce(i.clip, () => ( "")), _nullishCoalesce(i.asset, () => ( "")), _nullishCoalesce(i.marker, () => ( ""))].join("|");
664
665
  function checkVideoProject(project) {
665
666
  const issues = [];
666
- const assets = _chunkZQIWBJGHcjs.videoAssetMap.call(void 0, project);
667
- const sequences = _chunkZQIWBJGHcjs.videoSequenceMap.call(void 0, project);
667
+ const assets = _chunkXNZFVYC2cjs.videoAssetMap.call(void 0, project);
668
+ const sequences = _chunkXNZFVYC2cjs.videoSequenceMap.call(void 0, project);
668
669
  const used = /* @__PURE__ */ new Set();
669
670
  const usedSequences = /* @__PURE__ */ new Set();
670
671
  const cycles = /* @__PURE__ */ new Map();
@@ -672,7 +673,7 @@ function checkVideoProject(project) {
672
673
  if ((asset.kind === "video" || asset.kind === "audio") && asset.duration === void 0)
673
674
  issues.push({ code: "unknown-duration", severity: "warning", asset: asset.id, message: `Asset "${asset.id}" has no duration, so clips of it cannot be checked against its length; set "duration" in ms.` });
674
675
  const checkTrack = (track, sequence) => {
675
- const clips = _chunkZQIWBJGHcjs.sortedVideoClips.call(void 0, track);
676
+ const clips = _chunkXNZFVYC2cjs.sortedVideoClips.call(void 0, track);
676
677
  const where = sequence ? ` in sequence "${sequence}"` : "";
677
678
  for (let i = 0; i < clips.length; i++) {
678
679
  const clip = clips[i];
@@ -682,13 +683,13 @@ function checkVideoProject(project) {
682
683
  const seq = sequences.get(clip.sequence);
683
684
  if (!seq) issues.push({ code: "missing-sequence", severity: "error", ...at, message: `Compound clip "${clip.id}" plays sequence "${clip.sequence}", which is not in the project; add the sequence or delete the clip.` });
684
685
  else {
685
- if (!cycles.has(seq.id)) cycles.set(seq.id, _chunkZQIWBJGHcjs.findVideoSequenceCycle.call(void 0, project, seq.id));
686
+ if (!cycles.has(seq.id)) cycles.set(seq.id, _chunkXNZFVYC2cjs.findVideoSequenceCycle.call(void 0, project, seq.id));
686
687
  const cycle = cycles.get(seq.id);
687
688
  if (cycle) issues.push({ code: "sequence-cycle", severity: "error", ...at, message: `Compound clip "${clip.id}" plays sequence "${seq.id}", which contains itself (${cycle.join(" \u2192 ")}), so it is left out of the picture and sound; remove the compound clip that closes the loop.` });
688
- const length = _chunkZQIWBJGHcjs.videoSequenceDuration.call(void 0, seq);
689
- const range = _chunkZQIWBJGHcjs.videoClipSourceRange.call(void 0, clip);
690
- if (range.out > length + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON)
691
- issues.push({ code: "source-overrun", severity: "error", ...at, message: `Compound clip "${clip.id}" plays to ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, range.out)} of sequence "${seq.id}", which is only ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, length)} long; shorten the clip or move its in point.` });
689
+ const length = _chunkXNZFVYC2cjs.videoSequenceDuration.call(void 0, seq);
690
+ const range = _chunkXNZFVYC2cjs.videoClipSourceRange.call(void 0, clip);
691
+ if (range.out > length + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON)
692
+ issues.push({ code: "source-overrun", severity: "error", ...at, message: `Compound clip "${clip.id}" plays to ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, range.out)} of sequence "${seq.id}", which is only ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, length)} long; shorten the clip or move its in point.` });
692
693
  }
693
694
  } else if (clip.type === "media") {
694
695
  used.add(clip.asset);
@@ -697,32 +698,32 @@ function checkVideoProject(project) {
697
698
  else {
698
699
  if (track.kind === "audio" && asset.kind === "image") issues.push({ code: "wrong-track", severity: "error", ...at, message: `Clip "${clip.id}" is an image on audio track "${track.id}"; move it to a video track.` });
699
700
  if (track.kind === "video" && asset.kind === "audio") issues.push({ code: "wrong-track", severity: "error", ...at, message: `Clip "${clip.id}" is audio on video track "${track.id}"; move it to an audio track.` });
700
- const range = _chunkZQIWBJGHcjs.videoClipSourceRange.call(void 0, clip);
701
- if (asset.duration !== void 0 && range.out > asset.duration + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON)
702
- issues.push({ code: "source-overrun", severity: "error", ...at, message: `Clip "${clip.id}" plays to ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, range.out)} of "${asset.id}", which is only ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, asset.duration)} long; shorten the clip or move its in point.` });
701
+ const range = _chunkXNZFVYC2cjs.videoClipSourceRange.call(void 0, clip);
702
+ if (asset.duration !== void 0 && range.out > asset.duration + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON)
703
+ issues.push({ code: "source-overrun", severity: "error", ...at, message: `Clip "${clip.id}" plays to ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, range.out)} of "${asset.id}", which is only ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, asset.duration)} long; shorten the clip or move its in point.` });
703
704
  }
704
705
  } else if (track.kind === "audio") issues.push({ code: "wrong-track", severity: "error", ...at, message: `Clip "${clip.id}" is a ${clip.type} clip on audio track "${track.id}"; move it to a video track.` });
705
706
  if (clip.type === "adjustment" && (_nullishCoalesce(clip.scope, () => ( "underneath"))) === "track" && !(sequence ? _nullishCoalesce(_optionalChain([sequences, 'access', _4 => _4.get, 'call', _5 => _5(sequence), 'optionalAccess', _6 => _6.tracks]), () => ( [])) : project.tracks).some((t) => t.id === clip.targetTrack))
706
707
  issues.push({ code: "missing-target-track", severity: "warning", ...at, message: `Adjustment clip "${clip.id}" changes track "${clip.targetTrack}", which is not ${sequence ? `in sequence "${sequence}"` : "in the project"}, so it changes nothing; set its targetTrack to a track beside it or change its scope.` });
707
708
  const next = clips[i + 1];
708
- if (next && next.start < _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip) - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON)
709
- issues.push({ code: "overlap", severity: "error", ...at, message: `Clips "${clip.id}" and "${next.id}" overlap on track "${track.id}"${where} from ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, next.start)}; move one of them.` });
710
- if ((_nullishCoalesce(clip.fadeIn, () => ( 0))) + (_nullishCoalesce(clip.fadeOut, () => ( 0))) > clip.duration + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON)
709
+ if (next && next.start < _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip) - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON)
710
+ issues.push({ code: "overlap", severity: "error", ...at, message: `Clips "${clip.id}" and "${next.id}" overlap on track "${track.id}"${where} from ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, next.start)}; move one of them.` });
711
+ if ((_nullishCoalesce(clip.fadeIn, () => ( 0))) + (_nullishCoalesce(clip.fadeOut, () => ( 0))) > clip.duration + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON)
711
712
  issues.push({ code: "fades-too-long", severity: "warning", ...at, message: `Clip "${clip.id}"'s fades (${_nullishCoalesce(clip.fadeIn, () => ( 0))} + ${_nullishCoalesce(clip.fadeOut, () => ( 0))} ms) are longer than the clip (${clip.duration} ms); shorten them.` });
712
- const anim = (clip.animateIn ? _nullishCoalesce(clip.animateIn.duration, () => ( _chunkZQIWBJGHcjs.VIDEO_CLIP_ANIMATION_DURATION)) : 0) + (clip.animateOut ? _nullishCoalesce(clip.animateOut.duration, () => ( _chunkZQIWBJGHcjs.VIDEO_CLIP_ANIMATION_DURATION)) : 0);
713
- if (anim > clip.duration + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON)
713
+ const anim = (clip.animateIn ? _nullishCoalesce(clip.animateIn.duration, () => ( _chunkXNZFVYC2cjs.VIDEO_CLIP_ANIMATION_DURATION)) : 0) + (clip.animateOut ? _nullishCoalesce(clip.animateOut.duration, () => ( _chunkXNZFVYC2cjs.VIDEO_CLIP_ANIMATION_DURATION)) : 0);
714
+ if (anim > clip.duration + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON)
714
715
  issues.push({ code: "animations-too-long", severity: "warning", ...at, message: `Clip "${clip.id}"'s entrance and exit (${anim} ms together) are longer than the clip (${clip.duration} ms), so both are shortened; give them shorter durations.` });
715
716
  for (const which of ["animateIn", "animateOut"]) {
716
717
  const a = clip[which];
717
718
  if (!a) continue;
718
- const keyed = _chunkZQIWBJGHcjs.videoClipAnimationProperties.call(void 0, a).filter((p) => _chunkZQIWBJGHcjs.videoKeysOf.call(void 0, p === "opacity" ? clip.opacity : _optionalChain([clip, 'access', _7 => _7.transform, 'optionalAccess', _8 => _8[p]])).length);
719
+ const keyed = _chunkXNZFVYC2cjs.videoClipAnimationProperties.call(void 0, a).filter((p) => _chunkXNZFVYC2cjs.videoKeysOf.call(void 0, p === "opacity" ? clip.opacity : _optionalChain([clip, 'access', _7 => _7.transform, 'optionalAccess', _8 => _8[p]])).length);
719
720
  if (keyed.length)
720
721
  issues.push({ code: "animation-keyed", severity: "note", ...at, message: `Clip "${clip.id}"'s ${a.effect} ${which === "animateIn" ? "entrance" : "exit"} leaves ${keyed.join(", ")} alone, because the clip keys ${keyed.length > 1 ? "them" : "it"} itself; remove those keyframes or the animation.` });
721
722
  }
722
723
  if (clip.camera) {
723
- const last = Math.max(0, ..._chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES.flatMap((p) => _chunkZQIWBJGHcjs.videoKeysOf.call(void 0, _optionalChain([clip, 'access', _9 => _9.transform, 'optionalAccess', _10 => _10[p]])).map((k) => k.t)));
724
+ const last = Math.max(0, ..._chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES.flatMap((p) => _chunkXNZFVYC2cjs.videoKeysOf.call(void 0, _optionalChain([clip, 'access', _9 => _9.transform, 'optionalAccess', _10 => _10[p]])).map((k) => k.t)));
724
725
  const frame = 1e3 / (project.fps || 30);
725
- if (last > 0 && Math.abs(last - clip.duration) > frame + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON)
726
+ if (last > 0 && Math.abs(last - clip.duration) > frame + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON)
726
727
  issues.push({
727
728
  code: "camera-stale",
728
729
  severity: "warning",
@@ -731,7 +732,7 @@ function checkVideoProject(project) {
731
732
  });
732
733
  }
733
734
  for (const { property, keys } of videoClipKeyframes(clip)) {
734
- const outside = keys.filter((k) => k.t < -_chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON || k.t > clip.duration + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON);
735
+ const outside = keys.filter((k) => k.t < -_chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON || k.t > clip.duration + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON);
735
736
  if (outside.length)
736
737
  issues.push({
737
738
  code: "keyframes-outside-clip",
@@ -742,20 +743,20 @@ function checkVideoProject(project) {
742
743
  }
743
744
  if (clip.transition) {
744
745
  const d = clip.transition.duration;
745
- const before = _chunkZQIWBJGHcjs.videoClipBefore.call(void 0, track, clip);
746
+ const before = _chunkXNZFVYC2cjs.videoClipBefore.call(void 0, track, clip);
746
747
  if (!before) {
747
748
  issues.push({ code: "transition-without-cut", severity: "warning", ...at, message: `Clip "${clip.id}" has a transition but no clip ends where it starts on track "${track.id}", so it plays as nothing; butt a clip up against it or remove the transition.` });
748
749
  continue;
749
750
  }
750
- if (d > clip.duration + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON || d > before.duration + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) {
751
+ if (d > clip.duration + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON || d > before.duration + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) {
751
752
  issues.push({ code: "transition-too-long", severity: "error", ...at, message: `The ${d} ms transition into "${clip.id}" is longer than "${clip.id}" (${clip.duration} ms) or "${before.id}" (${before.duration} ms); make it at most ${Math.min(clip.duration, before.duration)} ms.` });
752
753
  continue;
753
754
  }
754
755
  if (clip.transition.type === "dip") continue;
755
- const outgoing = _chunkZQIWBJGHcjs.videoClipHandles.call(void 0, before, assets, sequences).after;
756
- const incoming = _chunkZQIWBJGHcjs.videoClipHandles.call(void 0, clip, assets, sequences).before;
756
+ const outgoing = _chunkXNZFVYC2cjs.videoClipHandles.call(void 0, before, assets, sequences).after;
757
+ const incoming = _chunkXNZFVYC2cjs.videoClipHandles.call(void 0, clip, assets, sequences).before;
757
758
  const half = d / 2;
758
- if (outgoing < half - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON || incoming < half - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) {
759
+ if (outgoing < half - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON || incoming < half - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) {
759
760
  const fits = 2 * Math.min(outgoing, incoming);
760
761
  issues.push({
761
762
  code: "transition-handles",
@@ -772,9 +773,9 @@ function checkVideoProject(project) {
772
773
  for (const sequence of _nullishCoalesce(project.sequences, () => ( [])))
773
774
  if (!usedSequences.has(sequence.id)) issues.push({ code: "unused-sequence", severity: "note", sequence: sequence.id, message: `Sequence "${sequence.id}" is not played by any compound clip.` });
774
775
  for (const asset of project.assets) if (!used.has(asset.id)) issues.push({ code: "unused-asset", severity: "note", asset: asset.id, message: `Asset "${asset.id}" is not used by any clip.` });
775
- const end = _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, project);
776
+ const end = _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, project);
776
777
  for (const marker of _nullishCoalesce(project.markers, () => ( [])))
777
- if (marker.time > end + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) issues.push({ code: "marker-past-end", severity: "note", marker: marker.id, message: `Marker "${marker.id}" at ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, marker.time)} is past the end (${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, end)}).` });
778
+ if (marker.time > end + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) issues.push({ code: "marker-past-end", severity: "note", marker: marker.id, message: `Marker "${marker.id}" at ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, marker.time)} is past the end (${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, end)}).` });
778
779
  if (!project.tracks.some((t) => t.clips.length)) issues.push({ code: "empty", severity: "note", message: "The project has no clips yet; add assets and then clips." });
779
780
  const rank = { error: 0, warning: 1, note: 2 };
780
781
  return issues.sort((a, b) => rank[a.severity] - rank[b.severity]);
@@ -828,7 +829,7 @@ function mergeSpans(spans) {
828
829
  const out = [];
829
830
  for (const [from, to] of [...spans].sort((a, b) => a[0] - b[0])) {
830
831
  const last = out[out.length - 1];
831
- if (last && from <= last[1] + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) last[1] = Math.max(last[1], to);
832
+ if (last && from <= last[1] + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) last[1] = Math.max(last[1], to);
832
833
  else out.push([from, to]);
833
834
  }
834
835
  return out;
@@ -842,13 +843,13 @@ function clipAnimatables(clip) {
842
843
  // A speed ramp is keys in clip time too, so trims and splits keep it on the same frames of source.
843
844
  { get: () => c.timeRemap, set: (v) => c.timeRemap = v }
844
845
  ];
845
- for (const p of _chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES) out.push({ get: () => _optionalChain([c, 'access', _11 => _11.transform, 'optionalAccess', _12 => _12[p]]), set: (v) => c.transform && (c.transform[p] = v) });
846
+ for (const p of _chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES) out.push({ get: () => _optionalChain([c, 'access', _11 => _11.transform, 'optionalAccess', _12 => _12[p]]), set: (v) => c.transform && (c.transform[p] = v) });
846
847
  return out;
847
848
  }
848
849
  function retimeClipKeys(clip, fn) {
849
850
  for (const a of clipAnimatables(clip)) {
850
851
  const v = a.get();
851
- if (_chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, v)) a.set(fn(v));
852
+ if (_chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, v)) a.set(fn(v));
852
853
  }
853
854
  }
854
855
  var OPTIONAL_CLIP_FIELDS = ["name", "effects", "mask", "camera", "scope", "targetTrack", "values", "provider", "opacity", "transform", "fit", "blend", "grade", "animateIn", "animateOut", "fadeIn", "fadeOut", "fadeInCurve", "fadeOutCurve", "transition", "in", "speed", "timeRemap", "volume", "muted", "color", "fontSize", "fontFamily", "fontWeight", "background"];
@@ -865,8 +866,8 @@ var Editor = (_class = class {
865
866
  return t;
866
867
  }
867
868
  clip(id) {
868
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, this.p, id);
869
- const nested = at ? null : _chunkZQIWBJGHcjs.findVideoSequenceClip.call(void 0, this.p, id);
869
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, this.p, id);
870
+ const nested = at ? null : _chunkXNZFVYC2cjs.findVideoSequenceClip.call(void 0, this.p, id);
870
871
  if (nested) refuse(`Clip "${id}" is inside sequence "${nested.sequence.id}", and clips inside sequences cannot be edited yet; edit the compound clip that plays the sequence instead (list_video_sequences shows which).`);
871
872
  if (!at) {
872
873
  const ids = this.p.tracks.flatMap((t) => t.clips.map((c) => c.id));
@@ -883,16 +884,16 @@ var Editor = (_class = class {
883
884
  return a;
884
885
  }
885
886
  fits(track, start, duration, ignore, what) {
886
- const hit = _chunkZQIWBJGHcjs.videoOverlap.call(void 0, track, start, start + duration, ignore);
887
+ const hit = _chunkXNZFVYC2cjs.videoOverlap.call(void 0, track, start, start + duration, ignore);
887
888
  if (hit) {
888
- const free = _chunkZQIWBJGHcjs.nextFreeVideoSlot.call(void 0, track, start, duration, ignore);
889
- refuse(`${what} at ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, start)}\u2013${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, start + duration)} would overlap clip "${hit.id}" (${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, hit.start)}\u2013${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, hit))}) on track "${track.id}"; the next free place is ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, free)}, or use mode "insert" to push later clips along or "overwrite" to replace what is there.`);
889
+ const free = _chunkXNZFVYC2cjs.nextFreeVideoSlot.call(void 0, track, start, duration, ignore);
890
+ refuse(`${what} at ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, start)}\u2013${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, start + duration)} would overlap clip "${hit.id}" (${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, hit.start)}\u2013${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, hit))}) on track "${track.id}"; the next free place is ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, free)}, or use mode "insert" to push later clips along or "overwrite" to replace what is there.`);
890
891
  }
891
892
  }
892
893
  /** An adjustment clip's target track must exist. */
893
894
  adjustmentTarget(clip) {
894
895
  if (clip.type !== "adjustment" || clip.targetTrack === void 0) return;
895
- const ids = _chunkZQIWBJGHcjs.allVideoTracks.call(void 0, this.p).map(({ track }) => track.id);
896
+ const ids = _chunkXNZFVYC2cjs.allVideoTracks.call(void 0, this.p).map(({ track }) => track.id);
896
897
  if (!ids.includes(clip.targetTrack)) refuse(`Adjustment clip "${clip.id}" targets track ${_chunkDGWOGQJ5cjs.namedWithSuggestion.call(void 0, clip.targetTrack, ids)}, which does not exist; the tracks are ${ids.map((t) => `"${t}"`).join(", ")}.`);
897
898
  }
898
899
  kindFits(track, clip) {
@@ -908,14 +909,14 @@ var Editor = (_class = class {
908
909
  /** Moves every clip on `track` starting at or after `from` by `delta`. */
909
910
  shift(track, from, delta, except = /* @__PURE__ */ new Set()) {
910
911
  if (!delta) return;
911
- for (const c of track.clips) if (!except.has(c.id) && c.start >= from - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) c.start = Math.max(0, c.start + delta);
912
+ for (const c of track.clips) if (!except.has(c.id) && c.start >= from - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) c.start = Math.max(0, c.start + delta);
912
913
  track.clips.sort((a, b) => a.start - b.start);
913
914
  }
914
915
  get frame() {
915
916
  return 1e3 / this.p.fps;
916
917
  }
917
918
  ids() {
918
- return _chunkZQIWBJGHcjs.allVideoClipIds.call(void 0, this.p);
919
+ return _chunkXNZFVYC2cjs.allVideoClipIds.call(void 0, this.p);
919
920
  }
920
921
  /**
921
922
  * The tracks a ripple on `sources` moves, top to bottom: the sources, and every unlocked
@@ -923,8 +924,8 @@ var Editor = (_class = class {
923
924
  */
924
925
  rippleTracks(sources) {
925
926
  const set = new Set(sources);
926
- if ([...set].some(_chunkZQIWBJGHcjs.videoTrackSyncLocked)) {
927
- for (const t of this.p.tracks) if (_chunkZQIWBJGHcjs.videoTrackSyncLocked.call(void 0, t) && !t.locked) set.add(t);
927
+ if ([...set].some(_chunkXNZFVYC2cjs.videoTrackSyncLocked)) {
928
+ for (const t of this.p.tracks) if (_chunkXNZFVYC2cjs.videoTrackSyncLocked.call(void 0, t) && !t.locked) set.add(t);
928
929
  }
929
930
  return this.p.tracks.filter((t) => set.has(t));
930
931
  }
@@ -941,7 +942,7 @@ var Editor = (_class = class {
941
942
  return open;
942
943
  }
943
944
  range(from, to) {
944
- if (!(to - from > _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON)) refuse(`"to" (${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, to)}) must be after "from" (${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, from)}).`);
945
+ if (!(to - from > _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON)) refuse(`"to" (${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, to)}) must be after "from" (${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, from)}).`);
945
946
  }
946
947
  /** Moves a media or compound clip's in point by `delta` of timeline time (stills, titles and colours have none). */
947
948
  moveIn(clip, delta) {
@@ -950,18 +951,18 @@ var Editor = (_class = class {
950
951
  if (clip.in < 1e-9) delete clip.in;
951
952
  return;
952
953
  }
953
- if (clip.type !== "media" || _optionalChain([_chunkZQIWBJGHcjs.videoAssetMap.call(void 0, this.p), 'access', _14 => _14.get, 'call', _15 => _15(clip.asset), 'optionalAccess', _16 => _16.kind]) === "image") return;
954
- clip.in = Math.max(0, (_nullishCoalesce(clip.in, () => ( 0))) + delta * _chunkZQIWBJGHcjs.videoClipSpeed.call(void 0, clip));
954
+ if (clip.type !== "media" || _optionalChain([_chunkXNZFVYC2cjs.videoAssetMap.call(void 0, this.p), 'access', _14 => _14.get, 'call', _15 => _15(clip.asset), 'optionalAccess', _16 => _16.kind]) === "image") return;
955
+ clip.in = Math.max(0, (_nullishCoalesce(clip.in, () => ( 0))) + delta * _chunkXNZFVYC2cjs.videoClipSpeed.call(void 0, clip));
955
956
  if (clip.in < 1e-9) delete clip.in;
956
957
  }
957
958
  /** Moves a clip's head `delta` later in time (start, in point and keys); the caller sets start and duration. */
958
959
  trimHead(clip, delta) {
959
960
  if (!isRamped(clip)) this.moveIn(clip, delta);
960
- retimeClipKeys(clip, (v) => _chunkZQIWBJGHcjs.retimeVideoAnimatable.call(void 0, v, -delta));
961
+ retimeClipKeys(clip, (v) => _chunkXNZFVYC2cjs.retimeVideoAnimatable.call(void 0, v, -delta));
961
962
  }
962
963
  /** Cuts `clip` at `at` (inside it): the left part keeps the id, the right part is returned. */
963
964
  cut(track, clip, at, id) {
964
- const end = _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip);
965
+ const end = _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip);
965
966
  const right = { ...structuredClone(clip), id: _nullishCoalesce(id, () => ( freshId(`${clip.id}-`, this.ids()))), start: at, duration: end - at };
966
967
  delete right.transition;
967
968
  delete right.fadeIn;
@@ -969,9 +970,9 @@ var Editor = (_class = class {
969
970
  delete right.animateIn;
970
971
  const leftValues = clipAnimatables(clip);
971
972
  clipAnimatables(right).forEach((r, i) => {
972
- const [l, rr] = _chunkZQIWBJGHcjs.splitVideoAnimatable.call(void 0, leftValues[i].get(), at - clip.start);
973
- if (_chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, l)) leftValues[i].set(l);
974
- if (_chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, rr)) r.set(rr);
973
+ const [l, rr] = _chunkXNZFVYC2cjs.splitVideoAnimatable.call(void 0, leftValues[i].get(), at - clip.start);
974
+ if (_chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, l)) leftValues[i].set(l);
975
+ if (_chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, rr)) r.set(rr);
975
976
  });
976
977
  if (!isRamped(right)) this.moveIn(right, at - clip.start);
977
978
  clip.duration = at - clip.start;
@@ -985,7 +986,7 @@ var Editor = (_class = class {
985
986
  /** Cuts every clip on `tracks` that runs across `at`; returns the new right-hand parts. */
986
987
  cutAcross(tracks, at) {
987
988
  const made = [];
988
- for (const t of tracks) for (const c of [...t.clips]) if (c.start < at - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON && _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c) > at + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) made.push(this.cut(t, c, at));
989
+ for (const t of tracks) for (const c of [...t.clips]) if (c.start < at - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON && _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c) > at + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) made.push(this.cut(t, c, at));
989
990
  return made;
990
991
  }
991
992
  /**
@@ -1003,10 +1004,10 @@ var Editor = (_class = class {
1003
1004
  */
1004
1005
  close(tracks, from, to) {
1005
1006
  for (const t of tracks) {
1006
- const hit = _chunkZQIWBJGHcjs.videoOverlap.call(void 0, t, from, to);
1007
+ const hit = _chunkXNZFVYC2cjs.videoOverlap.call(void 0, t, from, to);
1007
1008
  if (hit)
1008
1009
  refuse(
1009
- `Rippling out ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, from)}\u2013${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, to)} would pull track "${t.id}" out of sync: clip "${hit.id}" (${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, hit.start)}\u2013${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, hit))}) is in that stretch. Extract the range across "${t.id}" too (extract_range with its id in "tracks"), turn its sync lock off (update_track with syncLocked false) or lock it, or lift instead of rippling.`
1010
+ `Rippling out ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, from)}\u2013${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, to)} would pull track "${t.id}" out of sync: clip "${hit.id}" (${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, hit.start)}\u2013${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, hit))}) is in that stretch. Extract the range across "${t.id}" too (extract_range with its id in "tracks"), turn its sync lock off (update_track with syncLocked false) or lock it, or lift instead of rippling.`
1010
1011
  );
1011
1012
  }
1012
1013
  for (const t of tracks) this.shift(t, to, from - to);
@@ -1018,10 +1019,10 @@ var Editor = (_class = class {
1018
1019
  clear(track, from, to, report) {
1019
1020
  for (const c of [...track.clips]) {
1020
1021
  const start = c.start;
1021
- const end = _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c);
1022
- if (end <= from + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON || start >= to - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) continue;
1023
- const coversHead = start >= from - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON;
1024
- const coversTail = end <= to + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON;
1022
+ const end = _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c);
1023
+ if (end <= from + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON || start >= to - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) continue;
1024
+ const coversHead = start >= from - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON;
1025
+ const coversTail = end <= to + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON;
1025
1026
  if (coversHead && coversTail) {
1026
1027
  track.clips = track.clips.filter((x) => x !== c);
1027
1028
  report.removed.push(c.id);
@@ -1044,8 +1045,8 @@ var Editor = (_class = class {
1044
1045
  /** Clamps a slip, roll or slide to `[lo, hi]`, refusing when it cannot move that way at all. */
1045
1046
  clamp(delta, lo, hi, why) {
1046
1047
  const applied = Math.min(Math.max(delta, Math.min(0, lo)), Math.max(0, hi));
1047
- if (Math.abs(delta) > _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON && Math.abs(applied) <= _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) refuse(why());
1048
- return Math.abs(applied) <= _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON ? 0 : applied;
1048
+ if (Math.abs(delta) > _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON && Math.abs(applied) <= _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) refuse(why());
1049
+ return Math.abs(applied) <= _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON ? 0 : applied;
1049
1050
  }
1050
1051
  /** Places a clip on a track by `mode`, returning what it cut, trimmed, removed and rippled. */
1051
1052
  place(track, clip, mode, outcome) {
@@ -1055,14 +1056,14 @@ var Editor = (_class = class {
1055
1056
  outcome.rippled = tracks.map((t) => t.id);
1056
1057
  } else if (mode === "overwrite") {
1057
1058
  const report = { removed: [], trimmed: [], created: [] };
1058
- this.clear(track, clip.start, _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip), report);
1059
+ this.clear(track, clip.start, _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip), report);
1059
1060
  Object.assign(outcome, report);
1060
1061
  } else this.fits(track, clip.start, clip.duration, /* @__PURE__ */ new Set([clip.id]), `Clip "${clip.id}"`);
1061
1062
  track.clips.push(clip);
1062
1063
  track.clips.sort((a, b) => a.start - b.start);
1063
1064
  }
1064
1065
  placement(mode, ripple) {
1065
- if (mode !== void 0 && !_chunkZQIWBJGHcjs.VIDEO_PLACEMENT_MODES.includes(mode)) refuse(`"mode" must be ${_chunkZQIWBJGHcjs.VIDEO_PLACEMENT_MODES.map((m) => `"${m}"`).join(", ")}.`);
1066
+ if (mode !== void 0 && !_chunkXNZFVYC2cjs.VIDEO_PLACEMENT_MODES.includes(mode)) refuse(`"mode" must be ${_chunkXNZFVYC2cjs.VIDEO_PLACEMENT_MODES.map((m) => `"${m}"`).join(", ")}.`);
1066
1067
  if (ripple && mode !== void 0 && mode !== "insert") refuse(`"ripple" means mode "insert", so it cannot go with mode "${mode}"; pass one or the other.`);
1067
1068
  return _nullishCoalesce(mode, () => ( (ripple ? "insert" : "refuse")));
1068
1069
  }
@@ -1099,7 +1100,7 @@ var Editor = (_class = class {
1099
1100
  }
1100
1101
  case "remove_asset": {
1101
1102
  const asset = this.asset(e.asset);
1102
- const users = _chunkZQIWBJGHcjs.allVideoTracks.call(void 0, this.p).flatMap(({ track: t }) => t.clips.filter((c) => c.type === "media" && c.asset === asset.id).map((c) => c.id));
1103
+ const users = _chunkXNZFVYC2cjs.allVideoTracks.call(void 0, this.p).flatMap(({ track: t }) => t.clips.filter((c) => c.type === "media" && c.asset === asset.id).map((c) => c.id));
1103
1104
  if (users.length) refuse(`Asset "${asset.id}" is used by clip${users.length > 1 ? "s" : ""} ${users.map((u) => `"${u}"`).join(", ")}; delete ${users.length > 1 ? "them" : "it"} first.`);
1104
1105
  this.p.assets = this.p.assets.filter((a) => a !== asset);
1105
1106
  return this.outcomes.push({ op: e.op, asset: asset.id });
@@ -1152,12 +1153,12 @@ var Editor = (_class = class {
1152
1153
  else draft.duration = (asset.duration - (_nullishCoalesce(draft.in, () => ( 0)))) / (_nullishCoalesce(draft.speed, () => ( 1)));
1153
1154
  if (!(draft.duration > 0)) refuse(`"in" (${draft.in} ms) is at or past the end of "${asset.id}" (${asset.duration} ms).`);
1154
1155
  } else if (draft.type === "sequence") {
1155
- const length = _chunkZQIWBJGHcjs.videoSequenceDuration.call(void 0, _chunkZQIWBJGHcjs.videoSequenceMap.call(void 0, this.p).get(draft.sequence)) - (_nullishCoalesce(draft.in, () => ( 0)));
1156
+ const length = _chunkXNZFVYC2cjs.videoSequenceDuration.call(void 0, _chunkXNZFVYC2cjs.videoSequenceMap.call(void 0, this.p).get(draft.sequence)) - (_nullishCoalesce(draft.in, () => ( 0)));
1156
1157
  if (!(length > 0)) refuse(`"in" (${_nullishCoalesce(draft.in, () => ( 0))} ms) is at or past the end of sequence "${draft.sequence}".`);
1157
1158
  draft.duration = length;
1158
1159
  } else draft.duration = VIDEO_DEFAULT_TITLE_DURATION;
1159
1160
  }
1160
- const end = _chunkZQIWBJGHcjs.sortedVideoClips.call(void 0, track).reduce((m, c) => Math.max(m, _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c)), 0);
1161
+ const end = _chunkXNZFVYC2cjs.sortedVideoClips.call(void 0, track).reduce((m, c) => Math.max(m, _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c)), 0);
1161
1162
  draft.start ??= end;
1162
1163
  const clip = parseVideoClip(draft, "clip");
1163
1164
  this.adjustmentTarget(clip);
@@ -1183,20 +1184,20 @@ var Editor = (_class = class {
1183
1184
  case "trim_clip": {
1184
1185
  const { track, clip } = this.clip(e.clip);
1185
1186
  this.unlocked(track);
1186
- const speed = _chunkZQIWBJGHcjs.videoClipSpeed.call(void 0, clip);
1187
- const end = _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip);
1187
+ const speed = _chunkXNZFVYC2cjs.videoClipSpeed.call(void 0, clip);
1188
+ const end = _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip);
1188
1189
  const minimum = 1e3 / this.p.fps;
1189
- const assets = _chunkZQIWBJGHcjs.videoAssetMap.call(void 0, this.p);
1190
+ const assets = _chunkXNZFVYC2cjs.videoAssetMap.call(void 0, this.p);
1190
1191
  if (e.edge === "start") {
1191
1192
  const delta = e.to - clip.start;
1192
- if (clip.duration - delta < minimum - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) refuse(`Trimming the start to ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, e.to)} would leave "${clip.id}" shorter than a frame; it ends at ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, end)}.`);
1193
+ if (clip.duration - delta < minimum - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) refuse(`Trimming the start to ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, e.to)} would leave "${clip.id}" shorter than a frame; it ends at ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, end)}.`);
1193
1194
  if (clip.type === "media" && !isRamped(clip) || clip.type === "sequence") {
1194
1195
  const sourceIn = (_nullishCoalesce(clip.in, () => ( 0))) + delta * speed;
1195
- if (sourceIn < -_chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) refuse(`"${clip.id}" starts ${Math.round((_nullishCoalesce(clip.in, () => ( 0))) / speed)} ms into its source, so its start can move at most that far earlier (to ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, clip.start - (_nullishCoalesce(clip.in, () => ( 0))) / speed)}).`);
1196
+ if (sourceIn < -_chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) refuse(`"${clip.id}" starts ${Math.round((_nullishCoalesce(clip.in, () => ( 0))) / speed)} ms into its source, so its start can move at most that far earlier (to ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, clip.start - (_nullishCoalesce(clip.in, () => ( 0))) / speed)}).`);
1196
1197
  clip.in = Math.max(0, sourceIn);
1197
1198
  if (clip.in === 0) delete clip.in;
1198
1199
  }
1199
- retimeClipKeys(clip, (v) => _chunkZQIWBJGHcjs.retimeVideoAnimatable.call(void 0, v, -delta));
1200
+ retimeClipKeys(clip, (v) => _chunkXNZFVYC2cjs.retimeVideoAnimatable.call(void 0, v, -delta));
1200
1201
  if (e.ripple) {
1201
1202
  const tracks = this.rippleTracks([track]);
1202
1203
  if (delta > 0) {
@@ -1217,17 +1218,17 @@ var Editor = (_class = class {
1217
1218
  }
1218
1219
  } else {
1219
1220
  const duration = e.to - clip.start;
1220
- if (duration < minimum - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) refuse(`Trimming the end to ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, e.to)} would leave "${clip.id}" shorter than a frame; it starts at ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, clip.start)}.`);
1221
+ if (duration < minimum - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) refuse(`Trimming the end to ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, e.to)} would leave "${clip.id}" shorter than a frame; it starts at ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, clip.start)}.`);
1221
1222
  if (clip.type === "media" && !isRamped(clip)) {
1222
1223
  const asset = assets.get(clip.asset);
1223
1224
  const out = (_nullishCoalesce(clip.in, () => ( 0))) + duration * speed;
1224
- if (_optionalChain([asset, 'optionalAccess', _17 => _17.duration]) !== void 0 && out > asset.duration + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON)
1225
- refuse(`"${clip.id}" can end at most at ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, clip.start + (asset.duration - (_nullishCoalesce(clip.in, () => ( 0)))) / speed)}, where "${asset.id}" runs out.`);
1225
+ if (_optionalChain([asset, 'optionalAccess', _17 => _17.duration]) !== void 0 && out > asset.duration + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON)
1226
+ refuse(`"${clip.id}" can end at most at ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, clip.start + (asset.duration - (_nullishCoalesce(clip.in, () => ( 0)))) / speed)}, where "${asset.id}" runs out.`);
1226
1227
  }
1227
1228
  if (clip.type === "sequence") {
1228
- const seq = _chunkZQIWBJGHcjs.videoSequenceMap.call(void 0, this.p).get(clip.sequence);
1229
- const length = seq ? _chunkZQIWBJGHcjs.videoSequenceDuration.call(void 0, seq) : Infinity;
1230
- if ((_nullishCoalesce(clip.in, () => ( 0))) + duration > length + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) refuse(`"${clip.id}" can end at most at ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, clip.start + length - (_nullishCoalesce(clip.in, () => ( 0))))}, where sequence "${clip.sequence}" ends.`);
1229
+ const seq = _chunkXNZFVYC2cjs.videoSequenceMap.call(void 0, this.p).get(clip.sequence);
1230
+ const length = seq ? _chunkXNZFVYC2cjs.videoSequenceDuration.call(void 0, seq) : Infinity;
1231
+ if ((_nullishCoalesce(clip.in, () => ( 0))) + duration > length + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) refuse(`"${clip.id}" can end at most at ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, clip.start + length - (_nullishCoalesce(clip.in, () => ( 0))))}, where sequence "${clip.sequence}" ends.`);
1231
1232
  }
1232
1233
  if (e.ripple) {
1233
1234
  const tracks = this.rippleTracks([track]);
@@ -1249,9 +1250,9 @@ var Editor = (_class = class {
1249
1250
  case "split_clip": {
1250
1251
  const { track, clip } = this.clip(e.clip);
1251
1252
  this.unlocked(track);
1252
- const end = _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip);
1253
+ const end = _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip);
1253
1254
  const minimum = 1e3 / this.p.fps;
1254
- if (e.at < clip.start + minimum - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON || e.at > end - minimum + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) refuse(`${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, e.at)} is not inside "${clip.id}" (${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, clip.start)}\u2013${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, end)}), at least a frame from either end.`);
1255
+ if (e.at < clip.start + minimum - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON || e.at > end - minimum + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) refuse(`${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, e.at)} is not inside "${clip.id}" (${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, clip.start)}\u2013${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, end)}), at least a frame from either end.`);
1255
1256
  if (e.id !== void 0 && this.ids().includes(e.id)) refuse(`There is already a clip "${e.id}".`);
1256
1257
  const right = this.cut(track, clip, e.at, e.id);
1257
1258
  return this.outcomes.push({ op: e.op, clips: [clip.id, right.id], clip: right.id, track: track.id });
@@ -1262,12 +1263,12 @@ var Editor = (_class = class {
1262
1263
  for (const track of new Set(found.map((f) => f.track))) track.clips = track.clips.filter((c) => !found.some((f) => f.clip === c));
1263
1264
  if (!e.ripple) return this.outcomes.push({ op: e.op, clips: found.map((f) => f.clip.id) });
1264
1265
  const rippled = /* @__PURE__ */ new Set();
1265
- const groups = [...new Set(found.map((f) => f.track))].filter((t) => !_chunkZQIWBJGHcjs.videoTrackSyncLocked.call(void 0, t)).map((t) => [t]);
1266
- if (found.some((f) => _chunkZQIWBJGHcjs.videoTrackSyncLocked.call(void 0, f.track))) groups.push(found.filter((f) => _chunkZQIWBJGHcjs.videoTrackSyncLocked.call(void 0, f.track)).map((f) => f.track));
1266
+ const groups = [...new Set(found.map((f) => f.track))].filter((t) => !_chunkXNZFVYC2cjs.videoTrackSyncLocked.call(void 0, t)).map((t) => [t]);
1267
+ if (found.some((f) => _chunkXNZFVYC2cjs.videoTrackSyncLocked.call(void 0, f.track))) groups.push(found.filter((f) => _chunkXNZFVYC2cjs.videoTrackSyncLocked.call(void 0, f.track)).map((f) => f.track));
1267
1268
  for (const sources of groups) {
1268
1269
  const tracks = this.rippleTracks(sources);
1269
1270
  tracks.forEach((t) => rippled.add(t));
1270
- const spans = mergeSpans(found.filter((f) => sources.includes(f.track)).map((f) => [f.clip.start, _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, f.clip)]));
1271
+ const spans = mergeSpans(found.filter((f) => sources.includes(f.track)).map((f) => [f.clip.start, _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, f.clip)]));
1271
1272
  for (const [from, to] of spans.reverse()) this.close(tracks, from, to);
1272
1273
  }
1273
1274
  return this.outcomes.push({ op: e.op, clips: found.map((f) => f.clip.id), rippled: this.p.tracks.filter((t) => rippled.has(t)).map((t) => t.id) });
@@ -1283,7 +1284,7 @@ var Editor = (_class = class {
1283
1284
  if ("timeRemap" in set) refuse("Set a speed ramp with set_time_remap, which checks it against the media and moves later clips if asked.");
1284
1285
  let stretch = 1;
1285
1286
  if (at.clip.type === "media" && !("duration" in set)) {
1286
- const was = _chunkZQIWBJGHcjs.videoClipSpeed.call(void 0, at.clip);
1287
+ const was = _chunkXNZFVYC2cjs.videoClipSpeed.call(void 0, at.clip);
1287
1288
  const now = "speed" in set ? set.speed : _optionalChain([e, 'access', _18 => _18.remove, 'optionalAccess', _19 => _19.includes, 'call', _20 => _20("speed")]) ? 1 : was;
1288
1289
  if (now !== was) {
1289
1290
  set.duration = at.clip.duration * was / now;
@@ -1291,7 +1292,7 @@ var Editor = (_class = class {
1291
1292
  }
1292
1293
  }
1293
1294
  const next = { ...structuredClone(at.clip), ...set };
1294
- if (stretch !== 1) retimeClipKeys(next, (v) => _chunkZQIWBJGHcjs.retimeVideoAnimatable.call(void 0, v, 0, stretch));
1295
+ if (stretch !== 1) retimeClipKeys(next, (v) => _chunkXNZFVYC2cjs.retimeVideoAnimatable.call(void 0, v, 0, stretch));
1295
1296
  for (const k of _nullishCoalesce(e.remove, () => ( []))) delete next[k];
1296
1297
  const clip = parseVideoClip(next, "set");
1297
1298
  this.adjustmentTarget(clip);
@@ -1305,17 +1306,17 @@ var Editor = (_class = class {
1305
1306
  const { track, clip } = this.clip(e.clip);
1306
1307
  this.unlocked(track);
1307
1308
  if (clip.type === "sequence") refuse(`Clip "${clip.id}" is a compound clip, which plays its sequence at normal speed; ramp the clips inside the sequence instead.`);
1308
- if (clip.type !== "media") refuse(`Clip "${clip.id}" is a ${_chunkZQIWBJGHcjs.videoClipTypeLabel.call(void 0, clip)}, so it has no source to ramp; only video and audio clips change speed.`);
1309
+ if (clip.type !== "media") refuse(`Clip "${clip.id}" is a ${_chunkXNZFVYC2cjs.videoClipTypeLabel.call(void 0, clip)}, so it has no source to ramp; only video and audio clips change speed.`);
1309
1310
  const asset = this.asset(clip.asset);
1310
1311
  if (asset.kind === "image") refuse(`Clip "${clip.id}" is a still ("${asset.id}"), so it has no motion to ramp.`);
1311
1312
  const media = clip;
1312
- const end = _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, media);
1313
+ const end = _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, media);
1313
1314
  const duration = _nullishCoalesce(e.duration, () => ( media.duration));
1314
- if (!(duration >= 1e3 / this.p.fps - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON)) refuse(`"duration" must be at least a frame (${Math.ceil(1e3 / this.p.fps)} ms).`);
1315
+ if (!(duration >= 1e3 / this.p.fps - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON)) refuse(`"duration" must be at least a frame (${Math.ceil(1e3 / this.p.fps)} ms).`);
1315
1316
  if (e.keys === null) {
1316
1317
  if (!media.timeRemap) refuse(`Clip "${clip.id}" has no speed ramp to remove.`);
1317
1318
  const from = (_nullishCoalesce(media.in, () => ( 0))) + media.timeRemap.keys[0].v;
1318
- if (asset.duration !== void 0 && from + duration > asset.duration + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON)
1319
+ if (asset.duration !== void 0 && from + duration > asset.duration + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON)
1319
1320
  refuse(`At normal speed from ${Math.round(from)} ms, "${clip.id}" would run past the end of "${asset.id}" (${asset.duration} ms); give a duration of at most ${Math.floor(asset.duration - from)} ms.`);
1320
1321
  delete media.timeRemap;
1321
1322
  media.in = from;
@@ -1323,17 +1324,17 @@ var Editor = (_class = class {
1323
1324
  } else {
1324
1325
  if (!Array.isArray(e.keys) || !e.keys.length) refuse('"keys" must be a list of at least one { t, v, ease } (or null to remove the ramp).');
1325
1326
  const remap = parseVideoTimeRemap({ keys: e.keys }, void 0, "keys");
1326
- remap.keys = _chunkZQIWBJGHcjs.sortVideoKeys.call(void 0, remap.keys, { jumps: false });
1327
- _chunkZQIWBJGHcjs.checkVideoTimeRemap.call(void 0, remap, "keys");
1328
- const span = _chunkZQIWBJGHcjs.videoTimeRemapSpan.call(void 0, remap);
1329
- if (asset.duration !== void 0 && (_nullishCoalesce(media.in, () => ( 0))) + span.to > asset.duration + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON)
1327
+ remap.keys = _chunkXNZFVYC2cjs.sortVideoKeys.call(void 0, remap.keys, { jumps: false });
1328
+ _chunkXNZFVYC2cjs.checkVideoTimeRemap.call(void 0, remap, "keys");
1329
+ const span = _chunkXNZFVYC2cjs.videoTimeRemapSpan.call(void 0, remap);
1330
+ if (asset.duration !== void 0 && (_nullishCoalesce(media.in, () => ( 0))) + span.to > asset.duration + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON)
1330
1331
  refuse(`The ramp plays ${Math.round(span.to)} ms of source from the in point (${_nullishCoalesce(media.in, () => ( 0))} ms), past the end of "${asset.id}" (${asset.duration} ms); it can use at most ${Math.floor(asset.duration - (_nullishCoalesce(media.in, () => ( 0))))} ms.`);
1331
1332
  media.timeRemap = remap;
1332
1333
  delete media.speed;
1333
1334
  }
1334
1335
  const newEnd = media.start + duration;
1335
1336
  const outcome = { op: e.op, clip: clip.id, track: track.id };
1336
- if (Math.abs(newEnd - end) > _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) {
1337
+ if (Math.abs(newEnd - end) > _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) {
1337
1338
  if (e.ripple) {
1338
1339
  const tracks = this.rippleTracks([track]);
1339
1340
  if (newEnd < end) {
@@ -1362,11 +1363,11 @@ var Editor = (_class = class {
1362
1363
  case "slip_clip": {
1363
1364
  const { track, clip } = this.clip(e.clip);
1364
1365
  this.unlocked(track);
1365
- if (clip.type !== "media" && clip.type !== "sequence") refuse(`Clip "${clip.id}" is a ${_chunkZQIWBJGHcjs.videoClipTypeLabel.call(void 0, clip)}, so it has no source to slip; only video, audio and compound clips slip.`);
1366
+ if (clip.type !== "media" && clip.type !== "sequence") refuse(`Clip "${clip.id}" is a ${_chunkXNZFVYC2cjs.videoClipTypeLabel.call(void 0, clip)}, so it has no source to slip; only video, audio and compound clips slip.`);
1366
1367
  const source = clip.type === "sequence" ? `sequence "${clip.sequence}"` : `"${this.asset(clip.asset).id}"`;
1367
1368
  if (clip.type === "media" && this.asset(clip.asset).kind === "image") refuse(`Clip "${clip.id}" is a still ("${clip.asset}"), so it has no source to slip; only video and audio clips slip.`);
1368
- const handles = _chunkZQIWBJGHcjs.videoClipHandles.call(void 0, clip, _chunkZQIWBJGHcjs.videoAssetMap.call(void 0, this.p), _chunkZQIWBJGHcjs.videoSequenceMap.call(void 0, this.p));
1369
- const { lead, tail } = _chunkZQIWBJGHcjs.videoClipOverhang.call(void 0, track, clip);
1369
+ const handles = _chunkXNZFVYC2cjs.videoClipHandles.call(void 0, clip, _chunkXNZFVYC2cjs.videoAssetMap.call(void 0, this.p), _chunkXNZFVYC2cjs.videoSequenceMap.call(void 0, this.p));
1370
+ const { lead, tail } = _chunkXNZFVYC2cjs.videoClipOverhang.call(void 0, track, clip);
1370
1371
  const delta = this.clamp(
1371
1372
  e.delta,
1372
1373
  lead - handles.before,
@@ -1384,13 +1385,13 @@ var Editor = (_class = class {
1384
1385
  this.unlocked(track);
1385
1386
  const L = left.clip;
1386
1387
  const R = right.clip;
1387
- if (Math.abs(_chunkZQIWBJGHcjs.videoClipEnd.call(void 0, L) - R.start) > _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) {
1388
- if (Math.abs(_chunkZQIWBJGHcjs.videoClipEnd.call(void 0, R) - L.start) <= _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) refuse(`"${R.id}" comes before "${L.id}"; pass left "${R.id}" and right "${L.id}".`);
1389
- refuse(`"${L.id}" ends at ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, L))} but "${R.id}" starts at ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, R.start)}; a roll needs two clips that meet at a cut (use trim_clip to move one edge).`);
1388
+ if (Math.abs(_chunkXNZFVYC2cjs.videoClipEnd.call(void 0, L) - R.start) > _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) {
1389
+ if (Math.abs(_chunkXNZFVYC2cjs.videoClipEnd.call(void 0, R) - L.start) <= _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) refuse(`"${R.id}" comes before "${L.id}"; pass left "${R.id}" and right "${L.id}".`);
1390
+ refuse(`"${L.id}" ends at ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, L))} but "${R.id}" starts at ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, R.start)}; a roll needs two clips that meet at a cut (use trim_clip to move one edge).`);
1390
1391
  }
1391
- const assets = _chunkZQIWBJGHcjs.videoAssetMap.call(void 0, this.p);
1392
- const lo = Math.max(-(L.duration - this.frame), -(_chunkZQIWBJGHcjs.videoClipHandles.call(void 0, R, assets, _chunkZQIWBJGHcjs.videoSequenceMap.call(void 0, this.p)).before - _chunkZQIWBJGHcjs.videoClipOverhang.call(void 0, track, R).lead));
1393
- const hi = Math.min(R.duration - this.frame, _chunkZQIWBJGHcjs.videoClipHandles.call(void 0, L, assets, _chunkZQIWBJGHcjs.videoSequenceMap.call(void 0, this.p)).after - _chunkZQIWBJGHcjs.videoClipOverhang.call(void 0, track, L).tail);
1392
+ const assets = _chunkXNZFVYC2cjs.videoAssetMap.call(void 0, this.p);
1393
+ const lo = Math.max(-(L.duration - this.frame), -(_chunkXNZFVYC2cjs.videoClipHandles.call(void 0, R, assets, _chunkXNZFVYC2cjs.videoSequenceMap.call(void 0, this.p)).before - _chunkXNZFVYC2cjs.videoClipOverhang.call(void 0, track, R).lead));
1394
+ const hi = Math.min(R.duration - this.frame, _chunkXNZFVYC2cjs.videoClipHandles.call(void 0, L, assets, _chunkXNZFVYC2cjs.videoSequenceMap.call(void 0, this.p)).after - _chunkXNZFVYC2cjs.videoClipOverhang.call(void 0, track, L).tail);
1394
1395
  const delta = this.clamp(
1395
1396
  e.delta,
1396
1397
  lo,
@@ -1406,18 +1407,18 @@ var Editor = (_class = class {
1406
1407
  case "slide_clip": {
1407
1408
  const { track, clip } = this.clip(e.clip);
1408
1409
  this.unlocked(track);
1409
- const before = _chunkZQIWBJGHcjs.videoClipBefore.call(void 0, track, clip);
1410
- const after = _chunkZQIWBJGHcjs.videoClipAfter.call(void 0, track, clip);
1410
+ const before = _chunkXNZFVYC2cjs.videoClipBefore.call(void 0, track, clip);
1411
+ const after = _chunkXNZFVYC2cjs.videoClipAfter.call(void 0, track, clip);
1411
1412
  if (!before && !after) refuse(`"${clip.id}" has no clip right before or after it on track "${track.id}", so there is nothing to slide against; use move_clip.`);
1412
- const assets = _chunkZQIWBJGHcjs.videoAssetMap.call(void 0, this.p);
1413
- const end = _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip);
1413
+ const assets = _chunkXNZFVYC2cjs.videoAssetMap.call(void 0, this.p);
1414
+ const end = _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip);
1414
1415
  const others = track.clips.filter((c) => c !== clip);
1415
1416
  const room = {
1416
- earlier: before ? before.duration - this.frame : clip.start - others.filter((c) => _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c) <= clip.start + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON).reduce((m, c) => Math.max(m, _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c)), 0),
1417
- later: after ? after.duration - this.frame : others.filter((c) => c.start >= end - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON).reduce((m, c) => Math.min(m, c.start - end), Infinity)
1417
+ earlier: before ? before.duration - this.frame : clip.start - others.filter((c) => _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c) <= clip.start + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON).reduce((m, c) => Math.max(m, _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c)), 0),
1418
+ later: after ? after.duration - this.frame : others.filter((c) => c.start >= end - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON).reduce((m, c) => Math.min(m, c.start - end), Infinity)
1418
1419
  };
1419
- const lo = -Math.min(room.earlier, after ? _chunkZQIWBJGHcjs.videoClipHandles.call(void 0, after, assets, _chunkZQIWBJGHcjs.videoSequenceMap.call(void 0, this.p)).before - _chunkZQIWBJGHcjs.videoClipOverhang.call(void 0, track, after).lead : Infinity);
1420
- const hi = Math.min(room.later, before ? _chunkZQIWBJGHcjs.videoClipHandles.call(void 0, before, assets, _chunkZQIWBJGHcjs.videoSequenceMap.call(void 0, this.p)).after - _chunkZQIWBJGHcjs.videoClipOverhang.call(void 0, track, before).tail : Infinity);
1420
+ const lo = -Math.min(room.earlier, after ? _chunkXNZFVYC2cjs.videoClipHandles.call(void 0, after, assets, _chunkXNZFVYC2cjs.videoSequenceMap.call(void 0, this.p)).before - _chunkXNZFVYC2cjs.videoClipOverhang.call(void 0, track, after).lead : Infinity);
1421
+ const hi = Math.min(room.later, before ? _chunkXNZFVYC2cjs.videoClipHandles.call(void 0, before, assets, _chunkXNZFVYC2cjs.videoSequenceMap.call(void 0, this.p)).after - _chunkXNZFVYC2cjs.videoClipOverhang.call(void 0, track, before).tail : Infinity);
1421
1422
  const delta = this.clamp(
1422
1423
  e.delta,
1423
1424
  lo,
@@ -1450,29 +1451,29 @@ var Editor = (_class = class {
1450
1451
  }
1451
1452
  case "split_at": {
1452
1453
  const tracks = this.rangeTracks(e.tracks);
1453
- const lefts = tracks.flatMap((t) => t.clips.filter((c) => c.start < e.at - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON && _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c) > e.at + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON).map((c) => c.id));
1454
- if (!lefts.length) refuse(`No clip runs across ${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, e.at)} on ${e.tracks ? `track${tracks.length > 1 ? "s" : ""} ${tracks.map((t) => `"${t.id}"`).join(", ")}` : "the unlocked tracks"}, so there is nothing to split there.`);
1454
+ const lefts = tracks.flatMap((t) => t.clips.filter((c) => c.start < e.at - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON && _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c) > e.at + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON).map((c) => c.id));
1455
+ if (!lefts.length) refuse(`No clip runs across ${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, e.at)} on ${e.tracks ? `track${tracks.length > 1 ? "s" : ""} ${tracks.map((t) => `"${t.id}"`).join(", ")}` : "the unlocked tracks"}, so there is nothing to split there.`);
1455
1456
  const created = this.cutAcross(tracks, e.at).map((c) => c.id);
1456
1457
  return this.outcomes.push({ op: e.op, clips: lefts, created });
1457
1458
  }
1458
1459
  case "set_keyframes": {
1459
1460
  const { track, clip } = this.clip(e.clip);
1460
1461
  this.unlocked(track);
1461
- if (!_chunkZQIWBJGHcjs.VIDEO_KEYFRAME_PROPERTIES.includes(e.property)) refuse(`"${e.property}" cannot be keyframed; use one of ${_chunkZQIWBJGHcjs.VIDEO_KEYFRAME_PROPERTIES.join(", ")}.`);
1462
+ if (!_chunkXNZFVYC2cjs.VIDEO_KEYFRAME_PROPERTIES.includes(e.property)) refuse(`"${e.property}" cannot be keyframed; use one of ${_chunkXNZFVYC2cjs.VIDEO_KEYFRAME_PROPERTIES.join(", ")}.`);
1462
1463
  if (e.property === "volume" && clip.type !== "media" && clip.type !== "sequence") refuse(`Clip "${clip.id}" is a ${clip.type} clip and has no volume; volume keys go on media and compound clips.`);
1463
- const limits = _chunkZQIWBJGHcjs.VIDEO_KEYFRAME_LIMITS[e.property];
1464
- const transform = _chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES.includes(e.property);
1464
+ const limits = _chunkXNZFVYC2cjs.VIDEO_KEYFRAME_LIMITS[e.property];
1465
+ const transform = _chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES.includes(e.property);
1465
1466
  const c = clip;
1466
1467
  const current = transform ? _optionalChain([c, 'access', _23 => _23.transform, 'optionalAccess', _24 => _24[e.property]]) : c[e.property];
1467
1468
  let value;
1468
1469
  if (e.keys === null) {
1469
- const v = _chunkZQIWBJGHcjs.videoValueAt.call(void 0, current, 0, limits.default);
1470
- value = _chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, current) ? v === limits.default ? void 0 : v : current;
1470
+ const v = _chunkXNZFVYC2cjs.videoValueAt.call(void 0, current, 0, limits.default);
1471
+ value = _chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, current) ? v === limits.default ? void 0 : v : current;
1471
1472
  } else {
1472
1473
  if (!Array.isArray(e.keys) || !e.keys.length) refuse('"keys" must list at least one key { t, v }; pass null to remove the keyframes.');
1473
1474
  let sorted = [];
1474
1475
  try {
1475
- sorted = _chunkZQIWBJGHcjs.sortVideoKeys.call(void 0, e.keys);
1476
+ sorted = _chunkXNZFVYC2cjs.sortVideoKeys.call(void 0, e.keys);
1476
1477
  } catch (error) {
1477
1478
  refuse(error.message);
1478
1479
  }
@@ -1491,12 +1492,12 @@ var Editor = (_class = class {
1491
1492
  this.unlocked(track);
1492
1493
  let at = 0;
1493
1494
  const moved = [];
1494
- for (const clip of _chunkZQIWBJGHcjs.sortedVideoClips.call(void 0, track)) {
1495
- if (clip.start >= (_nullishCoalesce(e.from, () => ( 0))) - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON && clip.start > at + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) {
1495
+ for (const clip of _chunkXNZFVYC2cjs.sortedVideoClips.call(void 0, track)) {
1496
+ if (clip.start >= (_nullishCoalesce(e.from, () => ( 0))) - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON && clip.start > at + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) {
1496
1497
  clip.start = Math.max(at, _nullishCoalesce(e.from, () => ( 0)));
1497
1498
  moved.push(clip.id);
1498
1499
  }
1499
- at = Math.max(at, _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip));
1500
+ at = Math.max(at, _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip));
1500
1501
  }
1501
1502
  return this.outcomes.push({ op: e.op, track: track.id, clips: moved });
1502
1503
  }
@@ -1626,7 +1627,7 @@ function videoTranscriptTrack(project, track) {
1626
1627
  if (!project.tracks.some((t) => t.id === track)) throw new Error(`There is no track "${track}"; the tracks are ${project.tracks.map((t) => `"${t.id}"`).join(", ")}.`);
1627
1628
  return track;
1628
1629
  }
1629
- const assets = _chunkZQIWBJGHcjs.videoAssetMap.call(void 0, project);
1630
+ const assets = _chunkXNZFVYC2cjs.videoAssetMap.call(void 0, project);
1630
1631
  const transcribed = (t) => t.clips.some((c) => c.type === "media" && _optionalChain([assets, 'access', _26 => _26.get, 'call', _27 => _27(c.asset), 'optionalAccess', _28 => _28.transcript, 'optionalAccess', _29 => _29.length]));
1631
1632
  return _nullishCoalesce(_optionalChain([(_nullishCoalesce(project.tracks.find((t) => t.kind === "audio" && transcribed(t)), () => ( project.tracks.find(transcribed)))), 'optionalAccess', _30 => _30.id]), () => ( null));
1632
1633
  }
@@ -1634,16 +1635,16 @@ function videoTimelineTranscript(project, options = {}) {
1634
1635
  const id = videoTranscriptTrack(project, options.track);
1635
1636
  if (!id) return [];
1636
1637
  const track = project.tracks.find((t) => t.id === id);
1637
- const assets = _chunkZQIWBJGHcjs.videoAssetMap.call(void 0, project);
1638
+ const assets = _chunkXNZFVYC2cjs.videoAssetMap.call(void 0, project);
1638
1639
  const out = [];
1639
- for (const clip of _chunkZQIWBJGHcjs.sortedVideoClips.call(void 0, track)) {
1640
+ for (const clip of _chunkXNZFVYC2cjs.sortedVideoClips.call(void 0, track)) {
1640
1641
  if (clip.type !== "media") continue;
1641
1642
  const words = _optionalChain([assets, 'access', _31 => _31.get, 'call', _32 => _32(clip.asset), 'optionalAccess', _33 => _33.transcript]);
1642
1643
  if (!_optionalChain([words, 'optionalAccess', _34 => _34.length])) continue;
1643
- const speed = _chunkZQIWBJGHcjs.videoClipSpeed.call(void 0, clip);
1644
+ const speed = _chunkXNZFVYC2cjs.videoClipSpeed.call(void 0, clip);
1644
1645
  const from = _nullishCoalesce(clip.in, () => ( 0));
1645
1646
  const to = from + clip.duration * speed;
1646
- const toTimeline = (s) => Math.min(_chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip), Math.max(clip.start, clip.start + (s - from) / speed));
1647
+ const toTimeline = (s) => Math.min(_chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip), Math.max(clip.start, clip.start + (s - from) / speed));
1647
1648
  words.forEach((w, index) => {
1648
1649
  const mid = (w.start + w.end) / 2;
1649
1650
  if (mid < from || mid >= to) return;
@@ -1688,19 +1689,19 @@ function findVideoTranscriptPauses(words, options = {}) {
1688
1689
  let to = b.start - keep;
1689
1690
  if (options.fps) {
1690
1691
  const f = 1e3 / options.fps;
1691
- from = _chunkZQIWBJGHcjs.snapToVideoFrame.call(void 0, Math.ceil(from / f - 1e-9) * f, options.fps);
1692
- to = _chunkZQIWBJGHcjs.snapToVideoFrame.call(void 0, Math.floor(to / f + 1e-9) * f, options.fps);
1692
+ from = _chunkXNZFVYC2cjs.snapToVideoFrame.call(void 0, Math.ceil(from / f - 1e-9) * f, options.fps);
1693
+ to = _chunkXNZFVYC2cjs.snapToVideoFrame.call(void 0, Math.floor(to / f + 1e-9) * f, options.fps);
1693
1694
  }
1694
- if (to - from > _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) out.push({ from, to, text: `(pause after "${a.word}")` });
1695
+ if (to - from > _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) out.push({ from, to, text: `(pause after "${a.word}")` });
1695
1696
  }
1696
1697
  return out;
1697
1698
  }
1698
1699
  function mergeVideoRanges(ranges) {
1699
- const sorted = ranges.filter((r) => r.to - r.from > _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON).map((r) => ({ from: r.from, to: r.to })).sort((a, b) => a.from - b.from);
1700
+ const sorted = ranges.filter((r) => r.to - r.from > _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON).map((r) => ({ from: r.from, to: r.to })).sort((a, b) => a.from - b.from);
1700
1701
  const out = [];
1701
1702
  for (const r of sorted) {
1702
1703
  const last = out[out.length - 1];
1703
- if (last && r.from <= last.to + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) last.to = Math.max(last.to, r.to);
1704
+ if (last && r.from <= last.to + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) last.to = Math.max(last.to, r.to);
1704
1705
  else out.push(r);
1705
1706
  }
1706
1707
  return out;
@@ -1746,7 +1747,7 @@ function findVideoRepetitions(words, options = {}) {
1746
1747
  var VIDEO_DISFLUENCY_KINDS = ["filler", "pause", "repetition"];
1747
1748
  function detectVideoDisfluencies(words, options = {}) {
1748
1749
  const kinds = new Set(_nullishCoalesce(options.kinds, () => ( VIDEO_DISFLUENCY_KINDS)));
1749
- const startIndex = (time) => Math.max(0, words.findIndex((w) => w.start >= time - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON));
1750
+ const startIndex = (time) => Math.max(0, words.findIndex((w) => w.start >= time - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON));
1750
1751
  const out = [];
1751
1752
  if (kinds.has("filler"))
1752
1753
  for (const r of findVideoFillers(words, options.fillers)) {
@@ -1760,13 +1761,13 @@ function detectVideoDisfluencies(words, options = {}) {
1760
1761
  }
1761
1762
  if (kinds.has("pause"))
1762
1763
  for (const r of findVideoTranscriptPauses(words, options.pauses)) {
1763
- const after = words.findIndex((w) => w.start >= r.to - _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON);
1764
+ const after = words.findIndex((w) => w.start >= r.to - _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON);
1764
1765
  out.push({ ...r, kind: "pause", words: [Math.max(0, after - 1), Math.max(0, after)] });
1765
1766
  }
1766
1767
  return out.sort((a, b) => a.from - b.from || a.to - b.to);
1767
1768
  }
1768
1769
  function videoCutsWithMargin(ranges, keep) {
1769
- return ranges.map((r) => ({ ...r, from: r.from + keep, to: r.to - keep })).filter((r) => r.to - r.from > _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON);
1770
+ return ranges.map((r) => ({ ...r, from: r.from + keep, to: r.to - keep })).filter((r) => r.to - r.from > _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON);
1770
1771
  }
1771
1772
 
1772
1773
  // src/video-editor/mix.ts
@@ -1872,7 +1873,7 @@ function videoDuckingKeys(clip, speech, options = {}) {
1872
1873
  const gap = Math.max(_nullishCoalesce(options.mergeGap, () => ( 600)), attack + release);
1873
1874
  const base = _nullishCoalesce(options.base, () => ( 1));
1874
1875
  const low = Math.round(base * 10 ** (duckDb / 20) * 1e4) / 1e4;
1875
- const end = _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip);
1876
+ const end = _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip);
1876
1877
  const ranges = [];
1877
1878
  for (const r of mergeVideoRanges(speech)) {
1878
1879
  if (r.to <= clip.start - release || r.from >= end + attack) continue;
@@ -2077,7 +2078,7 @@ function videoClipWaveform(clip, peaks, columns) {
2077
2078
  const step = clip.duration / Math.max(1, n);
2078
2079
  for (let c = 0; c < n; c++) {
2079
2080
  const { min, max } = videoAudioPeakRange(peaks, start + c * step * speed, start + (c + 1) * step * speed);
2080
- const gain = _chunkZQIWBJGHcjs.videoClipSoundGain.call(void 0, clip, (c + 0.5) * step);
2081
+ const gain = _chunkXNZFVYC2cjs.videoClipSoundGain.call(void 0, clip, (c + 0.5) * step);
2081
2082
  out[2 * c] = min * gain;
2082
2083
  out[2 * c + 1] = max * gain;
2083
2084
  }
@@ -2205,10 +2206,77 @@ var VideoAudioPeaksCache = (_class2 = class {
2205
2206
  }
2206
2207
  }, _class2);
2207
2208
 
2209
+ // src/video-editor/effect-path.ts
2210
+ function videoClipPicture(project, clip) {
2211
+ const asset = clip.type === "media" ? project.assets.find((a) => a.id === clip.asset) : void 0;
2212
+ const size = asset ? { width: _nullishCoalesce(asset.width, () => ( project.width)), height: _nullishCoalesce(asset.height, () => ( project.height)) } : { width: project.width, height: project.height };
2213
+ const fit = _nullishCoalesce(clip.fit, () => ( (clip.type === "media" || clip.type === "sequence" ? "contain" : "fill")));
2214
+ const rect = _chunkXNZFVYC2cjs.placeVideoRect.call(void 0, project, size, clip.type === "text" ? "fill" : fit, clip.transform, 0);
2215
+ return { size, rect, rotation: _chunkXNZFVYC2cjs.videoTransformAt.call(void 0, clip.transform, 0).rotation };
2216
+ }
2217
+ function turn(x, y, cx, cy, deg) {
2218
+ if (!deg) return [x, y];
2219
+ const a = deg * Math.PI / 180;
2220
+ const dx = x - cx;
2221
+ const dy = y - cy;
2222
+ return [cx + dx * Math.cos(a) - dy * Math.sin(a), cy + dx * Math.sin(a) + dy * Math.cos(a)];
2223
+ }
2224
+ function framePointsToPicture(points, picture) {
2225
+ const { rect, size, rotation } = picture;
2226
+ const cx = rect.x + rect.width / 2;
2227
+ const cy = rect.y + rect.height / 2;
2228
+ const out = [];
2229
+ for (let i = 0; i + 1 < points.length; i += 2) {
2230
+ const [x, y] = turn(points[i], points[i + 1], cx, cy, -rotation);
2231
+ out.push(Math.round((x - rect.x) / rect.width * size.width * 100) / 100, Math.round((y - rect.y) / rect.height * size.height * 100) / 100);
2232
+ }
2233
+ return out;
2234
+ }
2235
+ function videoClipMaskOutline(project, clip) {
2236
+ if (!clip.mask) return null;
2237
+ const picture = videoClipPicture(project, clip);
2238
+ const { rect, rotation } = picture;
2239
+ const cx = rect.x + rect.width / 2;
2240
+ const cy = rect.y + rect.height / 2;
2241
+ const polygon = _chunkXNZFVYC2cjs.videoMaskPolygon.call(void 0, clip.mask, rect).map(([x, y]) => turn(x, y, cx, cy, rotation));
2242
+ if (polygon.length < 2) return null;
2243
+ return [...polygon, polygon[0]].flatMap(([x, y]) => [Math.round(x * 100) / 100, Math.round(y * 100) / 100]);
2244
+ }
2245
+ var VideoPathGesture = (_class3 = class {
2246
+ constructor(frame, spacing = 3) {;_class3.prototype.__init6.call(this);_class3.prototype.__init7.call(this);
2247
+ this.frame = frame;
2248
+ this.spacing = spacing;
2249
+ }
2250
+
2251
+
2252
+ __init6() {this.points = []}
2253
+ __init7() {this.drawing = false}
2254
+ at(e, box) {
2255
+ return [Math.round((e.clientX - box.left) / box.width * this.frame.width * 100) / 100, Math.round((e.clientY - box.top) / box.height * this.frame.height * 100) / 100];
2256
+ }
2257
+ down(e, box) {
2258
+ this.drawing = true;
2259
+ this.points = this.at(e, box);
2260
+ }
2261
+ move(e, box) {
2262
+ if (!this.drawing) return false;
2263
+ const [x, y] = this.at(e, box);
2264
+ const n = this.points.length;
2265
+ if (Math.hypot(x - this.points[n - 2], y - this.points[n - 1]) < this.spacing) return false;
2266
+ this.points.push(x, y);
2267
+ return true;
2268
+ }
2269
+ /** Ends the stroke; returns its points, or `null` for a tap (fewer than two points). */
2270
+ up() {
2271
+ this.drawing = false;
2272
+ return this.points.length >= 4 ? [...this.points] : null;
2273
+ }
2274
+ }, _class3);
2275
+
2208
2276
  // src/video-editor/plan.ts
2209
2277
  function clipIndex(project) {
2210
2278
  const out = /* @__PURE__ */ new Map();
2211
- for (const { track } of _chunkZQIWBJGHcjs.allVideoTracks.call(void 0, project)) for (const c of track.clips) out.set(c.id, c);
2279
+ for (const { track } of _chunkXNZFVYC2cjs.allVideoTracks.call(void 0, project)) for (const c of track.clips) out.set(c.id, c);
2212
2280
  return out;
2213
2281
  }
2214
2282
  function diffVideoProjects(before, after) {
@@ -2217,8 +2285,8 @@ function diffVideoProjects(before, after) {
2217
2285
  const clipsAdded = [...b.keys()].filter((id) => !a.has(id));
2218
2286
  const clipsRemoved = [...a.keys()].filter((id) => !b.has(id));
2219
2287
  const clipsChanged = [...b.keys()].filter((id) => a.has(id) && JSON.stringify(a.get(id)) !== JSON.stringify(b.get(id)));
2220
- const durationBefore = _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, before);
2221
- const durationAfter = _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, after);
2288
+ const durationBefore = _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, before);
2289
+ const durationAfter = _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, after);
2222
2290
  return { durationBefore, durationAfter, durationDelta: durationAfter - durationBefore, clipsAdded, clipsRemoved, clipsChanged };
2223
2291
  }
2224
2292
  function planVideoEdits(project, input) {
@@ -2533,10 +2601,10 @@ function videoScopeImage(kind, pixels, width = 256, height = 128, options = {})
2533
2601
  const size = Math.min(width, height);
2534
2602
  return videoVectorscopeImage(videoVectorscope(pixels, { ...options, size }), size);
2535
2603
  }
2536
- var VideoPreviewPixels = (_class3 = class {constructor() { _class3.prototype.__init6.call(this);_class3.prototype.__init7.call(this);_class3.prototype.__init8.call(this); }
2537
- __init6() {this.reader = null}
2538
- __init7() {this.drawnAt = null}
2539
- __init8() {this.listeners = /* @__PURE__ */ new Set()}
2604
+ var VideoPreviewPixels = (_class4 = class {constructor() { _class4.prototype.__init8.call(this);_class4.prototype.__init9.call(this);_class4.prototype.__init10.call(this); }
2605
+ __init8() {this.reader = null}
2606
+ __init9() {this.drawnAt = null}
2607
+ __init10() {this.listeners = /* @__PURE__ */ new Set()}
2540
2608
  /** Gives the canvas to read (the latest preview wins). Returns a function that takes it away again. */
2541
2609
  attach(reader) {
2542
2610
  this.reader = reader;
@@ -2604,7 +2672,7 @@ var VideoPreviewPixels = (_class3 = class {constructor() { _class3.prototype.__i
2604
2672
  emit() {
2605
2673
  for (const l of [...this.listeners]) l();
2606
2674
  }
2607
- }, _class3);
2675
+ }, _class4);
2608
2676
  function readVideoScopesPanel(feed, kinds = VIDEO_SCOPE_KINDS, options = {}) {
2609
2677
  let snap;
2610
2678
  try {
@@ -2645,10 +2713,10 @@ function videoTransformOfView(view, base, stage) {
2645
2713
  function videoCameraBase(clip) {
2646
2714
  if (clip.camera) return clip.camera.base;
2647
2715
  const t = _nullishCoalesce(clip.transform, () => ( {}));
2648
- const keyed = _chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES.filter((p) => _chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, t[p]));
2716
+ const keyed = _chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES.filter((p) => _chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, t[p]));
2649
2717
  if (keyed.length)
2650
2718
  throw new Error(`Clip "${clip.id}" keys its ${keyed.join(", ")}, which a camera move would replace; remove those keyframes first (set_video_keyframes with keys null).`);
2651
- return Object.fromEntries(_chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES.flatMap((p) => typeof t[p] === "number" ? [[p, t[p]]] : []));
2719
+ return Object.fromEntries(_chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES.flatMap((p) => typeof t[p] === "number" ? [[p, t[p]]] : []));
2652
2720
  }
2653
2721
  async function bakeVideoClipCamera(clip, camera, project, provider) {
2654
2722
  const stage = { width: project.width, height: project.height };
@@ -2659,22 +2727,22 @@ async function bakeVideoClipCamera(clip, camera, project, provider) {
2659
2727
  const windows = {};
2660
2728
  let keys = [];
2661
2729
  let inMs = 0;
2662
- const moveIn = _chunkJAOSL334cjs.cameraMoveParts.call(void 0, camera.in);
2730
+ const moveIn = _chunkGHCSC2WPcjs.cameraMoveParts.call(void 0, camera.in);
2663
2731
  if (moveIn) {
2664
- const { description } = await _chunkJAOSL334cjs.resolveCameraMoveSpec.call(void 0, provider, moveIn, "transition");
2732
+ const { description } = await _chunkGHCSC2WPcjs.resolveCameraMoveSpec.call(void 0, provider, moveIn, "transition");
2665
2733
  inMs = _nullishCoalesce(moveIn.ms, () => ( description.camera.durationMs));
2666
2734
  if (inMs > clip.duration) throw new Error(`The move into clip "${clip.id}" takes ${inMs} ms, longer than the clip (${clip.duration} ms); give a shorter "ms" or lengthen the clip.`);
2667
- const sample = await _chunkJAOSL334cjs.sampleEffectCameraMove.call(void 0, provider, moveIn.move, { from: videoCameraView(camera.from, stage), to, ms: inMs, stage, fps, values: moveIn.values });
2735
+ const sample = await _chunkGHCSC2WPcjs.sampleEffectCameraMove.call(void 0, provider, moveIn.move, { from: videoCameraView(camera.from, stage), to, ms: inMs, stage, fps, values: moveIn.values });
2668
2736
  keys.push(...sample.keys);
2669
2737
  if (sample.cut !== void 0) cuts.push(sample.cut);
2670
2738
  windows.in = { start: 0, end: inMs };
2671
2739
  }
2672
- const moveDuring = _chunkJAOSL334cjs.cameraMoveParts.call(void 0, camera.during);
2740
+ const moveDuring = _chunkGHCSC2WPcjs.cameraMoveParts.call(void 0, camera.during);
2673
2741
  const holdMs = clip.duration - inMs;
2674
2742
  if (moveDuring && holdMs > 0) {
2675
- await _chunkJAOSL334cjs.resolveCameraMoveSpec.call(void 0, provider, moveDuring, "hold");
2743
+ await _chunkGHCSC2WPcjs.resolveCameraMoveSpec.call(void 0, provider, moveDuring, "hold");
2676
2744
  const at = keys.length ? keys[keys.length - 1].view : to;
2677
- const sample = await _chunkJAOSL334cjs.sampleEffectCameraMove.call(void 0, provider, moveDuring.move, { from: at, to: at, ms: holdMs, stage, fps, values: moveDuring.values });
2745
+ const sample = await _chunkGHCSC2WPcjs.sampleEffectCameraMove.call(void 0, provider, moveDuring.move, { from: at, to: at, ms: holdMs, stage, fps, values: moveDuring.values });
2678
2746
  const shifted = sample.keys.map((k) => ({ t: k.t + inMs, view: k.view }));
2679
2747
  if (keys.length && shifted.length && sameView(keys[keys.length - 1].view, shifted[0].view)) shifted.shift();
2680
2748
  keys.push(...shifted);
@@ -2687,7 +2755,7 @@ async function bakeVideoClipCamera(clip, camera, project, provider) {
2687
2755
  const base = videoCameraBase(clip);
2688
2756
  const transforms = keys.map((k) => ({ t: Math.round(k.t * 1e3) / 1e3, value: videoTransformOfView(k.view, base, stage) }));
2689
2757
  const transform = {};
2690
- for (const p of _chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES) {
2758
+ for (const p of _chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES) {
2691
2759
  const out = [];
2692
2760
  for (const { t, value } of transforms) {
2693
2761
  const last = out[out.length - 1];
@@ -2701,12 +2769,12 @@ async function bakeVideoClipCamera(clip, camera, project, provider) {
2701
2769
  }
2702
2770
  var sameView = (a, b) => ["zoom", "scrollX", "scrollY", "tilt", "turn", "roll", "blur"].every((k) => Math.abs((_nullishCoalesce(a[k], () => ( 0))) - (_nullishCoalesce(b[k], () => ( 0)))) < 1e-9);
2703
2771
  function videoClipCameraMove(clip, role) {
2704
- return _chunkJAOSL334cjs.cameraMoveParts.call(void 0, _optionalChain([clip, 'optionalAccess', _45 => _45.camera, 'optionalAccess', _46 => _46[role === "transition" ? "in" : "during"]]));
2772
+ return _chunkGHCSC2WPcjs.cameraMoveParts.call(void 0, _optionalChain([clip, 'optionalAccess', _45 => _45.camera, 'optionalAccess', _46 => _46[role === "transition" ? "in" : "during"]]));
2705
2773
  }
2706
2774
 
2707
2775
  // src/video-editor/transcript-controller.ts
2708
- var TranscriptVideoController = (_class4 = class {
2709
- constructor(controller, options = {}) {;_class4.prototype.__init9.call(this);_class4.prototype.__init10.call(this);_class4.prototype.__init11.call(this);_class4.prototype.__init12.call(this);_class4.prototype.__init13.call(this);_class4.prototype.__init14.call(this);_class4.prototype.__init15.call(this);
2776
+ var TranscriptVideoController = (_class5 = class {
2777
+ constructor(controller, options = {}) {;_class5.prototype.__init11.call(this);_class5.prototype.__init12.call(this);_class5.prototype.__init13.call(this);_class5.prototype.__init14.call(this);_class5.prototype.__init15.call(this);_class5.prototype.__init16.call(this);_class5.prototype.__init17.call(this);
2710
2778
  this.controller = controller;
2711
2779
  this.options = options;
2712
2780
  this.track = options.track;
@@ -2715,22 +2783,22 @@ var TranscriptVideoController = (_class4 = class {
2715
2783
  }
2716
2784
 
2717
2785
 
2718
- __init9() {this.listeners = /* @__PURE__ */ new Set()}
2719
- __init10() {this.unsubscribe = null}
2786
+ __init11() {this.listeners = /* @__PURE__ */ new Set()}
2787
+ __init12() {this.unsubscribe = null}
2720
2788
 
2721
- __init11() {this.selection = null}
2722
- __init12() {this.error = null}
2789
+ __init13() {this.selection = null}
2790
+ __init14() {this.error = null}
2723
2791
 
2724
2792
  /** Words and disfluencies are worked out once per project. */
2725
- __init13() {this.cache = null}
2726
- __init14() {this.getState = () => this.state}
2793
+ __init15() {this.cache = null}
2794
+ __init16() {this.getState = () => this.state}
2727
2795
  connect() {
2728
2796
  if (this.unsubscribe) return;
2729
2797
  this.unsubscribe = this.controller.subscribe(() => this.refresh());
2730
2798
  this.refresh();
2731
2799
  }
2732
2800
  /** Listens for changes. Subscribing after `destroy` follows the editor again (React StrictMode remounts). */
2733
- __init15() {this.subscribe = (listener) => {
2801
+ __init17() {this.subscribe = (listener) => {
2734
2802
  this.connect();
2735
2803
  this.listeners.add(listener);
2736
2804
  return () => {
@@ -2871,7 +2939,7 @@ var TranscriptVideoController = (_class4 = class {
2871
2939
  true
2872
2940
  );
2873
2941
  }
2874
- }, _class4);
2942
+ }, _class5);
2875
2943
 
2876
2944
  // src/video-editor/proxy.ts
2877
2945
  var VIDEO_PROXY_SCALES = [0.5, 0.25];
@@ -2930,7 +2998,7 @@ function videoProxyFfmpeg(asset, options = {}) {
2930
2998
  output
2931
2999
  ];
2932
3000
  const proxy = { scale, src: output, ...asset.width && asset.height ? { width: Math.trunc(asset.width * scale / 2) * 2, height: Math.trunc(asset.height * scale / 2) * 2 } : {} };
2933
- return { asset: asset.id, args, command: ["ffmpeg", ...args].map(_chunkZQIWBJGHcjs.videoShellQuote).join(" "), proxy };
3001
+ return { asset: asset.id, args, command: ["ffmpeg", ...args].map(_chunkXNZFVYC2cjs.videoShellQuote).join(" "), proxy };
2934
3002
  }
2935
3003
  function videoProxyPlan(project, options = {}) {
2936
3004
  const scale = _nullishCoalesce(options.scale, () => ( 0.5));
@@ -2956,7 +3024,7 @@ var videoSourceFrameTime = (frame, fps) => (frame + 0.5) * 1e3 / fps;
2956
3024
  var videoFrameCacheKey = (src, frame) => `${frame}@${src}`;
2957
3025
  function videoFrameRequestsAt(project, time, srcFor = (l) => l.src) {
2958
3026
  const out = [];
2959
- for (const layer of _chunkZQIWBJGHcjs.videoFrameLeafLayers.call(void 0, _chunkZQIWBJGHcjs.videoFrameAt.call(void 0, project, time).layers)) {
3027
+ for (const layer of _chunkXNZFVYC2cjs.videoFrameLeafLayers.call(void 0, _chunkXNZFVYC2cjs.videoFrameAt.call(void 0, project, time).layers)) {
2960
3028
  if (layer.type !== "media" || layer.assetKind !== "video") continue;
2961
3029
  const src = srcFor(layer);
2962
3030
  if (!src) continue;
@@ -3004,26 +3072,26 @@ var defaultCapture = async (source) => {
3004
3072
  const image = await createImageBitmap(source);
3005
3073
  return { image, width: image.width, height: image.height };
3006
3074
  };
3007
- var VideoFrameCache = (_class5 = class {
3008
- constructor(options = {}) {;_class5.prototype.__init16.call(this);_class5.prototype.__init17.call(this);_class5.prototype.__init18.call(this);_class5.prototype.__init19.call(this);_class5.prototype.__init20.call(this);_class5.prototype.__init21.call(this);_class5.prototype.__init22.call(this);_class5.prototype.__init23.call(this);_class5.prototype.__init24.call(this);_class5.prototype.__init25.call(this);_class5.prototype.__init26.call(this);_class5.prototype.__init27.call(this);
3075
+ var VideoFrameCache = (_class6 = class {
3076
+ constructor(options = {}) {;_class6.prototype.__init18.call(this);_class6.prototype.__init19.call(this);_class6.prototype.__init20.call(this);_class6.prototype.__init21.call(this);_class6.prototype.__init22.call(this);_class6.prototype.__init23.call(this);_class6.prototype.__init24.call(this);_class6.prototype.__init25.call(this);_class6.prototype.__init26.call(this);_class6.prototype.__init27.call(this);_class6.prototype.__init28.call(this);_class6.prototype.__init29.call(this);
3009
3077
  this.options = options;
3010
3078
  this.maxBytes = _nullishCoalesce(options.maxBytes, () => ( 512 * 1024 * 1024));
3011
3079
  this.prefetch = _nullishCoalesce(options.prefetch, () => ( 2e3));
3012
3080
  this.decode = options.decode !== void 0 ? options.decode : typeof document !== "undefined" ? createVideoElementDecoder() : null;
3013
3081
  }
3014
3082
 
3015
- __init16() {this.entries = /* @__PURE__ */ new Map()}
3016
- __init17() {this.inFlight = /* @__PURE__ */ new Set()}
3017
- __init18() {this.queue = []}
3018
- __init19() {this.protect = /* @__PURE__ */ new Set()}
3019
- __init20() {this.listeners = /* @__PURE__ */ new Set()}
3020
- __init21() {this.playhead = 0}
3021
- __init22() {this.direction = 1}
3022
- __init23() {this.hits = 0}
3023
- __init24() {this.misses = 0}
3024
- __init25() {this.bytes = 0}
3025
- __init26() {this.generation = 0}
3026
- __init27() {this.destroyed = false}
3083
+ __init18() {this.entries = /* @__PURE__ */ new Map()}
3084
+ __init19() {this.inFlight = /* @__PURE__ */ new Set()}
3085
+ __init20() {this.queue = []}
3086
+ __init21() {this.protect = /* @__PURE__ */ new Set()}
3087
+ __init22() {this.listeners = /* @__PURE__ */ new Set()}
3088
+ __init23() {this.playhead = 0}
3089
+ __init24() {this.direction = 1}
3090
+ __init25() {this.hits = 0}
3091
+ __init26() {this.misses = 0}
3092
+ __init27() {this.bytes = 0}
3093
+ __init28() {this.generation = 0}
3094
+ __init29() {this.destroyed = false}
3027
3095
 
3028
3096
 
3029
3097
 
@@ -3158,7 +3226,7 @@ var VideoFrameCache = (_class5 = class {
3158
3226
  emit() {
3159
3227
  for (const l of [...this.listeners]) l();
3160
3228
  }
3161
- }, _class5);
3229
+ }, _class6);
3162
3230
  function createVideoElementDecoder(options = {}) {
3163
3231
  const videos = /* @__PURE__ */ new Map();
3164
3232
  const make = _nullishCoalesce(options.createVideo, () => ( (() => {
@@ -3200,8 +3268,8 @@ function createVideoElementDecoder(options = {}) {
3200
3268
  }
3201
3269
 
3202
3270
  // src/video-editor/preview.ts
3203
- var VideoPreviewEngine = (_class6 = class {
3204
- constructor(source, canvas2, options = {}) {;_class6.prototype.__init28.call(this);_class6.prototype.__init29.call(this);_class6.prototype.__init30.call(this);_class6.prototype.__init31.call(this);_class6.prototype.__init32.call(this);_class6.prototype.__init33.call(this);_class6.prototype.__init34.call(this);_class6.prototype.__init35.call(this);_class6.prototype.__init36.call(this);_class6.prototype.__init37.call(this);_class6.prototype.__init38.call(this);_class6.prototype.__init39.call(this);_class6.prototype.__init40.call(this);_class6.prototype.__init41.call(this);_class6.prototype.__init42.call(this);_class6.prototype.__init43.call(this);
3271
+ var VideoPreviewEngine = (_class7 = class {
3272
+ constructor(source, canvas2, options = {}) {;_class7.prototype.__init30.call(this);_class7.prototype.__init31.call(this);_class7.prototype.__init32.call(this);_class7.prototype.__init33.call(this);_class7.prototype.__init34.call(this);_class7.prototype.__init35.call(this);_class7.prototype.__init36.call(this);_class7.prototype.__init37.call(this);_class7.prototype.__init38.call(this);_class7.prototype.__init39.call(this);_class7.prototype.__init40.call(this);_class7.prototype.__init41.call(this);_class7.prototype.__init42.call(this);_class7.prototype.__init43.call(this);_class7.prototype.__init44.call(this);_class7.prototype.__init45.call(this);
3205
3273
  this.source = source;
3206
3274
  this.options = options;
3207
3275
  this.canvas = canvas2;
@@ -3226,25 +3294,25 @@ var VideoPreviewEngine = (_class6 = class {
3226
3294
 
3227
3295
 
3228
3296
 
3229
- __init28() {this.media = /* @__PURE__ */ new Map()}
3230
- __init29() {this.images = /* @__PURE__ */ new Map()}
3297
+ __init30() {this.media = /* @__PURE__ */ new Map()}
3298
+ __init31() {this.images = /* @__PURE__ */ new Map()}
3231
3299
 
3232
- __init30() {this.scheduled = false}
3233
- __init31() {this.destroyed = false}
3234
- __init32() {this.filterHost = null}
3235
- __init33() {this.filters = /* @__PURE__ */ new Set()}
3300
+ __init32() {this.scheduled = false}
3301
+ __init33() {this.destroyed = false}
3302
+ __init34() {this.filterHost = null}
3303
+ __init35() {this.filters = /* @__PURE__ */ new Set()}
3236
3304
 
3237
3305
 
3238
- __init34() {this.drawn = null}
3239
- __init35() {this.complete = true}
3306
+ __init36() {this.drawn = null}
3307
+ __init37() {this.complete = true}
3240
3308
 
3241
3309
 
3242
3310
 
3243
- __init36() {this.srcFor = (layer) => layer.src}
3244
- __init37() {this.playing = false}
3245
- __init38() {this.fps = 30}
3311
+ __init38() {this.srcFor = (layer) => layer.src}
3312
+ __init39() {this.playing = false}
3313
+ __init40() {this.fps = 30}
3246
3314
 
3247
- __init39() {this.scratchCanvases = /* @__PURE__ */ new Map()}
3315
+ __init41() {this.scratchCanvases = /* @__PURE__ */ new Map()}
3248
3316
 
3249
3317
 
3250
3318
  /** The canvas's pixels and the frame they show, or `null` when its context cannot be read. */
@@ -3297,7 +3365,7 @@ var VideoPreviewEngine = (_class6 = class {
3297
3365
  if (this.destroyed) return;
3298
3366
  const state = this.source.getState();
3299
3367
  const { project, time, playing } = state;
3300
- const frame = _chunkZQIWBJGHcjs.videoFrameAt.call(void 0, project, time);
3368
+ const frame = _chunkXNZFVYC2cjs.videoFrameAt.call(void 0, project, time);
3301
3369
  const scale = resolveVideoPreviewScale(_nullishCoalesce(this.options.previewScale, () => ( state.previewScale)), this.resolutionFor(project.width));
3302
3370
  const assets = new Map(project.assets.map((a) => [a.id, a]));
3303
3371
  this.srcFor = (layer) => videoPreviewSrc(assets.get(_nullishCoalesce(layer.asset, () => ( ""))), scale, layer.src);
@@ -3327,7 +3395,7 @@ var VideoPreviewEngine = (_class6 = class {
3327
3395
  }
3328
3396
  };
3329
3397
  const sounding = new Map(frame.audio.map((a) => [a.clip, a]));
3330
- for (const layer of _chunkZQIWBJGHcjs.videoFrameLeafLayers.call(void 0, frame.layers)) {
3398
+ for (const layer of _chunkXNZFVYC2cjs.videoFrameLeafLayers.call(void 0, frame.layers)) {
3331
3399
  if (layer.type !== "media" || layer.assetKind !== "video" || !layer.src) continue;
3332
3400
  const sound = sounding.get(layer.clip);
3333
3401
  sync(layer.clip, this.srcFor(layer), "video", _nullishCoalesce(layer.sourceTime, () => ( 0)), _nullishCoalesce(_optionalChain([sound, 'optionalAccess', _93 => _93.speed]), () => ( 1)), sound ? sound.gain : null);
@@ -3339,9 +3407,9 @@ var VideoPreviewEngine = (_class6 = class {
3339
3407
  }
3340
3408
  /** With effects, the frame is drawn at the start of its frame, so effect pictures are cached once per frame. */
3341
3409
  drawable(project, frame) {
3342
- if (!_optionalChain([this, 'access', _94 => _94.effects, 'optionalAccess', _95 => _95.available]) || !_chunkZQIWBJGHcjs.videoLayersUseEffects.call(void 0, frame.layers)) return frame;
3343
- const at = _chunkZQIWBJGHcjs.videoEffectFrameTime.call(void 0, frame.time, project.fps);
3344
- return at === frame.time ? frame : { ..._chunkZQIWBJGHcjs.videoFrameAt.call(void 0, project, at), time: frame.time };
3410
+ if (!_optionalChain([this, 'access', _94 => _94.effects, 'optionalAccess', _95 => _95.available]) || !_chunkXNZFVYC2cjs.videoLayersUseEffects.call(void 0, frame.layers)) return frame;
3411
+ const at = _chunkXNZFVYC2cjs.videoEffectFrameTime.call(void 0, frame.time, project.fps);
3412
+ return at === frame.time ? frame : { ..._chunkXNZFVYC2cjs.videoFrameAt.call(void 0, project, at), time: frame.time };
3345
3413
  }
3346
3414
  redraw() {
3347
3415
  if (this.scheduled || this.destroyed) return;
@@ -3350,10 +3418,10 @@ var VideoPreviewEngine = (_class6 = class {
3350
3418
  this.scheduled = false;
3351
3419
  if (this.destroyed) return;
3352
3420
  const { project, time } = this.source.getState();
3353
- this.draw(this.drawable(project, _chunkZQIWBJGHcjs.videoFrameAt.call(void 0, project, time)));
3421
+ this.draw(this.drawable(project, _chunkXNZFVYC2cjs.videoFrameAt.call(void 0, project, time)));
3354
3422
  });
3355
3423
  }
3356
- __init40() {this.sourceFor = (layer) => {
3424
+ __init42() {this.sourceFor = (layer) => {
3357
3425
  if (layer.assetKind === "image" && layer.src) {
3358
3426
  const img = this.image(layer.src);
3359
3427
  return img.complete ? img : null;
@@ -3393,7 +3461,7 @@ var VideoPreviewEngine = (_class6 = class {
3393
3461
  if (!source) this.complete = false;
3394
3462
  return source;
3395
3463
  };
3396
- _chunkZQIWBJGHcjs.drawVideoFrame.call(void 0, this.ctx, frame, sourceFor, resolution, {
3464
+ _chunkXNZFVYC2cjs.drawVideoFrame.call(void 0, this.ctx, frame, sourceFor, resolution, {
3397
3465
  defineSvgFilter: this.defineSvgFilter,
3398
3466
  lutFor: this.lutFor,
3399
3467
  scratch: this.scratch,
@@ -3407,12 +3475,12 @@ var VideoPreviewEngine = (_class6 = class {
3407
3475
  _optionalChain([this, 'access', _100 => _100.pixelsTarget, 'optionalAccess', _101 => _101.drawn, 'call', _102 => _102(frame.time, this.complete)]);
3408
3476
  }
3409
3477
  /** A grade's LUT once loaded; while it loads (or if it fails) the frame is drawn without it and counts as incomplete. */
3410
- __init41() {this.lutFor = (src) => {
3478
+ __init43() {this.lutFor = (src) => {
3411
3479
  const lut = _optionalChain([this, 'access', _103 => _103.lutCache, 'optionalAccess', _104 => _104.get, 'call', _105 => _105(src)]);
3412
3480
  if (!lut) this.complete = false;
3413
3481
  return lut;
3414
3482
  }}
3415
- __init42() {this.scratch = (width, height, slot) => {
3483
+ __init44() {this.scratch = (width, height, slot) => {
3416
3484
  if (!this.scratchCanvases.has(slot)) {
3417
3485
  let made = null;
3418
3486
  if (this.options.createScratch) made = this.options.createScratch(width, height, slot);
@@ -3430,7 +3498,7 @@ var VideoPreviewEngine = (_class6 = class {
3430
3498
  if (c.height !== height) c.height = height;
3431
3499
  return s;
3432
3500
  }}
3433
- __init43() {this.defineSvgFilter = (id, markup) => {
3501
+ __init45() {this.defineSvgFilter = (id, markup) => {
3434
3502
  if (this.options.defineSvgFilter === null) return;
3435
3503
  if (this.options.defineSvgFilter) return this.options.defineSvgFilter(id, markup);
3436
3504
  if (this.filters.has(id) || typeof document === "undefined") return;
@@ -3460,21 +3528,21 @@ var VideoPreviewEngine = (_class6 = class {
3460
3528
  for (const entry of [...this.media.values()]) this.release(entry);
3461
3529
  this.images.clear();
3462
3530
  }
3463
- }, _class6);
3531
+ }, _class7);
3464
3532
 
3465
3533
  // src/video-editor/sequence.ts
3466
3534
  var svgUrl = (svg) => svg.trimStart().startsWith("<") ? `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}` : svg;
3467
3535
  var GROUPS = ["base", "background", "subject", "overlay", "text"];
3468
3536
  function videoEditsFromSequence(project, sequence, options = {}) {
3469
- const at = _nullishCoalesce(options.at, () => ( _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, project)));
3537
+ const at = _nullishCoalesce(options.at, () => ( _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, project)));
3470
3538
  const W = project.width;
3471
3539
  const H = project.height;
3472
3540
  const sx = W / sequence.stage.width;
3473
3541
  const sy = H / sequence.stage.height;
3474
- const timing = _chunkJWCKJNDRcjs.effectSequenceTiming.call(void 0, sequence);
3542
+ const timing = _chunkK5DS2JTAcjs.effectSequenceTiming.call(void 0, sequence);
3475
3543
  const provider = options.provider ? { provider: options.provider } : {};
3476
3544
  const notes = [];
3477
- const usedClips = new Set(_chunkZQIWBJGHcjs.allVideoClipIds.call(void 0, project));
3545
+ const usedClips = new Set(_chunkXNZFVYC2cjs.allVideoClipIds.call(void 0, project));
3478
3546
  const usedTracks = new Set(project.tracks.map((t) => t.id));
3479
3547
  const usedAssets = new Set(project.assets.map((a) => a.id));
3480
3548
  const fresh = (used, base) => {
@@ -3516,11 +3584,11 @@ function videoEditsFromSequence(project, sequence, options = {}) {
3516
3584
  const shotEnd = _nullishCoalesce(timing.starts[i + 1], () => ( timing.total));
3517
3585
  let base;
3518
3586
  shot.layers.forEach((layer, j) => {
3519
- const span = _chunkJWCKJNDRcjs.effectLayerSpan.call(void 0, layer, i, timing.starts, timing.total);
3587
+ const span = _chunkK5DS2JTAcjs.effectLayerSpan.call(void 0, layer, i, timing.starts, timing.total);
3520
3588
  if (span.end - span.start <= 0) return void notes.push(`Shot ${i + 1}, layer ${j + 1} lasts no time, so it was left out.`);
3521
3589
  const clip = clipOf(layer, at + span.start, span.end - span.start, i);
3522
- const isBase = j === 0 && !base && span.start === shotStart && span.end === shotEnd && _chunkJWCKJNDRcjs.effectLayerRole.call(void 0, layer) === "background" && !layer.rect;
3523
- const item = { group: isBase ? "base" : _chunkJWCKJNDRcjs.effectLayerRole.call(void 0, layer), clip };
3590
+ const isBase = j === 0 && !base && span.start === shotStart && span.end === shotEnd && _chunkK5DS2JTAcjs.effectLayerRole.call(void 0, layer) === "background" && !layer.rect;
3591
+ const item = { group: isBase ? "base" : _chunkK5DS2JTAcjs.effectLayerRole.call(void 0, layer), clip };
3524
3592
  if (isBase) base = item;
3525
3593
  items.push(item);
3526
3594
  });
@@ -3563,13 +3631,13 @@ function videoEditsFromSequence(project, sequence, options = {}) {
3563
3631
  }
3564
3632
 
3565
3633
  // src/video-editor/controller.ts
3566
- var VideoEditorController = (_class7 = class _VideoEditorController {
3634
+ var VideoEditorController = (_class8 = class _VideoEditorController {
3567
3635
 
3568
3636
 
3569
3637
  /** Sound levels per asset, loaded on demand for waveforms and agents. */
3570
3638
 
3571
3639
  /** The pixels the preview last drew, for scopes and `get_video_scopes` (a `VideoPreviewEngine` fills it). */
3572
- __init44() {this.previewPixels = new VideoPreviewPixels()}
3640
+ __init46() {this.previewPixels = new VideoPreviewPixels()}
3573
3641
  /** Grades' LUTs, loaded on demand for the preview, SVG frames and agents. */
3574
3642
 
3575
3643
  /** The host's frame cache, if it gave one (the preview fills and reads it). */
@@ -3580,34 +3648,34 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3580
3648
 
3581
3649
 
3582
3650
 
3583
- __init45() {this.selection = []}
3651
+ __init47() {this.selection = []}
3584
3652
 
3585
3653
 
3586
- __init46() {this.error = null}
3587
- __init47() {this.revision = 0}
3588
- __init48() {this.applying = false}
3654
+ __init48() {this.error = null}
3655
+ __init49() {this.revision = 0}
3656
+ __init50() {this.applying = false}
3589
3657
 
3590
- __init49() {this.listeners = /* @__PURE__ */ new Set()}
3591
- __init50() {this.unsubscribers = []}
3658
+ __init51() {this.listeners = /* @__PURE__ */ new Set()}
3659
+ __init52() {this.unsubscribers = []}
3592
3660
 
3593
- __init51() {this.plans = []}
3661
+ __init53() {this.plans = []}
3594
3662
  /** The project each open plan was worked out against. */
3595
- __init52() {this.planBasis = /* @__PURE__ */ new Map()}
3596
- __init53() {this.planCount = 0}
3597
- constructor(options = {}) {;_class7.prototype.__init44.call(this);_class7.prototype.__init45.call(this);_class7.prototype.__init46.call(this);_class7.prototype.__init47.call(this);_class7.prototype.__init48.call(this);_class7.prototype.__init49.call(this);_class7.prototype.__init50.call(this);_class7.prototype.__init51.call(this);_class7.prototype.__init52.call(this);_class7.prototype.__init53.call(this);_class7.prototype.__init54.call(this);_class7.prototype.__init55.call(this);
3663
+ __init54() {this.planBasis = /* @__PURE__ */ new Map()}
3664
+ __init55() {this.planCount = 0}
3665
+ constructor(options = {}) {;_class8.prototype.__init46.call(this);_class8.prototype.__init47.call(this);_class8.prototype.__init48.call(this);_class8.prototype.__init49.call(this);_class8.prototype.__init50.call(this);_class8.prototype.__init51.call(this);_class8.prototype.__init52.call(this);_class8.prototype.__init53.call(this);_class8.prototype.__init54.call(this);_class8.prototype.__init55.call(this);_class8.prototype.__init56.call(this);_class8.prototype.__init57.call(this);_class8.prototype.__init58.call(this);
3598
3666
  this.history = _nullishCoalesce(options.history, () => ( new (0, _chunkFJ2MSI43cjs.HistoryManager)()));
3599
3667
  this.audioPeaks = options.audioPeaks instanceof VideoAudioPeaksCache ? options.audioPeaks : new VideoAudioPeaksCache(options.audioPeaks);
3600
- this.luts = options.luts instanceof _chunkZQIWBJGHcjs.VideoLutCache ? options.luts : new (0, _chunkZQIWBJGHcjs.VideoLutCache)(options.luts);
3668
+ this.luts = options.luts instanceof _chunkXNZFVYC2cjs.VideoLutCache ? options.luts : new (0, _chunkXNZFVYC2cjs.VideoLutCache)(options.luts);
3601
3669
  this.frameCache = _nullishCoalesce(options.frameCache, () => ( null));
3602
- this.effects = new (0, _chunkJAOSL334cjs.EffectsSlot)();
3670
+ this.effects = new (0, _chunkGHCSC2WPcjs.EffectsSlot)();
3603
3671
  if (options.effects) this.effects.set(options.effects);
3604
- this.effectsEngine = new (0, _chunkZQIWBJGHcjs.VideoEffectsEngine)({ slot: this.effects });
3672
+ this.effectsEngine = new (0, _chunkXNZFVYC2cjs.VideoEffectsEngine)({ slot: this.effects });
3605
3673
  this.project = options.project ? parseVideoProject(options.project) : createVideoProject();
3606
3674
  this.issues = checkVideoProject(this.project);
3607
3675
  this.readOnly = _nullishCoalesce(options.readOnly, () => ( false));
3608
3676
  this.previewScale = checkPreviewScale(_nullishCoalesce(options.previewScale, () => ( "auto")));
3609
3677
  this.onChange = options.onChange;
3610
- this.player = new (0, _chunkLJZRHVZVcjs.AnimationPlayer)({ clock: options.clock, duration: () => _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, this.project), loop: "none" });
3678
+ this.player = new (0, _chunkLJZRHVZVcjs.AnimationPlayer)({ clock: options.clock, duration: () => _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, this.project), loop: "none" });
3611
3679
  this.state = this.computeState();
3612
3680
  this.connect();
3613
3681
  }
@@ -3627,8 +3695,8 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3627
3695
  this.effectsEngine.reset();
3628
3696
  this.unsubscribers.splice(0).forEach((u) => u());
3629
3697
  }
3630
- __init54() {this.getState = () => this.state}
3631
- __init55() {this.subscribe = (listener) => {
3698
+ __init56() {this.getState = () => this.state}
3699
+ __init57() {this.subscribe = (listener) => {
3632
3700
  this.connect();
3633
3701
  this.listeners.add(listener);
3634
3702
  return () => {
@@ -3644,12 +3712,12 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3644
3712
  const h = this.history.getState();
3645
3713
  return {
3646
3714
  project: this.project,
3647
- duration: _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, this.project),
3715
+ duration: _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, this.project),
3648
3716
  time: p.time,
3649
3717
  playing: p.playing,
3650
3718
  loop: p.loop,
3651
3719
  selection: this.selection,
3652
- current: _chunkZQIWBJGHcjs.videoClipsAt.call(void 0, this.project, p.time).map((c) => c.clip.id),
3720
+ current: _chunkXNZFVYC2cjs.videoClipsAt.call(void 0, this.project, p.time).map((c) => c.clip.id),
3653
3721
  issues: this.issues,
3654
3722
  readOnly: this.readOnly,
3655
3723
  error: this.error,
@@ -3660,6 +3728,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3660
3728
  previewScale: this.previewScale,
3661
3729
  effectsProvider: this.effects.provider,
3662
3730
  plans: this.plans,
3731
+ pathDrawing: this.pathDrawing,
3663
3732
  revision: this.revision
3664
3733
  };
3665
3734
  }
@@ -3682,7 +3751,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3682
3751
  this.issues = checkVideoProject(project);
3683
3752
  const ids = new Set(project.tracks.flatMap((t) => t.clips.map((c) => c.id)));
3684
3753
  if (this.selection.some((id) => !ids.has(id))) this.selection = this.selection.filter((id) => ids.has(id));
3685
- this.player.setDuration(() => _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, this.project));
3754
+ this.player.setDuration(() => _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, this.project));
3686
3755
  } finally {
3687
3756
  this.applying = false;
3688
3757
  }
@@ -3844,7 +3913,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3844
3913
  }
3845
3914
  /** Selects clips (unknown ids are dropped). `add` toggles them into the current selection. */
3846
3915
  select(clips, options = {}) {
3847
- const known = _nullishCoalesce(_optionalChain([clips, 'optionalAccess', _117 => _117.filter, 'call', _118 => _118((id) => _chunkZQIWBJGHcjs.findVideoClip.call(void 0, this.project, id))]), () => ( []));
3916
+ const known = _nullishCoalesce(_optionalChain([clips, 'optionalAccess', _117 => _117.filter, 'call', _118 => _118((id) => _chunkXNZFVYC2cjs.findVideoClip.call(void 0, this.project, id))]), () => ( []));
3848
3917
  let next;
3849
3918
  if (options.add) {
3850
3919
  next = [...this.selection];
@@ -3871,7 +3940,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3871
3940
  step(frames) {
3872
3941
  this.player.pause();
3873
3942
  const fps = this.project.fps;
3874
- this.player.seek(Math.max(0, _chunkZQIWBJGHcjs.snapToVideoFrame.call(void 0, this.player.currentTime, fps) + frames * 1e3 / fps));
3943
+ this.player.seek(Math.max(0, _chunkXNZFVYC2cjs.snapToVideoFrame.call(void 0, this.player.currentTime, fps) + frames * 1e3 / fps));
3875
3944
  }
3876
3945
  setLoop(loop) {
3877
3946
  this.player.setLoop(loop);
@@ -3888,14 +3957,14 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3888
3957
  */
3889
3958
  snap(time, options = {}) {
3890
3959
  const threshold = _nullishCoalesce(options.threshold, () => ( 8 * 1e3 / this.project.fps));
3891
- const points = _chunkZQIWBJGHcjs.videoSnapPoints.call(void 0, this.project, { exclude: options.exclude, playhead: options.playhead === false ? void 0 : this.player.currentTime });
3892
- const hit = _chunkZQIWBJGHcjs.snapVideoTime.call(void 0, time, points, threshold);
3893
- return hit.snapped !== null ? hit : { time: Math.max(0, _chunkZQIWBJGHcjs.snapToVideoFrame.call(void 0, time, this.project.fps)), snapped: null };
3960
+ const points = _chunkXNZFVYC2cjs.videoSnapPoints.call(void 0, this.project, { exclude: options.exclude, playhead: options.playhead === false ? void 0 : this.player.currentTime });
3961
+ const hit = _chunkXNZFVYC2cjs.snapVideoTime.call(void 0, time, points, threshold);
3962
+ return hit.snapped !== null ? hit : { time: Math.max(0, _chunkXNZFVYC2cjs.snapToVideoFrame.call(void 0, time, this.project.fps)), snapped: null };
3894
3963
  }
3895
3964
  /** Splits the selected clips (or every clip) under the playhead there, as one undo step. */
3896
3965
  splitAtPlayhead() {
3897
- const t = _chunkZQIWBJGHcjs.snapToVideoFrame.call(void 0, this.player.currentTime, this.project.fps);
3898
- const under = _chunkZQIWBJGHcjs.videoClipsAt.call(void 0, this.project, t).filter(({ clip }) => t > clip.start && t < _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip));
3966
+ const t = _chunkXNZFVYC2cjs.snapToVideoFrame.call(void 0, this.player.currentTime, this.project.fps);
3967
+ const under = _chunkXNZFVYC2cjs.videoClipsAt.call(void 0, this.project, t).filter(({ clip }) => t > clip.start && t < _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip));
3899
3968
  const chosen = this.selection.length ? under.filter(({ clip }) => this.selection.includes(clip.id)) : under;
3900
3969
  if (!chosen.length) return this.refuse("No clip is under the playhead to split.");
3901
3970
  return this.apply(chosen.map(({ clip }) => ({ op: "split_clip", clip: clip.id, at: t })), "Split");
@@ -3923,7 +3992,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3923
3992
  /** The provider's description of an effect, checked for `place` (rejects without a provider or for an unknown id). */
3924
3993
  async describeEffect(effect, place) {
3925
3994
  const d = await this.effects.require().describe(effect);
3926
- if (place) _chunkZQIWBJGHcjs.checkVideoEffectPlace.call(void 0, d, place);
3995
+ if (place) _chunkXNZFVYC2cjs.checkVideoEffectPlace.call(void 0, d, place);
3927
3996
  return d;
3928
3997
  }
3929
3998
  /**
@@ -3938,9 +4007,9 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3938
4007
  if (options.at !== void 0 && !(Number.isFinite(options.at) && options.at >= 0)) return this.refused(`"at" is a time in ms, 0 or more (got ${options.at}).`);
3939
4008
  let filled;
3940
4009
  try {
3941
- filled = await _chunkJWCKJNDRcjs.fillEffectTemplate.call(void 0, this.effects.provider, template, values, options.name ? { name: options.name } : {});
4010
+ filled = await _chunkK5DS2JTAcjs.fillEffectTemplate.call(void 0, this.effects.provider, template, values, options.name ? { name: options.name } : {});
3942
4011
  } catch (error) {
3943
- if (_chunkJAOSL334cjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refused(error.message);
4012
+ if (_chunkGHCSC2WPcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refused(error.message);
3944
4013
  throw error;
3945
4014
  }
3946
4015
  const made = videoEditsFromSequence(this.getState().project, filled.sequence, { at: options.at, provider: this.effects.provider.id });
@@ -3959,7 +4028,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3959
4028
  try {
3960
4029
  plan = await run();
3961
4030
  } catch (error) {
3962
- if (_chunkJAOSL334cjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refused(error.message);
4031
+ if (_chunkGHCSC2WPcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refused(error.message);
3963
4032
  throw error;
3964
4033
  }
3965
4034
  const result = this.apply(plan.edit, plan.label, { merge });
@@ -3967,7 +4036,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3967
4036
  return { ...result, clip: plan.clip, ...plan.effect ? { effect: plan.effect() } : {} };
3968
4037
  }
3969
4038
  clipOrThrow(id) {
3970
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, this.project, id);
4039
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, this.project, id);
3971
4040
  if (!at) throw new Error(`There is no clip "${id}"; list_applied_effects or get_video_project lists the clips.`);
3972
4041
  return at.clip;
3973
4042
  }
@@ -3980,7 +4049,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
3980
4049
  return this.effectEdit(async () => {
3981
4050
  const current = this.clipOrThrow(clip);
3982
4051
  const d = await this.describeEffect(effect, "clip");
3983
- const values = _chunkZQIWBJGHcjs.checkVideoEffectValues.call(void 0, d, options.values, { keyframes: true });
4052
+ const values = _chunkXNZFVYC2cjs.checkVideoEffectValues.call(void 0, d, options.values, { keyframes: true });
3984
4053
  const stack = [..._nullishCoalesce(current.effects, () => ( []))];
3985
4054
  const taken = new Set(stack.map((e) => e.id));
3986
4055
  let n = 1;
@@ -4016,7 +4085,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
4016
4085
  if (!(k in d.controls.properties)) throw new Error(`"${k}" is not a control of "${d.id}"; its controls are ${Object.keys(d.controls.properties).join(", ")}.`);
4017
4086
  base[k] = d.defaults[k];
4018
4087
  }
4019
- next.values = _chunkZQIWBJGHcjs.checkVideoEffectValues.call(void 0, d, given, { base, keyframes: true });
4088
+ next.values = _chunkXNZFVYC2cjs.checkVideoEffectValues.call(void 0, d, given, { base, keyframes: true });
4020
4089
  }
4021
4090
  if (changes.enabled !== void 0) {
4022
4091
  if (changes.enabled) delete next.enabled;
@@ -4037,7 +4106,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
4037
4106
  return (await provider.list({ kind: "camera" })).filter((e) => e.kind === "camera" && e.camera && (!role || e.camera.role === role));
4038
4107
  }
4039
4108
  cameraClip(id) {
4040
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, this.project, id);
4109
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, this.project, id);
4041
4110
  if (!at) {
4042
4111
  const ids = this.project.tracks.flatMap((t) => t.clips.map((c) => c.id));
4043
4112
  throw new Error(`There is no clip "${id}"; the clips are ${ids.map((c) => `"${c}"`).join(", ") || "none"} (get_video_project lists them).`);
@@ -4058,7 +4127,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
4058
4127
  const bake = await bakeVideoClipCamera(clip, camera, this.project, this.effects.require());
4059
4128
  const r = this.apply({ op: "update_clip", clip: clipId, set: { camera, transform: bake.transform } }, label, { merge });
4060
4129
  if (!r.ok) return r;
4061
- const keys = Object.fromEntries(_chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES.map((p) => [p, _chunkZQIWBJGHcjs.videoKeysOf.call(void 0, bake.transform[p]).length]));
4130
+ const keys = Object.fromEntries(_chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES.map((p) => [p, _chunkXNZFVYC2cjs.videoKeysOf.call(void 0, bake.transform[p]).length]));
4062
4131
  return { ok: true, clip: clipId, camera, keys, cuts: bake.cuts, windows: bake.windows, notes: bake.notes };
4063
4132
  }
4064
4133
  /**
@@ -4073,10 +4142,10 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
4073
4142
  if (reason) return this.refused(reason);
4074
4143
  try {
4075
4144
  const current = this.cameraClip(clip);
4076
- const { spec: parts, description } = await _chunkJAOSL334cjs.resolveCameraMoveSpec.call(void 0, this.effects.require(), spec, role);
4145
+ const { spec: parts, description } = await _chunkGHCSC2WPcjs.resolveCameraMoveSpec.call(void 0, this.effects.require(), spec, role);
4077
4146
  const move = role === "transition" && parts.ms === void 0 ? { ...parts, ms: description.camera.durationMs } : parts;
4078
4147
  const simple = move.ms === void 0 && move.preset === void 0 && move.values === void 0;
4079
- const camera = { ..._nullishCoalesce(current.camera, () => ( { base: videoCameraBase(current) })), [_chunkJAOSL334cjs.cameraMoveField.call(void 0, role)]: simple ? move.move : move };
4148
+ const camera = { ..._nullishCoalesce(current.camera, () => ( { base: videoCameraBase(current) })), [_chunkGHCSC2WPcjs.cameraMoveField.call(void 0, role)]: simple ? move.move : move };
4080
4149
  for (const key of ["from", "framing"]) {
4081
4150
  if (options[key] === null) delete camera[key];
4082
4151
  else if (options[key] !== void 0) camera[key] = options[key];
@@ -4084,7 +4153,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
4084
4153
  if (camera.from && !camera.in) throw new Error('"from" is where a move in starts; set a transition move too, or leave "from" out.');
4085
4154
  return await this.cameraEdit(clip, camera, `${role === "hold" ? "Hold move" : "Camera move"} ${description.name}`, options.merge);
4086
4155
  } catch (error) {
4087
- if (_chunkJAOSL334cjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refused(error.message);
4156
+ if (_chunkGHCSC2WPcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refused(error.message);
4088
4157
  throw error;
4089
4158
  }
4090
4159
  }
@@ -4097,7 +4166,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
4097
4166
  if (reason) return this.refused(reason);
4098
4167
  try {
4099
4168
  const current = this.cameraClip(clip);
4100
- const field = _chunkJAOSL334cjs.cameraMoveField.call(void 0, role);
4169
+ const field = _chunkGHCSC2WPcjs.cameraMoveField.call(void 0, role);
4101
4170
  const other = field === "in" ? "during" : "in";
4102
4171
  if (_optionalChain([current, 'access', _121 => _121.camera, 'optionalAccess', _122 => _122[field]]) === void 0)
4103
4172
  throw new Error(`Clip "${clip}" has no camera "${field}" move to clear${_optionalChain([current, 'access', _123 => _123.camera, 'optionalAccess', _124 => _124[other]]) !== void 0 ? `; it has a "${other}" move (role ${role === "hold" ? "transition" : "hold"})` : ""}.`);
@@ -4107,7 +4176,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
4107
4176
  const left = camera.in !== void 0 || camera.during !== void 0;
4108
4177
  return await this.cameraEdit(clip, left ? camera : null, role === "hold" ? "Clear hold move" : "Clear camera move");
4109
4178
  } catch (error) {
4110
- if (_chunkJAOSL334cjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refused(error.message);
4179
+ if (_chunkGHCSC2WPcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refused(error.message);
4111
4180
  throw error;
4112
4181
  }
4113
4182
  }
@@ -4115,7 +4184,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
4115
4184
  removeClipEffect(clip, instance) {
4116
4185
  const reason = this.readOnlyReason();
4117
4186
  if (reason) return this.refused(reason);
4118
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, this.project, clip);
4187
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, this.project, clip);
4119
4188
  if (!at) return this.refused(`There is no clip "${clip}".`);
4120
4189
  const stack = _nullishCoalesce(at.clip.effects, () => ( []));
4121
4190
  const was = stack.find((e) => e.id === instance);
@@ -4132,7 +4201,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
4132
4201
  return this.effectEdit(async () => {
4133
4202
  this.clipOrThrow(clip);
4134
4203
  const d = await this.describeEffect(effect, "transition");
4135
- const values = _chunkZQIWBJGHcjs.checkVideoEffectValues.call(void 0, d, options.values);
4204
+ const values = _chunkXNZFVYC2cjs.checkVideoEffectValues.call(void 0, d, options.values);
4136
4205
  const duration = _nullishCoalesce(_nullishCoalesce(options.duration, () => ( d.duration)), () => ( 1e3));
4137
4206
  return { edit: { op: "set_transition", clip, transition: { type: "effect", duration, effect: { effect: d.id, provider: this.effects.require().id, name: d.name, values } } }, label: `Transition ${d.name}`, clip };
4138
4207
  });
@@ -4145,7 +4214,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
4145
4214
  addEffectClip(track, effect, options = {}) {
4146
4215
  return this.effectEdit(async () => {
4147
4216
  const d = await this.describeEffect(effect, "generator");
4148
- const values = _chunkZQIWBJGHcjs.checkVideoEffectValues.call(void 0, d, options.values, { keyframes: true });
4217
+ const values = _chunkXNZFVYC2cjs.checkVideoEffectValues.call(void 0, d, options.values, { keyframes: true });
4149
4218
  const duration = _nullishCoalesce(_nullishCoalesce(options.duration, () => ( d.duration)), () => ( 5e3));
4150
4219
  const label = `Add ${d.name}`;
4151
4220
  const clipId = _nullishCoalesce(options.id, () => ( ""));
@@ -4167,44 +4236,119 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
4167
4236
  if (part === "generator") {
4168
4237
  if (current.type !== "effect") throw new Error(`Clip "${clip}" is not an effect clip.`);
4169
4238
  const d2 = await this.describeEffect(current.effect);
4170
- return { edit: { op: "update_clip", clip, set: { values: _chunkZQIWBJGHcjs.checkVideoEffectValues.call(void 0, d2, values, { base: _nullishCoalesce(current.values, () => ( {})), keyframes: true }) } }, label: `Change ${_nullishCoalesce(current.name, () => ( d2.name))}`, clip };
4239
+ return { edit: { op: "update_clip", clip, set: { values: _chunkXNZFVYC2cjs.checkVideoEffectValues.call(void 0, d2, values, { base: _nullishCoalesce(current.values, () => ( {})), keyframes: true }) } }, label: `Change ${_nullishCoalesce(current.name, () => ( d2.name))}`, clip };
4171
4240
  }
4172
4241
  const t = current.transition;
4173
4242
  if (_optionalChain([t, 'optionalAccess', _128 => _128.type]) !== "effect" || !t.effect) throw new Error(`Clip "${clip}" has no effect transition.`);
4174
4243
  const d = await this.describeEffect(t.effect.effect);
4175
- const merged = _chunkZQIWBJGHcjs.checkVideoEffectValues.call(void 0, d, values, { base: _nullishCoalesce(t.effect.values, () => ( {})) });
4244
+ const merged = _chunkXNZFVYC2cjs.checkVideoEffectValues.call(void 0, d, values, { base: _nullishCoalesce(t.effect.values, () => ( {})) });
4176
4245
  return { edit: { op: "set_transition", clip, transition: { ...t, effect: { ...t.effect, values: merged } } }, label: `Change transition ${d.name}`, clip };
4177
4246
  }, options.merge);
4178
4247
  }
4248
+ /**
4249
+ * Gives an effect that draws along a path (see `pathControlsOf`) its path: on an effect clip
4250
+ * (`instance` "generator") or a clip effect (its id). The path is frame points (`points`
4251
+ * `[x0, y0, …]`, mapped into the pixels of the picture the effect renders: the project frame for
4252
+ * an effect clip, the clip's own picture for a clip effect), SVG path data (`d`, which the effect
4253
+ * fits as its control says; `""` clears it), the outline of a clip's mask (`mask`), or words the
4254
+ * provider writes as a single-stroke path (`text`). `control` picks the path control when there
4255
+ * are several. Checked before anything changes; one undo step. Returns the edit, the control and
4256
+ * the value it took.
4257
+ */
4258
+ async setEffectPath(clip, instance, path, options = {}) {
4259
+ const fail2 = (error) => ({ ok: false, error });
4260
+ try {
4261
+ const current = this.clipOrThrow(clip);
4262
+ const effect = instance === "generator" ? current.type === "effect" ? current.effect : null : _optionalChain([current, 'access', _129 => _129.effects, 'optionalAccess', _130 => _130.find, 'call', _131 => _131((e) => e.id === instance), 'optionalAccess', _132 => _132.effect]);
4263
+ if (!effect) {
4264
+ const ids = ["generator"].filter(() => current.type === "effect").concat((_nullishCoalesce(current.effects, () => ( []))).map((e) => e.id));
4265
+ return fail2(`Clip "${clip}" has no effect "${instance}"; its effects are ${ids.map((i) => `"${i}"`).join(", ") || "none"} ("generator" is an effect clip's own picture).`);
4266
+ }
4267
+ const d = await this.describeEffect(effect);
4268
+ const controls = _chunkGHCSC2WPcjs.pathControlsOf.call(void 0, d);
4269
+ if (!controls.length) return fail2(`"${d.id}" does not draw along a path. Find one that does with search_effects accepts ["path"].`);
4270
+ const control = _nullishCoalesce(options.control, () => ( (controls.length === 1 ? controls[0] : void 0)));
4271
+ if (!control) return fail2(`"${d.id}" has several path controls (${controls.join(", ")}); pass control.`);
4272
+ if (!controls.includes(control)) return fail2(`"${control}" is not a path control of "${d.id}"; its path controls are ${controls.join(", ")}.`);
4273
+ const picture = videoClipPicture(this.project, current);
4274
+ let value;
4275
+ if ("points" in path) {
4276
+ const pts = path.points;
4277
+ if (!Array.isArray(pts) || pts.length < 4 || pts.length % 2 || !pts.every(Number.isFinite)) return fail2("points must be at least two points as [x0, y0, x1, y1, \u2026] in frame pixels.");
4278
+ value = framePointsToPicture(pts, picture);
4279
+ } else if ("d" in path) {
4280
+ if (typeof path.d !== "string") return fail2('d must be SVG path data (a string), or "" to clear the path.');
4281
+ value = path.d;
4282
+ } else if ("mask" in path) {
4283
+ const from = _optionalChain([_chunkXNZFVYC2cjs.findVideoClip.call(void 0, this.project, path.mask.clip), 'optionalAccess', _133 => _133.clip]);
4284
+ if (!from) return fail2(`There is no clip "${path.mask.clip}" to take a mask from.`);
4285
+ const outline = videoClipMaskOutline(this.project, from);
4286
+ if (!outline) return fail2(`Clip "${path.mask.clip}" has no mask; add one with set_video_clip_mask, or pass points or d.`);
4287
+ value = framePointsToPicture(outline, picture);
4288
+ } else if ("text" in path) {
4289
+ const provider = this.effects.require();
4290
+ if (!provider.pathFromText) return fail2(`The effects provider "${provider.id}" cannot write words as a path; pass points or d.`);
4291
+ if (typeof path.text !== "string" || !path.text.trim()) return fail2("text is empty; pass the words to write.");
4292
+ value = await provider.pathFromText(path.text, { ...path.font ? { font: path.font } : {}, ...path.align ? { align: path.align } : {} });
4293
+ } else return fail2("Pass the path as one of points, d, mask or text.");
4294
+ const r = instance === "generator" ? await this.updateEffectValues(clip, "generator", { [control]: value }) : await this.updateClipEffect(clip, instance, { values: { [control]: value } });
4295
+ return r.ok ? { ...r, control, value } : r;
4296
+ } catch (e) {
4297
+ return fail2(e instanceof Error ? e.message : String(e));
4298
+ }
4299
+ }
4300
+ __init58() {this.pathDrawing = null}
4301
+ /**
4302
+ * Starts drawing a path on the preview for an effect that draws along one (the preview then
4303
+ * takes the pointer; `finishPathDrawing` with the frame points applies it). Editor state.
4304
+ */
4305
+ startPathDrawing(target) {
4306
+ this.pathDrawing = { ...target };
4307
+ this.notify();
4308
+ }
4309
+ /** Stops drawing a path without changing anything. */
4310
+ cancelPathDrawing() {
4311
+ if (!this.pathDrawing) return;
4312
+ this.pathDrawing = null;
4313
+ this.notify();
4314
+ }
4315
+ /** Applies the drawn path (frame points) to the effect being drawn for, and stops drawing. One undo step. */
4316
+ async finishPathDrawing(points) {
4317
+ const target = this.pathDrawing;
4318
+ this.pathDrawing = null;
4319
+ this.notify();
4320
+ if (!target) return { ok: false, error: "No path is being drawn; start one from the effect's Draw path button." };
4321
+ return this.setEffectPath(target.clip, target.instance, { points }, { control: target.control });
4322
+ }
4179
4323
  /** Keys for one numeric control of a clip effect (clip-relative ms), or `null` to stop animating it (keeping its value at the clip's start). */
4180
4324
  setClipEffectKeyframes(clip, instance, control, keys) {
4181
- const current = _optionalChain([_chunkZQIWBJGHcjs.findVideoClip.call(void 0, this.project, clip), 'optionalAccess', _129 => _129.clip]);
4182
- const was = _optionalChain([current, 'optionalAccess', _130 => _130.effects, 'optionalAccess', _131 => _131.find, 'call', _132 => _132((e) => e.id === instance)]);
4183
- const value = _optionalChain([was, 'optionalAccess', _133 => _133.values, 'optionalAccess', _134 => _134[control]]);
4184
- const plain = keys === null ? _chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, value) ? _optionalChain([value, 'access', _135 => _135.keys, 'access', _136 => _136[0], 'optionalAccess', _137 => _137.v]) : value : { keys: [...keys].sort((a, b) => a.t - b.t) };
4325
+ const current = _optionalChain([_chunkXNZFVYC2cjs.findVideoClip.call(void 0, this.project, clip), 'optionalAccess', _134 => _134.clip]);
4326
+ const was = _optionalChain([current, 'optionalAccess', _135 => _135.effects, 'optionalAccess', _136 => _136.find, 'call', _137 => _137((e) => e.id === instance)]);
4327
+ const value = _optionalChain([was, 'optionalAccess', _138 => _138.values, 'optionalAccess', _139 => _139[control]]);
4328
+ const plain = keys === null ? _chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, value) ? _optionalChain([value, 'access', _140 => _140.keys, 'access', _141 => _141[0], 'optionalAccess', _142 => _142.v]) : value : { keys: [...keys].sort((a, b) => a.t - b.t) };
4185
4329
  return this.updateClipEffect(clip, instance, { values: { [control]: _nullishCoalesce(plain, () => ( null)) } });
4186
4330
  }
4187
4331
  /** What plays at `time` (default: the playhead). */
4188
4332
  frame(time = this.player.currentTime) {
4189
- return _chunkZQIWBJGHcjs.videoFrameAt.call(void 0, this.project, time);
4333
+ return _chunkXNZFVYC2cjs.videoFrameAt.call(void 0, this.project, time);
4190
4334
  }
4191
4335
  /** The frame at `time` (default: the playhead) as SVG. */
4192
4336
  toSvg(time = this.player.currentTime, options = {}) {
4193
- return _chunkZQIWBJGHcjs.videoProjectSvg.call(void 0, this.project, time, { lutFor: (src) => this.luts.peek(src), ...options });
4337
+ return _chunkXNZFVYC2cjs.videoProjectSvg.call(void 0, this.project, time, { lutFor: (src) => this.luts.peek(src), ...options });
4194
4338
  }
4195
4339
  /** The project as an ffmpeg command. */
4196
4340
  toFfmpeg(options = {}) {
4197
- return _chunkZQIWBJGHcjs.toVideoFfmpeg.call(void 0, this.project, options);
4341
+ return _chunkXNZFVYC2cjs.toVideoFfmpeg.call(void 0, this.project, options);
4198
4342
  }
4199
4343
  /** The ffmpeg command that measures the mix's loudness (see `toVideoLoudnessMeasure`). */
4200
4344
  toLoudnessMeasure(options = {}) {
4201
- return _chunkZQIWBJGHcjs.toVideoLoudnessMeasure.call(void 0, this.project, options);
4345
+ return _chunkXNZFVYC2cjs.toVideoLoudnessMeasure.call(void 0, this.project, options);
4202
4346
  }
4203
4347
  /** One track as a CMX 3600 EDL. */
4204
4348
  toEdl(options = {}) {
4205
- return _chunkZQIWBJGHcjs.toVideoEdl.call(void 0, this.project, options);
4349
+ return _chunkXNZFVYC2cjs.toVideoEdl.call(void 0, this.project, options);
4206
4350
  }
4207
- }, _class7.__initStatic(), _class7);
4351
+ }, _class8.__initStatic(), _class8);
4208
4352
  function checkPreviewScale(scale) {
4209
4353
  if (scale === "auto" || scale === "full") return scale;
4210
4354
  if (typeof scale !== "number" || !(scale > 0 && scale <= 1)) throw new Error(`A preview scale is "auto", "full" or a fraction above 0 up to 1 (0.5 is half size), not ${JSON.stringify(scale)}.`);
@@ -4236,7 +4380,7 @@ function planVideoToolPlayback(tool, args) {
4236
4380
  const clips = clipsOf(args);
4237
4381
  const track = str2(args.track) ? args.track : void 0;
4238
4382
  const newClip = args.clip && typeof args.clip === "object" ? args.clip : null;
4239
- const time = [args.start, args.at, args.time, args.to, _optionalChain([newClip, 'optionalAccess', _138 => _138.start])].find(num2);
4383
+ const time = [args.start, args.at, args.time, args.to, _optionalChain([newClip, 'optionalAccess', _143 => _143.start])].find(num2);
4240
4384
  const click = (ref) => [{ type: "target", ref }, { type: "press" }, { type: "release" }];
4241
4385
  if (clips.length === 1 && (time !== void 0 || track) && tool !== "split_video_clip") {
4242
4386
  const clip = clips[0];
@@ -4270,12 +4414,12 @@ function videoRulerTicks(duration, pxPerSecond, fps) {
4270
4414
  const ticks = [];
4271
4415
  for (let t = 0; t <= duration + 1e-6; t += step) {
4272
4416
  const isMajor = Math.abs(t / major - Math.round(t / major)) < 1e-9;
4273
- ticks.push({ time: t, x: t * pxPerMs, major: isMajor, ...isMajor ? { label: _chunkZQIWBJGHcjs.formatVideoTimecode.call(void 0, t, fps).replace(/^00:/, "") } : {} });
4417
+ ticks.push({ time: t, x: t * pxPerMs, major: isMajor, ...isMajor ? { label: _chunkXNZFVYC2cjs.formatVideoTimecode.call(void 0, t, fps).replace(/^00:/, "") } : {} });
4274
4418
  }
4275
4419
  return ticks;
4276
4420
  }
4277
4421
  function videoClipShowsWaveform(clip, asset, mode = "audio") {
4278
- if (clip.type !== "media" || mode === "none" || !_chunkZQIWBJGHcjs.videoAssetHasSound.call(void 0, asset)) return false;
4422
+ if (clip.type !== "media" || mode === "none" || !_chunkXNZFVYC2cjs.videoAssetHasSound.call(void 0, asset)) return false;
4279
4423
  return mode === "all" || asset.kind === "audio";
4280
4424
  }
4281
4425
  var VIDEO_CLIP_ANIMATION_LABELS = {
@@ -4332,15 +4476,15 @@ function videoClipLabel(clip, asset, sequence) {
4332
4476
  if (clip.name) return clip.name;
4333
4477
  if (clip.type === "text") return clip.text.split("\n")[0];
4334
4478
  if (clip.type === "color") return clip.color;
4335
- if (clip.type === "sequence") return `Compound: ${_nullishCoalesce(_optionalChain([sequence, 'optionalAccess', _139 => _139.name]), () => ( clip.sequence))}`;
4479
+ if (clip.type === "sequence") return `Compound: ${_nullishCoalesce(_optionalChain([sequence, 'optionalAccess', _144 => _144.name]), () => ( clip.sequence))}`;
4336
4480
  if (clip.type === "effect") return `Effect: ${clip.effect}`;
4337
4481
  if (clip.type === "adjustment") return `Adjustment${clip.scope === "all" ? " (all tracks)" : clip.scope === "track" ? ` (${clip.targetTrack})` : ""}`;
4338
- const base = _nullishCoalesce(_nullishCoalesce(_optionalChain([asset, 'optionalAccess', _140 => _140.name]), () => ( _optionalChain([asset, 'optionalAccess', _141 => _141.src, 'access', _142 => _142.replace, 'call', _143 => _143(/^.*[\\/]/, "")]))), () => ( clip.asset));
4339
- const speed = _chunkZQIWBJGHcjs.videoClipSpeed.call(void 0, clip);
4482
+ const base = _nullishCoalesce(_nullishCoalesce(_optionalChain([asset, 'optionalAccess', _145 => _145.name]), () => ( _optionalChain([asset, 'optionalAccess', _146 => _146.src, 'access', _147 => _147.replace, 'call', _148 => _148(/^.*[\\/]/, "")]))), () => ( clip.asset));
4483
+ const speed = _chunkXNZFVYC2cjs.videoClipSpeed.call(void 0, clip);
4340
4484
  return speed !== 1 ? `${base} (${Math.round(speed * 100)}%)` : base;
4341
4485
  }
4342
4486
  function planVideoClipDrag(project, input) {
4343
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, project, input.clip);
4487
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, project, input.clip);
4344
4488
  if (!at) return null;
4345
4489
  const { clip, track } = at;
4346
4490
  const snap = _nullishCoalesce(input.snap, () => ( ((t) => t)));
@@ -4357,17 +4501,17 @@ function planVideoClipDrag(project, input) {
4357
4501
  }
4358
4502
  const minimum = 1e3 / project.fps;
4359
4503
  if (input.mode === "trim-start") {
4360
- const to2 = Math.min(snap(Math.max(0, clip.start + input.delta)), _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip) - minimum);
4504
+ const to2 = Math.min(snap(Math.max(0, clip.start + input.delta)), _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip) - minimum);
4361
4505
  const changed2 = Math.abs(to2 - clip.start) > 1e-6;
4362
- const plan = input.ripple ? { start: clip.start, duration: clip.duration - (to2 - clip.start) } : { start: to2, duration: _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip) - to2 };
4506
+ const plan = input.ripple ? { start: clip.start, duration: clip.duration - (to2 - clip.start) } : { start: to2, duration: _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip) - to2 };
4363
4507
  return { ...plan, track: track.id, edit: changed2 ? { op: "trim_clip", clip: clip.id, edge: "start", to: to2, ...input.ripple ? { ripple: true } : {} } : null };
4364
4508
  }
4365
- const to = Math.max(snap(_chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip) + input.delta), clip.start + minimum);
4366
- const changed = Math.abs(to - _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip)) > 1e-6;
4509
+ const to = Math.max(snap(_chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip) + input.delta), clip.start + minimum);
4510
+ const changed = Math.abs(to - _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip)) > 1e-6;
4367
4511
  return { start: clip.start, duration: to - clip.start, track: track.id, edit: changed ? { op: "trim_clip", clip: clip.id, edge: "end", to, ...input.ripple ? { ripple: true } : {} } : null };
4368
4512
  }
4369
4513
  function videoDropTracks(project, clipId) {
4370
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, project, clipId);
4514
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, project, clipId);
4371
4515
  if (!at) return [];
4372
4516
  return project.tracks.filter((t) => t.kind === at.track.kind && !t.locked).map((t) => t.id);
4373
4517
  }
@@ -4376,10 +4520,10 @@ function videoDragLabel(edit) {
4376
4520
  return edit.op === "trim_clip" && edit.ripple ? "Ripple trim" : "Trim clip";
4377
4521
  }
4378
4522
  function videoAssetDropEdit(project, assetId, options = {}) {
4379
- const asset = _chunkZQIWBJGHcjs.videoAssetMap.call(void 0, project).get(assetId);
4523
+ const asset = _chunkXNZFVYC2cjs.videoAssetMap.call(void 0, project).get(assetId);
4380
4524
  if (!asset) return null;
4381
4525
  const kind = asset.kind === "audio" ? "audio" : "video";
4382
- const track = _nullishCoalesce(options.track, () => ( _optionalChain([project, 'access', _144 => _144.tracks, 'access', _145 => _145.find, 'call', _146 => _146((t) => t.kind === kind && !t.locked), 'optionalAccess', _147 => _147.id])));
4526
+ const track = _nullishCoalesce(options.track, () => ( _optionalChain([project, 'access', _149 => _149.tracks, 'access', _150 => _150.find, 'call', _151 => _151((t) => t.kind === kind && !t.locked), 'optionalAccess', _152 => _152.id])));
4383
4527
  if (!track) return null;
4384
4528
  return { op: "add_clip", track, clip: { type: "media", asset: asset.id, ...options.start !== void 0 ? { start: options.start } : {} }, ...options.ripple ? { ripple: true } : {}, ...options.mode && options.mode !== "refuse" ? { mode: options.mode } : {} };
4385
4529
  }
@@ -4428,25 +4572,25 @@ var KEY_LABELS = {
4428
4572
  scale: { label: "Scale", step: 0.05 },
4429
4573
  rotation: { label: "Rotation", step: 1 }
4430
4574
  };
4431
- var animatableOf = (clip, property) => _chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES.includes(property) ? _optionalChain([clip, 'access', _148 => _148.transform, 'optionalAccess', _149 => _149[property]]) : property === "volume" ? clip.type === "media" || clip.type === "sequence" ? clip.volume : void 0 : clip.opacity;
4575
+ var animatableOf = (clip, property) => _chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES.includes(property) ? _optionalChain([clip, 'access', _153 => _153.transform, 'optionalAccess', _154 => _154[property]]) : property === "volume" ? clip.type === "media" || clip.type === "sequence" ? clip.volume : void 0 : clip.opacity;
4432
4576
  var playheadInClip = (clip, time) => Math.round(Math.min(clip.duration, Math.max(0, time - clip.start)));
4433
4577
  function videoKeyframeRows(project, clipId, time) {
4434
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, project, clipId);
4578
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, project, clipId);
4435
4579
  if (!at) return [];
4436
4580
  const { clip } = at;
4437
- const asset = clip.type === "media" ? _chunkZQIWBJGHcjs.videoAssetMap.call(void 0, project).get(clip.asset) : void 0;
4438
- const visual = !(_optionalChain([asset, 'optionalAccess', _150 => _150.kind]) === "audio" || at.track.kind === "audio");
4439
- const audible = clip.type === "media" && _chunkZQIWBJGHcjs.videoAssetHasSound.call(void 0, asset) || clip.type === "sequence";
4440
- const properties = [...visual ? ["opacity"] : [], ...audible ? ["volume"] : [], ...visual ? _chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES : []];
4581
+ const asset = clip.type === "media" ? _chunkXNZFVYC2cjs.videoAssetMap.call(void 0, project).get(clip.asset) : void 0;
4582
+ const visual = !(_optionalChain([asset, 'optionalAccess', _155 => _155.kind]) === "audio" || at.track.kind === "audio");
4583
+ const audible = clip.type === "media" && _chunkXNZFVYC2cjs.videoAssetHasSound.call(void 0, asset) || clip.type === "sequence";
4584
+ const properties = [...visual ? ["opacity"] : [], ...audible ? ["volume"] : [], ...visual ? _chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES : []];
4441
4585
  const clipTime = playheadInClip(clip, time);
4442
4586
  return properties.map((property) => {
4443
4587
  const prop = animatableOf(clip, property);
4444
- const keys = _chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, prop) ? prop.keys : [];
4445
- const limits = _chunkZQIWBJGHcjs.VIDEO_KEYFRAME_LIMITS[property];
4588
+ const keys = _chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, prop) ? prop.keys : [];
4589
+ const limits = _chunkXNZFVYC2cjs.VIDEO_KEYFRAME_LIMITS[property];
4446
4590
  return {
4447
4591
  property,
4448
4592
  ...KEY_LABELS[property],
4449
- value: Math.round(_chunkZQIWBJGHcjs.videoValueAt.call(void 0, prop, clipTime, limits.default) * 1e3) / 1e3,
4593
+ value: Math.round(_chunkXNZFVYC2cjs.videoValueAt.call(void 0, prop, clipTime, limits.default) * 1e3) / 1e3,
4450
4594
  keyed: keys.length > 0,
4451
4595
  keys: keys.length,
4452
4596
  onKey: keys.some((k) => Math.abs(k.t - clipTime) < 0.5),
@@ -4457,44 +4601,44 @@ function videoKeyframeRows(project, clipId, time) {
4457
4601
  });
4458
4602
  }
4459
4603
  function plainValueEdit(clip, property, value) {
4460
- if (!_chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES.includes(property))
4604
+ if (!_chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES.includes(property))
4461
4605
  return value === void 0 ? { op: "update_clip", clip: clip.id, remove: [property] } : { op: "update_clip", clip: clip.id, set: { [property]: value } };
4462
4606
  const transform = { ...clip.transform, [property]: value };
4463
4607
  if (value === void 0) delete transform[property];
4464
4608
  return Object.keys(transform).length ? { op: "update_clip", clip: clip.id, set: { transform } } : { op: "update_clip", clip: clip.id, remove: ["transform"] };
4465
4609
  }
4466
4610
  function videoKeyframeValueEdit(project, clipId, property, time, value) {
4467
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, project, clipId);
4611
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, project, clipId);
4468
4612
  if (!at) return null;
4469
4613
  const prop = animatableOf(at.clip, property);
4470
- if (!_chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, prop)) return plainValueEdit(at.clip, property, value);
4614
+ if (!_chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, prop)) return plainValueEdit(at.clip, property, value);
4471
4615
  if (value === void 0) return null;
4472
- return { op: "set_keyframes", clip: clipId, property, keys: _chunkZQIWBJGHcjs.setVideoKey.call(void 0, prop, { t: playheadInClip(at.clip, time), v: value }, _chunkZQIWBJGHcjs.VIDEO_KEYFRAME_LIMITS[property].default).keys };
4616
+ return { op: "set_keyframes", clip: clipId, property, keys: _chunkXNZFVYC2cjs.setVideoKey.call(void 0, prop, { t: playheadInClip(at.clip, time), v: value }, _chunkXNZFVYC2cjs.VIDEO_KEYFRAME_LIMITS[property].default).keys };
4473
4617
  }
4474
4618
  function videoKeyframeToggleEdit(project, clipId, property, time) {
4475
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, project, clipId);
4619
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, project, clipId);
4476
4620
  if (!at) return null;
4477
4621
  const prop = animatableOf(at.clip, property);
4478
4622
  const t = playheadInClip(at.clip, time);
4479
- const fallback = _chunkZQIWBJGHcjs.VIDEO_KEYFRAME_LIMITS[property].default;
4480
- if (_chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, prop)) {
4623
+ const fallback = _chunkXNZFVYC2cjs.VIDEO_KEYFRAME_LIMITS[property].default;
4624
+ if (_chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, prop)) {
4481
4625
  const key = prop.keys.find((k) => Math.abs(k.t - t) < 0.5);
4482
4626
  if (key) {
4483
- const rest = _chunkZQIWBJGHcjs.removeVideoKey.call(void 0, prop, key.t);
4484
- return _chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, rest) ? { op: "set_keyframes", clip: clipId, property, keys: rest.keys } : plainValueEdit(at.clip, property, rest === fallback ? void 0 : rest);
4627
+ const rest = _chunkXNZFVYC2cjs.removeVideoKey.call(void 0, prop, key.t);
4628
+ return _chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, rest) ? { op: "set_keyframes", clip: clipId, property, keys: rest.keys } : plainValueEdit(at.clip, property, rest === fallback ? void 0 : rest);
4485
4629
  }
4486
4630
  }
4487
- const v = _chunkZQIWBJGHcjs.videoValueAt.call(void 0, prop, t, fallback);
4488
- return { op: "set_keyframes", clip: clipId, property, keys: _chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, prop) ? _chunkZQIWBJGHcjs.setVideoKey.call(void 0, prop, { t, v }, fallback).keys : [{ t, v }] };
4631
+ const v = _chunkXNZFVYC2cjs.videoValueAt.call(void 0, prop, t, fallback);
4632
+ return { op: "set_keyframes", clip: clipId, property, keys: _chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, prop) ? _chunkXNZFVYC2cjs.setVideoKey.call(void 0, prop, { t, v }, fallback).keys : [{ t, v }] };
4489
4633
  }
4490
4634
  function videoLutEdits(project, clips, lut) {
4491
4635
  const edits = [];
4492
4636
  for (const id of clips) {
4493
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, project, id);
4637
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, project, id);
4494
4638
  if (!at) continue;
4495
4639
  const { lut: current, ...rest } = _nullishCoalesce(at.clip.grade, () => ( {}));
4496
4640
  if (!lut && !current) continue;
4497
- const grade = _chunkZQIWBJGHcjs.normalizeVideoGrade.call(void 0, lut ? { ...rest, lut } : rest);
4641
+ const grade = _chunkXNZFVYC2cjs.normalizeVideoGrade.call(void 0, lut ? { ...rest, lut } : rest);
4498
4642
  edits.push(grade ? { op: "update_clip", clip: id, set: { grade } } : { op: "update_clip", clip: id, remove: ["grade"] });
4499
4643
  }
4500
4644
  return edits;
@@ -4515,9 +4659,9 @@ function videoAddAdjustmentEdits(project, time, options = {}) {
4515
4659
  const duration = _nullishCoalesce(options.duration, () => ( 3e3));
4516
4660
  const start = Math.max(0, time);
4517
4661
  const top = project.tracks[0];
4518
- const free = top && top.kind === "video" && !top.locked && !top.clips.some((c) => c.start < start + duration && _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c) > start);
4662
+ const free = top && top.kind === "video" && !top.locked && !top.clips.some((c) => c.start < start + duration && _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c) > start);
4519
4663
  const edits = [];
4520
- let track = _optionalChain([top, 'optionalAccess', _151 => _151.id]);
4664
+ let track = _optionalChain([top, 'optionalAccess', _156 => _156.id]);
4521
4665
  if (!free) {
4522
4666
  const ids = new Set(project.tracks.map((t) => t.id));
4523
4667
  let n = 1;
@@ -4534,8 +4678,8 @@ function videoMaskEdit(clip, mask) {
4534
4678
  function videoSkinProtectionEdits(project, clips, amount) {
4535
4679
  const edits = [];
4536
4680
  for (const id of clips) {
4537
- const clip = _optionalChain([_chunkZQIWBJGHcjs.findVideoClip.call(void 0, project, id), 'optionalAccess', _152 => _152.clip]);
4538
- const lut = _optionalChain([clip, 'optionalAccess', _153 => _153.grade, 'optionalAccess', _154 => _154.lut]);
4681
+ const clip = _optionalChain([_chunkXNZFVYC2cjs.findVideoClip.call(void 0, project, id), 'optionalAccess', _157 => _157.clip]);
4682
+ const lut = _optionalChain([clip, 'optionalAccess', _158 => _158.grade, 'optionalAccess', _159 => _159.lut]);
4539
4683
  if (!clip || !lut) continue;
4540
4684
  const { preserveSkinTones: _p, ...rest } = lut;
4541
4685
  const k = Math.min(1, Math.max(0, amount));
@@ -4568,7 +4712,7 @@ var RIPPLE = {
4568
4712
  };
4569
4713
  var MODE = {
4570
4714
  type: "string",
4571
- enum: [..._chunkZQIWBJGHcjs.VIDEO_PLACEMENT_MODES],
4715
+ enum: [..._chunkXNZFVYC2cjs.VIDEO_PLACEMENT_MODES],
4572
4716
  description: 'What to do with clips already where it lands: "refuse" (default) fails with the next free place; "overwrite" cuts, trims or removes what is underneath on that track; "insert" cuts everything across the start and pushes later material along by its length on this track and every sync-locked track.'
4573
4717
  };
4574
4718
  var DELTA = (what) => ({ type: "number", description: `${what}, in milliseconds of timeline time: positive is later, negative earlier. It is clamped to what the media and neighbours allow; the result says how far it went.` });
@@ -4585,11 +4729,11 @@ var TRANSFORM = object(
4585
4729
  );
4586
4730
  var TRANSITION = object(
4587
4731
  {
4588
- type: { type: "string", enum: _chunkZQIWBJGHcjs.VIDEO_TRANSITION_TYPES.filter((t) => t !== "effect"), description: "crossfade (this clip fades up over the one before), dip (down into a colour and up out of it), wipe (an edge travels across revealing this clip), push (this clip slides in and pushes the one before out), slide (this clip slides in over the one before) or iris (a circle opens from the centre). For a transition effect from the effects provider use set_video_effect_transition." },
4732
+ type: { type: "string", enum: _chunkXNZFVYC2cjs.VIDEO_TRANSITION_TYPES.filter((t) => t !== "effect"), description: "crossfade (this clip fades up over the one before), dip (down into a colour and up out of it), wipe (an edge travels across revealing this clip), push (this clip slides in and pushes the one before out), slide (this clip slides in over the one before) or iris (a circle opens from the centre). For a transition effect from the effects provider use set_video_effect_transition." },
4589
4733
  duration: { type: "number", exclusiveMinimum: 0, description: "Length in ms, centred on the cut. Every type but dip needs half of it in media past the cut on both sides (handles); a dip needs none." },
4590
4734
  color: COLOR("For dip: the colour passed through (default black)"),
4591
- direction: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_WIPE_DIRECTIONS], description: "For wipe, push and slide: the way the edge or picture travels (default right, coming in from the left)." },
4592
- audioCurve: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_FADE_CURVES], description: "Shape of the sound's fades through it: default equal-power for every type but dip (steady loudness while the two sounds overlap), linear for dip; or s-curve, exponential, logarithmic." }
4735
+ direction: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_WIPE_DIRECTIONS], description: "For wipe, push and slide: the way the edge or picture travels (default right, coming in from the left)." },
4736
+ audioCurve: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_FADE_CURVES], description: "Shape of the sound's fades through it: default equal-power for every type but dip (steady loudness while the two sounds overlap), linear for dip; or s-curve, exponential, logarithmic." }
4593
4737
  },
4594
4738
  ["type", "duration"],
4595
4739
  "A transition from the clip that ends where this one starts on the same track."
@@ -4599,7 +4743,7 @@ var LUT_STRENGTH = { type: "number", minimum: 0, maximum: 1, description: "How m
4599
4743
  var SKIN = { type: "number", minimum: 0, maximum: 1, description: "How much of the LUT's change to hold back on skin tones, 0 (none, the default) to 1 (skin keeps its colour); 0.5-0.8 keeps faces natural under a heavy look. Applied in the preview and frame renders; ffmpeg's lut3d cannot, so the export notes it." };
4600
4744
  var GRADE = object(
4601
4745
  {
4602
- ...Object.fromEntries(_chunkZQIWBJGHcjs.VIDEO_GRADE_CONTROLS.map((c) => [c.key, { type: "number", minimum: c.min, maximum: c.max, description: c.description }])),
4746
+ ...Object.fromEntries(_chunkXNZFVYC2cjs.VIDEO_GRADE_CONTROLS.map((c) => [c.key, { type: "number", minimum: c.min, maximum: c.max, description: c.description }])),
4603
4747
  lut: object({ src: LUT_SRC, strength: LUT_STRENGTH, name: { type: "string", minLength: 1, description: "A label for the look." }, preserveSkinTones: SKIN }, ["src"], "A 3D LUT applied after the other settings (set_video_lut checks the file first).")
4604
4748
  },
4605
4749
  [],
@@ -4607,7 +4751,7 @@ var GRADE = object(
4607
4751
  );
4608
4752
  var ANIMATION = (when) => object(
4609
4753
  {
4610
- effect: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_CLIP_ANIMATION_EFFECTS], description: "fade; rise (up into place) or drop (down into place); slide-left / slide-right (moving that way); zoom (grows into place); pop (grows past its size and settles). Each also fades; an exit plays the movement backwards." },
4754
+ effect: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_CLIP_ANIMATION_EFFECTS], description: "fade; rise (up into place) or drop (down into place); slide-left / slide-right (moving that way); zoom (grows into place); pop (grows past its size and settles). Each also fades; an exit plays the movement backwards." },
4611
4755
  duration: { type: "number", exclusiveMinimum: 0, description: "Length in ms (default 500)." }
4612
4756
  },
4613
4757
  ["effect"],
@@ -4617,11 +4761,11 @@ var CLIP_COMMON = {
4617
4761
  name: { type: "string", description: "A label for the clip." },
4618
4762
  opacity: { type: "number", minimum: 0, maximum: 1, description: "Opacity 0\u20131 (default 1). A number replaces any keyframes; set_video_keyframes animates it." },
4619
4763
  transform: TRANSFORM,
4620
- fit: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_FITS], description: "How the picture fits the frame before the transform, as CSS object-fit (default contain for media, fill for colours)." },
4764
+ fit: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_FITS], description: "How the picture fits the frame before the transform, as CSS object-fit (default contain for media, fill for colours)." },
4621
4765
  grade: GRADE,
4622
4766
  animateIn: ANIMATION("How the picture enters, from the clip's start (on top of any fade in). Titles usually rise, pop or fade in."),
4623
4767
  animateOut: ANIMATION("How the picture leaves, ending at the clip's end."),
4624
- blend: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_BLEND_MODES], description: "How the picture mixes with what is beneath it, as CSS mix-blend-mode (default normal): multiply darkens (shadows, textures), screen and add lighten (light leaks, flares, glows), overlay and soft-light add contrast, difference and exclusion invert." },
4768
+ blend: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_BLEND_MODES], description: "How the picture mixes with what is beneath it, as CSS mix-blend-mode (default normal): multiply darkens (shadows, textures), screen and add lighten (light leaks, flares, glows), overlay and soft-light add contrast, difference and exclusion invert." },
4625
4769
  fadeIn: MS("Fade up from nothing (picture and sound) over this long"),
4626
4770
  fadeOut: MS("Fade down to nothing over this long")
4627
4771
  };
@@ -4630,8 +4774,8 @@ var MEDIA_FIELDS = {
4630
4774
  speed: { type: "number", minimum: 0.05, maximum: 20, description: "Playback speed (default 1). Changing it keeps the stretch of source, so the clip gets shorter or longer." },
4631
4775
  volume: { type: "number", minimum: 0, maximum: 4, description: "Gain (1 = unchanged, default 1). A number replaces any keyframes; set_video_keyframes animates it." },
4632
4776
  muted: { type: "boolean", description: "Silence this clip (default false)." },
4633
- fadeInCurve: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_FADE_CURVES], description: "Shape of the sound's fade in (default linear; the picture always fades linearly): linear, equal-power (steady loudness, best for crossfades), s-curve (gentle at both ends), exponential (slow start, natural from silence) or logarithmic (fast start)." },
4634
- fadeOutCurve: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_FADE_CURVES], description: "Shape of the sound's fade out (default linear), the same choices as fadeInCurve; exponential sounds natural fading to silence." }
4777
+ fadeInCurve: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_FADE_CURVES], description: "Shape of the sound's fade in (default linear; the picture always fades linearly): linear, equal-power (steady loudness, best for crossfades), s-curve (gentle at both ends), exponential (slow start, natural from silence) or logarithmic (fast start)." },
4778
+ fadeOutCurve: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_FADE_CURVES], description: "Shape of the sound's fade out (default linear), the same choices as fadeInCurve; exponential sounds natural fading to silence." }
4635
4779
  };
4636
4780
  var TEXT_FIELDS = {
4637
4781
  text: { type: "string", minLength: 1, description: `The title's text ("\\n" breaks lines).` },
@@ -4680,7 +4824,7 @@ var ASSET_FIELDS = {
4680
4824
  };
4681
4825
  var KEY_PROPERTY = {
4682
4826
  type: "string",
4683
- enum: [..._chunkZQIWBJGHcjs.VIDEO_KEYFRAME_PROPERTIES],
4827
+ enum: [..._chunkXNZFVYC2cjs.VIDEO_KEYFRAME_PROPERTIES],
4684
4828
  description: "Which property: opacity (0\u20131), volume (media only, 0\u20134 gain), x / y (pixels from the frame's centre, right / down), scale (1 = fitted size) or rotation (degrees clockwise)."
4685
4829
  };
4686
4830
  var KEYS = {
@@ -4695,7 +4839,7 @@ var KEYS = {
4695
4839
  ease: {
4696
4840
  description: "How the value moves from this key to the next (default linear): linear, hold (stays, then jumps at the next key), ease-in, ease-out, ease-in-out, or CSS cubic-bezier points [x1, y1, x2, y2] with x1 and x2 in 0\u20131.",
4697
4841
  anyOf: [
4698
- { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_EASE_NAMES] },
4842
+ { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_EASE_NAMES] },
4699
4843
  { type: "array", items: { type: "number" }, minItems: 4, maxItems: 4 }
4700
4844
  ]
4701
4845
  }
@@ -4724,19 +4868,19 @@ var describeVideoTracks = (tracks) => tracks.map((t, index) => ({
4724
4868
  ...t.locked ? { locked: true } : {},
4725
4869
  ...t.syncLocked === false ? { syncLocked: false } : {},
4726
4870
  ...t.volume !== void 0 ? { volume: t.volume } : {},
4727
- clips: _chunkZQIWBJGHcjs.sortedVideoClips.call(void 0, t).map((c) => ({ ...c, end: _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c), ...c.type === "media" || c.type === "sequence" ? { source: _chunkZQIWBJGHcjs.videoClipSourceRange.call(void 0, c) } : {} }))
4871
+ clips: _chunkXNZFVYC2cjs.sortedVideoClips.call(void 0, t).map((c) => ({ ...c, end: _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c), ...c.type === "media" || c.type === "sequence" ? { source: _chunkXNZFVYC2cjs.videoClipSourceRange.call(void 0, c) } : {} }))
4728
4872
  }));
4729
- var videoSequenceUsers = (project, id) => _chunkZQIWBJGHcjs.allVideoTracks.call(void 0, project).flatMap(
4730
- ({ sequence, track }) => track.clips.flatMap((c) => c.type === "sequence" && c.sequence === id ? [{ clip: c.id, ...sequence ? { inSequence: sequence } : {}, track: track.id, start: c.start, end: _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c), source: _chunkZQIWBJGHcjs.videoClipSourceRange.call(void 0, c) }] : [])
4873
+ var videoSequenceUsers = (project, id) => _chunkXNZFVYC2cjs.allVideoTracks.call(void 0, project).flatMap(
4874
+ ({ sequence, track }) => track.clips.flatMap((c) => c.type === "sequence" && c.sequence === id ? [{ clip: c.id, ...sequence ? { inSequence: sequence } : {}, track: track.id, start: c.start, end: _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c), source: _chunkXNZFVYC2cjs.videoClipSourceRange.call(void 0, c) }] : [])
4731
4875
  );
4732
4876
  function describeVideoSequence(project, sequence, tracks = true) {
4733
- const cycle = _chunkZQIWBJGHcjs.findVideoSequenceCycle.call(void 0, project, sequence.id);
4877
+ const cycle = _chunkXNZFVYC2cjs.findVideoSequenceCycle.call(void 0, project, sequence.id);
4734
4878
  return {
4735
4879
  id: sequence.id,
4736
4880
  ...sequence.name ? { name: sequence.name } : {},
4737
- duration: _chunkZQIWBJGHcjs.videoSequenceDuration.call(void 0, sequence),
4881
+ duration: _chunkXNZFVYC2cjs.videoSequenceDuration.call(void 0, sequence),
4738
4882
  clipCount: sequence.tracks.reduce((n, t) => n + t.clips.length, 0),
4739
- nests: _chunkZQIWBJGHcjs.videoSequenceChildren.call(void 0, sequence),
4883
+ nests: _chunkXNZFVYC2cjs.videoSequenceChildren.call(void 0, sequence),
4740
4884
  usedBy: videoSequenceUsers(project, sequence.id),
4741
4885
  ...cycle ? { cycle } : {},
4742
4886
  ...tracks ? { tracks: describeVideoTracks(sequence.tracks) } : { trackCount: sequence.tracks.length }
@@ -4748,11 +4892,11 @@ function describeVideoProject(project) {
4748
4892
  width: project.width,
4749
4893
  height: project.height,
4750
4894
  fps: project.fps,
4751
- duration: _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, project),
4895
+ duration: _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, project),
4752
4896
  ...project.background ? { background: project.background } : {},
4753
4897
  assets: project.assets.map(videoAssetOut),
4754
4898
  tracks: describeVideoTracks(project.tracks),
4755
- ..._optionalChain([project, 'access', _155 => _155.sequences, 'optionalAccess', _156 => _156.length]) ? { sequences: project.sequences.map((q) => describeVideoSequence(project, q, false)) } : {},
4899
+ ..._optionalChain([project, 'access', _160 => _160.sequences, 'optionalAccess', _161 => _161.length]) ? { sequences: project.sequences.map((q) => describeVideoSequence(project, q, false)) } : {},
4756
4900
  markers: _nullishCoalesce(project.markers, () => ( []))
4757
4901
  };
4758
4902
  }
@@ -4765,7 +4909,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
4765
4909
  const project = () => controller.getProject();
4766
4910
  const outcome = (result, extra = {}) => {
4767
4911
  if (!result.ok) throw new Error(result.error);
4768
- return { ...extra, duration: _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, result.project), issues: issueSummary(result.issues) };
4912
+ return { ...extra, duration: _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, result.project), issues: issueSummary(result.issues) };
4769
4913
  };
4770
4914
  const apply = (edits, label, extra) => {
4771
4915
  const result = controller.apply(edits, label);
@@ -4774,19 +4918,19 @@ function createVideoEditorToolProvider(controller, options = {}) {
4774
4918
  const clipOut = (p, id) => {
4775
4919
  for (const t of p.tracks) {
4776
4920
  const c = t.clips.find((x) => x.id === id);
4777
- if (c) return { track: t.id, ...c, end: _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c), ...c.type === "media" || c.type === "sequence" ? { source: _chunkZQIWBJGHcjs.videoClipSourceRange.call(void 0, c) } : {} };
4921
+ if (c) return { track: t.id, ...c, end: _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c), ...c.type === "media" || c.type === "sequence" ? { source: _chunkXNZFVYC2cjs.videoClipSourceRange.call(void 0, c) } : {} };
4778
4922
  }
4779
4923
  return null;
4780
4924
  };
4781
4925
  const placed = (o) => ({
4782
- ..._optionalChain([o, 'access', _157 => _157.created, 'optionalAccess', _158 => _158.length]) ? { created: o.created } : {},
4783
- ..._optionalChain([o, 'access', _159 => _159.trimmed, 'optionalAccess', _160 => _160.length]) ? { trimmed: o.trimmed } : {},
4784
- ..._optionalChain([o, 'access', _161 => _161.removed, 'optionalAccess', _162 => _162.length]) ? { removed: o.removed } : {},
4926
+ ..._optionalChain([o, 'access', _162 => _162.created, 'optionalAccess', _163 => _163.length]) ? { created: o.created } : {},
4927
+ ..._optionalChain([o, 'access', _164 => _164.trimmed, 'optionalAccess', _165 => _165.length]) ? { trimmed: o.trimmed } : {},
4928
+ ..._optionalChain([o, 'access', _166 => _166.removed, 'optionalAccess', _167 => _167.length]) ? { removed: o.removed } : {},
4785
4929
  ...o.rippled ? { rippled: o.rippled } : {}
4786
4930
  });
4787
4931
  const keysOut = (p, clip, property) => {
4788
4932
  const c = clipOut(p, clip);
4789
- const value = _chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES.includes(property) ? _optionalChain([c, 'optionalAccess', _163 => _163.transform, 'optionalAccess', _164 => _164[property]]) : _optionalChain([c, 'optionalAccess', _165 => _165[property]]);
4933
+ const value = _chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES.includes(property) ? _optionalChain([c, 'optionalAccess', _168 => _168.transform, 'optionalAccess', _169 => _169[property]]) : _optionalChain([c, 'optionalAccess', _170 => _170[property]]);
4790
4934
  return typeof value === "object" ? { keys: value.keys } : { keys: [], value: _nullishCoalesce(value, () => ( null)) };
4791
4935
  };
4792
4936
  const getProject = {
@@ -4808,8 +4952,8 @@ function createVideoEditorToolProvider(controller, options = {}) {
4808
4952
  inputSchema: object({ time: MS("Time from the start (default: the playhead)") }),
4809
4953
  annotations: { title: "What plays at a moment", ...READ },
4810
4954
  handler: ({ time }) => {
4811
- const frame = _chunkZQIWBJGHcjs.videoFrameAt.call(void 0, project(), _nullishCoalesce(time, () => ( controller.getState().time)));
4812
- return { ...frame, timecode: _chunkZQIWBJGHcjs.formatVideoTimecode.call(void 0, frame.time, project().fps) };
4955
+ const frame = _chunkXNZFVYC2cjs.videoFrameAt.call(void 0, project(), _nullishCoalesce(time, () => ( controller.getState().time)));
4956
+ return { ...frame, timecode: _chunkXNZFVYC2cjs.formatVideoTimecode.call(void 0, frame.time, project().fps) };
4813
4957
  }
4814
4958
  };
4815
4959
  const listSequences = {
@@ -4837,7 +4981,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
4837
4981
  annotations: { title: "Find gaps", ...READ },
4838
4982
  handler: ({ track }) => {
4839
4983
  if (track !== void 0 && !project().tracks.some((t) => t.id === track)) throw new Error(`There is no track "${track}"; the tracks are ${project().tracks.map((t) => `"${t.id}"`).join(", ")}.`);
4840
- return { gaps: _chunkZQIWBJGHcjs.findVideoGaps.call(void 0, project(), track) };
4984
+ return { gaps: _chunkXNZFVYC2cjs.findVideoGaps.call(void 0, project(), track) };
4841
4985
  }
4842
4986
  };
4843
4987
  const checkProject = {
@@ -4864,10 +5008,10 @@ function createVideoEditorToolProvider(controller, options = {}) {
4864
5008
  annotations: { title: "Render a frame", ...READ },
4865
5009
  handler: async ({ time, times, columns, format = "svg" }) => {
4866
5010
  const p = project();
4867
- const lutSrcs = [...new Set(p.tracks.flatMap((t) => t.clips.map((c) => _optionalChain([c, 'access', _166 => _166.grade, 'optionalAccess', _167 => _167.lut, 'optionalAccess', _168 => _168.src])).filter((x) => !!x)))];
5011
+ const lutSrcs = [...new Set(p.tracks.flatMap((t) => t.clips.map((c) => _optionalChain([c, 'access', _171 => _171.grade, 'optionalAccess', _172 => _172.lut, 'optionalAccess', _173 => _173.src])).filter((x) => !!x)))];
4868
5012
  const missing = (await Promise.all(lutSrcs.map((src) => controller.luts.load(src).then(() => null, (e) => e.message)))).filter((m) => !!m);
4869
5013
  const svgOptions = { lutFor: (src) => controller.luts.peek(src), ...columns ? { columns } : {} };
4870
- const svg = times ? _chunkZQIWBJGHcjs.videoContactSheetSvg.call(void 0, p, times, svgOptions) : _chunkZQIWBJGHcjs.videoProjectSvg.call(void 0, p, _nullishCoalesce(time, () => ( controller.getState().time)), svgOptions);
5014
+ const svg = times ? _chunkXNZFVYC2cjs.videoContactSheetSvg.call(void 0, p, times, svgOptions) : _chunkXNZFVYC2cjs.videoProjectSvg.call(void 0, p, _nullishCoalesce(time, () => ( controller.getState().time)), svgOptions);
4871
5015
  const notes = [...missing.map((m) => `${m}; that LUT is left out of the picture.`), ...lutSrcs.length > missing.length ? ["LUTs are drawn approximately in SVG (curves and a colour matrix); the preview and export apply them exactly."] : []];
4872
5016
  if (format === "png") {
4873
5017
  if (!options.rasterize) throw new Error('This host cannot make PNG images; call render_video_frame with format "svg".');
@@ -4957,7 +5101,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
4957
5101
  if (play === true) controller.play();
4958
5102
  if (play === false) controller.pause();
4959
5103
  const state = controller.getState();
4960
- return { time: state.time, timecode: _chunkZQIWBJGHcjs.formatVideoTimecode.call(void 0, state.time, p.fps), playing: state.playing, clips: state.current };
5104
+ return { time: state.time, timecode: _chunkXNZFVYC2cjs.formatVideoTimecode.call(void 0, state.time, p.fps), playing: state.playing, clips: state.current };
4961
5105
  }
4962
5106
  };
4963
5107
  const setSettings = {
@@ -5083,7 +5227,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
5083
5227
  inputSchema: object(
5084
5228
  {
5085
5229
  clip: CLIP_ID,
5086
- set: object({ ...CLIP_COMMON, ...MEDIA_FIELDS, asset: { ...ASSET_ID, description: "For media: play another asset (same in point)." }, ...TEXT_FIELDS, color: COLOR("Text colour, or a colour clip's fill"), scope: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_ADJUSTMENT_SCOPES], description: "For adjustment clips: which pictures it changes, underneath (default), all or track." }, targetTrack: { ...TRACK_ID, description: 'For adjustment clips with scope "track": the track whose pictures it changes.' } }, [], "Fields to replace (only those that fit the clip's type)."),
5230
+ set: object({ ...CLIP_COMMON, ...MEDIA_FIELDS, asset: { ...ASSET_ID, description: "For media: play another asset (same in point)." }, ...TEXT_FIELDS, color: COLOR("Text colour, or a colour clip's fill"), scope: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_ADJUSTMENT_SCOPES], description: "For adjustment clips: which pictures it changes, underneath (default), all or track." }, targetTrack: { ...TRACK_ID, description: 'For adjustment clips with scope "track": the track whose pictures it changes.' } }, [], "Fields to replace (only those that fit the clip's type)."),
5087
5231
  remove: { type: "array", items: { type: "string", enum: ["name", "opacity", "transform", "fit", "blend", "grade", "animateIn", "animateOut", "fadeIn", "fadeOut", "fadeInCurve", "fadeOutCurve", "in", "speed", "volume", "muted", "fontSize", "fontFamily", "fontWeight", "background", "scope", "targetTrack"] }, description: 'Fields to reset to their defaults (an adjustment clip going from scope "track" to another scope must also remove targetTrack).' }
5088
5232
  },
5089
5233
  ["clip"]
@@ -5102,10 +5246,10 @@ function createVideoEditorToolProvider(controller, options = {}) {
5102
5246
  const gradeTargets = (ids) => {
5103
5247
  const p = project();
5104
5248
  for (const id of ids) {
5105
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, p, id);
5249
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, p, id);
5106
5250
  if (!at) throw new Error(`There is no clip "${id}"; get_video_project lists the clips.`);
5107
5251
  const { clip } = at;
5108
- if (at.track.kind !== "video" || clip.type === "media" && _optionalChain([p, 'access', _169 => _169.assets, 'access', _170 => _170.find, 'call', _171 => _171((a) => a.id === clip.asset), 'optionalAccess', _172 => _172.kind]) === "audio")
5252
+ if (at.track.kind !== "video" || clip.type === "media" && _optionalChain([p, 'access', _174 => _174.assets, 'access', _175 => _175.find, 'call', _176 => _176((a) => a.id === clip.asset), 'optionalAccess', _177 => _177.kind]) === "audio")
5109
5253
  throw new Error(`Clip "${id}" is sound only; grades change pictures. Pass clips on video tracks.`);
5110
5254
  }
5111
5255
  };
@@ -5116,7 +5260,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
5116
5260
  inputSchema: object(
5117
5261
  {
5118
5262
  clips: { type: "array", items: CLIP_ID, minItems: 1, description: "Clips on video tracks to grade." },
5119
- preset: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_GRADE_PRESET_NAMES], description: "The look." },
5263
+ preset: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_GRADE_PRESET_NAMES], description: "The look." },
5120
5264
  amount: { type: "number", minimum: 0, maximum: 1, description: "Strength, 0 (none) to 1 (full, the default); 0.5 is a subtler version." }
5121
5265
  },
5122
5266
  ["clips", "preset"]
@@ -5125,10 +5269,10 @@ function createVideoEditorToolProvider(controller, options = {}) {
5125
5269
  handler: ({ clips, preset, amount }) => {
5126
5270
  gradeTargets(clips);
5127
5271
  const edits = clips.map((clip) => {
5128
- const grade = _chunkZQIWBJGHcjs.videoGradeLook.call(void 0, _chunkZQIWBJGHcjs.findVideoClip.call(void 0, project(), clip).clip.grade, preset, _nullishCoalesce(amount, () => ( 1)));
5272
+ const grade = _chunkXNZFVYC2cjs.videoGradeLook.call(void 0, _chunkXNZFVYC2cjs.findVideoClip.call(void 0, project(), clip).clip.grade, preset, _nullishCoalesce(amount, () => ( 1)));
5129
5273
  return grade ? { op: "update_clip", clip, set: { grade } } : { op: "update_clip", clip, remove: ["grade"] };
5130
5274
  });
5131
- return apply(edits, `Apply ${preset} look`, (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([_chunkZQIWBJGHcjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _173 => _173.clip, 'access', _174 => _174.grade]), () => ( null)) })) }));
5275
+ return apply(edits, `Apply ${preset} look`, (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([_chunkXNZFVYC2cjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _178 => _178.clip, 'access', _179 => _179.grade]), () => ( null)) })) }));
5132
5276
  }
5133
5277
  };
5134
5278
  const copyGrade = {
@@ -5139,7 +5283,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
5139
5283
  annotations: { title: "Copy a colour grade", ...WRITE_IDEMPOTENT },
5140
5284
  handler: ({ from, to }) => {
5141
5285
  gradeTargets([from, ...to]);
5142
- const grade = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, project(), from).clip.grade;
5286
+ const grade = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, project(), from).clip.grade;
5143
5287
  const edits = to.map((clip) => grade ? { op: "update_clip", clip, set: { grade: { ...grade } } } : { op: "update_clip", clip, remove: ["grade"] });
5144
5288
  return apply(edits, "Copy grade", () => ({ grade: _nullishCoalesce(grade, () => ( null)), clips: to }));
5145
5289
  }
@@ -5165,7 +5309,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
5165
5309
  const lut = await controller.luts.load(src);
5166
5310
  const label = _nullishCoalesce(name, () => ( lut.title));
5167
5311
  const setting = { src, ...strength !== void 0 && strength !== 1 ? { strength } : {}, ...label ? { name: label } : {}, ...preserve_skin_tones ? { preserveSkinTones: preserve_skin_tones } : {} };
5168
- return apply(videoLutEdits(project(), clips, setting), "Apply LUT", (r) => ({ lut: { src, ...lut.title ? { title: lut.title } : {}, size: lut.size }, clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([_chunkZQIWBJGHcjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _175 => _175.clip, 'access', _176 => _176.grade]), () => ( null)) })) }));
5312
+ return apply(videoLutEdits(project(), clips, setting), "Apply LUT", (r) => ({ lut: { src, ...lut.title ? { title: lut.title } : {}, size: lut.size }, clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([_chunkXNZFVYC2cjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _180 => _180.clip, 'access', _181 => _181.grade]), () => ( null)) })) }));
5169
5313
  }
5170
5314
  };
5171
5315
  const removeLut = {
@@ -5177,9 +5321,9 @@ function createVideoEditorToolProvider(controller, options = {}) {
5177
5321
  handler: ({ clips }) => {
5178
5322
  gradeTargets(clips);
5179
5323
  const p = project();
5180
- const withLut = clips.filter((id) => _optionalChain([_chunkZQIWBJGHcjs.findVideoClip.call(void 0, p, id), 'access', _177 => _177.clip, 'access', _178 => _178.grade, 'optionalAccess', _179 => _179.lut]));
5324
+ const withLut = clips.filter((id) => _optionalChain([_chunkXNZFVYC2cjs.findVideoClip.call(void 0, p, id), 'access', _182 => _182.clip, 'access', _183 => _183.grade, 'optionalAccess', _184 => _184.lut]));
5181
5325
  if (!withLut.length) throw new Error(`None of ${clips.map((c) => `"${c}"`).join(", ")} has a LUT; get_video_project shows each clip's grade.`);
5182
- return apply(videoLutEdits(p, withLut, null), "Remove LUT", (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([_chunkZQIWBJGHcjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _180 => _180.clip, 'access', _181 => _181.grade]), () => ( null)) })) }));
5326
+ return apply(videoLutEdits(p, withLut, null), "Remove LUT", (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([_chunkXNZFVYC2cjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _185 => _185.clip, 'access', _186 => _186.grade]), () => ( null)) })) }));
5183
5327
  }
5184
5328
  };
5185
5329
  const PROXY_SCALE = { type: "number", exclusiveMinimum: 0, exclusiveMaximum: 1, description: "Proxy size as a fraction of the original: 0.5 (half width and height, the default) or 0.25 for very large footage." };
@@ -5237,7 +5381,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
5237
5381
  controller.setPreviewScale(scale);
5238
5382
  const s = controller.getState().previewScale;
5239
5383
  const fixed = s === "full" ? 1 : typeof s === "number" ? s : null;
5240
- const plays = fixed === null ? void 0 : project().assets.filter((a) => a.kind === "video").map((a) => ({ asset: a.id, src: _nullishCoalesce(_optionalChain([videoAssetProxy, 'call', _182 => _182(a, fixed), 'optionalAccess', _183 => _183.src]), () => ( a.src)), proxy: !!videoAssetProxy(a, fixed) }));
5384
+ const plays = fixed === null ? void 0 : project().assets.filter((a) => a.kind === "video").map((a) => ({ asset: a.id, src: _nullishCoalesce(_optionalChain([videoAssetProxy, 'call', _187 => _187(a, fixed), 'optionalAccess', _188 => _188.src]), () => ( a.src)), proxy: !!videoAssetProxy(a, fixed) }));
5241
5385
  return { previewScale: s, ...plays ? { plays } : { note: "auto picks the smallest proxy at least as large as the preview canvas shows, so it depends on the preview's size." } };
5242
5386
  }
5243
5387
  };
@@ -5288,7 +5432,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
5288
5432
  approximate: parsed.approximate,
5289
5433
  first: list[0],
5290
5434
  last: list[list.length - 1],
5291
- ...a.duration !== void 0 && list[list.length - 1].end > a.duration + _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON ? { warning: `The transcript runs to ${list[list.length - 1].end} ms, past the asset's ${a.duration} ms: is it for this asset?` } : {}
5435
+ ...a.duration !== void 0 && list[list.length - 1].end > a.duration + _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON ? { warning: `The transcript runs to ${list[list.length - 1].end} ms, past the asset's ${a.duration} ms: is it for this asset?` } : {}
5292
5436
  }));
5293
5437
  }
5294
5438
  };
@@ -5306,7 +5450,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
5306
5450
  handler: ({ track, from, to, limit }) => {
5307
5451
  const all = timelineWords(track).filter((w) => w.end > (_nullishCoalesce(from, () => ( 0))) && w.start < (_nullishCoalesce(to, () => ( Infinity))));
5308
5452
  const words = all.slice(0, _nullishCoalesce(limit, () => ( 1e3)));
5309
- return { track: _nullishCoalesce(_optionalChain([words, 'access', _184 => _184[0], 'optionalAccess', _185 => _185.track]), () => ( videoTranscriptTrack(project(), track))), text: words.map((w) => w.word).join(" "), words: words.map((w) => ({ word: w.word, start: round(w.start), end: round(w.end), clip: w.clip })), more: all.length > words.length };
5453
+ return { track: _nullishCoalesce(_optionalChain([words, 'access', _189 => _189[0], 'optionalAccess', _190 => _190.track]), () => ( videoTranscriptTrack(project(), track))), text: words.map((w) => w.word).join(" "), words: words.map((w) => ({ word: w.word, start: round(w.start), end: round(w.end), clip: w.clip })), more: all.length > words.length };
5310
5454
  }
5311
5455
  };
5312
5456
  const findText = {
@@ -5359,22 +5503,22 @@ function createVideoEditorToolProvider(controller, options = {}) {
5359
5503
  const bad = ranges.findIndex((r) => !(r.to > r.from));
5360
5504
  if (bad >= 0) throw new Error(`Range ${bad + 1} is empty or backwards (${ranges[bad].from}\u2013${ranges[bad].to} ms); "to" must be after "from".`);
5361
5505
  const merged = mergeVideoRanges(ranges);
5362
- const before = _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, project());
5363
- return apply(videoRemoveRangesEdits(merged, tracks), merged.length > 1 ? `Cut ${merged.length} stretches` : "Cut stretch", (r) => ({ removed: merged.length, time: round(before - _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, r.project)), duration: _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, r.project) }));
5506
+ const before = _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, project());
5507
+ return apply(videoRemoveRangesEdits(merged, tracks), merged.length > 1 ? `Cut ${merged.length} stretches` : "Cut stretch", (r) => ({ removed: merged.length, time: round(before - _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, r.project)), duration: _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, r.project) }));
5364
5508
  }
5365
5509
  };
5366
5510
  const rampTarget = (id) => {
5367
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, project(), id);
5511
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, project(), id);
5368
5512
  if (!at) throw new Error(`There is no clip "${id}"; get_video_project lists the clips.`);
5369
5513
  const { clip } = at;
5370
5514
  if (clip.type === "sequence") throw new Error(`Clip "${id}" is a compound clip, which plays its sequence at normal speed; change the speed of the clips inside the sequence instead.`);
5371
- if (clip.type !== "media") throw new Error(`Clip "${id}" is a ${_chunkZQIWBJGHcjs.videoClipTypeLabel.call(void 0, clip)}, so it has no source to change the speed of; use a video or audio clip.`);
5372
- if (_optionalChain([project, 'call', _186 => _186(), 'access', _187 => _187.assets, 'access', _188 => _188.find, 'call', _189 => _189((a) => a.id === clip.asset), 'optionalAccess', _190 => _190.kind]) === "image") throw new Error(`Clip "${id}" is a still, so it has no motion to change the speed of.`);
5515
+ if (clip.type !== "media") throw new Error(`Clip "${id}" is a ${_chunkXNZFVYC2cjs.videoClipTypeLabel.call(void 0, clip)}, so it has no source to change the speed of; use a video or audio clip.`);
5516
+ if (_optionalChain([project, 'call', _191 => _191(), 'access', _192 => _192.assets, 'access', _193 => _193.find, 'call', _194 => _194((a) => a.id === clip.asset), 'optionalAccess', _195 => _195.kind]) === "image") throw new Error(`Clip "${id}" is a still, so it has no motion to change the speed of.`);
5373
5517
  return clip;
5374
5518
  };
5375
5519
  const rampOut = (r, id) => {
5376
5520
  const outcome2 = r.outcomes[r.outcomes.length - 1];
5377
- return { clip: clipOut(r.project, id), ...outcome2.rippled ? { rippled: outcome2.rippled } : {}, duration: _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, r.project) };
5521
+ return { clip: clipOut(r.project, id), ...outcome2.rippled ? { rippled: outcome2.rippled } : {}, duration: _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, r.project) };
5378
5522
  };
5379
5523
  const RIPPLE_RAMP = { type: "boolean", description: "Move later material on every sync-locked track by the change in length (default true); false refuses if the clip would overlap the next one." };
5380
5524
  const setSpeedRamp = {
@@ -5405,8 +5549,8 @@ function createVideoEditorToolProvider(controller, options = {}) {
5405
5549
  ),
5406
5550
  annotations: { title: "Ramp the speed", ...WRITE_IDEMPOTENT },
5407
5551
  handler: ({ clip, segments, ripple }) => {
5408
- const edit = _chunkZQIWBJGHcjs.videoSpeedRampEdit.call(void 0, rampTarget(clip), segments, _nullishCoalesce(ripple, () => ( true)));
5409
- return apply(edit, "Speed ramp", (r) => ({ ...rampOut(r, clip), source: Math.round(_chunkZQIWBJGHcjs.videoSpeedRampKeys.call(void 0, segments).source) }));
5552
+ const edit = _chunkXNZFVYC2cjs.videoSpeedRampEdit.call(void 0, rampTarget(clip), segments, _nullishCoalesce(ripple, () => ( true)));
5553
+ return apply(edit, "Speed ramp", (r) => ({ ...rampOut(r, clip), source: Math.round(_chunkXNZFVYC2cjs.videoSpeedRampKeys.call(void 0, segments).source) }));
5410
5554
  }
5411
5555
  };
5412
5556
  const addFreeze = {
@@ -5426,8 +5570,8 @@ function createVideoEditorToolProvider(controller, options = {}) {
5426
5570
  handler: ({ clip, at, duration, ripple }) => {
5427
5571
  const c = rampTarget(clip);
5428
5572
  const t = at - c.start;
5429
- if (t < 0 || t > c.duration) throw new Error(`${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, at)} is outside clip "${clip}" (${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, c.start)}\u2013${_chunkZQIWBJGHcjs.formatVideoSeconds.call(void 0, _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c))}); pick a time inside it.`);
5430
- return apply(_chunkZQIWBJGHcjs.videoFreezeFrameEdit.call(void 0, c, t, duration, _nullishCoalesce(ripple, () => ( true))), "Freeze frame", (r) => rampOut(r, clip));
5573
+ if (t < 0 || t > c.duration) throw new Error(`${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, at)} is outside clip "${clip}" (${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, c.start)}\u2013${_chunkXNZFVYC2cjs.formatVideoSeconds.call(void 0, _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c))}); pick a time inside it.`);
5574
+ return apply(_chunkXNZFVYC2cjs.videoFreezeFrameEdit.call(void 0, c, t, duration, _nullishCoalesce(ripple, () => ( true))), "Freeze frame", (r) => rampOut(r, clip));
5431
5575
  }
5432
5576
  };
5433
5577
  const removeRamp = {
@@ -5600,7 +5744,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
5600
5744
  let from;
5601
5745
  let to;
5602
5746
  if (args.clip !== void 0) {
5603
- const found = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, p, args.clip);
5747
+ const found = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, p, args.clip);
5604
5748
  if (!found) throw new Error(`There is no clip "${args.clip}"; get_video_project lists the clips.`);
5605
5749
  const c = found.clip;
5606
5750
  if (c.type === "sequence") throw new Error(`Clip "${c.id}" is a compound clip; its sound is the mix of its sequence "${c.sequence}", so read the levels of the media in it (list_video_sequences lists its clips and assets).`);
@@ -5610,7 +5754,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
5610
5754
  toSource = (t) => (_nullishCoalesce(c.in, () => ( 0))) + (t - c.start) * speed;
5611
5755
  toOut = (s) => c.start + (s - (_nullishCoalesce(c.in, () => ( 0)))) / speed;
5612
5756
  from = Math.max(c.start, _nullishCoalesce(args.from, () => ( c.start)));
5613
- to = Math.min(_chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c), _nullishCoalesce(args.to, () => ( _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c))));
5757
+ to = Math.min(_chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c), _nullishCoalesce(args.to, () => ( _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c))));
5614
5758
  } else {
5615
5759
  asset = p.assets.find((a) => a.id === args.asset);
5616
5760
  if (!asset) throw new Error(`There is no asset "${args.asset}"; the assets are ${p.assets.map((a) => `"${a.id}"`).join(", ") || "none"}.`);
@@ -5691,15 +5835,15 @@ function createVideoEditorToolProvider(controller, options = {}) {
5691
5835
  annotations: { title: "Measure a frame with scopes", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
5692
5836
  handler: async ({ time, bins, columns }) => {
5693
5837
  const p = project();
5694
- const end = _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, p);
5838
+ const end = _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, p);
5695
5839
  const t = _nullishCoalesce(time, () => ( controller.getState().time));
5696
5840
  if (time !== void 0 && time > end) throw new Error(`Time ${time} ms is past the end of the project (${end} ms).`);
5697
5841
  const pixels = await pixelsAt(t);
5698
- return { time: t, timecode: _chunkZQIWBJGHcjs.formatVideoTimecode.call(void 0, t, p.fps), width: pixels.width, height: pixels.height, ...summarizeVideoScopes(pixels, { bins, columns }) };
5842
+ return { time: t, timecode: _chunkXNZFVYC2cjs.formatVideoTimecode.call(void 0, t, p.fps), width: pixels.width, height: pixels.height, ...summarizeVideoScopes(pixels, { bins, columns }) };
5699
5843
  }
5700
5844
  };
5701
5845
  const MASK_FIELDS = {
5702
- shape: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_MASK_SHAPES], description: "rectangle (with corner_radius), ellipse, linear (a straight split: the side above the line at rotation 0 shows) or polygon (points)." },
5846
+ shape: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_MASK_SHAPES], description: "rectangle (with corner_radius), ellipse, linear (a straight split: the side above the line at rotation 0 shows) or polygon (points)." },
5703
5847
  x: { type: "number", description: "Centre across the clip's picture, 0 (left edge) to 1 (right edge); default 0.5." },
5704
5848
  y: { type: "number", description: "Centre down the clip's picture, 0 (top) to 1 (bottom); default 0.5." },
5705
5849
  width: { type: "number", minimum: 0, description: "Width as a fraction of the picture's width (default 0.5). Unused by linear." },
@@ -5719,10 +5863,10 @@ function createVideoEditorToolProvider(controller, options = {}) {
5719
5863
  track: { ...TRACK_ID, description: 'A video track to put it on; tracks below it are "underneath".' },
5720
5864
  start: MS("Where it starts on the timeline (default: the end of the track)"),
5721
5865
  duration: { type: "number", exclusiveMinimum: 0, description: "How long it lasts, in ms (default 3000)." },
5722
- scope: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_ADJUSTMENT_SCOPES], description: "Which pictures it changes: underneath (default), all or track." },
5866
+ scope: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_ADJUSTMENT_SCOPES], description: "Which pictures it changes: underneath (default), all or track." },
5723
5867
  target_track: { ...TRACK_ID, description: 'For scope "track" (required then): the track whose pictures it changes.' },
5724
5868
  grade: GRADE,
5725
- preset: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_GRADE_PRESET_NAMES], description: "A named look to start from (grade settings given override it)." },
5869
+ preset: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_GRADE_PRESET_NAMES], description: "A named look to start from (grade settings given override it)." },
5726
5870
  amount: { type: "number", minimum: 0, maximum: 1, description: "Strength of the preset, 0\u20131 (default 1)." },
5727
5871
  name: { type: "string", minLength: 1, description: 'A label for the clip (e.g. "Night look").' },
5728
5872
  id: { type: "string", minLength: 1, description: 'Your own id for the clip (default: a fresh one such as "c7").' },
@@ -5736,13 +5880,13 @@ function createVideoEditorToolProvider(controller, options = {}) {
5736
5880
  if (t && t.kind !== "video") throw new Error(`Track "${track}" is an audio track; adjustment clips change pictures, so put it on a video track.`);
5737
5881
  if (scope === "track" && !target_track) throw new Error('Scope "track" needs target_track: the id of the track whose pictures it changes.');
5738
5882
  if (target_track !== void 0 && scope !== "track") throw new Error('target_track is only for scope "track"; leave it out or set scope to "track".');
5739
- const look = { ...preset ? _chunkZQIWBJGHcjs.videoGradePreset.call(void 0, preset, _nullishCoalesce(amount, () => ( 1))) : {}, ..._nullishCoalesce(grade, () => ( {})) };
5883
+ const look = { ...preset ? _chunkXNZFVYC2cjs.videoGradePreset.call(void 0, preset, _nullishCoalesce(amount, () => ( 1))) : {}, ..._nullishCoalesce(grade, () => ( {})) };
5740
5884
  const clip = { type: "adjustment", ...id ? { id } : {}, ...name ? { name } : {}, ...start !== void 0 ? { start } : {}, duration: _nullishCoalesce(duration, () => ( 3e3)), ...scope ? { scope } : {}, ...target_track ? { targetTrack: target_track } : {}, ...Object.keys(look).length ? { grade: look } : {} };
5741
5885
  return apply({ op: "add_clip", track, clip, mode }, "Add adjustment clip", (r) => ({ clip: clipOut(r.project, r.outcomes[0].clip), ...placed(r.outcomes[0]), ...Object.keys(look).length ? {} : { hint: "It changes nothing yet: give it a grade (update_video_clip), effects (apply_effect) or a mask." } }));
5742
5886
  }
5743
5887
  };
5744
5888
  const maskTarget = (id) => {
5745
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, project(), id);
5889
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, project(), id);
5746
5890
  if (!at) throw new Error(`There is no clip "${id}"; get_video_project lists the clips.`);
5747
5891
  if (at.track.kind !== "video") throw new Error(`Clip "${id}" is on audio track "${at.track.id}"; masks cut pictures, so pass a clip on a video track.`);
5748
5892
  return at;
@@ -5784,13 +5928,13 @@ function createVideoEditorToolProvider(controller, options = {}) {
5784
5928
  gradeTargets(clips);
5785
5929
  const edits = [];
5786
5930
  for (const id of clips) {
5787
- const clip = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, project(), id).clip;
5788
- const lut = _optionalChain([clip, 'access', _191 => _191.grade, 'optionalAccess', _192 => _192.lut]);
5931
+ const clip = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, project(), id).clip;
5932
+ const lut = _optionalChain([clip, 'access', _196 => _196.grade, 'optionalAccess', _197 => _197.lut]);
5789
5933
  if (!lut) throw new Error(`Clip "${id}" has no LUT to protect skin from; add one with set_video_lut first.`);
5790
5934
  const { preserveSkinTones: _p, ...rest } = lut;
5791
5935
  edits.push({ op: "update_clip", clip: id, set: { grade: { ...clip.grade, lut: amount > 0 ? { ...rest, preserveSkinTones: amount } : rest } } });
5792
5936
  }
5793
- return apply(edits, amount > 0 ? "Protect skin tones" : "Stop protecting skin tones", (r) => ({ clips: clips.map((id) => ({ id, lut: _nullishCoalesce(_optionalChain([_chunkZQIWBJGHcjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _193 => _193.clip, 'access', _194 => _194.grade, 'optionalAccess', _195 => _195.lut]), () => ( null)) })) }));
5937
+ return apply(edits, amount > 0 ? "Protect skin tones" : "Stop protecting skin tones", (r) => ({ clips: clips.map((id) => ({ id, lut: _nullishCoalesce(_optionalChain([_chunkXNZFVYC2cjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _198 => _198.clip, 'access', _199 => _199.grade, 'optionalAccess', _200 => _200.lut]), () => ( null)) })) }));
5794
5938
  }
5795
5939
  };
5796
5940
  const planOut = (plan) => ({
@@ -5843,7 +5987,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
5843
5987
  handler: ({ plan }) => {
5844
5988
  const r = controller.applyPlan(plan);
5845
5989
  if (!r.ok) throw new Error(r.error);
5846
- return { plan: r.plan.id, title: r.plan.title, stale: r.stale, outcomes: r.outcomes, duration: _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, r.project), issues: issueSummary(r.issues) };
5990
+ return { plan: r.plan.id, title: r.plan.title, stale: r.stale, outcomes: r.outcomes, duration: _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, r.project), issues: issueSummary(r.issues) };
5847
5991
  }
5848
5992
  };
5849
5993
  const discardPlan = {
@@ -5916,7 +6060,7 @@ function videoCameraMoveTools(controller, ctx) {
5916
6060
  annotations: { title: "List camera moves for clips", ...ctx.annotations.read },
5917
6061
  handler: async (args) => {
5918
6062
  const provider = controller.effectsProvider;
5919
- if (!_optionalChain([provider, 'optionalAccess', _196 => _196.capabilities, 'access', _197 => _197.supportsCamera]) || !provider.cameraView)
6063
+ if (!_optionalChain([provider, 'optionalAccess', _201 => _201.capabilities, 'access', _202 => _202.supportsCamera]) || !provider.cameraView)
5920
6064
  return { available: false, reason: provider ? `${provider.name} has no camera moves (capabilities.supportsCamera is not set).` : "No effects provider is registered, so there are no camera moves.", moves: [] };
5921
6065
  return { available: true, provider: provider.name, moves: (await controller.cameraMoves(args.role)).map(summary) };
5922
6066
  }
@@ -5931,7 +6075,7 @@ function videoCameraMoveTools(controller, ctx) {
5931
6075
  clip: { type: "string", minLength: 1, description: "A clip id with a picture, from get_video_project." },
5932
6076
  role: ROLE,
5933
6077
  move: { type: "string", minLength: 1, description: "A camera move id of that role from list_video_camera_moves." },
5934
- ms: { type: "number", minimum: 0, maximum: _chunkJAOSL334cjs.CAMERA_MOVE_MAX_MS, description: `How long a transition takes, ms (default the move's durationMs; at most the clip's length). Not for a hold, which plays across the rest of the clip.` },
6078
+ ms: { type: "number", minimum: 0, maximum: _chunkGHCSC2WPcjs.CAMERA_MOVE_MAX_MS, description: `How long a transition takes, ms (default the move's durationMs; at most the clip's length). Not for a hold, which plays across the rest of the clip.` },
5935
6079
  preset: { type: "string", minLength: 1, description: "A preset of the move by name, from describe_effect." },
5936
6080
  values: ctx.valuesSchema("Control values over the move's defaults (and the preset's), from describe_effect"),
5937
6081
  from: FRAMING("Where a transition starts."),
@@ -5968,7 +6112,7 @@ function videoClipAppliedEffects(clip) {
5968
6112
  const out = [];
5969
6113
  const ref = (r) => ({ effect: r.effect, ...r.name ? { name: r.name } : {}, ...r.provider ? { provider: r.provider } : {} });
5970
6114
  if (clip.type === "effect") out.push({ id: "generator", ...ref(clip), role: "effect clip", enabled: true, values: _nullishCoalesce(clip.values, () => ( {})) });
5971
- if (_optionalChain([clip, 'access', _198 => _198.transition, 'optionalAccess', _199 => _199.type]) === "effect" && clip.transition.effect) out.push({ id: "transition", ...ref(clip.transition.effect), role: "transition", enabled: true, values: { ..._nullishCoalesce(clip.transition.effect.values, () => ( {})) }, duration: clip.transition.duration });
6115
+ if (_optionalChain([clip, 'access', _203 => _203.transition, 'optionalAccess', _204 => _204.type]) === "effect" && clip.transition.effect) out.push({ id: "transition", ...ref(clip.transition.effect), role: "transition", enabled: true, values: { ..._nullishCoalesce(clip.transition.effect.values, () => ( {})) }, duration: clip.transition.duration });
5972
6116
  (_nullishCoalesce(clip.effects, () => ( []))).forEach((e, index) => out.push({ id: e.id, ...ref(e), role: "clip effect", enabled: e.enabled !== false, ...e.opacity !== void 0 ? { opacity: e.opacity } : {}, values: _nullishCoalesce(e.values, () => ( {})), index }));
5973
6117
  return out;
5974
6118
  }
@@ -5981,7 +6125,7 @@ var KEYS2 = {
5981
6125
  properties: {
5982
6126
  t: { type: "number", description: "Clip-relative time in ms (0 = the clip's start)." },
5983
6127
  v: { type: "number", description: "The control's value at t, within its range from describe_effect." },
5984
- ease: { anyOf: [{ type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_EASE_NAMES] }, { type: "array", items: { type: "number" }, minItems: 4, maxItems: 4 }], description: "How the value moves to the next key: linear (default), hold, ease-in, ease-out, ease-in-out, or CSS cubic-bezier [x1, y1, x2, y2]." }
6128
+ ease: { anyOf: [{ type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_EASE_NAMES] }, { type: "array", items: { type: "number" }, minItems: 4, maxItems: 4 }], description: "How the value moves to the next key: linear (default), hold, ease-in, ease-out, ease-in-out, or CSS cubic-bezier [x1, y1, x2, y2]." }
5985
6129
  },
5986
6130
  required: ["t", "v"],
5987
6131
  additionalProperties: false
@@ -5995,7 +6139,7 @@ function createVideoEffectsToolProvider(controller, options = {}) {
5995
6139
  return controller.readOnlyReason();
5996
6140
  };
5997
6141
  const clipOf = (id) => {
5998
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, controller.getProject(), id);
6142
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, controller.getProject(), id);
5999
6143
  if (!at) {
6000
6144
  const ids = controller.getProject().tracks.flatMap((t) => t.clips.map((c) => c.id));
6001
6145
  throw new Error(`There is no clip "${id}"; the clips are ${ids.map((c) => `"${c}"`).join(", ") || "none"} (get_video_project lists them).`);
@@ -6005,10 +6149,10 @@ function createVideoEffectsToolProvider(controller, options = {}) {
6005
6149
  const result = (r, target, instance, extra = {}) => {
6006
6150
  if (!r.ok) throw new Error(r.error);
6007
6151
  const effects = videoClipAppliedEffects(clipOf(target));
6008
- const effect = _nullishCoalesce(effects.find((e) => e.id === (_nullishCoalesce(instance, () => ( _optionalChain([r, 'access', _200 => _200.effect, 'optionalAccess', _201 => _201.id]))))), () => ( (r.effect ? { id: r.effect.id, effect: r.effect.effect, role: "clip effect", enabled: r.effect.enabled !== false, values: _nullishCoalesce(r.effect.values, () => ( {})) } : effects[0])));
6152
+ const effect = _nullishCoalesce(effects.find((e) => e.id === (_nullishCoalesce(instance, () => ( _optionalChain([r, 'access', _205 => _205.effect, 'optionalAccess', _206 => _206.id]))))), () => ( (r.effect ? { id: r.effect.id, effect: r.effect.effect, role: "clip effect", enabled: r.effect.enabled !== false, values: _nullishCoalesce(r.effect.values, () => ( {})) } : effects[0])));
6009
6153
  return { target, effect, effects, ...extra };
6010
6154
  };
6011
- return withVideoPlayback(_chunkJAOSL334cjs.createEffectToolProvider.call(void 0, {
6155
+ return withVideoPlayback(_chunkGHCSC2WPcjs.createEffectToolProvider.call(void 0, {
6012
6156
  id: _nullishCoalesce(options.id, () => ( "video-effects")),
6013
6157
  namespace: options.namespace,
6014
6158
  title: "Video effects",
@@ -6054,7 +6198,7 @@ function createVideoEffectsToolProvider(controller, options = {}) {
6054
6198
  subscribe: (notify) => controller.subscribe(() => notify()),
6055
6199
  extraTools: (ctx) => [
6056
6200
  ...videoCameraMoveTools(controller, ctx),
6057
- ..._chunkJWCKJNDRcjs.effectTemplateTools.call(void 0,
6201
+ ..._chunkK5DS2JTAcjs.effectTemplateTools.call(void 0,
6058
6202
  {
6059
6203
  provider: () => controller.effectsProvider,
6060
6204
  fillDetails: `It goes on the timeline at "at" (default the end of the project), on new tracks above the others: each shot's bottom layer on a base track (with the shot's transition), other layers as effect, picture and text clips on tracks by role, titles and captions as text clips; an open subject slot becomes a grey placeholder clip named after it. Camera moves are not carried over. Returns { template, tracks, clips, assets, start, end (ms), placeholders (clip ids by open slot), openSlots, notes }. To fill an open slot, add the picture with add_video_asset and put it on the placeholder's track at its start with add_video_clip in overwrite mode.`,
@@ -6081,7 +6225,7 @@ function createVideoEffectsToolProvider(controller, options = {}) {
6081
6225
  duration: { type: "number", exclusiveMinimum: 0, description: "Length in ms (default: the effect's own length, else 5000)." },
6082
6226
  values: ctx.valuesSchema("Control values over the effect's defaults", true),
6083
6227
  name: { type: "string", minLength: 1, description: "A label for the clip (default: the effect's name)." },
6084
- mode: { type: "string", enum: [..._chunkZQIWBJGHcjs.VIDEO_PLACEMENT_MODES], description: "What to do with clips already there: refuse (default), overwrite or insert." }
6228
+ mode: { type: "string", enum: [..._chunkXNZFVYC2cjs.VIDEO_PLACEMENT_MODES], description: "What to do with clips already there: refuse (default), overwrite or insert." }
6085
6229
  },
6086
6230
  required: ["track", "effect"],
6087
6231
  additionalProperties: false
@@ -6117,6 +6261,47 @@ function createVideoEffectsToolProvider(controller, options = {}) {
6117
6261
  return { clip: args.clip, transition: clipOf(args.clip).transition, effects: videoClipAppliedEffects(clipOf(args.clip)) };
6118
6262
  }
6119
6263
  },
6264
+ {
6265
+ name: "set_video_effect_path",
6266
+ title: "Run an effect along a path",
6267
+ description: `Gives an effect that draws along a path (search_effects with accepts ["path"]; describe_effect lists its pathControls) the path to draw along: on an effect clip (instance "generator", added with add_video_effect_clip) or a clip effect (its id, from apply_effect). Pass exactly one of: points (frame pixels from the top left, as on the preview; mapped into the pixels of the picture the effect renders, so a clip effect lines up with its moved or scaled clip), d (SVG path data the effect fits into its picture; "" clears the path), mask (use the outline of a clip's mask, in frame pixels), or text (words the provider writes as a single-stroke path, when it can). Refuses an effect without a path control, naming how to find one. One undo step. Returns the clip, instance, the control set and the value it took (points in picture pixels, or path data).`,
6268
+ inputSchema: {
6269
+ type: "object",
6270
+ properties: {
6271
+ clip: { type: "string", minLength: 1, description: "The clip id from get_video_project." },
6272
+ instance: { type: "string", minLength: 1, description: `"generator" for an effect clip's own picture, or a clip effect id from list_applied_effects.` },
6273
+ control: { type: "string", minLength: 1, description: "Which path control (default: the effect's only one; describe_effect pathControls lists them)." },
6274
+ points: { type: "array", minItems: 4, maxItems: 4096, items: { type: "number", description: "x or y, frame pixels." }, description: "The path as frame points [x0, y0, x1, y1, \u2026] in pixels from the frame's top left." },
6275
+ d: { type: "string", description: `SVG path data, fitted into the effect's picture as its control says; "" clears the path.` },
6276
+ mask: { type: "object", properties: { clip: { type: "string", minLength: 1, description: "The clip whose mask outline to use." } }, required: ["clip"], additionalProperties: false, description: "Use the outline of this clip's mask (set_video_clip_mask), in frame pixels." },
6277
+ text: {
6278
+ type: "object",
6279
+ properties: {
6280
+ text: { type: "string", minLength: 1, description: "The words to write." },
6281
+ font: { type: "string", minLength: 1, description: "A single-stroke font the provider offers (default its first)." },
6282
+ align: { type: "string", enum: ["start", "middle", "end"], description: "Where the line sits (default start)." }
6283
+ },
6284
+ required: ["text"],
6285
+ additionalProperties: false,
6286
+ description: "Words the provider writes as a single-stroke path (a signature, handwriting)."
6287
+ }
6288
+ },
6289
+ required: ["clip", "instance"],
6290
+ oneOf: [{ required: ["points"] }, { required: ["d"] }, { required: ["mask"] }, { required: ["text"] }],
6291
+ additionalProperties: false
6292
+ },
6293
+ annotations: { title: "Run an effect along a path", ...ctx.annotations.write },
6294
+ handler: async (args) => {
6295
+ ctx.requireProvider();
6296
+ const given = ["points", "d", "mask", "text"].filter((k2) => args[k2] !== void 0);
6297
+ if (given.length !== 1) throw new Error(`Pass exactly one of points, d, mask or text${given.length ? ` (got ${given.join(", ")})` : ""}.`);
6298
+ const k = given[0];
6299
+ const path = k === "text" ? { ...args.text } : { [k]: args[k] };
6300
+ const r = await controller.setEffectPath(args.clip, args.instance, path, { control: args.control });
6301
+ if (!r.ok) throw new Error(r.error);
6302
+ return { clip: args.clip, instance: args.instance, control: r.control, value: r.value };
6303
+ }
6304
+ },
6120
6305
  {
6121
6306
  name: "set_video_effect_keyframes",
6122
6307
  title: "Keyframe an effect control",
@@ -6140,8 +6325,8 @@ function createVideoEffectsToolProvider(controller, options = {}) {
6140
6325
  if (args.effect === "generator") {
6141
6326
  const clip = clipOf(args.clip);
6142
6327
  if (clip.type !== "effect") throw new Error(`Clip "${args.clip}" is not an effect clip; give the id of one of its effects (list_applied_effects).`);
6143
- const was = _optionalChain([clip, 'access', _202 => _202.values, 'optionalAccess', _203 => _203[args.control]]);
6144
- const plain = keys === null ? _chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, was) ? _optionalChain([was, 'access', _204 => _204.keys, 'access', _205 => _205[0], 'optionalAccess', _206 => _206.v]) : was : { keys: [...keys].sort((a, b) => a.t - b.t) };
6328
+ const was = _optionalChain([clip, 'access', _207 => _207.values, 'optionalAccess', _208 => _208[args.control]]);
6329
+ const plain = keys === null ? _chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, was) ? _optionalChain([was, 'access', _209 => _209.keys, 'access', _210 => _210[0], 'optionalAccess', _211 => _211.v]) : was : { keys: [...keys].sort((a, b) => a.t - b.t) };
6145
6330
  if (plain === void 0) throw new Error(`"${args.control}" has no value to keep; give keys instead.`);
6146
6331
  r = await controller.updateEffectValues(args.clip, "generator", { [args.control]: plain });
6147
6332
  } else r = await controller.setClipEffectKeyframes(args.clip, args.effect, args.control, keys);
@@ -6219,7 +6404,7 @@ function createVideoDialogueToolProvider(controller, options = {}) {
6219
6404
  const r = controller.proposePlan({ title, description: "Cuts fillers, long pauses and stutters found in the transcript, closing up every sync-locked track.", edits: videoRemoveRangesEdits(cuts), ranges: cuts.map((d) => ({ from: d.from, to: d.to, text: d.text, reason: d.kind })), source: "plan_video_dialogue_cleanup" });
6220
6405
  if (!r.ok) throw new Error(r.error);
6221
6406
  const p = r.plan;
6222
- return { plan: { id: p.id, title: p.title, summary: p.summary, text: describeVideoEditPlan(p), cuts: cuts.length }, durationNow: _chunkZQIWBJGHcjs.videoProjectDuration.call(void 0, controller.getProject()), hint: `Nothing changed yet. Show the user the plan, then call apply_video_edit_plan with plan "${p.id}" (or discard_video_edit_plan).` };
6407
+ return { plan: { id: p.id, title: p.title, summary: p.summary, text: describeVideoEditPlan(p), cuts: cuts.length }, durationNow: _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, controller.getProject()), hint: `Nothing changed yet. Show the user the plan, then call apply_video_edit_plan with plan "${p.id}" (or discard_video_edit_plan).` };
6223
6408
  }
6224
6409
  };
6225
6410
  return withVideoPlayback(
@@ -6266,7 +6451,7 @@ function createVideoMusicToolProvider(controller, options = {}) {
6266
6451
  };
6267
6452
  const project = () => controller.getProject();
6268
6453
  const soundClip = (p, id) => {
6269
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, p, id);
6454
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, p, id);
6270
6455
  if (!at) throw new Error(`There is no clip "${id}"; get_video_project lists the clips.`);
6271
6456
  const c = at.clip;
6272
6457
  if (c.type !== "media") throw new Error(`Clip "${id}" is a ${c.type} clip and has no sound of its own; pass a video or audio clip.`);
@@ -6282,8 +6467,8 @@ function createVideoMusicToolProvider(controller, options = {}) {
6282
6467
  const { clip, asset: asset2 } = soundClip(p, args.clip);
6283
6468
  const speed = _nullishCoalesce(clip.speed, () => ( 1));
6284
6469
  const from2 = Math.max(clip.start, _nullishCoalesce(args.from, () => ( clip.start)));
6285
- const to2 = Math.min(_chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip), _nullishCoalesce(args.to, () => ( _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip))));
6286
- if (!(to2 > from2)) throw new Error(`The stretch is empty (${from2}\u2013${to2} ms); "from" and "to" must be inside the clip (${clip.start}\u2013${_chunkZQIWBJGHcjs.videoClipEnd.call(void 0, clip)} ms) with "to" after "from".`);
6470
+ const to2 = Math.min(_chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip), _nullishCoalesce(args.to, () => ( _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip))));
6471
+ if (!(to2 > from2)) throw new Error(`The stretch is empty (${from2}\u2013${to2} ms); "from" and "to" must be inside the clip (${clip.start}\u2013${_chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip)} ms) with "to" after "from".`);
6287
6472
  return { asset: asset2, from: (_nullishCoalesce(clip.in, () => ( 0))) + (from2 - clip.start) * speed, to: (_nullishCoalesce(clip.in, () => ( 0))) + (to2 - clip.start) * speed, out: (s) => clip.start + (s - (_nullishCoalesce(clip.in, () => ( 0)))) / speed };
6288
6473
  }
6289
6474
  const asset = p.assets.find((a) => a.id === args.asset);
@@ -6325,7 +6510,7 @@ function createVideoMusicToolProvider(controller, options = {}) {
6325
6510
  handler: async ({ clips, target, ceiling, replace }) => {
6326
6511
  const p = project();
6327
6512
  const targets = clips.map((id) => soundClip(p, id));
6328
- for (const t of targets) if (_chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, t.clip.volume) && !replace) throw new Error(`Clip "${t.clip.id}" has volume keyframes, which a constant gain would replace; pass replace: true, or remove them first.`);
6513
+ for (const t of targets) if (_chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, t.clip.volume) && !replace) throw new Error(`Clip "${t.clip.id}" has volume keyframes, which a constant gain would replace; pass replace: true, or remove them first.`);
6329
6514
  const results = [];
6330
6515
  const edits = [];
6331
6516
  for (const { clip, asset } of targets) {
@@ -6370,7 +6555,7 @@ function createVideoMusicToolProvider(controller, options = {}) {
6370
6555
  handler: async (args) => {
6371
6556
  const p = project();
6372
6557
  const music = args.music.map((id) => soundClip(p, id));
6373
- for (const m of music) if (_chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, m.clip.volume) && !args.replace) throw new Error(`Music clip "${m.clip.id}" already has volume keyframes; pass replace: true to replace them, or remove them first.`);
6558
+ for (const m of music) if (_chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, m.clip.volume) && !args.replace) throw new Error(`Music clip "${m.clip.id}" already has volume keyframes; pass replace: true to replace them, or remove them first.`);
6374
6559
  const transcriptTrack = videoTranscriptTrack(p, args.dialogue_track);
6375
6560
  const mode = _nullishCoalesce(args.speech, () => ( (transcriptTrack && videoTimelineTranscript(p, { track: transcriptTrack }).length ? "transcript" : "audio")));
6376
6561
  let ranges = [];
@@ -6383,7 +6568,7 @@ function createVideoMusicToolProvider(controller, options = {}) {
6383
6568
  const track = p.tracks.find((t) => t.id === args.dialogue_track);
6384
6569
  if (!track) throw new Error(`There is no track "${args.dialogue_track}".`);
6385
6570
  const musicIds = new Set(music.map((m) => m.clip.id));
6386
- for (const c of _chunkZQIWBJGHcjs.sortedVideoClips.call(void 0, track)) {
6571
+ for (const c of _chunkXNZFVYC2cjs.sortedVideoClips.call(void 0, track)) {
6387
6572
  if (c.type !== "media" || musicIds.has(c.id)) continue;
6388
6573
  const asset = p.assets.find((a) => a.id === c.asset);
6389
6574
  if (!asset || asset.kind === "image" || asset.hasAudio === false) continue;
@@ -6394,10 +6579,10 @@ function createVideoMusicToolProvider(controller, options = {}) {
6394
6579
  let at = c.start;
6395
6580
  for (const s of silences) {
6396
6581
  const a = c.start + (s.start - src0) / speed;
6397
- if (a - at > _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) ranges.push({ from: at, to: a });
6582
+ if (a - at > _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) ranges.push({ from: at, to: a });
6398
6583
  at = c.start + (s.end - src0) / speed;
6399
6584
  }
6400
- if (_chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c) - at > _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) ranges.push({ from: at, to: _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, c) });
6585
+ if (_chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c) - at > _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) ranges.push({ from: at, to: _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, c) });
6401
6586
  }
6402
6587
  if (!ranges.length) throw new Error(`Track "${args.dialogue_track}" has no sound above -40 dBFS, so there is no speech to duck under.`);
6403
6588
  }
@@ -6460,7 +6645,7 @@ function createVideoMusicToolProvider(controller, options = {}) {
6460
6645
  if (!beats.length) throw new Error(`No beats were found in "${args.music}"; try a lower sensitivity, or pass beats.`);
6461
6646
  } else beats = [...args.beats].sort((a, b) => a - b);
6462
6647
  const tolerance = _nullishCoalesce(args.tolerance, () => ( 150));
6463
- const clips = _chunkZQIWBJGHcjs.sortedVideoClips.call(void 0, track);
6648
+ const clips = _chunkXNZFVYC2cjs.sortedVideoClips.call(void 0, track);
6464
6649
  const edits = [];
6465
6650
  const ranges = [];
6466
6651
  const skipped = [];
@@ -6468,8 +6653,8 @@ function createVideoMusicToolProvider(controller, options = {}) {
6468
6653
  for (let i = 0; i + 1 < clips.length; i++) {
6469
6654
  const left = clips[i];
6470
6655
  const right = clips[i + 1];
6471
- const cut = _chunkZQIWBJGHcjs.videoClipEnd.call(void 0, left);
6472
- if (Math.abs(right.start - cut) > _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON) continue;
6656
+ const cut = _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, left);
6657
+ if (Math.abs(right.start - cut) > _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON) continue;
6473
6658
  const beat = nearestVideoBeat(beats, cut, tolerance);
6474
6659
  if (beat === null) {
6475
6660
  skipped.push({ cut: round4(cut), reason: `no beat within ${tolerance} ms` });
@@ -6544,7 +6729,7 @@ function videoClipEffectDocument(clip, instance, providerId) {
6544
6729
  const values = {};
6545
6730
  const tracks = {};
6546
6731
  for (const [control, v] of Object.entries(_nullishCoalesce(effect.values, () => ( {})))) {
6547
- if (_chunkZQIWBJGHcjs.isVideoKeyframes.call(void 0, v)) {
6732
+ if (_chunkXNZFVYC2cjs.isVideoKeyframes.call(void 0, v)) {
6548
6733
  values[control] = v.keys[0].v;
6549
6734
  tracks[control] = v.keys.map((k) => ({ time: k.t, value: k.v, ...k.ease && k.ease !== "linear" ? { easing: videoEaseToAnimationEasing(k.ease) } : {} }));
6550
6735
  } else values[control] = v;
@@ -6585,10 +6770,10 @@ function videoEffectValuesFromDocument(doc) {
6585
6770
  async function openVideoClipEffectAuthoring(controller, clip, instance, options = {}) {
6586
6771
  const provider = controller.effectsProvider;
6587
6772
  if (!provider) throw new Error("No effects provider is registered, so the effect cannot be opened for authoring; register one with setEffectsProvider.");
6588
- const at = _chunkZQIWBJGHcjs.findVideoClip.call(void 0, controller.getProject(), clip);
6773
+ const at = _chunkXNZFVYC2cjs.findVideoClip.call(void 0, controller.getProject(), clip);
6589
6774
  if (!at) throw new Error(`There is no clip "${clip}".`);
6590
6775
  const doc = videoClipEffectDocument(at.clip, instance, provider.id);
6591
- const session = await _chunkA7PQNIBXcjs.createEffectAuthoringSession.call(void 0, { document: doc }, { ...options, provider });
6776
+ const session = await _chunk7V7QMFTIcjs.createEffectAuthoringSession.call(void 0, { document: doc }, { ...options, provider });
6592
6777
  return {
6593
6778
  clip,
6594
6779
  instance,
@@ -6938,4 +7123,8 @@ function createVideoEditorDocument(controller) {
6938
7123
 
6939
7124
 
6940
7125
 
6941
- exports.TranscriptVideoController = TranscriptVideoController; exports.VIDEO_ADJUSTMENT_SCOPES = _chunkZQIWBJGHcjs.VIDEO_ADJUSTMENT_SCOPES; exports.VIDEO_ADJUSTMENT_SCOPE_LABELS = VIDEO_ADJUSTMENT_SCOPE_LABELS; exports.VIDEO_BLEND_MODES = _chunkZQIWBJGHcjs.VIDEO_BLEND_MODES; exports.VIDEO_BLEND_MODE_LABELS = VIDEO_BLEND_MODE_LABELS; exports.VIDEO_CLIP_ANIMATION_DURATION = _chunkZQIWBJGHcjs.VIDEO_CLIP_ANIMATION_DURATION; exports.VIDEO_CLIP_ANIMATION_EFFECTS = _chunkZQIWBJGHcjs.VIDEO_CLIP_ANIMATION_EFFECTS; exports.VIDEO_CLIP_ANIMATION_LABELS = VIDEO_CLIP_ANIMATION_LABELS; exports.VIDEO_CLIP_TYPES = _chunkZQIWBJGHcjs.VIDEO_CLIP_TYPES; exports.VIDEO_DEFAULT_FILLERS = VIDEO_DEFAULT_FILLERS; exports.VIDEO_DEFAULT_STILL_DURATION = VIDEO_DEFAULT_STILL_DURATION; exports.VIDEO_DEFAULT_TITLE_DURATION = VIDEO_DEFAULT_TITLE_DURATION; exports.VIDEO_DISFLUENCY_KINDS = VIDEO_DISFLUENCY_KINDS; exports.VIDEO_EASE_NAMES = _chunkZQIWBJGHcjs.VIDEO_EASE_NAMES; exports.VIDEO_EDIT_OPS = VIDEO_EDIT_OPS; exports.VIDEO_EFFECT_PLACES = _chunkZQIWBJGHcjs.VIDEO_EFFECT_PLACES; exports.VIDEO_FADE_CURVES = _chunkZQIWBJGHcjs.VIDEO_FADE_CURVES; exports.VIDEO_FADE_CURVE_LABELS = VIDEO_FADE_CURVE_LABELS; exports.VIDEO_FITS = _chunkZQIWBJGHcjs.VIDEO_FITS; exports.VIDEO_GRADE_CONTROLS = _chunkZQIWBJGHcjs.VIDEO_GRADE_CONTROLS; exports.VIDEO_GRADE_PRESETS = _chunkZQIWBJGHcjs.VIDEO_GRADE_PRESETS; exports.VIDEO_GRADE_PRESET_NAMES = _chunkZQIWBJGHcjs.VIDEO_GRADE_PRESET_NAMES; exports.VIDEO_ISSUE_CODES = VIDEO_ISSUE_CODES; exports.VIDEO_KEYFRAME_LIMITS = _chunkZQIWBJGHcjs.VIDEO_KEYFRAME_LIMITS; exports.VIDEO_KEYFRAME_PROPERTIES = _chunkZQIWBJGHcjs.VIDEO_KEYFRAME_PROPERTIES; exports.VIDEO_LOUDNESS_HOP = VIDEO_LOUDNESS_HOP; exports.VIDEO_LUT_MAX_SIZE = _chunkZQIWBJGHcjs.VIDEO_LUT_MAX_SIZE; exports.VIDEO_MASK_DEFAULTS = _chunkZQIWBJGHcjs.VIDEO_MASK_DEFAULTS; exports.VIDEO_MASK_SHAPES = _chunkZQIWBJGHcjs.VIDEO_MASK_SHAPES; exports.VIDEO_MASK_SHAPE_LABELS = VIDEO_MASK_SHAPE_LABELS; exports.VIDEO_PEAK_BLOCK = VIDEO_PEAK_BLOCK; exports.VIDEO_PLACEMENT_MODES = _chunkZQIWBJGHcjs.VIDEO_PLACEMENT_MODES; exports.VIDEO_PREVIEW_SCALE_OPTIONS = VIDEO_PREVIEW_SCALE_OPTIONS; exports.VIDEO_PROXY_SCALES = VIDEO_PROXY_SCALES; exports.VIDEO_SCOPE_KINDS = VIDEO_SCOPE_KINDS; exports.VIDEO_TIME_EPSILON = _chunkZQIWBJGHcjs.VIDEO_TIME_EPSILON; exports.VIDEO_TRANSFORM_PROPERTIES = _chunkZQIWBJGHcjs.VIDEO_TRANSFORM_PROPERTIES; exports.VIDEO_TRANSITION_LABELS = VIDEO_TRANSITION_LABELS; exports.VIDEO_TRANSITION_TYPES = _chunkZQIWBJGHcjs.VIDEO_TRANSITION_TYPES; exports.VIDEO_VECTORSCOPE_TARGETS = VIDEO_VECTORSCOPE_TARGETS; exports.VIDEO_WIPE_DIRECTIONS = _chunkZQIWBJGHcjs.VIDEO_WIPE_DIRECTIONS; exports.VideoAudioPeaksCache = VideoAudioPeaksCache; exports.VideoEditorController = VideoEditorController; exports.VideoEffectsEngine = _chunkZQIWBJGHcjs.VideoEffectsEngine; exports.VideoFrameCache = VideoFrameCache; exports.VideoLutCache = _chunkZQIWBJGHcjs.VideoLutCache; exports.VideoPreviewEngine = VideoPreviewEngine; exports.VideoPreviewPixels = VideoPreviewPixels; exports.allVideoClipIds = _chunkZQIWBJGHcjs.allVideoClipIds; exports.allVideoTracks = _chunkZQIWBJGHcjs.allVideoTracks; exports.animationEasingToVideoEase = animationEasingToVideoEase; exports.applyVideoEdits = applyVideoEdits; exports.applyVideoGrade = _chunkZQIWBJGHcjs.applyVideoGrade; exports.applyVideoLut = _chunkZQIWBJGHcjs.applyVideoLut; exports.applyVideoLutToPixels = _chunkZQIWBJGHcjs.applyVideoLutToPixels; exports.bakeVideoClipCamera = bakeVideoClipCamera; exports.buildVideoAudioPeaks = buildVideoAudioPeaks; exports.checkVideoEffectPlace = _chunkZQIWBJGHcjs.checkVideoEffectPlace; exports.checkVideoEffectValues = _chunkZQIWBJGHcjs.checkVideoEffectValues; exports.checkVideoProject = checkVideoProject; exports.checkVideoTimeRemap = _chunkZQIWBJGHcjs.checkVideoTimeRemap; exports.createVideoDialogueToolProvider = createVideoDialogueToolProvider; exports.createVideoEditorDocument = createVideoEditorDocument; exports.createVideoEditorToolProvider = createVideoEditorToolProvider; exports.createVideoEffectsToolProvider = createVideoEffectsToolProvider; exports.createVideoElementDecoder = createVideoElementDecoder; exports.createVideoMusicToolProvider = createVideoMusicToolProvider; exports.createVideoProject = createVideoProject; exports.decodeVideoAudioPeaks = decodeVideoAudioPeaks; exports.describeVideoEditPlan = describeVideoEditPlan; exports.describeVideoProject = describeVideoProject; exports.describeVideoSequence = describeVideoSequence; exports.detectVideoDisfluencies = detectVideoDisfluencies; exports.diffVideoProjects = diffVideoProjects; exports.drawVideoFrame = _chunkZQIWBJGHcjs.drawVideoFrame; exports.ffmpegFilterValue = _chunkZQIWBJGHcjs.ffmpegFilterValue; exports.findVideoAudioBeats = findVideoAudioBeats; exports.findVideoAudioSilences = findVideoAudioSilences; exports.findVideoClip = _chunkZQIWBJGHcjs.findVideoClip; exports.findVideoFillers = findVideoFillers; exports.findVideoGaps = _chunkZQIWBJGHcjs.findVideoGaps; exports.findVideoRepetitions = findVideoRepetitions; exports.findVideoSequenceClip = _chunkZQIWBJGHcjs.findVideoSequenceClip; exports.findVideoSequenceCycle = _chunkZQIWBJGHcjs.findVideoSequenceCycle; exports.findVideoTranscriptPauses = findVideoTranscriptPauses; exports.findVideoTranscriptText = findVideoTranscriptText; exports.formatVideoSeconds = _chunkZQIWBJGHcjs.formatVideoSeconds; exports.formatVideoTimecode = _chunkZQIWBJGHcjs.formatVideoTimecode; exports.formatVideoTimecodeFrames = _chunkZQIWBJGHcjs.formatVideoTimecodeFrames; exports.isVideoDropFrameRate = _chunkZQIWBJGHcjs.isVideoDropFrameRate; exports.isVideoKeyframes = _chunkZQIWBJGHcjs.isVideoKeyframes; exports.measureVideoLoudness = measureVideoLoudness; exports.mergeVideoRanges = mergeVideoRanges; exports.mixEffectPixels = _chunkZQIWBJGHcjs.mixEffectPixels; exports.nearestVideoBeat = nearestVideoBeat; exports.nextFreeVideoSlot = _chunkZQIWBJGHcjs.nextFreeVideoSlot; exports.normalizeVideoClipMask = _chunkZQIWBJGHcjs.normalizeVideoClipMask; exports.normalizeVideoGrade = _chunkZQIWBJGHcjs.normalizeVideoGrade; exports.normalizeVideoGradeLut = _chunkZQIWBJGHcjs.normalizeVideoGradeLut; exports.normalizeVideoWord = normalizeVideoWord; exports.openVideoClipEffectAuthoring = openVideoClipEffectAuthoring; exports.overEffectPixels = _chunkZQIWBJGHcjs.overEffectPixels; exports.parseVideoAnimatable = parseVideoAnimatable; exports.parseVideoAsset = parseVideoAsset; exports.parseVideoAssetProxies = parseVideoAssetProxies; exports.parseVideoClip = parseVideoClip; exports.parseVideoClipAnimation = parseVideoClipAnimation; exports.parseVideoClipCamera = parseVideoClipCamera; exports.parseVideoClipEffects = parseVideoClipEffects; exports.parseVideoClipMask = parseVideoClipMask; exports.parseVideoCubeLut = _chunkZQIWBJGHcjs.parseVideoCubeLut; exports.parseVideoEffectRef = parseVideoEffectRef; exports.parseVideoEffectValues = parseVideoEffectValues; exports.parseVideoGrade = parseVideoGrade; exports.parseVideoGradeLut = parseVideoGradeLut; exports.parseVideoKeyframes = parseVideoKeyframes; exports.parseVideoLoudnessMeasurement = _chunkZQIWBJGHcjs.parseVideoLoudnessMeasurement; exports.parseVideoMarker = parseVideoMarker; exports.parseVideoPreviewScale = parseVideoPreviewScale; exports.parseVideoProject = parseVideoProject; exports.parseVideoSequence = parseVideoSequence; exports.parseVideoTimeRef = parseVideoTimeRef; exports.parseVideoTimeRemap = parseVideoTimeRemap; exports.parseVideoTrack = parseVideoTrack; exports.parseVideoTranscript = parseVideoTranscript; exports.parseVideoTranscriptWords = parseVideoTranscriptWords; exports.parseVideoTransform = parseVideoTransform; exports.parseVideoTransition = parseVideoTransition; exports.placeVideoRect = _chunkZQIWBJGHcjs.placeVideoRect; exports.planVideoClipDrag = planVideoClipDrag; exports.planVideoEdits = planVideoEdits; exports.planVideoPrefetch = planVideoPrefetch; exports.planVideoToolPlayback = planVideoToolPlayback; exports.probeVideoMedia = probeVideoMedia; exports.readVideoScopesPanel = readVideoScopesPanel; exports.removeVideoKey = _chunkZQIWBJGHcjs.removeVideoKey; exports.renderVideoFrameExact = _chunkZQIWBJGHcjs.renderVideoFrameExact; exports.resolveVideoPreviewScale = resolveVideoPreviewScale; exports.retimeVideoAnimatable = _chunkZQIWBJGHcjs.retimeVideoAnimatable; exports.setVideoKey = _chunkZQIWBJGHcjs.setVideoKey; exports.snapToVideoFrame = _chunkZQIWBJGHcjs.snapToVideoFrame; exports.snapVideoTime = _chunkZQIWBJGHcjs.snapVideoTime; exports.sortVideoKeys = _chunkZQIWBJGHcjs.sortVideoKeys; exports.sortedVideoClips = _chunkZQIWBJGHcjs.sortedVideoClips; exports.splitVideoAnimatable = _chunkZQIWBJGHcjs.splitVideoAnimatable; exports.summarizeVideoScopes = summarizeVideoScopes; exports.toVideoEdl = _chunkZQIWBJGHcjs.toVideoEdl; exports.toVideoFfmpeg = _chunkZQIWBJGHcjs.toVideoFfmpeg; exports.toVideoLoudnessMeasure = _chunkZQIWBJGHcjs.toVideoLoudnessMeasure; exports.videoAddAdjustmentEdits = videoAddAdjustmentEdits; exports.videoAssetDropEdit = videoAssetDropEdit; exports.videoAssetHasSound = _chunkZQIWBJGHcjs.videoAssetHasSound; exports.videoAssetKindOf = videoAssetKindOf; exports.videoAssetMap = _chunkZQIWBJGHcjs.videoAssetMap; exports.videoAssetProxy = videoAssetProxy; exports.videoAudioLevels = videoAudioLevels; exports.videoAudioLoudness = videoAudioLoudness; exports.videoAudioPeakRange = videoAudioPeakRange; exports.videoAudioPeakSpans = videoAudioPeakSpans; exports.videoAudioPeaksDuration = videoAudioPeaksDuration; exports.videoAuthorableEffects = videoAuthorableEffects; exports.videoCacheEvictions = videoCacheEvictions; exports.videoCameraBase = videoCameraBase; exports.videoCameraMoveTools = videoCameraMoveTools; exports.videoCameraView = videoCameraView; exports.videoChroma = videoChroma; exports.videoClipAfter = _chunkZQIWBJGHcjs.videoClipAfter; exports.videoClipAnimated = _chunkZQIWBJGHcjs.videoClipAnimated; exports.videoClipAnimationProperties = _chunkZQIWBJGHcjs.videoClipAnimationProperties; exports.videoClipAnimationSpans = _chunkZQIWBJGHcjs.videoClipAnimationSpans; exports.videoClipAppliedEffects = videoClipAppliedEffects; exports.videoClipBefore = _chunkZQIWBJGHcjs.videoClipBefore; exports.videoClipCameraMove = videoClipCameraMove; exports.videoClipEffectDocument = videoClipEffectDocument; exports.videoClipEffectUses = _chunkZQIWBJGHcjs.videoClipEffectUses; exports.videoClipEnd = _chunkZQIWBJGHcjs.videoClipEnd; exports.videoClipHandles = _chunkZQIWBJGHcjs.videoClipHandles; exports.videoClipHeading = videoClipHeading; exports.videoClipKeyframes = videoClipKeyframes; exports.videoClipLabel = videoClipLabel; exports.videoClipOverhang = _chunkZQIWBJGHcjs.videoClipOverhang; exports.videoClipShowsWaveform = videoClipShowsWaveform; exports.videoClipSoundGain = _chunkZQIWBJGHcjs.videoClipSoundGain; exports.videoClipSourceRange = _chunkZQIWBJGHcjs.videoClipSourceRange; exports.videoClipSourceTime = _chunkZQIWBJGHcjs.videoClipSourceTime; exports.videoClipSpeed = _chunkZQIWBJGHcjs.videoClipSpeed; exports.videoClipSpeedAt = _chunkZQIWBJGHcjs.videoClipSpeedAt; exports.videoClipTint = videoClipTint; exports.videoClipTypeLabel = _chunkZQIWBJGHcjs.videoClipTypeLabel; exports.videoClipWaveform = videoClipWaveform; exports.videoClipWaveformPath = videoClipWaveformPath; exports.videoClipsAt = _chunkZQIWBJGHcjs.videoClipsAt; exports.videoContactSheetSvg = _chunkZQIWBJGHcjs.videoContactSheetSvg; exports.videoCutsWithMargin = videoCutsWithMargin; exports.videoDragLabel = videoDragLabel; exports.videoDropTracks = videoDropTracks; exports.videoDuckingKeys = videoDuckingKeys; exports.videoEaseBezier = _chunkZQIWBJGHcjs.videoEaseBezier; exports.videoEaseProgress = _chunkZQIWBJGHcjs.videoEaseProgress; exports.videoEaseToAnimationEasing = videoEaseToAnimationEasing; exports.videoEditsFromSequence = videoEditsFromSequence; exports.videoEffectFrameTime = _chunkZQIWBJGHcjs.videoEffectFrameTime; exports.videoEffectLayerKey = _chunkZQIWBJGHcjs.videoEffectLayerKey; exports.videoEffectValuesAt = _chunkZQIWBJGHcjs.videoEffectValuesAt; exports.videoEffectValuesFromDocument = videoEffectValuesFromDocument; exports.videoExposureNotes = videoExposureNotes; exports.videoExposureStats = videoExposureStats; exports.videoFadeCurveGain = _chunkZQIWBJGHcjs.videoFadeCurveGain; exports.videoFfmpegUnsupportedEffects = _chunkZQIWBJGHcjs.videoFfmpegUnsupportedEffects; exports.videoFfmpegUnsupportedFeatures = _chunkZQIWBJGHcjs.videoFfmpegUnsupportedFeatures; exports.videoFrameAt = _chunkZQIWBJGHcjs.videoFrameAt; exports.videoFrameCacheKey = videoFrameCacheKey; exports.videoFrameDuration = _chunkZQIWBJGHcjs.videoFrameDuration; exports.videoFrameLeafLayers = _chunkZQIWBJGHcjs.videoFrameLeafLayers; exports.videoFrameRequestsAt = videoFrameRequestsAt; exports.videoFrameToSvg = _chunkZQIWBJGHcjs.videoFrameToSvg; exports.videoFrames = _chunkZQIWBJGHcjs.videoFrames; exports.videoFreezeFrameEdit = _chunkZQIWBJGHcjs.videoFreezeFrameEdit; exports.videoGradeCssFilter = _chunkZQIWBJGHcjs.videoGradeCssFilter; exports.videoGradeFfmpegFilters = _chunkZQIWBJGHcjs.videoGradeFfmpegFilters; exports.videoGradeGainsFilterId = _chunkZQIWBJGHcjs.videoGradeGainsFilterId; exports.videoGradeLook = _chunkZQIWBJGHcjs.videoGradeLook; exports.videoGradePreset = _chunkZQIWBJGHcjs.videoGradePreset; exports.videoGradeStepMatrix = _chunkZQIWBJGHcjs.videoGradeStepMatrix; exports.videoGradeStepSvgValues = _chunkZQIWBJGHcjs.videoGradeStepSvgValues; exports.videoGradeSteps = _chunkZQIWBJGHcjs.videoGradeSteps; exports.videoGradeSvgDefs = _chunkZQIWBJGHcjs.videoGradeSvgDefs; exports.videoGradeSvgFilter = _chunkZQIWBJGHcjs.videoGradeSvgFilter; exports.videoHistogram = videoHistogram; exports.videoHistogramImage = videoHistogramImage; exports.videoHourFrames = _chunkZQIWBJGHcjs.videoHourFrames; exports.videoIrisRadius = _chunkZQIWBJGHcjs.videoIrisRadius; exports.videoIssueKey = videoIssueKey; exports.videoKeyTimesProblem = _chunkZQIWBJGHcjs.videoKeyTimesProblem; exports.videoKeyframeBreakpoints = _chunkZQIWBJGHcjs.videoKeyframeBreakpoints; exports.videoKeyframeFfmpegExpr = _chunkZQIWBJGHcjs.videoKeyframeFfmpegExpr; exports.videoKeyframeRows = videoKeyframeRows; exports.videoKeyframeToggleEdit = videoKeyframeToggleEdit; exports.videoKeyframeValueEdit = videoKeyframeValueEdit; exports.videoKeysOf = _chunkZQIWBJGHcjs.videoKeysOf; exports.videoLayerMask = _chunkZQIWBJGHcjs.videoLayerMask; exports.videoLayersUseEffects = _chunkZQIWBJGHcjs.videoLayersUseEffects; exports.videoLayersWithoutTransitionEffects = _chunkZQIWBJGHcjs.videoLayersWithoutTransitionEffects; exports.videoLoudnessEnergy = videoLoudnessEnergy; exports.videoLoudnessGain = videoLoudnessGain; exports.videoLoudnessOf = videoLoudnessOf; exports.videoLuma = videoLuma; exports.videoLumaWaveform = videoLumaWaveform; exports.videoLutEdits = videoLutEdits; exports.videoLutFromFunction = _chunkZQIWBJGHcjs.videoLutFromFunction; exports.videoLutSvgApproximation = _chunkZQIWBJGHcjs.videoLutSvgApproximation; exports.videoLutSvgPrimitives = _chunkZQIWBJGHcjs.videoLutSvgPrimitives; exports.videoLutToCube = _chunkZQIWBJGHcjs.videoLutToCube; exports.videoMaskContains = _chunkZQIWBJGHcjs.videoMaskContains; exports.videoMaskEdit = videoMaskEdit; exports.videoMaskPolygon = _chunkZQIWBJGHcjs.videoMaskPolygon; exports.videoMaskSvgPath = _chunkZQIWBJGHcjs.videoMaskSvgPath; exports.videoOverlap = _chunkZQIWBJGHcjs.videoOverlap; exports.videoPeakDb = videoPeakDb; exports.videoPreviewSrc = videoPreviewSrc; exports.videoProjectDuration = _chunkZQIWBJGHcjs.videoProjectDuration; exports.videoProjectEffects = _chunkZQIWBJGHcjs.videoProjectEffects; exports.videoProjectHasProxies = videoProjectHasProxies; exports.videoProjectSvg = _chunkZQIWBJGHcjs.videoProjectSvg; exports.videoProxyFfmpeg = videoProxyFfmpeg; exports.videoProxyName = videoProxyName; exports.videoProxyPlan = videoProxyPlan; exports.videoRemoveRangesEdits = videoRemoveRangesEdits; exports.videoRulerTicks = videoRulerTicks; exports.videoScopeImage = videoScopeImage; exports.videoSequenceChildren = _chunkZQIWBJGHcjs.videoSequenceChildren; exports.videoSequenceDuration = _chunkZQIWBJGHcjs.videoSequenceDuration; exports.videoSequenceMap = _chunkZQIWBJGHcjs.videoSequenceMap; exports.videoShellQuote = _chunkZQIWBJGHcjs.videoShellQuote; exports.videoSkinProtectionEdits = videoSkinProtectionEdits; exports.videoSkinToneWeight = _chunkZQIWBJGHcjs.videoSkinToneWeight; exports.videoSlowMotionRamp = _chunkZQIWBJGHcjs.videoSlowMotionRamp; exports.videoSnapPoints = _chunkZQIWBJGHcjs.videoSnapPoints; exports.videoSourceFrame = videoSourceFrame; exports.videoSourceFrameTime = videoSourceFrameTime; exports.videoSpeechRanges = videoSpeechRanges; exports.videoSpeedRampEdit = _chunkZQIWBJGHcjs.videoSpeedRampEdit; exports.videoSpeedRampKeys = _chunkZQIWBJGHcjs.videoSpeedRampKeys; exports.videoTextStyle = _chunkZQIWBJGHcjs.videoTextStyle; exports.videoTimeRef = videoTimeRef; exports.videoTimeRemapBreakpoints = _chunkZQIWBJGHcjs.videoTimeRemapBreakpoints; exports.videoTimeRemapSpan = _chunkZQIWBJGHcjs.videoTimeRemapSpan; exports.videoTimecodeFrames = _chunkZQIWBJGHcjs.videoTimecodeFrames; exports.videoTimelineTranscript = videoTimelineTranscript; exports.videoTitleFrame = _chunkZQIWBJGHcjs.videoTitleFrame; exports.videoTrackSyncLocked = _chunkZQIWBJGHcjs.videoTrackSyncLocked; exports.videoTranscriptEdit = videoTranscriptEdit; exports.videoTranscriptTrack = videoTranscriptTrack; exports.videoTransformAt = _chunkZQIWBJGHcjs.videoTransformAt; exports.videoTransformOfView = videoTransformOfView; exports.videoTransitionAudioCurve = _chunkZQIWBJGHcjs.videoTransitionAudioCurve; exports.videoTransitionEase = _chunkZQIWBJGHcjs.videoTransitionEase; exports.videoTransitionHasDirection = videoTransitionHasDirection; exports.videoValueAt = _chunkZQIWBJGHcjs.videoValueAt; exports.videoVectorscope = videoVectorscope; exports.videoVectorscopeAngle = videoVectorscopeAngle; exports.videoVectorscopeImage = videoVectorscopeImage; exports.videoVectorscopePoint = videoVectorscopePoint; exports.videoWaveformImage = videoWaveformImage; exports.videoWaveformPath = videoWaveformPath; exports.videoWipeRect = _chunkZQIWBJGHcjs.videoWipeRect; exports.videoWordAt = videoWordAt; exports.videoWordsRange = videoWordsRange; exports.withVideoPlayback = withVideoPlayback;
7126
+
7127
+
7128
+
7129
+
7130
+ exports.TranscriptVideoController = TranscriptVideoController; exports.VIDEO_ADJUSTMENT_SCOPES = _chunkXNZFVYC2cjs.VIDEO_ADJUSTMENT_SCOPES; exports.VIDEO_ADJUSTMENT_SCOPE_LABELS = VIDEO_ADJUSTMENT_SCOPE_LABELS; exports.VIDEO_BLEND_MODES = _chunkXNZFVYC2cjs.VIDEO_BLEND_MODES; exports.VIDEO_BLEND_MODE_LABELS = VIDEO_BLEND_MODE_LABELS; exports.VIDEO_CLIP_ANIMATION_DURATION = _chunkXNZFVYC2cjs.VIDEO_CLIP_ANIMATION_DURATION; exports.VIDEO_CLIP_ANIMATION_EFFECTS = _chunkXNZFVYC2cjs.VIDEO_CLIP_ANIMATION_EFFECTS; exports.VIDEO_CLIP_ANIMATION_LABELS = VIDEO_CLIP_ANIMATION_LABELS; exports.VIDEO_CLIP_TYPES = _chunkXNZFVYC2cjs.VIDEO_CLIP_TYPES; exports.VIDEO_DEFAULT_FILLERS = VIDEO_DEFAULT_FILLERS; exports.VIDEO_DEFAULT_STILL_DURATION = VIDEO_DEFAULT_STILL_DURATION; exports.VIDEO_DEFAULT_TITLE_DURATION = VIDEO_DEFAULT_TITLE_DURATION; exports.VIDEO_DISFLUENCY_KINDS = VIDEO_DISFLUENCY_KINDS; exports.VIDEO_EASE_NAMES = _chunkXNZFVYC2cjs.VIDEO_EASE_NAMES; exports.VIDEO_EDIT_OPS = VIDEO_EDIT_OPS; exports.VIDEO_EFFECT_PLACES = _chunkXNZFVYC2cjs.VIDEO_EFFECT_PLACES; exports.VIDEO_FADE_CURVES = _chunkXNZFVYC2cjs.VIDEO_FADE_CURVES; exports.VIDEO_FADE_CURVE_LABELS = VIDEO_FADE_CURVE_LABELS; exports.VIDEO_FITS = _chunkXNZFVYC2cjs.VIDEO_FITS; exports.VIDEO_GRADE_CONTROLS = _chunkXNZFVYC2cjs.VIDEO_GRADE_CONTROLS; exports.VIDEO_GRADE_PRESETS = _chunkXNZFVYC2cjs.VIDEO_GRADE_PRESETS; exports.VIDEO_GRADE_PRESET_NAMES = _chunkXNZFVYC2cjs.VIDEO_GRADE_PRESET_NAMES; exports.VIDEO_ISSUE_CODES = VIDEO_ISSUE_CODES; exports.VIDEO_KEYFRAME_LIMITS = _chunkXNZFVYC2cjs.VIDEO_KEYFRAME_LIMITS; exports.VIDEO_KEYFRAME_PROPERTIES = _chunkXNZFVYC2cjs.VIDEO_KEYFRAME_PROPERTIES; exports.VIDEO_LOUDNESS_HOP = VIDEO_LOUDNESS_HOP; exports.VIDEO_LUT_MAX_SIZE = _chunkXNZFVYC2cjs.VIDEO_LUT_MAX_SIZE; exports.VIDEO_MASK_DEFAULTS = _chunkXNZFVYC2cjs.VIDEO_MASK_DEFAULTS; exports.VIDEO_MASK_SHAPES = _chunkXNZFVYC2cjs.VIDEO_MASK_SHAPES; exports.VIDEO_MASK_SHAPE_LABELS = VIDEO_MASK_SHAPE_LABELS; exports.VIDEO_PEAK_BLOCK = VIDEO_PEAK_BLOCK; exports.VIDEO_PLACEMENT_MODES = _chunkXNZFVYC2cjs.VIDEO_PLACEMENT_MODES; exports.VIDEO_PREVIEW_SCALE_OPTIONS = VIDEO_PREVIEW_SCALE_OPTIONS; exports.VIDEO_PROXY_SCALES = VIDEO_PROXY_SCALES; exports.VIDEO_SCOPE_KINDS = VIDEO_SCOPE_KINDS; exports.VIDEO_TIME_EPSILON = _chunkXNZFVYC2cjs.VIDEO_TIME_EPSILON; exports.VIDEO_TRANSFORM_PROPERTIES = _chunkXNZFVYC2cjs.VIDEO_TRANSFORM_PROPERTIES; exports.VIDEO_TRANSITION_LABELS = VIDEO_TRANSITION_LABELS; exports.VIDEO_TRANSITION_TYPES = _chunkXNZFVYC2cjs.VIDEO_TRANSITION_TYPES; exports.VIDEO_VECTORSCOPE_TARGETS = VIDEO_VECTORSCOPE_TARGETS; exports.VIDEO_WIPE_DIRECTIONS = _chunkXNZFVYC2cjs.VIDEO_WIPE_DIRECTIONS; exports.VideoAudioPeaksCache = VideoAudioPeaksCache; exports.VideoEditorController = VideoEditorController; exports.VideoEffectsEngine = _chunkXNZFVYC2cjs.VideoEffectsEngine; exports.VideoFrameCache = VideoFrameCache; exports.VideoLutCache = _chunkXNZFVYC2cjs.VideoLutCache; exports.VideoPathGesture = VideoPathGesture; exports.VideoPreviewEngine = VideoPreviewEngine; exports.VideoPreviewPixels = VideoPreviewPixels; exports.allVideoClipIds = _chunkXNZFVYC2cjs.allVideoClipIds; exports.allVideoTracks = _chunkXNZFVYC2cjs.allVideoTracks; exports.animationEasingToVideoEase = animationEasingToVideoEase; exports.applyVideoEdits = applyVideoEdits; exports.applyVideoGrade = _chunkXNZFVYC2cjs.applyVideoGrade; exports.applyVideoLut = _chunkXNZFVYC2cjs.applyVideoLut; exports.applyVideoLutToPixels = _chunkXNZFVYC2cjs.applyVideoLutToPixels; exports.bakeVideoClipCamera = bakeVideoClipCamera; exports.buildVideoAudioPeaks = buildVideoAudioPeaks; exports.checkVideoEffectPlace = _chunkXNZFVYC2cjs.checkVideoEffectPlace; exports.checkVideoEffectValues = _chunkXNZFVYC2cjs.checkVideoEffectValues; exports.checkVideoProject = checkVideoProject; exports.checkVideoTimeRemap = _chunkXNZFVYC2cjs.checkVideoTimeRemap; exports.createVideoDialogueToolProvider = createVideoDialogueToolProvider; exports.createVideoEditorDocument = createVideoEditorDocument; exports.createVideoEditorToolProvider = createVideoEditorToolProvider; exports.createVideoEffectsToolProvider = createVideoEffectsToolProvider; exports.createVideoElementDecoder = createVideoElementDecoder; exports.createVideoMusicToolProvider = createVideoMusicToolProvider; exports.createVideoProject = createVideoProject; exports.decodeVideoAudioPeaks = decodeVideoAudioPeaks; exports.describeVideoEditPlan = describeVideoEditPlan; exports.describeVideoProject = describeVideoProject; exports.describeVideoSequence = describeVideoSequence; exports.detectVideoDisfluencies = detectVideoDisfluencies; exports.diffVideoProjects = diffVideoProjects; exports.drawVideoFrame = _chunkXNZFVYC2cjs.drawVideoFrame; exports.ffmpegFilterValue = _chunkXNZFVYC2cjs.ffmpegFilterValue; exports.findVideoAudioBeats = findVideoAudioBeats; exports.findVideoAudioSilences = findVideoAudioSilences; exports.findVideoClip = _chunkXNZFVYC2cjs.findVideoClip; exports.findVideoFillers = findVideoFillers; exports.findVideoGaps = _chunkXNZFVYC2cjs.findVideoGaps; exports.findVideoRepetitions = findVideoRepetitions; exports.findVideoSequenceClip = _chunkXNZFVYC2cjs.findVideoSequenceClip; exports.findVideoSequenceCycle = _chunkXNZFVYC2cjs.findVideoSequenceCycle; exports.findVideoTranscriptPauses = findVideoTranscriptPauses; exports.findVideoTranscriptText = findVideoTranscriptText; exports.formatVideoSeconds = _chunkXNZFVYC2cjs.formatVideoSeconds; exports.formatVideoTimecode = _chunkXNZFVYC2cjs.formatVideoTimecode; exports.formatVideoTimecodeFrames = _chunkXNZFVYC2cjs.formatVideoTimecodeFrames; exports.framePointsToPicture = framePointsToPicture; exports.isVideoDropFrameRate = _chunkXNZFVYC2cjs.isVideoDropFrameRate; exports.isVideoKeyframes = _chunkXNZFVYC2cjs.isVideoKeyframes; exports.measureVideoLoudness = measureVideoLoudness; exports.mergeVideoRanges = mergeVideoRanges; exports.mixEffectPixels = _chunkXNZFVYC2cjs.mixEffectPixels; exports.nearestVideoBeat = nearestVideoBeat; exports.nextFreeVideoSlot = _chunkXNZFVYC2cjs.nextFreeVideoSlot; exports.normalizeVideoClipMask = _chunkXNZFVYC2cjs.normalizeVideoClipMask; exports.normalizeVideoGrade = _chunkXNZFVYC2cjs.normalizeVideoGrade; exports.normalizeVideoGradeLut = _chunkXNZFVYC2cjs.normalizeVideoGradeLut; exports.normalizeVideoWord = normalizeVideoWord; exports.openVideoClipEffectAuthoring = openVideoClipEffectAuthoring; exports.overEffectPixels = _chunkXNZFVYC2cjs.overEffectPixels; exports.parseVideoAnimatable = parseVideoAnimatable; exports.parseVideoAsset = parseVideoAsset; exports.parseVideoAssetProxies = parseVideoAssetProxies; exports.parseVideoClip = parseVideoClip; exports.parseVideoClipAnimation = parseVideoClipAnimation; exports.parseVideoClipCamera = parseVideoClipCamera; exports.parseVideoClipEffects = parseVideoClipEffects; exports.parseVideoClipMask = parseVideoClipMask; exports.parseVideoCubeLut = _chunkXNZFVYC2cjs.parseVideoCubeLut; exports.parseVideoEffectRef = parseVideoEffectRef; exports.parseVideoEffectValues = parseVideoEffectValues; exports.parseVideoGrade = parseVideoGrade; exports.parseVideoGradeLut = parseVideoGradeLut; exports.parseVideoKeyframes = parseVideoKeyframes; exports.parseVideoLoudnessMeasurement = _chunkXNZFVYC2cjs.parseVideoLoudnessMeasurement; exports.parseVideoMarker = parseVideoMarker; exports.parseVideoPreviewScale = parseVideoPreviewScale; exports.parseVideoProject = parseVideoProject; exports.parseVideoSequence = parseVideoSequence; exports.parseVideoTimeRef = parseVideoTimeRef; exports.parseVideoTimeRemap = parseVideoTimeRemap; exports.parseVideoTrack = parseVideoTrack; exports.parseVideoTranscript = parseVideoTranscript; exports.parseVideoTranscriptWords = parseVideoTranscriptWords; exports.parseVideoTransform = parseVideoTransform; exports.parseVideoTransition = parseVideoTransition; exports.placeVideoRect = _chunkXNZFVYC2cjs.placeVideoRect; exports.planVideoClipDrag = planVideoClipDrag; exports.planVideoEdits = planVideoEdits; exports.planVideoPrefetch = planVideoPrefetch; exports.planVideoToolPlayback = planVideoToolPlayback; exports.probeVideoMedia = probeVideoMedia; exports.readVideoScopesPanel = readVideoScopesPanel; exports.removeVideoKey = _chunkXNZFVYC2cjs.removeVideoKey; exports.renderVideoFrameExact = _chunkXNZFVYC2cjs.renderVideoFrameExact; exports.resolveVideoPreviewScale = resolveVideoPreviewScale; exports.retimeVideoAnimatable = _chunkXNZFVYC2cjs.retimeVideoAnimatable; exports.setVideoKey = _chunkXNZFVYC2cjs.setVideoKey; exports.snapToVideoFrame = _chunkXNZFVYC2cjs.snapToVideoFrame; exports.snapVideoTime = _chunkXNZFVYC2cjs.snapVideoTime; exports.sortVideoKeys = _chunkXNZFVYC2cjs.sortVideoKeys; exports.sortedVideoClips = _chunkXNZFVYC2cjs.sortedVideoClips; exports.splitVideoAnimatable = _chunkXNZFVYC2cjs.splitVideoAnimatable; exports.summarizeVideoScopes = summarizeVideoScopes; exports.toVideoEdl = _chunkXNZFVYC2cjs.toVideoEdl; exports.toVideoFfmpeg = _chunkXNZFVYC2cjs.toVideoFfmpeg; exports.toVideoLoudnessMeasure = _chunkXNZFVYC2cjs.toVideoLoudnessMeasure; exports.videoAddAdjustmentEdits = videoAddAdjustmentEdits; exports.videoAssetDropEdit = videoAssetDropEdit; exports.videoAssetHasSound = _chunkXNZFVYC2cjs.videoAssetHasSound; exports.videoAssetKindOf = videoAssetKindOf; exports.videoAssetMap = _chunkXNZFVYC2cjs.videoAssetMap; exports.videoAssetProxy = videoAssetProxy; exports.videoAudioLevels = videoAudioLevels; exports.videoAudioLoudness = videoAudioLoudness; exports.videoAudioPeakRange = videoAudioPeakRange; exports.videoAudioPeakSpans = videoAudioPeakSpans; exports.videoAudioPeaksDuration = videoAudioPeaksDuration; exports.videoAuthorableEffects = videoAuthorableEffects; exports.videoCacheEvictions = videoCacheEvictions; exports.videoCameraBase = videoCameraBase; exports.videoCameraMoveTools = videoCameraMoveTools; exports.videoCameraView = videoCameraView; exports.videoChroma = videoChroma; exports.videoClipAfter = _chunkXNZFVYC2cjs.videoClipAfter; exports.videoClipAnimated = _chunkXNZFVYC2cjs.videoClipAnimated; exports.videoClipAnimationProperties = _chunkXNZFVYC2cjs.videoClipAnimationProperties; exports.videoClipAnimationSpans = _chunkXNZFVYC2cjs.videoClipAnimationSpans; exports.videoClipAppliedEffects = videoClipAppliedEffects; exports.videoClipBefore = _chunkXNZFVYC2cjs.videoClipBefore; exports.videoClipCameraMove = videoClipCameraMove; exports.videoClipEffectDocument = videoClipEffectDocument; exports.videoClipEffectUses = _chunkXNZFVYC2cjs.videoClipEffectUses; exports.videoClipEnd = _chunkXNZFVYC2cjs.videoClipEnd; exports.videoClipHandles = _chunkXNZFVYC2cjs.videoClipHandles; exports.videoClipHeading = videoClipHeading; exports.videoClipKeyframes = videoClipKeyframes; exports.videoClipLabel = videoClipLabel; exports.videoClipMaskOutline = videoClipMaskOutline; exports.videoClipOverhang = _chunkXNZFVYC2cjs.videoClipOverhang; exports.videoClipPicture = videoClipPicture; exports.videoClipShowsWaveform = videoClipShowsWaveform; exports.videoClipSoundGain = _chunkXNZFVYC2cjs.videoClipSoundGain; exports.videoClipSourceRange = _chunkXNZFVYC2cjs.videoClipSourceRange; exports.videoClipSourceTime = _chunkXNZFVYC2cjs.videoClipSourceTime; exports.videoClipSpeed = _chunkXNZFVYC2cjs.videoClipSpeed; exports.videoClipSpeedAt = _chunkXNZFVYC2cjs.videoClipSpeedAt; exports.videoClipTint = videoClipTint; exports.videoClipTypeLabel = _chunkXNZFVYC2cjs.videoClipTypeLabel; exports.videoClipWaveform = videoClipWaveform; exports.videoClipWaveformPath = videoClipWaveformPath; exports.videoClipsAt = _chunkXNZFVYC2cjs.videoClipsAt; exports.videoContactSheetSvg = _chunkXNZFVYC2cjs.videoContactSheetSvg; exports.videoCutsWithMargin = videoCutsWithMargin; exports.videoDragLabel = videoDragLabel; exports.videoDropTracks = videoDropTracks; exports.videoDuckingKeys = videoDuckingKeys; exports.videoEaseBezier = _chunkXNZFVYC2cjs.videoEaseBezier; exports.videoEaseProgress = _chunkXNZFVYC2cjs.videoEaseProgress; exports.videoEaseToAnimationEasing = videoEaseToAnimationEasing; exports.videoEditsFromSequence = videoEditsFromSequence; exports.videoEffectFrameTime = _chunkXNZFVYC2cjs.videoEffectFrameTime; exports.videoEffectLayerKey = _chunkXNZFVYC2cjs.videoEffectLayerKey; exports.videoEffectValuesAt = _chunkXNZFVYC2cjs.videoEffectValuesAt; exports.videoEffectValuesFromDocument = videoEffectValuesFromDocument; exports.videoExposureNotes = videoExposureNotes; exports.videoExposureStats = videoExposureStats; exports.videoFadeCurveGain = _chunkXNZFVYC2cjs.videoFadeCurveGain; exports.videoFfmpegUnsupportedEffects = _chunkXNZFVYC2cjs.videoFfmpegUnsupportedEffects; exports.videoFfmpegUnsupportedFeatures = _chunkXNZFVYC2cjs.videoFfmpegUnsupportedFeatures; exports.videoFrameAt = _chunkXNZFVYC2cjs.videoFrameAt; exports.videoFrameCacheKey = videoFrameCacheKey; exports.videoFrameDuration = _chunkXNZFVYC2cjs.videoFrameDuration; exports.videoFrameLeafLayers = _chunkXNZFVYC2cjs.videoFrameLeafLayers; exports.videoFrameRequestsAt = videoFrameRequestsAt; exports.videoFrameToSvg = _chunkXNZFVYC2cjs.videoFrameToSvg; exports.videoFrames = _chunkXNZFVYC2cjs.videoFrames; exports.videoFreezeFrameEdit = _chunkXNZFVYC2cjs.videoFreezeFrameEdit; exports.videoGradeCssFilter = _chunkXNZFVYC2cjs.videoGradeCssFilter; exports.videoGradeFfmpegFilters = _chunkXNZFVYC2cjs.videoGradeFfmpegFilters; exports.videoGradeGainsFilterId = _chunkXNZFVYC2cjs.videoGradeGainsFilterId; exports.videoGradeLook = _chunkXNZFVYC2cjs.videoGradeLook; exports.videoGradePreset = _chunkXNZFVYC2cjs.videoGradePreset; exports.videoGradeStepMatrix = _chunkXNZFVYC2cjs.videoGradeStepMatrix; exports.videoGradeStepSvgValues = _chunkXNZFVYC2cjs.videoGradeStepSvgValues; exports.videoGradeSteps = _chunkXNZFVYC2cjs.videoGradeSteps; exports.videoGradeSvgDefs = _chunkXNZFVYC2cjs.videoGradeSvgDefs; exports.videoGradeSvgFilter = _chunkXNZFVYC2cjs.videoGradeSvgFilter; exports.videoHistogram = videoHistogram; exports.videoHistogramImage = videoHistogramImage; exports.videoHourFrames = _chunkXNZFVYC2cjs.videoHourFrames; exports.videoIrisRadius = _chunkXNZFVYC2cjs.videoIrisRadius; exports.videoIssueKey = videoIssueKey; exports.videoKeyTimesProblem = _chunkXNZFVYC2cjs.videoKeyTimesProblem; exports.videoKeyframeBreakpoints = _chunkXNZFVYC2cjs.videoKeyframeBreakpoints; exports.videoKeyframeFfmpegExpr = _chunkXNZFVYC2cjs.videoKeyframeFfmpegExpr; exports.videoKeyframeRows = videoKeyframeRows; exports.videoKeyframeToggleEdit = videoKeyframeToggleEdit; exports.videoKeyframeValueEdit = videoKeyframeValueEdit; exports.videoKeysOf = _chunkXNZFVYC2cjs.videoKeysOf; exports.videoLayerMask = _chunkXNZFVYC2cjs.videoLayerMask; exports.videoLayersUseEffects = _chunkXNZFVYC2cjs.videoLayersUseEffects; exports.videoLayersWithoutTransitionEffects = _chunkXNZFVYC2cjs.videoLayersWithoutTransitionEffects; exports.videoLoudnessEnergy = videoLoudnessEnergy; exports.videoLoudnessGain = videoLoudnessGain; exports.videoLoudnessOf = videoLoudnessOf; exports.videoLuma = videoLuma; exports.videoLumaWaveform = videoLumaWaveform; exports.videoLutEdits = videoLutEdits; exports.videoLutFromFunction = _chunkXNZFVYC2cjs.videoLutFromFunction; exports.videoLutSvgApproximation = _chunkXNZFVYC2cjs.videoLutSvgApproximation; exports.videoLutSvgPrimitives = _chunkXNZFVYC2cjs.videoLutSvgPrimitives; exports.videoLutToCube = _chunkXNZFVYC2cjs.videoLutToCube; exports.videoMaskContains = _chunkXNZFVYC2cjs.videoMaskContains; exports.videoMaskEdit = videoMaskEdit; exports.videoMaskPolygon = _chunkXNZFVYC2cjs.videoMaskPolygon; exports.videoMaskSvgPath = _chunkXNZFVYC2cjs.videoMaskSvgPath; exports.videoOverlap = _chunkXNZFVYC2cjs.videoOverlap; exports.videoPeakDb = videoPeakDb; exports.videoPreviewSrc = videoPreviewSrc; exports.videoProjectDuration = _chunkXNZFVYC2cjs.videoProjectDuration; exports.videoProjectEffects = _chunkXNZFVYC2cjs.videoProjectEffects; exports.videoProjectHasProxies = videoProjectHasProxies; exports.videoProjectSvg = _chunkXNZFVYC2cjs.videoProjectSvg; exports.videoProxyFfmpeg = videoProxyFfmpeg; exports.videoProxyName = videoProxyName; exports.videoProxyPlan = videoProxyPlan; exports.videoRemoveRangesEdits = videoRemoveRangesEdits; exports.videoRulerTicks = videoRulerTicks; exports.videoScopeImage = videoScopeImage; exports.videoSequenceChildren = _chunkXNZFVYC2cjs.videoSequenceChildren; exports.videoSequenceDuration = _chunkXNZFVYC2cjs.videoSequenceDuration; exports.videoSequenceMap = _chunkXNZFVYC2cjs.videoSequenceMap; exports.videoShellQuote = _chunkXNZFVYC2cjs.videoShellQuote; exports.videoSkinProtectionEdits = videoSkinProtectionEdits; exports.videoSkinToneWeight = _chunkXNZFVYC2cjs.videoSkinToneWeight; exports.videoSlowMotionRamp = _chunkXNZFVYC2cjs.videoSlowMotionRamp; exports.videoSnapPoints = _chunkXNZFVYC2cjs.videoSnapPoints; exports.videoSourceFrame = videoSourceFrame; exports.videoSourceFrameTime = videoSourceFrameTime; exports.videoSpeechRanges = videoSpeechRanges; exports.videoSpeedRampEdit = _chunkXNZFVYC2cjs.videoSpeedRampEdit; exports.videoSpeedRampKeys = _chunkXNZFVYC2cjs.videoSpeedRampKeys; exports.videoTextStyle = _chunkXNZFVYC2cjs.videoTextStyle; exports.videoTimeRef = videoTimeRef; exports.videoTimeRemapBreakpoints = _chunkXNZFVYC2cjs.videoTimeRemapBreakpoints; exports.videoTimeRemapSpan = _chunkXNZFVYC2cjs.videoTimeRemapSpan; exports.videoTimecodeFrames = _chunkXNZFVYC2cjs.videoTimecodeFrames; exports.videoTimelineTranscript = videoTimelineTranscript; exports.videoTitleFrame = _chunkXNZFVYC2cjs.videoTitleFrame; exports.videoTrackSyncLocked = _chunkXNZFVYC2cjs.videoTrackSyncLocked; exports.videoTranscriptEdit = videoTranscriptEdit; exports.videoTranscriptTrack = videoTranscriptTrack; exports.videoTransformAt = _chunkXNZFVYC2cjs.videoTransformAt; exports.videoTransformOfView = videoTransformOfView; exports.videoTransitionAudioCurve = _chunkXNZFVYC2cjs.videoTransitionAudioCurve; exports.videoTransitionEase = _chunkXNZFVYC2cjs.videoTransitionEase; exports.videoTransitionHasDirection = videoTransitionHasDirection; exports.videoValueAt = _chunkXNZFVYC2cjs.videoValueAt; exports.videoVectorscope = videoVectorscope; exports.videoVectorscopeAngle = videoVectorscopeAngle; exports.videoVectorscopeImage = videoVectorscopeImage; exports.videoVectorscopePoint = videoVectorscopePoint; exports.videoWaveformImage = videoWaveformImage; exports.videoWaveformPath = videoWaveformPath; exports.videoWipeRect = _chunkXNZFVYC2cjs.videoWipeRect; exports.videoWordAt = videoWordAt; exports.videoWordsRange = videoWordsRange; exports.withVideoPlayback = withVideoPlayback;