@pixerate/editor 0.241.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.
- package/dist/animation-editor/controller.d.cts +10 -0
- package/dist/animation-editor/controller.d.ts +10 -0
- package/dist/animation-editor/effects.d.cts +1 -1
- package/dist/animation-editor/effects.d.ts +1 -1
- package/dist/animation-editor/index.cjs +137 -88
- package/dist/animation-editor/index.js +60 -11
- package/dist/canvas/index.cjs +7 -7
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-A7PQNIBX.cjs → chunk-7V7QMFTI.cjs} +14 -14
- package/dist/{chunk-JAOSL334.cjs → chunk-GHCSC2WP.cjs} +38 -16
- package/dist/{chunk-JWCKJNDR.cjs → chunk-K5DS2JTA.cjs} +6 -6
- package/dist/{chunk-WDDUPWVG.js → chunk-L3JFOTBQ.js} +1 -1
- package/dist/{chunk-SIK3LT6M.js → chunk-OFH6Q67U.js} +28 -6
- package/dist/{chunk-G3RUKJ5C.js → chunk-RXZL4NG5.js} +1 -1
- package/dist/{chunk-TEFQISBY.js → chunk-X3ZINLIP.js} +1 -1
- package/dist/{chunk-ZQIWBJGH.cjs → chunk-XNZFVYC2.cjs} +7 -7
- package/dist/effects/fake.d.cts +4 -0
- package/dist/effects/fake.d.ts +4 -0
- package/dist/effects/helpers.d.cts +6 -0
- package/dist/effects/helpers.d.ts +6 -0
- package/dist/effects/index.cjs +222 -94
- package/dist/effects/index.js +131 -3
- package/dist/effects/types.d.cts +31 -0
- package/dist/effects/types.d.ts +31 -0
- package/dist/image-editor/index.cjs +13 -13
- package/dist/image-editor/index.js +1 -1
- package/dist/paint-editor/index.cjs +7 -7
- package/dist/paint-editor/index.js +2 -2
- package/dist/vector/index.cjs +6 -6
- package/dist/vector/index.js +1 -1
- package/dist/video-editor/controller.d.cts +49 -1
- package/dist/video-editor/controller.d.ts +49 -1
- package/dist/video-editor/effect-path.d.cts +66 -0
- package/dist/video-editor/effect-path.d.ts +66 -0
- package/dist/video-editor/index.cjs +616 -427
- package/dist/video-editor/index.d.cts +1 -0
- package/dist/video-editor/index.d.ts +1 -0
- package/dist/video-editor/index.js +193 -4
- package/package.json +1 -1
- package/skills/pixerate-animation-editor/SKILL.md +1 -1
- 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
|
|
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
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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([...
|
|
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(
|
|
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,
|
|
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,
|
|
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,
|
|
344
|
-
audioCurve: oneOf(v.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")),
|
|
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,
|
|
482
|
-
blend: oneOf(v.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,
|
|
504
|
-
fadeOutCurve: oneOf(v.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,
|
|
517
|
-
fadeOutCurve: oneOf(v.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,
|
|
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:
|
|
636
|
-
{ property: "volume", keys: clip.type === "media" || clip.type === "sequence" ?
|
|
637
|
-
...
|
|
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 =
|
|
667
|
-
const sequences =
|
|
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 =
|
|
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,
|
|
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 =
|
|
689
|
-
const range =
|
|
690
|
-
if (range.out > length +
|
|
691
|
-
issues.push({ code: "source-overrun", severity: "error", ...at, message: `Compound clip "${clip.id}" plays to ${
|
|
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 =
|
|
701
|
-
if (asset.duration !== void 0 && range.out > asset.duration +
|
|
702
|
-
issues.push({ code: "source-overrun", severity: "error", ...at, message: `Clip "${clip.id}" plays to ${
|
|
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 <
|
|
709
|
-
issues.push({ code: "overlap", severity: "error", ...at, message: `Clips "${clip.id}" and "${next.id}" overlap on track "${track.id}"${where} from ${
|
|
710
|
-
if ((_nullishCoalesce(clip.fadeIn, () => ( 0))) + (_nullishCoalesce(clip.fadeOut, () => ( 0))) > clip.duration +
|
|
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, () => (
|
|
713
|
-
if (anim > clip.duration +
|
|
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 =
|
|
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, ...
|
|
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 +
|
|
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 < -
|
|
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 =
|
|
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 +
|
|
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 =
|
|
756
|
-
const incoming =
|
|
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 -
|
|
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 =
|
|
776
|
+
const end = _chunkXNZFVYC2cjs.videoProjectDuration.call(void 0, project);
|
|
776
777
|
for (const marker of _nullishCoalesce(project.markers, () => ( [])))
|
|
777
|
-
if (marker.time > 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] +
|
|
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
|
|
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 (
|
|
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 =
|
|
869
|
-
const nested = at ? null :
|
|
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 =
|
|
887
|
+
const hit = _chunkXNZFVYC2cjs.videoOverlap.call(void 0, track, start, start + duration, ignore);
|
|
887
888
|
if (hit) {
|
|
888
|
-
const free =
|
|
889
|
-
refuse(`${what} at ${
|
|
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 =
|
|
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 -
|
|
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
|
|
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(
|
|
927
|
-
for (const t of this.p.tracks) if (
|
|
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 >
|
|
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([
|
|
954
|
-
clip.in = Math.max(0, (_nullishCoalesce(clip.in, () => ( 0))) + delta *
|
|
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) =>
|
|
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 =
|
|
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] =
|
|
973
|
-
if (
|
|
974
|
-
if (
|
|
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 -
|
|
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 =
|
|
1007
|
+
const hit = _chunkXNZFVYC2cjs.videoOverlap.call(void 0, t, from, to);
|
|
1007
1008
|
if (hit)
|
|
1008
1009
|
refuse(
|
|
1009
|
-
`Rippling out ${
|
|
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 =
|
|
1022
|
-
if (end <= from +
|
|
1023
|
-
const coversHead = start >= from -
|
|
1024
|
-
const coversTail = end <= to +
|
|
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) >
|
|
1048
|
-
return Math.abs(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,
|
|
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 && !
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
1187
|
-
const end =
|
|
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 =
|
|
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 -
|
|
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 < -
|
|
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) =>
|
|
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 -
|
|
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 +
|
|
1225
|
-
refuse(`"${clip.id}" can end at most at ${
|
|
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 =
|
|
1229
|
-
const length = seq ?
|
|
1230
|
-
if ((_nullishCoalesce(clip.in, () => ( 0))) + duration > length +
|
|
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 =
|
|
1253
|
+
const end = _chunkXNZFVYC2cjs.videoClipEnd.call(void 0, clip);
|
|
1253
1254
|
const minimum = 1e3 / this.p.fps;
|
|
1254
|
-
if (e.at < clip.start + minimum -
|
|
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) => !
|
|
1266
|
-
if (found.some((f) =>
|
|
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,
|
|
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 =
|
|
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) =>
|
|
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 ${
|
|
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 =
|
|
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 -
|
|
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 +
|
|
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 =
|
|
1327
|
-
|
|
1328
|
-
const span =
|
|
1329
|
-
if (asset.duration !== void 0 && (_nullishCoalesce(media.in, () => ( 0))) + span.to > asset.duration +
|
|
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) >
|
|
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 ${
|
|
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 =
|
|
1369
|
-
const { lead, tail } =
|
|
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(
|
|
1388
|
-
if (Math.abs(
|
|
1389
|
-
refuse(`"${L.id}" ends at ${
|
|
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 =
|
|
1392
|
-
const lo = Math.max(-(L.duration - this.frame), -(
|
|
1393
|
-
const hi = Math.min(R.duration - this.frame,
|
|
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 =
|
|
1410
|
-
const after =
|
|
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 =
|
|
1413
|
-
const end =
|
|
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) =>
|
|
1417
|
-
later: after ? after.duration - this.frame : others.filter((c) => c.start >= end -
|
|
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 ?
|
|
1420
|
-
const hi = Math.min(room.later, before ?
|
|
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 -
|
|
1454
|
-
if (!lefts.length) refuse(`No clip runs across ${
|
|
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 (!
|
|
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 =
|
|
1464
|
-
const transform =
|
|
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 =
|
|
1470
|
-
value =
|
|
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 =
|
|
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
|
|
1495
|
-
if (clip.start >= (_nullishCoalesce(e.from, () => ( 0))) -
|
|
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,
|
|
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 =
|
|
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 =
|
|
1638
|
+
const assets = _chunkXNZFVYC2cjs.videoAssetMap.call(void 0, project);
|
|
1638
1639
|
const out = [];
|
|
1639
|
-
for (const clip of
|
|
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 =
|
|
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(
|
|
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 =
|
|
1692
|
-
to =
|
|
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 >
|
|
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 >
|
|
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 +
|
|
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 -
|
|
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 -
|
|
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 >
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
2221
|
-
const durationAfter =
|
|
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 = (
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
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
|
-
},
|
|
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 =
|
|
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(
|
|
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 =
|
|
2730
|
+
const moveIn = _chunkGHCSC2WPcjs.cameraMoveParts.call(void 0, camera.in);
|
|
2663
2731
|
if (moveIn) {
|
|
2664
|
-
const { description } = await
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 = (
|
|
2709
|
-
constructor(controller, options = {}) {;
|
|
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
|
-
|
|
2719
|
-
|
|
2786
|
+
__init11() {this.listeners = /* @__PURE__ */ new Set()}
|
|
2787
|
+
__init12() {this.unsubscribe = null}
|
|
2720
2788
|
|
|
2721
|
-
|
|
2722
|
-
|
|
2789
|
+
__init13() {this.selection = null}
|
|
2790
|
+
__init14() {this.error = null}
|
|
2723
2791
|
|
|
2724
2792
|
/** Words and disfluencies are worked out once per project. */
|
|
2725
|
-
|
|
2726
|
-
|
|
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
|
-
|
|
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
|
-
},
|
|
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(
|
|
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
|
|
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 = (
|
|
3008
|
-
constructor(options = {}) {;
|
|
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
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
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
|
-
},
|
|
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 = (
|
|
3204
|
-
constructor(source, canvas2, options = {}) {;
|
|
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
|
-
|
|
3230
|
-
|
|
3297
|
+
__init30() {this.media = /* @__PURE__ */ new Map()}
|
|
3298
|
+
__init31() {this.images = /* @__PURE__ */ new Map()}
|
|
3231
3299
|
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
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
|
-
|
|
3239
|
-
|
|
3306
|
+
__init36() {this.drawn = null}
|
|
3307
|
+
__init37() {this.complete = true}
|
|
3240
3308
|
|
|
3241
3309
|
|
|
3242
3310
|
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3311
|
+
__init38() {this.srcFor = (layer) => layer.src}
|
|
3312
|
+
__init39() {this.playing = false}
|
|
3313
|
+
__init40() {this.fps = 30}
|
|
3246
3314
|
|
|
3247
|
-
|
|
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 =
|
|
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
|
|
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]) || !
|
|
3343
|
-
const at =
|
|
3344
|
-
return at === frame.time ? frame : { ...
|
|
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,
|
|
3421
|
+
this.draw(this.drawable(project, _chunkXNZFVYC2cjs.videoFrameAt.call(void 0, project, time)));
|
|
3354
3422
|
});
|
|
3355
3423
|
}
|
|
3356
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
},
|
|
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, () => (
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 &&
|
|
3523
|
-
const item = { group: isBase ? "base" :
|
|
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 = (
|
|
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
|
-
|
|
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
|
-
|
|
3651
|
+
__init47() {this.selection = []}
|
|
3584
3652
|
|
|
3585
3653
|
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3654
|
+
__init48() {this.error = null}
|
|
3655
|
+
__init49() {this.revision = 0}
|
|
3656
|
+
__init50() {this.applying = false}
|
|
3589
3657
|
|
|
3590
|
-
|
|
3591
|
-
|
|
3658
|
+
__init51() {this.listeners = /* @__PURE__ */ new Set()}
|
|
3659
|
+
__init52() {this.unsubscribers = []}
|
|
3592
3660
|
|
|
3593
|
-
|
|
3661
|
+
__init53() {this.plans = []}
|
|
3594
3662
|
/** The project each open plan was worked out against. */
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
constructor(options = {}) {;
|
|
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
|
|
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,
|
|
3670
|
+
this.effects = new (0, _chunkGHCSC2WPcjs.EffectsSlot)();
|
|
3603
3671
|
if (options.effects) this.effects.set(options.effects);
|
|
3604
|
-
this.effectsEngine = new (0,
|
|
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: () =>
|
|
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
|
-
|
|
3631
|
-
|
|
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:
|
|
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:
|
|
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(() =>
|
|
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) =>
|
|
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,
|
|
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 =
|
|
3892
|
-
const hit =
|
|
3893
|
-
return hit.snapped !== null ? hit : { time: Math.max(0,
|
|
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 =
|
|
3898
|
-
const under =
|
|
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)
|
|
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
|
|
4010
|
+
filled = await _chunkK5DS2JTAcjs.fillEffectTemplate.call(void 0, this.effects.provider, template, values, options.name ? { name: options.name } : {});
|
|
3942
4011
|
} catch (error) {
|
|
3943
|
-
if (
|
|
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 (
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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
|
|
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) })), [
|
|
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 (
|
|
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 =
|
|
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 (
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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:
|
|
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 =
|
|
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([
|
|
4182
|
-
const was = _optionalChain([current, 'optionalAccess',
|
|
4183
|
-
const value = _optionalChain([was, 'optionalAccess',
|
|
4184
|
-
const plain = keys === null ?
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
4349
|
+
return _chunkXNZFVYC2cjs.toVideoEdl.call(void 0, this.project, options);
|
|
4206
4350
|
}
|
|
4207
|
-
},
|
|
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',
|
|
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:
|
|
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" || !
|
|
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',
|
|
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',
|
|
4339
|
-
const speed =
|
|
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 =
|
|
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)),
|
|
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:
|
|
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(
|
|
4366
|
-
const changed = Math.abs(to -
|
|
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 =
|
|
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 =
|
|
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',
|
|
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) =>
|
|
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 =
|
|
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" ?
|
|
4438
|
-
const visual = !(_optionalChain([asset, 'optionalAccess',
|
|
4439
|
-
const audible = clip.type === "media" &&
|
|
4440
|
-
const properties = [...visual ? ["opacity"] : [], ...audible ? ["volume"] : [], ...visual ?
|
|
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 =
|
|
4445
|
-
const limits =
|
|
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(
|
|
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 (!
|
|
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 =
|
|
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 (!
|
|
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:
|
|
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 =
|
|
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 =
|
|
4480
|
-
if (
|
|
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 =
|
|
4484
|
-
return
|
|
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 =
|
|
4488
|
-
return { op: "set_keyframes", clip: clipId, property, keys:
|
|
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 =
|
|
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 =
|
|
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 &&
|
|
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',
|
|
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([
|
|
4538
|
-
const lut = _optionalChain([clip, 'optionalAccess',
|
|
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: [...
|
|
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:
|
|
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: [...
|
|
4592
|
-
audioCurve: { type: "string", enum: [...
|
|
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(
|
|
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: [...
|
|
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: [...
|
|
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: [...
|
|
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: [...
|
|
4634
|
-
fadeOutCurve: { type: "string", enum: [...
|
|
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: [...
|
|
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: [...
|
|
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:
|
|
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) =>
|
|
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:
|
|
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 =
|
|
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:
|
|
4881
|
+
duration: _chunkXNZFVYC2cjs.videoSequenceDuration.call(void 0, sequence),
|
|
4738
4882
|
clipCount: sequence.tracks.reduce((n, t) => n + t.clips.length, 0),
|
|
4739
|
-
nests:
|
|
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:
|
|
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',
|
|
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:
|
|
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:
|
|
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',
|
|
4783
|
-
..._optionalChain([o, 'access',
|
|
4784
|
-
..._optionalChain([o, 'access',
|
|
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 =
|
|
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 =
|
|
4812
|
-
return { ...frame, timecode:
|
|
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:
|
|
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',
|
|
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 ?
|
|
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:
|
|
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: [...
|
|
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 =
|
|
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',
|
|
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: [...
|
|
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 =
|
|
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([
|
|
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 =
|
|
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([
|
|
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([
|
|
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([
|
|
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',
|
|
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 +
|
|
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',
|
|
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 =
|
|
5363
|
-
return apply(videoRemoveRangesEdits(merged, tracks), merged.length > 1 ? `Cut ${merged.length} stretches` : "Cut stretch", (r) => ({ removed: merged.length, time: round(before -
|
|
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 =
|
|
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 ${
|
|
5372
|
-
if (_optionalChain([project, 'call',
|
|
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:
|
|
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 =
|
|
5409
|
-
return apply(edit, "Speed ramp", (r) => ({ ...rampOut(r, clip), source: Math.round(
|
|
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(`${
|
|
5430
|
-
return apply(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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:
|
|
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: [...
|
|
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: [...
|
|
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: [...
|
|
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 ?
|
|
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 =
|
|
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 =
|
|
5788
|
-
const lut = _optionalChain([clip, 'access',
|
|
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([
|
|
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:
|
|
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',
|
|
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:
|
|
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',
|
|
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: [...
|
|
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 =
|
|
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',
|
|
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(
|
|
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
|
-
...
|
|
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: [...
|
|
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',
|
|
6144
|
-
const plain = keys === null ?
|
|
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:
|
|
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 =
|
|
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(
|
|
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${
|
|
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 (
|
|
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 (
|
|
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
|
|
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 >
|
|
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 (
|
|
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 =
|
|
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 =
|
|
6472
|
-
if (Math.abs(right.start - cut) >
|
|
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 (
|
|
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 =
|
|
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
|
|
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;
|