@pixerate/editor 0.123.0 → 0.124.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/agent/index.cjs +2 -2
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.js +3 -3
- package/dist/animation/index.d.cts +2 -1
- package/dist/animation/index.d.ts +2 -1
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +11 -733
- package/dist/animation-editor/index.d.ts +11 -733
- package/dist/animation-editor/index.js.map +1 -1
- package/dist/{bezier-C-W9LFyD.d.cts → bezier-CBzKKDjl.d.cts} +2 -66
- package/dist/{bezier-DQZE5dxA.d.ts → bezier-CWv6LQal.d.ts} +2 -66
- package/dist/{brushstrokeRender-M4S65DHT.cjs → brushstrokeRender-EELTV7U4.cjs} +8 -8
- package/dist/{brushstrokeRender-M4S65DHT.cjs.map → brushstrokeRender-EELTV7U4.cjs.map} +1 -1
- package/dist/{brushstrokeRender-CDDRSV2W.js → brushstrokeRender-LRV7GXGD.js} +3 -3
- package/dist/canvas/index.cjs +6 -6
- package/dist/canvas/index.d.cts +10 -6
- package/dist/canvas/index.d.ts +10 -6
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-TVXFHE4T.js → chunk-64PYNEHJ.js} +45 -12
- package/dist/chunk-64PYNEHJ.js.map +1 -0
- package/dist/{chunk-2IW3BWRT.cjs → chunk-7LQO6OHH.cjs} +2 -2
- package/dist/{chunk-2IW3BWRT.cjs.map → chunk-7LQO6OHH.cjs.map} +1 -1
- package/dist/chunk-IOXKXQNW.cjs +178 -0
- package/dist/chunk-IOXKXQNW.cjs.map +1 -0
- package/dist/{chunk-SMJGE7HM.cjs → chunk-IWSMDQE5.cjs} +523 -39
- package/dist/chunk-IWSMDQE5.cjs.map +1 -0
- package/dist/{chunk-KMBC4HNV.js → chunk-J67OLQUQ.js} +2 -2
- package/dist/{chunk-6CJRDJCU.cjs → chunk-PEHYWUVV.cjs} +176 -111
- package/dist/chunk-PEHYWUVV.cjs.map +1 -0
- package/dist/chunk-TGKT5QAB.js +178 -0
- package/dist/chunk-TGKT5QAB.js.map +1 -0
- package/dist/chunk-TK53AB4Q.cjs +215 -0
- package/dist/chunk-TK53AB4Q.cjs.map +1 -0
- package/dist/chunk-VFAKN46Z.js +215 -0
- package/dist/chunk-VFAKN46Z.js.map +1 -0
- package/dist/{chunk-6ZBR4J62.js → chunk-WATAQ2Z2.js} +79 -14
- package/dist/chunk-WATAQ2Z2.js.map +1 -0
- package/dist/{chunk-IPFRWILU.js → chunk-YVVSTD3B.js} +499 -15
- package/dist/chunk-YVVSTD3B.js.map +1 -0
- package/dist/{chunk-RLRUAPBJ.cjs → chunk-Z6OUCS2K.cjs} +47 -14
- package/dist/chunk-Z6OUCS2K.cjs.map +1 -0
- package/dist/effects/index.cjs +588 -0
- package/dist/effects/index.cjs.map +1 -0
- package/dist/effects/index.d.cts +131 -0
- package/dist/effects/index.d.ts +131 -0
- package/dist/effects/index.js +588 -0
- package/dist/effects/index.js.map +1 -0
- package/dist/evaluate-2S3vSPLy.d.cts +55 -0
- package/dist/evaluate-CfmT6xA3.d.ts +55 -0
- package/dist/{export-DfjzHAJI.d.ts → export-8RnlngAv.d.ts} +534 -128
- package/dist/{export-Dv0-ZVrV.d.ts → export-BzSRXyH6.d.cts} +390 -5
- package/dist/{export-Dv0-ZVrV.d.cts → export-DM3h7QEI.d.ts} +390 -5
- package/dist/{export-lU5qSpHE.d.cts → export-TqXMOlDt.d.cts} +534 -128
- package/dist/flair-CxB3fOcU.d.ts +739 -0
- package/dist/flair-D7BxyBwL.d.cts +739 -0
- package/dist/gradient-KDfCvhuj.d.cts +66 -0
- package/dist/gradient-KDfCvhuj.d.ts +66 -0
- package/dist/helpers-777mC6dc.d.cts +253 -0
- package/dist/helpers-DX2_7L5t.d.ts +253 -0
- package/dist/image-editor/index.cjs +1307 -805
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +39 -182
- package/dist/image-editor/index.d.ts +39 -182
- package/dist/image-editor/index.js +508 -6
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{opentype-p8Xxf-Wh.d.ts → opentype-14PDI5D2.d.ts} +1 -1
- package/dist/{opentype-BV7wWatY.d.cts → opentype-D80AVmMu.d.cts} +1 -1
- package/dist/paint/index.cjs +2 -2
- package/dist/paint/index.d.cts +32 -10
- package/dist/paint/index.d.ts +32 -10
- package/dist/paint/index.js +1 -1
- package/dist/paint-editor/index.cjs +10 -8
- package/dist/paint-editor/index.cjs.map +1 -1
- package/dist/paint-editor/index.d.cts +11 -5
- package/dist/paint-editor/index.d.ts +11 -5
- package/dist/paint-editor/index.js +4 -2
- package/dist/paint-editor/index.js.map +1 -1
- package/dist/parameters/index.d.cts +4 -184
- package/dist/parameters/index.d.ts +4 -184
- package/dist/{pathfinder-IxcyhO00.d.cts → pathfinder-C0UoFypx.d.cts} +1 -1
- package/dist/{pathfinder-StVChJOT.d.ts → pathfinder-DjISxkUv.d.ts} +1 -1
- package/dist/{player-DrcP2xqj.d.cts → player-CBtEoU2x.d.cts} +2 -54
- package/dist/{player-DV4Jujdq.d.ts → player-cGLrngL_.d.ts} +2 -54
- package/dist/{svg-BtND4TJu.d.cts → svg-BDrjRnL1.d.cts} +3 -2
- package/dist/{svg-BfVXG7hL.d.ts → svg-C-vZ3q50.d.ts} +3 -2
- package/dist/tools/index.cjs +2 -2
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.js +3 -3
- package/dist/tools-C7JtLYzo.d.ts +126 -0
- package/dist/tools-DHKGHiSK.d.cts +126 -0
- package/dist/{types-fuXEme9j.d.ts → types-BcX7sCsn.d.ts} +2 -2
- package/dist/{types-DJF3Ghn5.d.cts → types-CznabG7m.d.cts} +2 -2
- package/dist/types-D3-J3TFf.d.ts +185 -0
- package/dist/types-DMcf_z4J.d.cts +185 -0
- package/dist/vector/index.d.cts +10 -10
- package/dist/vector/index.d.ts +10 -10
- package/dist/video-editor/index.cjs +749 -277
- package/dist/video-editor/index.cjs.map +1 -1
- package/dist/video-editor/index.d.cts +265 -138
- package/dist/video-editor/index.d.ts +265 -138
- package/dist/video-editor/index.js +490 -18
- package/dist/video-editor/index.js.map +1 -1
- package/dist/{warp-BjmAgQwq.d.cts → warp-CH9MM435.d.cts} +1 -1
- package/dist/{warp-Ca5fedzS.d.ts → warp-k_PdtXOG.d.ts} +1 -1
- package/package.json +6 -1
- package/skills/pixerate-image-editor/SKILL.md +7 -0
- package/skills/pixerate-image-editor/references/provider-effects.md +35 -0
- package/skills/pixerate-video-editor/SKILL.md +39 -1
- package/dist/chunk-6CJRDJCU.cjs.map +0 -1
- package/dist/chunk-6ZBR4J62.js.map +0 -1
- package/dist/chunk-IPFRWILU.js.map +0 -1
- package/dist/chunk-RLRUAPBJ.cjs.map +0 -1
- package/dist/chunk-SMJGE7HM.cjs.map +0 -1
- package/dist/chunk-TVXFHE4T.js.map +0 -1
- /package/dist/{brushstrokeRender-CDDRSV2W.js.map → brushstrokeRender-LRV7GXGD.js.map} +0 -0
- /package/dist/{chunk-KMBC4HNV.js.map → chunk-J67OLQUQ.js.map} +0 -0
|
@@ -119,7 +119,30 @@
|
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
var _chunkIWSMDQE5cjs = require('../chunk-IWSMDQE5.cjs');
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
var _chunkTK53AB4Qcjs = require('../chunk-TK53AB4Q.cjs');
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
var _chunkIOXKXQNWcjs = require('../chunk-IOXKXQNW.cjs');
|
|
145
|
+
require('../chunk-RIWPYSKU.cjs');
|
|
123
146
|
|
|
124
147
|
|
|
125
148
|
var _chunkWAJQKWQUcjs = require('../chunk-WAJQKWQU.cjs');
|
|
@@ -169,7 +192,7 @@ function parseVideoEase(v, path) {
|
|
|
169
192
|
if (v[0] < 0 || v[0] > 1 || v[2] < 0 || v[2] > 1) fail(path, "must have x1 and x2 between 0 and 1");
|
|
170
193
|
return [v[0], v[1], v[2], v[3]];
|
|
171
194
|
}
|
|
172
|
-
return oneOf(v,
|
|
195
|
+
return oneOf(v, _chunkIWSMDQE5cjs.VIDEO_EASE_NAMES, path);
|
|
173
196
|
}
|
|
174
197
|
function parseVideoKeyframes(v, path, { min, max } = {}) {
|
|
175
198
|
if (!isObject(v)) return fail(path, "must be a number or keyframes { keys: [{ t, v, ease }] }");
|
|
@@ -207,7 +230,7 @@ function parseVideoTimeRemap(v, speed, path) {
|
|
|
207
230
|
if (typeof remap === "number" || remap === void 0) return fail(path, "must be keyframes { keys: [{ t, v, ease }] } (v: ms of source after the in point)");
|
|
208
231
|
if (speed !== void 0 && speed !== 1) fail(path, 'cannot be used with a speed; a ramp sets the speed itself (remove "speed")');
|
|
209
232
|
try {
|
|
210
|
-
|
|
233
|
+
_chunkIWSMDQE5cjs.checkVideoTimeRemap.call(void 0, remap, path);
|
|
211
234
|
} catch (e) {
|
|
212
235
|
throw new Error(e.message.replace(/\.?$/, "."));
|
|
213
236
|
}
|
|
@@ -217,17 +240,17 @@ function parseVideoClipAnimation(v, path) {
|
|
|
217
240
|
if (v === void 0) return void 0;
|
|
218
241
|
if (!isObject(v)) return fail(path, "must be an object { effect, duration }");
|
|
219
242
|
return compact({
|
|
220
|
-
effect: oneOf(v.effect,
|
|
243
|
+
effect: oneOf(v.effect, _chunkIWSMDQE5cjs.VIDEO_CLIP_ANIMATION_EFFECTS, `${path}.effect`, false),
|
|
221
244
|
duration: num(v.duration, `${path}.duration`, { optional: true, positive: true })
|
|
222
245
|
});
|
|
223
246
|
}
|
|
224
247
|
function parseVideoGrade(v, path) {
|
|
225
248
|
if (v === void 0) return void 0;
|
|
226
249
|
if (!isObject(v)) return fail(path, "must be an object such as { exposure, contrast, saturation }");
|
|
227
|
-
const known = /* @__PURE__ */ new Set([...
|
|
250
|
+
const known = /* @__PURE__ */ new Set([..._chunkIWSMDQE5cjs.VIDEO_GRADE_CONTROLS.map((c) => c.key), "lut"]);
|
|
228
251
|
const unknown = Object.keys(v).find((k) => !known.has(k));
|
|
229
252
|
if (unknown) fail(`${path}.${unknown}`, `is not a grade setting; use ${[...known].join(", ")}`);
|
|
230
|
-
return compact({ ...Object.fromEntries(
|
|
253
|
+
return compact({ ...Object.fromEntries(_chunkIWSMDQE5cjs.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`) });
|
|
231
254
|
}
|
|
232
255
|
function parseVideoGradeLut(v, path) {
|
|
233
256
|
if (v === void 0) return void 0;
|
|
@@ -239,13 +262,52 @@ function parseVideoGradeLut(v, path) {
|
|
|
239
262
|
function parseVideoTransition(v, path) {
|
|
240
263
|
if (v === void 0) return void 0;
|
|
241
264
|
if (!isObject(v)) return fail(path, "must be an object { type, duration }");
|
|
265
|
+
const type = oneOf(v.type, _chunkIWSMDQE5cjs.VIDEO_TRANSITION_TYPES, `${path}.type`, false);
|
|
266
|
+
if (type === "effect" && v.effect === void 0) fail(`${path}.effect`, 'is required for an effect transition: { effect: "<effect id>", values }');
|
|
267
|
+
if (type !== "effect" && v.effect !== void 0) fail(`${path}.effect`, 'is only for transitions of type "effect"');
|
|
242
268
|
return compact({
|
|
243
|
-
type
|
|
269
|
+
type,
|
|
244
270
|
duration: num(v.duration, `${path}.duration`, { positive: true }),
|
|
245
271
|
color: str(v.color, `${path}.color`, true),
|
|
246
|
-
direction: oneOf(v.direction,
|
|
247
|
-
audioCurve: oneOf(v.audioCurve,
|
|
272
|
+
direction: oneOf(v.direction, _chunkIWSMDQE5cjs.VIDEO_WIPE_DIRECTIONS, `${path}.direction`),
|
|
273
|
+
audioCurve: oneOf(v.audioCurve, _chunkIWSMDQE5cjs.VIDEO_FADE_CURVES, `${path}.audioCurve`),
|
|
274
|
+
effect: v.effect === void 0 ? void 0 : parseVideoEffectRef(v.effect, `${path}.effect`, false)
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
var isEffectValue = (x) => typeof x === "string" || typeof x === "boolean" || typeof x === "number" && Number.isFinite(x) || Array.isArray(x) && x.every((n) => typeof n === "number" && Number.isFinite(n));
|
|
278
|
+
function parseVideoEffectValues(v, path, keyframes = true) {
|
|
279
|
+
if (v === void 0) return void 0;
|
|
280
|
+
if (!isObject(v)) return fail(path, "must be an object of control values from describe_effect");
|
|
281
|
+
const out = {};
|
|
282
|
+
for (const [k, x] of Object.entries(v)) {
|
|
283
|
+
if (isEffectValue(x)) out[k] = Array.isArray(x) ? [...x] : x;
|
|
284
|
+
else if (keyframes && isObject(x)) out[k] = parseVideoKeyframes(x, `${path}.${k}`);
|
|
285
|
+
else fail(`${path}.${k}`, keyframes ? "must be a number, string, true / false, a list of numbers, or keyframes { keys }" : "must be a number, string, true / false or a list of numbers");
|
|
286
|
+
}
|
|
287
|
+
return out;
|
|
288
|
+
}
|
|
289
|
+
function parseVideoEffectRef(v, path, keyframes = true) {
|
|
290
|
+
if (!isObject(v)) return fail(path, "must be an object { effect, values }");
|
|
291
|
+
const unknown = Object.keys(v).find((k) => !["effect", "provider", "name", "values"].includes(k));
|
|
292
|
+
if (unknown) fail(`${path}.${unknown}`, "is not an effect field; use effect, provider, name, values");
|
|
293
|
+
return compact({ effect: str(v.effect, `${path}.effect`), provider: str(v.provider, `${path}.provider`, true), name: str(v.name, `${path}.name`, true), values: parseVideoEffectValues(v.values, `${path}.values`, keyframes) });
|
|
294
|
+
}
|
|
295
|
+
function parseVideoClipEffects(v, path) {
|
|
296
|
+
if (v === void 0) return void 0;
|
|
297
|
+
if (!Array.isArray(v)) return fail(path, "must be a list of effects { id, effect, values }");
|
|
298
|
+
const ids = /* @__PURE__ */ new Set();
|
|
299
|
+
const out = v.map((e, i) => {
|
|
300
|
+
const at = `${path}[${i}]`;
|
|
301
|
+
if (!isObject(e)) return fail(at, "must be an object { id, effect, values }");
|
|
302
|
+
const unknown = Object.keys(e).find((k) => !["id", "effect", "provider", "name", "values", "enabled", "opacity"].includes(k));
|
|
303
|
+
if (unknown) fail(`${at}.${unknown}`, "is not a clip effect field; use id, effect, provider, name, values, enabled, opacity");
|
|
304
|
+
const id = str(e.id, `${at}.id`);
|
|
305
|
+
if (ids.has(id)) fail(`${at}.id`, `repeats "${id}"; each effect on a clip needs its own id`);
|
|
306
|
+
ids.add(id);
|
|
307
|
+
const { effect, provider, name, values } = parseVideoEffectRef({ effect: e.effect, provider: e.provider, name: e.name, values: e.values }, at);
|
|
308
|
+
return compact({ id, effect, provider, name, values, enabled: bool(e.enabled, `${at}.enabled`), opacity: parseVideoAnimatable(e.opacity, `${at}.opacity`, { optional: true, min: 0, max: 1 }) });
|
|
248
309
|
});
|
|
310
|
+
return out.length ? out : void 0;
|
|
249
311
|
}
|
|
250
312
|
function parseVideoTranscriptWords(v, path) {
|
|
251
313
|
if (v === void 0) return void 0;
|
|
@@ -301,7 +363,7 @@ function parseVideoAssetProxies(v, path) {
|
|
|
301
363
|
}
|
|
302
364
|
function parseVideoClip(v, path = "clip") {
|
|
303
365
|
if (!isObject(v)) return fail(path, "must be an object");
|
|
304
|
-
const type = oneOf(_nullishCoalesce(v.type, () => ( "media")),
|
|
366
|
+
const type = oneOf(_nullishCoalesce(v.type, () => ( "media")), _chunkIWSMDQE5cjs.VIDEO_CLIP_TYPES, `${path}.type`, false);
|
|
305
367
|
const base = {
|
|
306
368
|
id: str(v.id, `${path}.id`),
|
|
307
369
|
name: str(v.name, `${path}.name`, true),
|
|
@@ -309,14 +371,15 @@ function parseVideoClip(v, path = "clip") {
|
|
|
309
371
|
duration: num(v.duration, `${path}.duration`, { positive: true }),
|
|
310
372
|
opacity: parseVideoAnimatable(v.opacity, `${path}.opacity`, { optional: true, min: 0, max: 1 }),
|
|
311
373
|
transform: parseVideoTransform(v.transform, `${path}.transform`),
|
|
312
|
-
fit: oneOf(v.fit,
|
|
313
|
-
blend: oneOf(v.blend,
|
|
374
|
+
fit: oneOf(v.fit, _chunkIWSMDQE5cjs.VIDEO_FITS, `${path}.fit`),
|
|
375
|
+
blend: oneOf(v.blend, _chunkIWSMDQE5cjs.VIDEO_BLEND_MODES, `${path}.blend`),
|
|
314
376
|
grade: parseVideoGrade(v.grade, `${path}.grade`),
|
|
315
377
|
animateIn: parseVideoClipAnimation(v.animateIn, `${path}.animateIn`),
|
|
316
378
|
animateOut: parseVideoClipAnimation(v.animateOut, `${path}.animateOut`),
|
|
317
379
|
fadeIn: num(v.fadeIn, `${path}.fadeIn`, { optional: true, min: 0 }),
|
|
318
380
|
fadeOut: num(v.fadeOut, `${path}.fadeOut`, { optional: true, min: 0 }),
|
|
319
|
-
transition: parseVideoTransition(v.transition, `${path}.transition`)
|
|
381
|
+
transition: parseVideoTransition(v.transition, `${path}.transition`),
|
|
382
|
+
effects: parseVideoClipEffects(v.effects, `${path}.effects`)
|
|
320
383
|
};
|
|
321
384
|
if (type === "media")
|
|
322
385
|
return compact({
|
|
@@ -328,8 +391,8 @@ function parseVideoClip(v, path = "clip") {
|
|
|
328
391
|
volume: parseVideoAnimatable(v.volume, `${path}.volume`, { optional: true, min: 0, max: 4 }),
|
|
329
392
|
muted: bool(v.muted, `${path}.muted`),
|
|
330
393
|
timeRemap: parseVideoTimeRemap(v.timeRemap, v.speed, `${path}.timeRemap`),
|
|
331
|
-
fadeInCurve: oneOf(v.fadeInCurve,
|
|
332
|
-
fadeOutCurve: oneOf(v.fadeOutCurve,
|
|
394
|
+
fadeInCurve: oneOf(v.fadeInCurve, _chunkIWSMDQE5cjs.VIDEO_FADE_CURVES, `${path}.fadeInCurve`),
|
|
395
|
+
fadeOutCurve: oneOf(v.fadeOutCurve, _chunkIWSMDQE5cjs.VIDEO_FADE_CURVES, `${path}.fadeOutCurve`)
|
|
333
396
|
});
|
|
334
397
|
if (type === "sequence") {
|
|
335
398
|
for (const key of ["speed", "timeRemap"])
|
|
@@ -341,8 +404,8 @@ function parseVideoClip(v, path = "clip") {
|
|
|
341
404
|
in: num(v.in, `${path}.in`, { optional: true, min: 0 }),
|
|
342
405
|
volume: parseVideoAnimatable(v.volume, `${path}.volume`, { optional: true, min: 0, max: 4 }),
|
|
343
406
|
muted: bool(v.muted, `${path}.muted`),
|
|
344
|
-
fadeInCurve: oneOf(v.fadeInCurve,
|
|
345
|
-
fadeOutCurve: oneOf(v.fadeOutCurve,
|
|
407
|
+
fadeInCurve: oneOf(v.fadeInCurve, _chunkIWSMDQE5cjs.VIDEO_FADE_CURVES, `${path}.fadeInCurve`),
|
|
408
|
+
fadeOutCurve: oneOf(v.fadeOutCurve, _chunkIWSMDQE5cjs.VIDEO_FADE_CURVES, `${path}.fadeOutCurve`)
|
|
346
409
|
});
|
|
347
410
|
}
|
|
348
411
|
if (type === "text")
|
|
@@ -356,6 +419,10 @@ function parseVideoClip(v, path = "clip") {
|
|
|
356
419
|
fontWeight: num(v.fontWeight, `${path}.fontWeight`, { optional: true, min: 100, max: 1e3 }),
|
|
357
420
|
background: str(v.background, `${path}.background`, true)
|
|
358
421
|
});
|
|
422
|
+
if (type === "effect") {
|
|
423
|
+
const ref = parseVideoEffectRef({ effect: v.effect, provider: v.provider, name: v.name === void 0 ? void 0 : v.name, values: v.values }, path);
|
|
424
|
+
return compact({ type, ...base, ...ref, name: base.name });
|
|
425
|
+
}
|
|
359
426
|
return compact({ type, ...base, color: str(v.color, `${path}.color`) });
|
|
360
427
|
}
|
|
361
428
|
function parseVideoTrack(v, path = "track") {
|
|
@@ -449,9 +516,9 @@ function createVideoProject(options = {}) {
|
|
|
449
516
|
// src/video-editor/check.ts
|
|
450
517
|
function videoClipKeyframes(clip) {
|
|
451
518
|
const out = [
|
|
452
|
-
{ property: "opacity", keys:
|
|
453
|
-
{ property: "volume", keys: clip.type === "media" || clip.type === "sequence" ?
|
|
454
|
-
...
|
|
519
|
+
{ property: "opacity", keys: _chunkIWSMDQE5cjs.videoKeysOf.call(void 0, clip.opacity) },
|
|
520
|
+
{ property: "volume", keys: clip.type === "media" || clip.type === "sequence" ? _chunkIWSMDQE5cjs.videoKeysOf.call(void 0, clip.volume) : [] },
|
|
521
|
+
..._chunkIWSMDQE5cjs.VIDEO_TRANSFORM_PROPERTIES.map((p) => ({ property: p, keys: _chunkIWSMDQE5cjs.videoKeysOf.call(void 0, _optionalChain([clip, 'access', _2 => _2.transform, 'optionalAccess', _3 => _3[p]])) }))
|
|
455
522
|
];
|
|
456
523
|
return out.filter((o) => o.keys.length);
|
|
457
524
|
}
|
|
@@ -478,8 +545,8 @@ var VIDEO_ISSUE_CODES = [
|
|
|
478
545
|
var videoIssueKey = (i) => [i.code, _nullishCoalesce(i.sequence, () => ( "")), _nullishCoalesce(i.track, () => ( "")), _nullishCoalesce(i.clip, () => ( "")), _nullishCoalesce(i.asset, () => ( "")), _nullishCoalesce(i.marker, () => ( ""))].join("|");
|
|
479
546
|
function checkVideoProject(project) {
|
|
480
547
|
const issues = [];
|
|
481
|
-
const assets =
|
|
482
|
-
const sequences =
|
|
548
|
+
const assets = _chunkIWSMDQE5cjs.videoAssetMap.call(void 0, project);
|
|
549
|
+
const sequences = _chunkIWSMDQE5cjs.videoSequenceMap.call(void 0, project);
|
|
483
550
|
const used = /* @__PURE__ */ new Set();
|
|
484
551
|
const usedSequences = /* @__PURE__ */ new Set();
|
|
485
552
|
const cycles = /* @__PURE__ */ new Map();
|
|
@@ -487,7 +554,7 @@ function checkVideoProject(project) {
|
|
|
487
554
|
if ((asset.kind === "video" || asset.kind === "audio") && asset.duration === void 0)
|
|
488
555
|
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.` });
|
|
489
556
|
const checkTrack = (track, sequence) => {
|
|
490
|
-
const clips =
|
|
557
|
+
const clips = _chunkIWSMDQE5cjs.sortedVideoClips.call(void 0, track);
|
|
491
558
|
const where = sequence ? ` in sequence "${sequence}"` : "";
|
|
492
559
|
for (let i = 0; i < clips.length; i++) {
|
|
493
560
|
const clip = clips[i];
|
|
@@ -497,13 +564,13 @@ function checkVideoProject(project) {
|
|
|
497
564
|
const seq = sequences.get(clip.sequence);
|
|
498
565
|
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.` });
|
|
499
566
|
else {
|
|
500
|
-
if (!cycles.has(seq.id)) cycles.set(seq.id,
|
|
567
|
+
if (!cycles.has(seq.id)) cycles.set(seq.id, _chunkIWSMDQE5cjs.findVideoSequenceCycle.call(void 0, project, seq.id));
|
|
501
568
|
const cycle = cycles.get(seq.id);
|
|
502
569
|
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.` });
|
|
503
|
-
const length =
|
|
504
|
-
const range =
|
|
505
|
-
if (range.out > length +
|
|
506
|
-
issues.push({ code: "source-overrun", severity: "error", ...at, message: `Compound clip "${clip.id}" plays to ${
|
|
570
|
+
const length = _chunkIWSMDQE5cjs.videoSequenceDuration.call(void 0, seq);
|
|
571
|
+
const range = _chunkIWSMDQE5cjs.videoClipSourceRange.call(void 0, clip);
|
|
572
|
+
if (range.out > length + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON)
|
|
573
|
+
issues.push({ code: "source-overrun", severity: "error", ...at, message: `Compound clip "${clip.id}" plays to ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, range.out)} of sequence "${seq.id}", which is only ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, length)} long; shorten the clip or move its in point.` });
|
|
507
574
|
}
|
|
508
575
|
} else if (clip.type === "media") {
|
|
509
576
|
used.add(clip.asset);
|
|
@@ -512,28 +579,28 @@ function checkVideoProject(project) {
|
|
|
512
579
|
else {
|
|
513
580
|
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.` });
|
|
514
581
|
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.` });
|
|
515
|
-
const range =
|
|
516
|
-
if (asset.duration !== void 0 && range.out > asset.duration +
|
|
517
|
-
issues.push({ code: "source-overrun", severity: "error", ...at, message: `Clip "${clip.id}" plays to ${
|
|
582
|
+
const range = _chunkIWSMDQE5cjs.videoClipSourceRange.call(void 0, clip);
|
|
583
|
+
if (asset.duration !== void 0 && range.out > asset.duration + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON)
|
|
584
|
+
issues.push({ code: "source-overrun", severity: "error", ...at, message: `Clip "${clip.id}" plays to ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, range.out)} of "${asset.id}", which is only ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, asset.duration)} long; shorten the clip or move its in point.` });
|
|
518
585
|
}
|
|
519
586
|
} 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.` });
|
|
520
587
|
const next = clips[i + 1];
|
|
521
|
-
if (next && next.start <
|
|
522
|
-
issues.push({ code: "overlap", severity: "error", ...at, message: `Clips "${clip.id}" and "${next.id}" overlap on track "${track.id}"${where} from ${
|
|
523
|
-
if ((_nullishCoalesce(clip.fadeIn, () => ( 0))) + (_nullishCoalesce(clip.fadeOut, () => ( 0))) > clip.duration +
|
|
588
|
+
if (next && next.start < _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip) - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON)
|
|
589
|
+
issues.push({ code: "overlap", severity: "error", ...at, message: `Clips "${clip.id}" and "${next.id}" overlap on track "${track.id}"${where} from ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, next.start)}; move one of them.` });
|
|
590
|
+
if ((_nullishCoalesce(clip.fadeIn, () => ( 0))) + (_nullishCoalesce(clip.fadeOut, () => ( 0))) > clip.duration + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON)
|
|
524
591
|
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.` });
|
|
525
|
-
const anim = (clip.animateIn ? _nullishCoalesce(clip.animateIn.duration, () => (
|
|
526
|
-
if (anim > clip.duration +
|
|
592
|
+
const anim = (clip.animateIn ? _nullishCoalesce(clip.animateIn.duration, () => ( _chunkIWSMDQE5cjs.VIDEO_CLIP_ANIMATION_DURATION)) : 0) + (clip.animateOut ? _nullishCoalesce(clip.animateOut.duration, () => ( _chunkIWSMDQE5cjs.VIDEO_CLIP_ANIMATION_DURATION)) : 0);
|
|
593
|
+
if (anim > clip.duration + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON)
|
|
527
594
|
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.` });
|
|
528
595
|
for (const which of ["animateIn", "animateOut"]) {
|
|
529
596
|
const a = clip[which];
|
|
530
597
|
if (!a) continue;
|
|
531
|
-
const keyed =
|
|
598
|
+
const keyed = _chunkIWSMDQE5cjs.videoClipAnimationProperties.call(void 0, a).filter((p) => _chunkIWSMDQE5cjs.videoKeysOf.call(void 0, p === "opacity" ? clip.opacity : _optionalChain([clip, 'access', _4 => _4.transform, 'optionalAccess', _5 => _5[p]])).length);
|
|
532
599
|
if (keyed.length)
|
|
533
600
|
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.` });
|
|
534
601
|
}
|
|
535
602
|
for (const { property, keys } of videoClipKeyframes(clip)) {
|
|
536
|
-
const outside = keys.filter((k) => k.t < -
|
|
603
|
+
const outside = keys.filter((k) => k.t < -_chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON || k.t > clip.duration + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON);
|
|
537
604
|
if (outside.length)
|
|
538
605
|
issues.push({
|
|
539
606
|
code: "keyframes-outside-clip",
|
|
@@ -544,20 +611,20 @@ function checkVideoProject(project) {
|
|
|
544
611
|
}
|
|
545
612
|
if (clip.transition) {
|
|
546
613
|
const d = clip.transition.duration;
|
|
547
|
-
const before =
|
|
614
|
+
const before = _chunkIWSMDQE5cjs.videoClipBefore.call(void 0, track, clip);
|
|
548
615
|
if (!before) {
|
|
549
616
|
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.` });
|
|
550
617
|
continue;
|
|
551
618
|
}
|
|
552
|
-
if (d > clip.duration +
|
|
619
|
+
if (d > clip.duration + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON || d > before.duration + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) {
|
|
553
620
|
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.` });
|
|
554
621
|
continue;
|
|
555
622
|
}
|
|
556
623
|
if (clip.transition.type === "dip") continue;
|
|
557
|
-
const outgoing =
|
|
558
|
-
const incoming =
|
|
624
|
+
const outgoing = _chunkIWSMDQE5cjs.videoClipHandles.call(void 0, before, assets, sequences).after;
|
|
625
|
+
const incoming = _chunkIWSMDQE5cjs.videoClipHandles.call(void 0, clip, assets, sequences).before;
|
|
559
626
|
const half = d / 2;
|
|
560
|
-
if (outgoing < half -
|
|
627
|
+
if (outgoing < half - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON || incoming < half - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) {
|
|
561
628
|
const fits = 2 * Math.min(outgoing, incoming);
|
|
562
629
|
issues.push({
|
|
563
630
|
code: "transition-handles",
|
|
@@ -574,9 +641,9 @@ function checkVideoProject(project) {
|
|
|
574
641
|
for (const sequence of _nullishCoalesce(project.sequences, () => ( [])))
|
|
575
642
|
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.` });
|
|
576
643
|
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.` });
|
|
577
|
-
const end =
|
|
644
|
+
const end = _chunkIWSMDQE5cjs.videoProjectDuration.call(void 0, project);
|
|
578
645
|
for (const marker of _nullishCoalesce(project.markers, () => ( [])))
|
|
579
|
-
if (marker.time > end +
|
|
646
|
+
if (marker.time > end + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) issues.push({ code: "marker-past-end", severity: "note", marker: marker.id, message: `Marker "${marker.id}" at ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, marker.time)} is past the end (${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, end)}).` });
|
|
580
647
|
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." });
|
|
581
648
|
const rank = { error: 0, warning: 1, note: 2 };
|
|
582
649
|
return issues.sort((a, b) => rank[a.severity] - rank[b.severity]);
|
|
@@ -630,7 +697,7 @@ function mergeSpans(spans) {
|
|
|
630
697
|
const out = [];
|
|
631
698
|
for (const [from, to] of [...spans].sort((a, b) => a[0] - b[0])) {
|
|
632
699
|
const last = out[out.length - 1];
|
|
633
|
-
if (last && from <= last[1] +
|
|
700
|
+
if (last && from <= last[1] + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) last[1] = Math.max(last[1], to);
|
|
634
701
|
else out.push([from, to]);
|
|
635
702
|
}
|
|
636
703
|
return out;
|
|
@@ -644,16 +711,16 @@ function clipAnimatables(clip) {
|
|
|
644
711
|
// A speed ramp is keys in clip time too, so trims and splits keep it on the same frames of source.
|
|
645
712
|
{ get: () => c.timeRemap, set: (v) => c.timeRemap = v }
|
|
646
713
|
];
|
|
647
|
-
for (const p of
|
|
714
|
+
for (const p of _chunkIWSMDQE5cjs.VIDEO_TRANSFORM_PROPERTIES) out.push({ get: () => _optionalChain([c, 'access', _6 => _6.transform, 'optionalAccess', _7 => _7[p]]), set: (v) => c.transform && (c.transform[p] = v) });
|
|
648
715
|
return out;
|
|
649
716
|
}
|
|
650
717
|
function retimeClipKeys(clip, fn) {
|
|
651
718
|
for (const a of clipAnimatables(clip)) {
|
|
652
719
|
const v = a.get();
|
|
653
|
-
if (
|
|
720
|
+
if (_chunkIWSMDQE5cjs.isVideoKeyframes.call(void 0, v)) a.set(fn(v));
|
|
654
721
|
}
|
|
655
722
|
}
|
|
656
|
-
var OPTIONAL_CLIP_FIELDS = ["name", "opacity", "transform", "fit", "blend", "grade", "animateIn", "animateOut", "fadeIn", "fadeOut", "fadeInCurve", "fadeOutCurve", "transition", "in", "speed", "timeRemap", "volume", "muted", "color", "fontSize", "fontFamily", "fontWeight", "background"];
|
|
723
|
+
var OPTIONAL_CLIP_FIELDS = ["name", "effects", "values", "provider", "opacity", "transform", "fit", "blend", "grade", "animateIn", "animateOut", "fadeIn", "fadeOut", "fadeInCurve", "fadeOutCurve", "transition", "in", "speed", "timeRemap", "volume", "muted", "color", "fontSize", "fontFamily", "fontWeight", "background"];
|
|
657
724
|
var TIME_FIELDS = { slip_clip: ["delta"], roll_edit: ["delta"], slide_clip: ["delta"], lift_range: ["from", "to"], extract_range: ["from", "to"], split_at: ["at"] };
|
|
658
725
|
var Editor = (_class = class {
|
|
659
726
|
constructor(p) {;_class.prototype.__init.call(this);
|
|
@@ -667,8 +734,8 @@ var Editor = (_class = class {
|
|
|
667
734
|
return t;
|
|
668
735
|
}
|
|
669
736
|
clip(id) {
|
|
670
|
-
const at =
|
|
671
|
-
const nested = at ? null :
|
|
737
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, this.p, id);
|
|
738
|
+
const nested = at ? null : _chunkIWSMDQE5cjs.findVideoSequenceClip.call(void 0, this.p, id);
|
|
672
739
|
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).`);
|
|
673
740
|
if (!at) {
|
|
674
741
|
const ids = this.p.tracks.flatMap((t) => t.clips.map((c) => c.id));
|
|
@@ -685,10 +752,10 @@ var Editor = (_class = class {
|
|
|
685
752
|
return a;
|
|
686
753
|
}
|
|
687
754
|
fits(track, start, duration, ignore, what) {
|
|
688
|
-
const hit =
|
|
755
|
+
const hit = _chunkIWSMDQE5cjs.videoOverlap.call(void 0, track, start, start + duration, ignore);
|
|
689
756
|
if (hit) {
|
|
690
|
-
const free =
|
|
691
|
-
refuse(`${what} at ${
|
|
757
|
+
const free = _chunkIWSMDQE5cjs.nextFreeVideoSlot.call(void 0, track, start, duration, ignore);
|
|
758
|
+
refuse(`${what} at ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, start)}\u2013${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, start + duration)} would overlap clip "${hit.id}" (${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, hit.start)}\u2013${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, hit))}) on track "${track.id}"; the next free place is ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, free)}, or use mode "insert" to push later clips along or "overwrite" to replace what is there.`);
|
|
692
759
|
}
|
|
693
760
|
}
|
|
694
761
|
kindFits(track, clip) {
|
|
@@ -704,14 +771,14 @@ var Editor = (_class = class {
|
|
|
704
771
|
/** Moves every clip on `track` starting at or after `from` by `delta`. */
|
|
705
772
|
shift(track, from, delta, except = /* @__PURE__ */ new Set()) {
|
|
706
773
|
if (!delta) return;
|
|
707
|
-
for (const c of track.clips) if (!except.has(c.id) && c.start >= from -
|
|
774
|
+
for (const c of track.clips) if (!except.has(c.id) && c.start >= from - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) c.start = Math.max(0, c.start + delta);
|
|
708
775
|
track.clips.sort((a, b) => a.start - b.start);
|
|
709
776
|
}
|
|
710
777
|
get frame() {
|
|
711
778
|
return 1e3 / this.p.fps;
|
|
712
779
|
}
|
|
713
780
|
ids() {
|
|
714
|
-
return
|
|
781
|
+
return _chunkIWSMDQE5cjs.allVideoClipIds.call(void 0, this.p);
|
|
715
782
|
}
|
|
716
783
|
/**
|
|
717
784
|
* The tracks a ripple on `sources` moves, top to bottom: the sources, and every unlocked
|
|
@@ -719,8 +786,8 @@ var Editor = (_class = class {
|
|
|
719
786
|
*/
|
|
720
787
|
rippleTracks(sources) {
|
|
721
788
|
const set = new Set(sources);
|
|
722
|
-
if ([...set].some(
|
|
723
|
-
for (const t of this.p.tracks) if (
|
|
789
|
+
if ([...set].some(_chunkIWSMDQE5cjs.videoTrackSyncLocked)) {
|
|
790
|
+
for (const t of this.p.tracks) if (_chunkIWSMDQE5cjs.videoTrackSyncLocked.call(void 0, t) && !t.locked) set.add(t);
|
|
724
791
|
}
|
|
725
792
|
return this.p.tracks.filter((t) => set.has(t));
|
|
726
793
|
}
|
|
@@ -737,7 +804,7 @@ var Editor = (_class = class {
|
|
|
737
804
|
return open;
|
|
738
805
|
}
|
|
739
806
|
range(from, to) {
|
|
740
|
-
if (!(to - from >
|
|
807
|
+
if (!(to - from > _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON)) refuse(`"to" (${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, to)}) must be after "from" (${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, from)}).`);
|
|
741
808
|
}
|
|
742
809
|
/** Moves a media or compound clip's in point by `delta` of timeline time (stills, titles and colours have none). */
|
|
743
810
|
moveIn(clip, delta) {
|
|
@@ -746,18 +813,18 @@ var Editor = (_class = class {
|
|
|
746
813
|
if (clip.in < 1e-9) delete clip.in;
|
|
747
814
|
return;
|
|
748
815
|
}
|
|
749
|
-
if (clip.type !== "media" || _optionalChain([
|
|
750
|
-
clip.in = Math.max(0, (_nullishCoalesce(clip.in, () => ( 0))) + delta *
|
|
816
|
+
if (clip.type !== "media" || _optionalChain([_chunkIWSMDQE5cjs.videoAssetMap.call(void 0, this.p), 'access', _9 => _9.get, 'call', _10 => _10(clip.asset), 'optionalAccess', _11 => _11.kind]) === "image") return;
|
|
817
|
+
clip.in = Math.max(0, (_nullishCoalesce(clip.in, () => ( 0))) + delta * _chunkIWSMDQE5cjs.videoClipSpeed.call(void 0, clip));
|
|
751
818
|
if (clip.in < 1e-9) delete clip.in;
|
|
752
819
|
}
|
|
753
820
|
/** Moves a clip's head `delta` later in time (start, in point and keys); the caller sets start and duration. */
|
|
754
821
|
trimHead(clip, delta) {
|
|
755
822
|
if (!isRamped(clip)) this.moveIn(clip, delta);
|
|
756
|
-
retimeClipKeys(clip, (v) =>
|
|
823
|
+
retimeClipKeys(clip, (v) => _chunkIWSMDQE5cjs.retimeVideoAnimatable.call(void 0, v, -delta));
|
|
757
824
|
}
|
|
758
825
|
/** Cuts `clip` at `at` (inside it): the left part keeps the id, the right part is returned. */
|
|
759
826
|
cut(track, clip, at, id) {
|
|
760
|
-
const end =
|
|
827
|
+
const end = _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip);
|
|
761
828
|
const right = { ...structuredClone(clip), id: _nullishCoalesce(id, () => ( freshId(`${clip.id}-`, this.ids()))), start: at, duration: end - at };
|
|
762
829
|
delete right.transition;
|
|
763
830
|
delete right.fadeIn;
|
|
@@ -765,9 +832,9 @@ var Editor = (_class = class {
|
|
|
765
832
|
delete right.animateIn;
|
|
766
833
|
const leftValues = clipAnimatables(clip);
|
|
767
834
|
clipAnimatables(right).forEach((r, i) => {
|
|
768
|
-
const [l, rr] =
|
|
769
|
-
if (
|
|
770
|
-
if (
|
|
835
|
+
const [l, rr] = _chunkIWSMDQE5cjs.splitVideoAnimatable.call(void 0, leftValues[i].get(), at - clip.start);
|
|
836
|
+
if (_chunkIWSMDQE5cjs.isVideoKeyframes.call(void 0, l)) leftValues[i].set(l);
|
|
837
|
+
if (_chunkIWSMDQE5cjs.isVideoKeyframes.call(void 0, rr)) r.set(rr);
|
|
771
838
|
});
|
|
772
839
|
if (!isRamped(right)) this.moveIn(right, at - clip.start);
|
|
773
840
|
clip.duration = at - clip.start;
|
|
@@ -781,7 +848,7 @@ var Editor = (_class = class {
|
|
|
781
848
|
/** Cuts every clip on `tracks` that runs across `at`; returns the new right-hand parts. */
|
|
782
849
|
cutAcross(tracks, at) {
|
|
783
850
|
const made = [];
|
|
784
|
-
for (const t of tracks) for (const c of [...t.clips]) if (c.start < at -
|
|
851
|
+
for (const t of tracks) for (const c of [...t.clips]) if (c.start < at - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON && _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c) > at + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) made.push(this.cut(t, c, at));
|
|
785
852
|
return made;
|
|
786
853
|
}
|
|
787
854
|
/**
|
|
@@ -799,10 +866,10 @@ var Editor = (_class = class {
|
|
|
799
866
|
*/
|
|
800
867
|
close(tracks, from, to) {
|
|
801
868
|
for (const t of tracks) {
|
|
802
|
-
const hit =
|
|
869
|
+
const hit = _chunkIWSMDQE5cjs.videoOverlap.call(void 0, t, from, to);
|
|
803
870
|
if (hit)
|
|
804
871
|
refuse(
|
|
805
|
-
`Rippling out ${
|
|
872
|
+
`Rippling out ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, from)}\u2013${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, to)} would pull track "${t.id}" out of sync: clip "${hit.id}" (${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, hit.start)}\u2013${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, _chunkIWSMDQE5cjs.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.`
|
|
806
873
|
);
|
|
807
874
|
}
|
|
808
875
|
for (const t of tracks) this.shift(t, to, from - to);
|
|
@@ -814,10 +881,10 @@ var Editor = (_class = class {
|
|
|
814
881
|
clear(track, from, to, report) {
|
|
815
882
|
for (const c of [...track.clips]) {
|
|
816
883
|
const start = c.start;
|
|
817
|
-
const end =
|
|
818
|
-
if (end <= from +
|
|
819
|
-
const coversHead = start >= from -
|
|
820
|
-
const coversTail = end <= to +
|
|
884
|
+
const end = _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c);
|
|
885
|
+
if (end <= from + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON || start >= to - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) continue;
|
|
886
|
+
const coversHead = start >= from - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON;
|
|
887
|
+
const coversTail = end <= to + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON;
|
|
821
888
|
if (coversHead && coversTail) {
|
|
822
889
|
track.clips = track.clips.filter((x) => x !== c);
|
|
823
890
|
report.removed.push(c.id);
|
|
@@ -840,8 +907,8 @@ var Editor = (_class = class {
|
|
|
840
907
|
/** Clamps a slip, roll or slide to `[lo, hi]`, refusing when it cannot move that way at all. */
|
|
841
908
|
clamp(delta, lo, hi, why) {
|
|
842
909
|
const applied = Math.min(Math.max(delta, Math.min(0, lo)), Math.max(0, hi));
|
|
843
|
-
if (Math.abs(delta) >
|
|
844
|
-
return Math.abs(applied) <=
|
|
910
|
+
if (Math.abs(delta) > _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON && Math.abs(applied) <= _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) refuse(why());
|
|
911
|
+
return Math.abs(applied) <= _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON ? 0 : applied;
|
|
845
912
|
}
|
|
846
913
|
/** Places a clip on a track by `mode`, returning what it cut, trimmed, removed and rippled. */
|
|
847
914
|
place(track, clip, mode, outcome) {
|
|
@@ -851,14 +918,14 @@ var Editor = (_class = class {
|
|
|
851
918
|
outcome.rippled = tracks.map((t) => t.id);
|
|
852
919
|
} else if (mode === "overwrite") {
|
|
853
920
|
const report = { removed: [], trimmed: [], created: [] };
|
|
854
|
-
this.clear(track, clip.start,
|
|
921
|
+
this.clear(track, clip.start, _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip), report);
|
|
855
922
|
Object.assign(outcome, report);
|
|
856
923
|
} else this.fits(track, clip.start, clip.duration, /* @__PURE__ */ new Set([clip.id]), `Clip "${clip.id}"`);
|
|
857
924
|
track.clips.push(clip);
|
|
858
925
|
track.clips.sort((a, b) => a.start - b.start);
|
|
859
926
|
}
|
|
860
927
|
placement(mode, ripple) {
|
|
861
|
-
if (mode !== void 0 && !
|
|
928
|
+
if (mode !== void 0 && !_chunkIWSMDQE5cjs.VIDEO_PLACEMENT_MODES.includes(mode)) refuse(`"mode" must be ${_chunkIWSMDQE5cjs.VIDEO_PLACEMENT_MODES.map((m) => `"${m}"`).join(", ")}.`);
|
|
862
929
|
if (ripple && mode !== void 0 && mode !== "insert") refuse(`"ripple" means mode "insert", so it cannot go with mode "${mode}"; pass one or the other.`);
|
|
863
930
|
return _nullishCoalesce(mode, () => ( (ripple ? "insert" : "refuse")));
|
|
864
931
|
}
|
|
@@ -895,7 +962,7 @@ var Editor = (_class = class {
|
|
|
895
962
|
}
|
|
896
963
|
case "remove_asset": {
|
|
897
964
|
const asset = this.asset(e.asset);
|
|
898
|
-
const users =
|
|
965
|
+
const users = _chunkIWSMDQE5cjs.allVideoTracks.call(void 0, this.p).flatMap(({ track: t }) => t.clips.filter((c) => c.type === "media" && c.asset === asset.id).map((c) => c.id));
|
|
899
966
|
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.`);
|
|
900
967
|
this.p.assets = this.p.assets.filter((a) => a !== asset);
|
|
901
968
|
return this.outcomes.push({ op: e.op, asset: asset.id });
|
|
@@ -948,12 +1015,12 @@ var Editor = (_class = class {
|
|
|
948
1015
|
else draft.duration = (asset.duration - (_nullishCoalesce(draft.in, () => ( 0)))) / (_nullishCoalesce(draft.speed, () => ( 1)));
|
|
949
1016
|
if (!(draft.duration > 0)) refuse(`"in" (${draft.in} ms) is at or past the end of "${asset.id}" (${asset.duration} ms).`);
|
|
950
1017
|
} else if (draft.type === "sequence") {
|
|
951
|
-
const length =
|
|
1018
|
+
const length = _chunkIWSMDQE5cjs.videoSequenceDuration.call(void 0, _chunkIWSMDQE5cjs.videoSequenceMap.call(void 0, this.p).get(draft.sequence)) - (_nullishCoalesce(draft.in, () => ( 0)));
|
|
952
1019
|
if (!(length > 0)) refuse(`"in" (${_nullishCoalesce(draft.in, () => ( 0))} ms) is at or past the end of sequence "${draft.sequence}".`);
|
|
953
1020
|
draft.duration = length;
|
|
954
1021
|
} else draft.duration = VIDEO_DEFAULT_TITLE_DURATION;
|
|
955
1022
|
}
|
|
956
|
-
const end =
|
|
1023
|
+
const end = _chunkIWSMDQE5cjs.sortedVideoClips.call(void 0, track).reduce((m, c) => Math.max(m, _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c)), 0);
|
|
957
1024
|
draft.start ??= end;
|
|
958
1025
|
const clip = parseVideoClip(draft, "clip");
|
|
959
1026
|
const outcome = { op: e.op, clip: clip.id, track: track.id };
|
|
@@ -978,20 +1045,20 @@ var Editor = (_class = class {
|
|
|
978
1045
|
case "trim_clip": {
|
|
979
1046
|
const { track, clip } = this.clip(e.clip);
|
|
980
1047
|
this.unlocked(track);
|
|
981
|
-
const speed =
|
|
982
|
-
const end =
|
|
1048
|
+
const speed = _chunkIWSMDQE5cjs.videoClipSpeed.call(void 0, clip);
|
|
1049
|
+
const end = _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip);
|
|
983
1050
|
const minimum = 1e3 / this.p.fps;
|
|
984
|
-
const assets =
|
|
1051
|
+
const assets = _chunkIWSMDQE5cjs.videoAssetMap.call(void 0, this.p);
|
|
985
1052
|
if (e.edge === "start") {
|
|
986
1053
|
const delta = e.to - clip.start;
|
|
987
|
-
if (clip.duration - delta < minimum -
|
|
1054
|
+
if (clip.duration - delta < minimum - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) refuse(`Trimming the start to ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, e.to)} would leave "${clip.id}" shorter than a frame; it ends at ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, end)}.`);
|
|
988
1055
|
if (clip.type === "media" && !isRamped(clip) || clip.type === "sequence") {
|
|
989
1056
|
const sourceIn = (_nullishCoalesce(clip.in, () => ( 0))) + delta * speed;
|
|
990
|
-
if (sourceIn < -
|
|
1057
|
+
if (sourceIn < -_chunkIWSMDQE5cjs.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 ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, clip.start - (_nullishCoalesce(clip.in, () => ( 0))) / speed)}).`);
|
|
991
1058
|
clip.in = Math.max(0, sourceIn);
|
|
992
1059
|
if (clip.in === 0) delete clip.in;
|
|
993
1060
|
}
|
|
994
|
-
retimeClipKeys(clip, (v) =>
|
|
1061
|
+
retimeClipKeys(clip, (v) => _chunkIWSMDQE5cjs.retimeVideoAnimatable.call(void 0, v, -delta));
|
|
995
1062
|
if (e.ripple) {
|
|
996
1063
|
const tracks = this.rippleTracks([track]);
|
|
997
1064
|
if (delta > 0) {
|
|
@@ -1012,17 +1079,17 @@ var Editor = (_class = class {
|
|
|
1012
1079
|
}
|
|
1013
1080
|
} else {
|
|
1014
1081
|
const duration = e.to - clip.start;
|
|
1015
|
-
if (duration < minimum -
|
|
1082
|
+
if (duration < minimum - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) refuse(`Trimming the end to ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, e.to)} would leave "${clip.id}" shorter than a frame; it starts at ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, clip.start)}.`);
|
|
1016
1083
|
if (clip.type === "media" && !isRamped(clip)) {
|
|
1017
1084
|
const asset = assets.get(clip.asset);
|
|
1018
1085
|
const out = (_nullishCoalesce(clip.in, () => ( 0))) + duration * speed;
|
|
1019
|
-
if (_optionalChain([asset, 'optionalAccess', _12 => _12.duration]) !== void 0 && out > asset.duration +
|
|
1020
|
-
refuse(`"${clip.id}" can end at most at ${
|
|
1086
|
+
if (_optionalChain([asset, 'optionalAccess', _12 => _12.duration]) !== void 0 && out > asset.duration + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON)
|
|
1087
|
+
refuse(`"${clip.id}" can end at most at ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, clip.start + (asset.duration - (_nullishCoalesce(clip.in, () => ( 0)))) / speed)}, where "${asset.id}" runs out.`);
|
|
1021
1088
|
}
|
|
1022
1089
|
if (clip.type === "sequence") {
|
|
1023
|
-
const seq =
|
|
1024
|
-
const length = seq ?
|
|
1025
|
-
if ((_nullishCoalesce(clip.in, () => ( 0))) + duration > length +
|
|
1090
|
+
const seq = _chunkIWSMDQE5cjs.videoSequenceMap.call(void 0, this.p).get(clip.sequence);
|
|
1091
|
+
const length = seq ? _chunkIWSMDQE5cjs.videoSequenceDuration.call(void 0, seq) : Infinity;
|
|
1092
|
+
if ((_nullishCoalesce(clip.in, () => ( 0))) + duration > length + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) refuse(`"${clip.id}" can end at most at ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, clip.start + length - (_nullishCoalesce(clip.in, () => ( 0))))}, where sequence "${clip.sequence}" ends.`);
|
|
1026
1093
|
}
|
|
1027
1094
|
if (e.ripple) {
|
|
1028
1095
|
const tracks = this.rippleTracks([track]);
|
|
@@ -1044,9 +1111,9 @@ var Editor = (_class = class {
|
|
|
1044
1111
|
case "split_clip": {
|
|
1045
1112
|
const { track, clip } = this.clip(e.clip);
|
|
1046
1113
|
this.unlocked(track);
|
|
1047
|
-
const end =
|
|
1114
|
+
const end = _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip);
|
|
1048
1115
|
const minimum = 1e3 / this.p.fps;
|
|
1049
|
-
if (e.at < clip.start + minimum -
|
|
1116
|
+
if (e.at < clip.start + minimum - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON || e.at > end - minimum + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) refuse(`${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, e.at)} is not inside "${clip.id}" (${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, clip.start)}\u2013${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, end)}), at least a frame from either end.`);
|
|
1050
1117
|
if (e.id !== void 0 && this.ids().includes(e.id)) refuse(`There is already a clip "${e.id}".`);
|
|
1051
1118
|
const right = this.cut(track, clip, e.at, e.id);
|
|
1052
1119
|
return this.outcomes.push({ op: e.op, clips: [clip.id, right.id], clip: right.id, track: track.id });
|
|
@@ -1057,12 +1124,12 @@ var Editor = (_class = class {
|
|
|
1057
1124
|
for (const track of new Set(found.map((f) => f.track))) track.clips = track.clips.filter((c) => !found.some((f) => f.clip === c));
|
|
1058
1125
|
if (!e.ripple) return this.outcomes.push({ op: e.op, clips: found.map((f) => f.clip.id) });
|
|
1059
1126
|
const rippled = /* @__PURE__ */ new Set();
|
|
1060
|
-
const groups = [...new Set(found.map((f) => f.track))].filter((t) => !
|
|
1061
|
-
if (found.some((f) =>
|
|
1127
|
+
const groups = [...new Set(found.map((f) => f.track))].filter((t) => !_chunkIWSMDQE5cjs.videoTrackSyncLocked.call(void 0, t)).map((t) => [t]);
|
|
1128
|
+
if (found.some((f) => _chunkIWSMDQE5cjs.videoTrackSyncLocked.call(void 0, f.track))) groups.push(found.filter((f) => _chunkIWSMDQE5cjs.videoTrackSyncLocked.call(void 0, f.track)).map((f) => f.track));
|
|
1062
1129
|
for (const sources of groups) {
|
|
1063
1130
|
const tracks = this.rippleTracks(sources);
|
|
1064
1131
|
tracks.forEach((t) => rippled.add(t));
|
|
1065
|
-
const spans = mergeSpans(found.filter((f) => sources.includes(f.track)).map((f) => [f.clip.start,
|
|
1132
|
+
const spans = mergeSpans(found.filter((f) => sources.includes(f.track)).map((f) => [f.clip.start, _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, f.clip)]));
|
|
1066
1133
|
for (const [from, to] of spans.reverse()) this.close(tracks, from, to);
|
|
1067
1134
|
}
|
|
1068
1135
|
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) });
|
|
@@ -1078,7 +1145,7 @@ var Editor = (_class = class {
|
|
|
1078
1145
|
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.");
|
|
1079
1146
|
let stretch = 1;
|
|
1080
1147
|
if (at.clip.type === "media" && !("duration" in set)) {
|
|
1081
|
-
const was =
|
|
1148
|
+
const was = _chunkIWSMDQE5cjs.videoClipSpeed.call(void 0, at.clip);
|
|
1082
1149
|
const now = "speed" in set ? set.speed : _optionalChain([e, 'access', _13 => _13.remove, 'optionalAccess', _14 => _14.includes, 'call', _15 => _15("speed")]) ? 1 : was;
|
|
1083
1150
|
if (now !== was) {
|
|
1084
1151
|
set.duration = at.clip.duration * was / now;
|
|
@@ -1086,7 +1153,7 @@ var Editor = (_class = class {
|
|
|
1086
1153
|
}
|
|
1087
1154
|
}
|
|
1088
1155
|
const next = { ...structuredClone(at.clip), ...set };
|
|
1089
|
-
if (stretch !== 1) retimeClipKeys(next, (v) =>
|
|
1156
|
+
if (stretch !== 1) retimeClipKeys(next, (v) => _chunkIWSMDQE5cjs.retimeVideoAnimatable.call(void 0, v, 0, stretch));
|
|
1090
1157
|
for (const k of _nullishCoalesce(e.remove, () => ( []))) delete next[k];
|
|
1091
1158
|
const clip = parseVideoClip(next, "set");
|
|
1092
1159
|
if (clip.type === "media" && clip.asset !== at.clip.asset) this.kindFits(at.track, clip);
|
|
@@ -1099,17 +1166,17 @@ var Editor = (_class = class {
|
|
|
1099
1166
|
const { track, clip } = this.clip(e.clip);
|
|
1100
1167
|
this.unlocked(track);
|
|
1101
1168
|
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.`);
|
|
1102
|
-
if (clip.type !== "media") refuse(`Clip "${clip.id}" is a ${clip.type === "text" ? "title" : "colour"}, so it has no source to ramp; only video and audio clips change speed.`);
|
|
1169
|
+
if (clip.type !== "media") refuse(`Clip "${clip.id}" is a ${clip.type === "text" ? "title" : clip.type === "effect" ? "effect clip" : "colour"}, so it has no source to ramp; only video and audio clips change speed.`);
|
|
1103
1170
|
const asset = this.asset(clip.asset);
|
|
1104
1171
|
if (asset.kind === "image") refuse(`Clip "${clip.id}" is a still ("${asset.id}"), so it has no motion to ramp.`);
|
|
1105
1172
|
const media = clip;
|
|
1106
|
-
const end =
|
|
1173
|
+
const end = _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, media);
|
|
1107
1174
|
const duration = _nullishCoalesce(e.duration, () => ( media.duration));
|
|
1108
|
-
if (!(duration >= 1e3 / this.p.fps -
|
|
1175
|
+
if (!(duration >= 1e3 / this.p.fps - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON)) refuse(`"duration" must be at least a frame (${Math.ceil(1e3 / this.p.fps)} ms).`);
|
|
1109
1176
|
if (e.keys === null) {
|
|
1110
1177
|
if (!media.timeRemap) refuse(`Clip "${clip.id}" has no speed ramp to remove.`);
|
|
1111
1178
|
const from = (_nullishCoalesce(media.in, () => ( 0))) + media.timeRemap.keys[0].v;
|
|
1112
|
-
if (asset.duration !== void 0 && from + duration > asset.duration +
|
|
1179
|
+
if (asset.duration !== void 0 && from + duration > asset.duration + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON)
|
|
1113
1180
|
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.`);
|
|
1114
1181
|
delete media.timeRemap;
|
|
1115
1182
|
media.in = from;
|
|
@@ -1117,17 +1184,17 @@ var Editor = (_class = class {
|
|
|
1117
1184
|
} else {
|
|
1118
1185
|
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).');
|
|
1119
1186
|
const remap = parseVideoTimeRemap({ keys: e.keys }, void 0, "keys");
|
|
1120
|
-
remap.keys =
|
|
1121
|
-
|
|
1122
|
-
const span =
|
|
1123
|
-
if (asset.duration !== void 0 && (_nullishCoalesce(media.in, () => ( 0))) + span.to > asset.duration +
|
|
1187
|
+
remap.keys = _chunkIWSMDQE5cjs.sortVideoKeys.call(void 0, remap.keys);
|
|
1188
|
+
_chunkIWSMDQE5cjs.checkVideoTimeRemap.call(void 0, remap, "keys");
|
|
1189
|
+
const span = _chunkIWSMDQE5cjs.videoTimeRemapSpan.call(void 0, remap);
|
|
1190
|
+
if (asset.duration !== void 0 && (_nullishCoalesce(media.in, () => ( 0))) + span.to > asset.duration + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON)
|
|
1124
1191
|
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.`);
|
|
1125
1192
|
media.timeRemap = remap;
|
|
1126
1193
|
delete media.speed;
|
|
1127
1194
|
}
|
|
1128
1195
|
const newEnd = media.start + duration;
|
|
1129
1196
|
const outcome = { op: e.op, clip: clip.id, track: track.id };
|
|
1130
|
-
if (Math.abs(newEnd - end) >
|
|
1197
|
+
if (Math.abs(newEnd - end) > _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) {
|
|
1131
1198
|
if (e.ripple) {
|
|
1132
1199
|
const tracks = this.rippleTracks([track]);
|
|
1133
1200
|
if (newEnd < end) {
|
|
@@ -1156,11 +1223,11 @@ var Editor = (_class = class {
|
|
|
1156
1223
|
case "slip_clip": {
|
|
1157
1224
|
const { track, clip } = this.clip(e.clip);
|
|
1158
1225
|
this.unlocked(track);
|
|
1159
|
-
if (clip.type !== "media" && clip.type !== "sequence") refuse(`Clip "${clip.id}" is a ${clip.type === "text" ? "title" : "colour"}, so it has no source to slip; only video, audio and compound clips slip.`);
|
|
1226
|
+
if (clip.type !== "media" && clip.type !== "sequence") refuse(`Clip "${clip.id}" is a ${clip.type === "text" ? "title" : clip.type === "effect" ? "effect clip" : "colour"}, so it has no source to slip; only video, audio and compound clips slip.`);
|
|
1160
1227
|
const source = clip.type === "sequence" ? `sequence "${clip.sequence}"` : `"${this.asset(clip.asset).id}"`;
|
|
1161
1228
|
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.`);
|
|
1162
|
-
const handles =
|
|
1163
|
-
const { lead, tail } =
|
|
1229
|
+
const handles = _chunkIWSMDQE5cjs.videoClipHandles.call(void 0, clip, _chunkIWSMDQE5cjs.videoAssetMap.call(void 0, this.p), _chunkIWSMDQE5cjs.videoSequenceMap.call(void 0, this.p));
|
|
1230
|
+
const { lead, tail } = _chunkIWSMDQE5cjs.videoClipOverhang.call(void 0, track, clip);
|
|
1164
1231
|
const delta = this.clamp(
|
|
1165
1232
|
e.delta,
|
|
1166
1233
|
lead - handles.before,
|
|
@@ -1178,13 +1245,13 @@ var Editor = (_class = class {
|
|
|
1178
1245
|
this.unlocked(track);
|
|
1179
1246
|
const L = left.clip;
|
|
1180
1247
|
const R = right.clip;
|
|
1181
|
-
if (Math.abs(
|
|
1182
|
-
if (Math.abs(
|
|
1183
|
-
refuse(`"${L.id}" ends at ${
|
|
1248
|
+
if (Math.abs(_chunkIWSMDQE5cjs.videoClipEnd.call(void 0, L) - R.start) > _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) {
|
|
1249
|
+
if (Math.abs(_chunkIWSMDQE5cjs.videoClipEnd.call(void 0, R) - L.start) <= _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) refuse(`"${R.id}" comes before "${L.id}"; pass left "${R.id}" and right "${L.id}".`);
|
|
1250
|
+
refuse(`"${L.id}" ends at ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, L))} but "${R.id}" starts at ${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, R.start)}; a roll needs two clips that meet at a cut (use trim_clip to move one edge).`);
|
|
1184
1251
|
}
|
|
1185
|
-
const assets =
|
|
1186
|
-
const lo = Math.max(-(L.duration - this.frame), -(
|
|
1187
|
-
const hi = Math.min(R.duration - this.frame,
|
|
1252
|
+
const assets = _chunkIWSMDQE5cjs.videoAssetMap.call(void 0, this.p);
|
|
1253
|
+
const lo = Math.max(-(L.duration - this.frame), -(_chunkIWSMDQE5cjs.videoClipHandles.call(void 0, R, assets, _chunkIWSMDQE5cjs.videoSequenceMap.call(void 0, this.p)).before - _chunkIWSMDQE5cjs.videoClipOverhang.call(void 0, track, R).lead));
|
|
1254
|
+
const hi = Math.min(R.duration - this.frame, _chunkIWSMDQE5cjs.videoClipHandles.call(void 0, L, assets, _chunkIWSMDQE5cjs.videoSequenceMap.call(void 0, this.p)).after - _chunkIWSMDQE5cjs.videoClipOverhang.call(void 0, track, L).tail);
|
|
1188
1255
|
const delta = this.clamp(
|
|
1189
1256
|
e.delta,
|
|
1190
1257
|
lo,
|
|
@@ -1200,18 +1267,18 @@ var Editor = (_class = class {
|
|
|
1200
1267
|
case "slide_clip": {
|
|
1201
1268
|
const { track, clip } = this.clip(e.clip);
|
|
1202
1269
|
this.unlocked(track);
|
|
1203
|
-
const before =
|
|
1204
|
-
const after =
|
|
1270
|
+
const before = _chunkIWSMDQE5cjs.videoClipBefore.call(void 0, track, clip);
|
|
1271
|
+
const after = _chunkIWSMDQE5cjs.videoClipAfter.call(void 0, track, clip);
|
|
1205
1272
|
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.`);
|
|
1206
|
-
const assets =
|
|
1207
|
-
const end =
|
|
1273
|
+
const assets = _chunkIWSMDQE5cjs.videoAssetMap.call(void 0, this.p);
|
|
1274
|
+
const end = _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip);
|
|
1208
1275
|
const others = track.clips.filter((c) => c !== clip);
|
|
1209
1276
|
const room = {
|
|
1210
|
-
earlier: before ? before.duration - this.frame : clip.start - others.filter((c) =>
|
|
1211
|
-
later: after ? after.duration - this.frame : others.filter((c) => c.start >= end -
|
|
1277
|
+
earlier: before ? before.duration - this.frame : clip.start - others.filter((c) => _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c) <= clip.start + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON).reduce((m, c) => Math.max(m, _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c)), 0),
|
|
1278
|
+
later: after ? after.duration - this.frame : others.filter((c) => c.start >= end - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON).reduce((m, c) => Math.min(m, c.start - end), Infinity)
|
|
1212
1279
|
};
|
|
1213
|
-
const lo = -Math.min(room.earlier, after ?
|
|
1214
|
-
const hi = Math.min(room.later, before ?
|
|
1280
|
+
const lo = -Math.min(room.earlier, after ? _chunkIWSMDQE5cjs.videoClipHandles.call(void 0, after, assets, _chunkIWSMDQE5cjs.videoSequenceMap.call(void 0, this.p)).before - _chunkIWSMDQE5cjs.videoClipOverhang.call(void 0, track, after).lead : Infinity);
|
|
1281
|
+
const hi = Math.min(room.later, before ? _chunkIWSMDQE5cjs.videoClipHandles.call(void 0, before, assets, _chunkIWSMDQE5cjs.videoSequenceMap.call(void 0, this.p)).after - _chunkIWSMDQE5cjs.videoClipOverhang.call(void 0, track, before).tail : Infinity);
|
|
1215
1282
|
const delta = this.clamp(
|
|
1216
1283
|
e.delta,
|
|
1217
1284
|
lo,
|
|
@@ -1244,29 +1311,29 @@ var Editor = (_class = class {
|
|
|
1244
1311
|
}
|
|
1245
1312
|
case "split_at": {
|
|
1246
1313
|
const tracks = this.rangeTracks(e.tracks);
|
|
1247
|
-
const lefts = tracks.flatMap((t) => t.clips.filter((c) => c.start < e.at -
|
|
1248
|
-
if (!lefts.length) refuse(`No clip runs across ${
|
|
1314
|
+
const lefts = tracks.flatMap((t) => t.clips.filter((c) => c.start < e.at - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON && _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c) > e.at + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON).map((c) => c.id));
|
|
1315
|
+
if (!lefts.length) refuse(`No clip runs across ${_chunkIWSMDQE5cjs.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.`);
|
|
1249
1316
|
const created = this.cutAcross(tracks, e.at).map((c) => c.id);
|
|
1250
1317
|
return this.outcomes.push({ op: e.op, clips: lefts, created });
|
|
1251
1318
|
}
|
|
1252
1319
|
case "set_keyframes": {
|
|
1253
1320
|
const { track, clip } = this.clip(e.clip);
|
|
1254
1321
|
this.unlocked(track);
|
|
1255
|
-
if (!
|
|
1322
|
+
if (!_chunkIWSMDQE5cjs.VIDEO_KEYFRAME_PROPERTIES.includes(e.property)) refuse(`"${e.property}" cannot be keyframed; use one of ${_chunkIWSMDQE5cjs.VIDEO_KEYFRAME_PROPERTIES.join(", ")}.`);
|
|
1256
1323
|
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.`);
|
|
1257
|
-
const limits =
|
|
1258
|
-
const transform =
|
|
1324
|
+
const limits = _chunkIWSMDQE5cjs.VIDEO_KEYFRAME_LIMITS[e.property];
|
|
1325
|
+
const transform = _chunkIWSMDQE5cjs.VIDEO_TRANSFORM_PROPERTIES.includes(e.property);
|
|
1259
1326
|
const c = clip;
|
|
1260
1327
|
const current = transform ? _optionalChain([c, 'access', _18 => _18.transform, 'optionalAccess', _19 => _19[e.property]]) : c[e.property];
|
|
1261
1328
|
let value;
|
|
1262
1329
|
if (e.keys === null) {
|
|
1263
|
-
const v =
|
|
1264
|
-
value =
|
|
1330
|
+
const v = _chunkIWSMDQE5cjs.videoValueAt.call(void 0, current, 0, limits.default);
|
|
1331
|
+
value = _chunkIWSMDQE5cjs.isVideoKeyframes.call(void 0, current) ? v === limits.default ? void 0 : v : current;
|
|
1265
1332
|
} else {
|
|
1266
1333
|
if (!Array.isArray(e.keys) || !e.keys.length) refuse('"keys" must list at least one key { t, v }; pass null to remove the keyframes.');
|
|
1267
1334
|
let sorted = [];
|
|
1268
1335
|
try {
|
|
1269
|
-
sorted =
|
|
1336
|
+
sorted = _chunkIWSMDQE5cjs.sortVideoKeys.call(void 0, e.keys);
|
|
1270
1337
|
} catch (error) {
|
|
1271
1338
|
refuse(error.message);
|
|
1272
1339
|
}
|
|
@@ -1285,12 +1352,12 @@ var Editor = (_class = class {
|
|
|
1285
1352
|
this.unlocked(track);
|
|
1286
1353
|
let at = 0;
|
|
1287
1354
|
const moved = [];
|
|
1288
|
-
for (const clip of
|
|
1289
|
-
if (clip.start >= (_nullishCoalesce(e.from, () => ( 0))) -
|
|
1355
|
+
for (const clip of _chunkIWSMDQE5cjs.sortedVideoClips.call(void 0, track)) {
|
|
1356
|
+
if (clip.start >= (_nullishCoalesce(e.from, () => ( 0))) - _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON && clip.start > at + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) {
|
|
1290
1357
|
clip.start = Math.max(at, _nullishCoalesce(e.from, () => ( 0)));
|
|
1291
1358
|
moved.push(clip.id);
|
|
1292
1359
|
}
|
|
1293
|
-
at = Math.max(at,
|
|
1360
|
+
at = Math.max(at, _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip));
|
|
1294
1361
|
}
|
|
1295
1362
|
return this.outcomes.push({ op: e.op, track: track.id, clips: moved });
|
|
1296
1363
|
}
|
|
@@ -1445,7 +1512,7 @@ function videoClipWaveform(clip, peaks, columns) {
|
|
|
1445
1512
|
const step = clip.duration / Math.max(1, n);
|
|
1446
1513
|
for (let c = 0; c < n; c++) {
|
|
1447
1514
|
const { min, max } = videoAudioPeakRange(peaks, start + c * step * speed, start + (c + 1) * step * speed);
|
|
1448
|
-
const gain =
|
|
1515
|
+
const gain = _chunkIWSMDQE5cjs.videoClipSoundGain.call(void 0, clip, (c + 0.5) * step);
|
|
1449
1516
|
out[2 * c] = min * gain;
|
|
1450
1517
|
out[2 * c + 1] = max * gain;
|
|
1451
1518
|
}
|
|
@@ -2010,7 +2077,7 @@ function videoTranscriptTrack(project, track) {
|
|
|
2010
2077
|
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(", ")}.`);
|
|
2011
2078
|
return track;
|
|
2012
2079
|
}
|
|
2013
|
-
const assets =
|
|
2080
|
+
const assets = _chunkIWSMDQE5cjs.videoAssetMap.call(void 0, project);
|
|
2014
2081
|
const transcribed = (t) => t.clips.some((c) => c.type === "media" && _optionalChain([assets, 'access', _21 => _21.get, 'call', _22 => _22(c.asset), 'optionalAccess', _23 => _23.transcript, 'optionalAccess', _24 => _24.length]));
|
|
2015
2082
|
return _nullishCoalesce(_optionalChain([(_nullishCoalesce(project.tracks.find((t) => t.kind === "audio" && transcribed(t)), () => ( project.tracks.find(transcribed)))), 'optionalAccess', _25 => _25.id]), () => ( null));
|
|
2016
2083
|
}
|
|
@@ -2018,16 +2085,16 @@ function videoTimelineTranscript(project, options = {}) {
|
|
|
2018
2085
|
const id = videoTranscriptTrack(project, options.track);
|
|
2019
2086
|
if (!id) return [];
|
|
2020
2087
|
const track = project.tracks.find((t) => t.id === id);
|
|
2021
|
-
const assets =
|
|
2088
|
+
const assets = _chunkIWSMDQE5cjs.videoAssetMap.call(void 0, project);
|
|
2022
2089
|
const out = [];
|
|
2023
|
-
for (const clip of
|
|
2090
|
+
for (const clip of _chunkIWSMDQE5cjs.sortedVideoClips.call(void 0, track)) {
|
|
2024
2091
|
if (clip.type !== "media") continue;
|
|
2025
2092
|
const words = _optionalChain([assets, 'access', _26 => _26.get, 'call', _27 => _27(clip.asset), 'optionalAccess', _28 => _28.transcript]);
|
|
2026
2093
|
if (!_optionalChain([words, 'optionalAccess', _29 => _29.length])) continue;
|
|
2027
|
-
const speed =
|
|
2094
|
+
const speed = _chunkIWSMDQE5cjs.videoClipSpeed.call(void 0, clip);
|
|
2028
2095
|
const from = _nullishCoalesce(clip.in, () => ( 0));
|
|
2029
2096
|
const to = from + clip.duration * speed;
|
|
2030
|
-
const toTimeline = (s) => Math.min(
|
|
2097
|
+
const toTimeline = (s) => Math.min(_chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip), Math.max(clip.start, clip.start + (s - from) / speed));
|
|
2031
2098
|
words.forEach((w, index) => {
|
|
2032
2099
|
const mid = (w.start + w.end) / 2;
|
|
2033
2100
|
if (mid < from || mid >= to) return;
|
|
@@ -2072,19 +2139,19 @@ function findVideoTranscriptPauses(words, options = {}) {
|
|
|
2072
2139
|
let to = b.start - keep;
|
|
2073
2140
|
if (options.fps) {
|
|
2074
2141
|
const f = 1e3 / options.fps;
|
|
2075
|
-
from =
|
|
2076
|
-
to =
|
|
2142
|
+
from = _chunkIWSMDQE5cjs.snapToVideoFrame.call(void 0, Math.ceil(from / f - 1e-9) * f, options.fps);
|
|
2143
|
+
to = _chunkIWSMDQE5cjs.snapToVideoFrame.call(void 0, Math.floor(to / f + 1e-9) * f, options.fps);
|
|
2077
2144
|
}
|
|
2078
|
-
if (to - from >
|
|
2145
|
+
if (to - from > _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) out.push({ from, to, text: `(pause after "${a.word}")` });
|
|
2079
2146
|
}
|
|
2080
2147
|
return out;
|
|
2081
2148
|
}
|
|
2082
2149
|
function mergeVideoRanges(ranges) {
|
|
2083
|
-
const sorted = ranges.filter((r) => r.to - r.from >
|
|
2150
|
+
const sorted = ranges.filter((r) => r.to - r.from > _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON).map((r) => ({ from: r.from, to: r.to })).sort((a, b) => a.from - b.from);
|
|
2084
2151
|
const out = [];
|
|
2085
2152
|
for (const r of sorted) {
|
|
2086
2153
|
const last = out[out.length - 1];
|
|
2087
|
-
if (last && r.from <= last.to +
|
|
2154
|
+
if (last && r.from <= last.to + _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON) last.to = Math.max(last.to, r.to);
|
|
2088
2155
|
else out.push(r);
|
|
2089
2156
|
}
|
|
2090
2157
|
return out;
|
|
@@ -2168,7 +2235,7 @@ function videoProxyFfmpeg(asset, options = {}) {
|
|
|
2168
2235
|
output
|
|
2169
2236
|
];
|
|
2170
2237
|
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 } : {} };
|
|
2171
|
-
return { asset: asset.id, args, command: ["ffmpeg", ...args].map(
|
|
2238
|
+
return { asset: asset.id, args, command: ["ffmpeg", ...args].map(_chunkIWSMDQE5cjs.videoShellQuote).join(" "), proxy };
|
|
2172
2239
|
}
|
|
2173
2240
|
function videoProxyPlan(project, options = {}) {
|
|
2174
2241
|
const scale = _nullishCoalesce(options.scale, () => ( 0.5));
|
|
@@ -2194,7 +2261,7 @@ var videoSourceFrameTime = (frame, fps) => (frame + 0.5) * 1e3 / fps;
|
|
|
2194
2261
|
var videoFrameCacheKey = (src, frame) => `${frame}@${src}`;
|
|
2195
2262
|
function videoFrameRequestsAt(project, time, srcFor = (l) => l.src) {
|
|
2196
2263
|
const out = [];
|
|
2197
|
-
for (const layer of
|
|
2264
|
+
for (const layer of _chunkIWSMDQE5cjs.videoFrameLeafLayers.call(void 0, _chunkIWSMDQE5cjs.videoFrameAt.call(void 0, project, time).layers)) {
|
|
2198
2265
|
if (layer.type !== "media" || layer.assetKind !== "video") continue;
|
|
2199
2266
|
const src = srcFor(layer);
|
|
2200
2267
|
if (!src) continue;
|
|
@@ -2451,6 +2518,9 @@ var VideoPreviewEngine = (_class5 = class {
|
|
|
2451
2518
|
this.frameCache = options.frameCache !== void 0 ? options.frameCache : _nullishCoalesce(source.frameCache, () => ( null));
|
|
2452
2519
|
this.unsubscribeFrames = this.frameCache ? this.frameCache.subscribe(() => this.redraw()) : () => {
|
|
2453
2520
|
};
|
|
2521
|
+
this.effects = options.effects !== void 0 ? options.effects : _nullishCoalesce(source.effectsEngine, () => ( null));
|
|
2522
|
+
this.unsubscribeEffects = this.effects ? this.effects.subscribe(() => this.redraw()) : () => {
|
|
2523
|
+
};
|
|
2454
2524
|
const pixels = options.pixels !== void 0 ? options.pixels : source.previewPixels;
|
|
2455
2525
|
this.detachPixels = pixels ? pixels.attach(() => this.readPixels()) : () => {
|
|
2456
2526
|
};
|
|
@@ -2480,6 +2550,8 @@ var VideoPreviewEngine = (_class5 = class {
|
|
|
2480
2550
|
__init31() {this.fps = 30}
|
|
2481
2551
|
|
|
2482
2552
|
__init32() {this.scratchCanvases = /* @__PURE__ */ new Map()}
|
|
2553
|
+
|
|
2554
|
+
|
|
2483
2555
|
/** The canvas's pixels and the frame they show, or `null` when its context cannot be read. */
|
|
2484
2556
|
readPixels() {
|
|
2485
2557
|
const ctx = this.ctx;
|
|
@@ -2530,7 +2602,7 @@ var VideoPreviewEngine = (_class5 = class {
|
|
|
2530
2602
|
if (this.destroyed) return;
|
|
2531
2603
|
const state = this.source.getState();
|
|
2532
2604
|
const { project, time, playing } = state;
|
|
2533
|
-
const frame =
|
|
2605
|
+
const frame = _chunkIWSMDQE5cjs.videoFrameAt.call(void 0, project, time);
|
|
2534
2606
|
const scale = resolveVideoPreviewScale(_nullishCoalesce(this.options.previewScale, () => ( state.previewScale)), this.resolutionFor(project.width));
|
|
2535
2607
|
const assets = new Map(project.assets.map((a) => [a.id, a]));
|
|
2536
2608
|
this.srcFor = (layer) => videoPreviewSrc(assets.get(_nullishCoalesce(layer.asset, () => ( ""))), scale, layer.src);
|
|
@@ -2560,7 +2632,7 @@ var VideoPreviewEngine = (_class5 = class {
|
|
|
2560
2632
|
}
|
|
2561
2633
|
};
|
|
2562
2634
|
const sounding = new Map(frame.audio.map((a) => [a.clip, a]));
|
|
2563
|
-
for (const layer of
|
|
2635
|
+
for (const layer of _chunkIWSMDQE5cjs.videoFrameLeafLayers.call(void 0, frame.layers)) {
|
|
2564
2636
|
if (layer.type !== "media" || layer.assetKind !== "video" || !layer.src) continue;
|
|
2565
2637
|
const sound = sounding.get(layer.clip);
|
|
2566
2638
|
sync(layer.clip, this.srcFor(layer), "video", _nullishCoalesce(layer.sourceTime, () => ( 0)), _nullishCoalesce(_optionalChain([sound, 'optionalAccess', _71 => _71.speed]), () => ( 1)), sound ? sound.gain : null);
|
|
@@ -2568,14 +2640,22 @@ var VideoPreviewEngine = (_class5 = class {
|
|
|
2568
2640
|
}
|
|
2569
2641
|
for (const a of sounding.values()) sync(a.clip, a.src, "audio", a.sourceTime, a.speed, a.gain);
|
|
2570
2642
|
for (const entry of [...this.media.values()]) if (!active.has(entry.clip)) this.release(entry);
|
|
2571
|
-
this.draw(frame);
|
|
2643
|
+
this.draw(this.drawable(project, frame));
|
|
2644
|
+
}
|
|
2645
|
+
/** With effects, the frame is drawn at the start of its frame, so effect pictures are cached once per frame. */
|
|
2646
|
+
drawable(project, frame) {
|
|
2647
|
+
if (!_optionalChain([this, 'access', _72 => _72.effects, 'optionalAccess', _73 => _73.available]) || !_chunkIWSMDQE5cjs.videoLayersUseEffects.call(void 0, frame.layers)) return frame;
|
|
2648
|
+
const at = _chunkIWSMDQE5cjs.videoEffectFrameTime.call(void 0, frame.time, project.fps);
|
|
2649
|
+
return at === frame.time ? frame : { ..._chunkIWSMDQE5cjs.videoFrameAt.call(void 0, project, at), time: frame.time };
|
|
2572
2650
|
}
|
|
2573
2651
|
redraw() {
|
|
2574
2652
|
if (this.scheduled || this.destroyed) return;
|
|
2575
2653
|
this.scheduled = true;
|
|
2576
2654
|
queueMicrotask(() => {
|
|
2577
2655
|
this.scheduled = false;
|
|
2578
|
-
if (
|
|
2656
|
+
if (this.destroyed) return;
|
|
2657
|
+
const { project, time } = this.source.getState();
|
|
2658
|
+
this.draw(this.drawable(project, _chunkIWSMDQE5cjs.videoFrameAt.call(void 0, project, time)));
|
|
2579
2659
|
});
|
|
2580
2660
|
}
|
|
2581
2661
|
__init33() {this.sourceFor = (layer) => {
|
|
@@ -2586,7 +2666,7 @@ var VideoPreviewEngine = (_class5 = class {
|
|
|
2586
2666
|
const entry = this.media.get(layer.clip);
|
|
2587
2667
|
const ready = !!entry && entry.media.readyState >= 2;
|
|
2588
2668
|
const cache = this.frameCache;
|
|
2589
|
-
const src = _nullishCoalesce(_optionalChain([entry, 'optionalAccess',
|
|
2669
|
+
const src = _nullishCoalesce(_optionalChain([entry, 'optionalAccess', _74 => _74.src]), () => ( this.srcFor(layer)));
|
|
2590
2670
|
const sourceTime = _nullishCoalesce(layer.sourceTime, () => ( 0));
|
|
2591
2671
|
if (cache && src && (!this.playing || !ready || entry.media.seeking)) {
|
|
2592
2672
|
const hit = cache.get(src, sourceTime, this.fps);
|
|
@@ -2613,18 +2693,27 @@ var VideoPreviewEngine = (_class5 = class {
|
|
|
2613
2693
|
if (this.canvas.height !== h) this.canvas.height = h;
|
|
2614
2694
|
this.complete = true;
|
|
2615
2695
|
const sourceFor = (layer) => {
|
|
2696
|
+
if (layer.type === "effect") return null;
|
|
2616
2697
|
const source = this.sourceFor(layer);
|
|
2617
2698
|
if (!source) this.complete = false;
|
|
2618
2699
|
return source;
|
|
2619
2700
|
};
|
|
2620
|
-
|
|
2701
|
+
_chunkIWSMDQE5cjs.drawVideoFrame.call(void 0, this.ctx, frame, sourceFor, resolution, {
|
|
2702
|
+
defineSvgFilter: this.defineSvgFilter,
|
|
2703
|
+
lutFor: this.lutFor,
|
|
2704
|
+
scratch: this.scratch,
|
|
2705
|
+
effects: this.effects,
|
|
2706
|
+
onEffectWaiting: () => {
|
|
2707
|
+
this.complete = false;
|
|
2708
|
+
}
|
|
2709
|
+
});
|
|
2621
2710
|
this.drawn = { time: frame.time, complete: this.complete };
|
|
2622
|
-
_optionalChain([this, 'access',
|
|
2623
|
-
_optionalChain([this, 'access',
|
|
2711
|
+
_optionalChain([this, 'access', _75 => _75.options, 'access', _76 => _76.onFrame, 'optionalCall', _77 => _77(frame)]);
|
|
2712
|
+
_optionalChain([this, 'access', _78 => _78.pixelsTarget, 'optionalAccess', _79 => _79.drawn, 'call', _80 => _80(frame.time, this.complete)]);
|
|
2624
2713
|
}
|
|
2625
2714
|
/** A grade's LUT once loaded; while it loads (or if it fails) the frame is drawn without it and counts as incomplete. */
|
|
2626
2715
|
__init34() {this.lutFor = (src) => {
|
|
2627
|
-
const lut = _optionalChain([this, 'access',
|
|
2716
|
+
const lut = _optionalChain([this, 'access', _81 => _81.lutCache, 'optionalAccess', _82 => _82.get, 'call', _83 => _83(src)]);
|
|
2628
2717
|
if (!lut) this.complete = false;
|
|
2629
2718
|
return lut;
|
|
2630
2719
|
}}
|
|
@@ -2668,7 +2757,8 @@ var VideoPreviewEngine = (_class5 = class {
|
|
|
2668
2757
|
this.detachPixels();
|
|
2669
2758
|
this.unsubscribeLuts();
|
|
2670
2759
|
this.unsubscribeFrames();
|
|
2671
|
-
|
|
2760
|
+
this.unsubscribeEffects();
|
|
2761
|
+
_optionalChain([this, 'access', _84 => _84.filterHost, 'optionalAccess', _85 => _85.remove, 'call', _86 => _86()]);
|
|
2672
2762
|
this.filterHost = null;
|
|
2673
2763
|
this.filters.clear();
|
|
2674
2764
|
this.unsubscribe();
|
|
@@ -2689,6 +2779,10 @@ var VideoEditorController = (_class6 = class {
|
|
|
2689
2779
|
|
|
2690
2780
|
/** The host's frame cache, if it gave one (the preview fills and reads it). */
|
|
2691
2781
|
|
|
2782
|
+
/** The effects provider slot (see `setEffectsProvider`). */
|
|
2783
|
+
|
|
2784
|
+
/** Rendered effect pictures for the preview and frame-exact exports. */
|
|
2785
|
+
|
|
2692
2786
|
|
|
2693
2787
|
|
|
2694
2788
|
__init38() {this.selection = []}
|
|
@@ -2704,14 +2798,17 @@ var VideoEditorController = (_class6 = class {
|
|
|
2704
2798
|
constructor(options = {}) {;_class6.prototype.__init37.call(this);_class6.prototype.__init38.call(this);_class6.prototype.__init39.call(this);_class6.prototype.__init40.call(this);_class6.prototype.__init41.call(this);_class6.prototype.__init42.call(this);_class6.prototype.__init43.call(this);_class6.prototype.__init44.call(this);_class6.prototype.__init45.call(this);
|
|
2705
2799
|
this.history = _nullishCoalesce(options.history, () => ( new (0, _chunkQKLRAA4Tcjs.HistoryManager)()));
|
|
2706
2800
|
this.audioPeaks = options.audioPeaks instanceof VideoAudioPeaksCache ? options.audioPeaks : new VideoAudioPeaksCache(options.audioPeaks);
|
|
2707
|
-
this.luts = options.luts instanceof
|
|
2801
|
+
this.luts = options.luts instanceof _chunkIWSMDQE5cjs.VideoLutCache ? options.luts : new (0, _chunkIWSMDQE5cjs.VideoLutCache)(options.luts);
|
|
2708
2802
|
this.frameCache = _nullishCoalesce(options.frameCache, () => ( null));
|
|
2803
|
+
this.effects = new (0, _chunkIOXKXQNWcjs.EffectsSlot)();
|
|
2804
|
+
if (options.effects) this.effects.set(options.effects);
|
|
2805
|
+
this.effectsEngine = new (0, _chunkIWSMDQE5cjs.VideoEffectsEngine)({ slot: this.effects });
|
|
2709
2806
|
this.project = options.project ? parseVideoProject(options.project) : createVideoProject();
|
|
2710
2807
|
this.issues = checkVideoProject(this.project);
|
|
2711
2808
|
this.readOnly = _nullishCoalesce(options.readOnly, () => ( false));
|
|
2712
2809
|
this.previewScale = checkPreviewScale(_nullishCoalesce(options.previewScale, () => ( "auto")));
|
|
2713
2810
|
this.onChange = options.onChange;
|
|
2714
|
-
this.player = new (0, _chunk477UVMNRcjs.AnimationPlayer)({ clock: options.clock, duration: () =>
|
|
2811
|
+
this.player = new (0, _chunk477UVMNRcjs.AnimationPlayer)({ clock: options.clock, duration: () => _chunkIWSMDQE5cjs.videoProjectDuration.call(void 0, this.project), loop: "none" });
|
|
2715
2812
|
this.state = this.computeState();
|
|
2716
2813
|
this.connect();
|
|
2717
2814
|
}
|
|
@@ -2721,12 +2818,14 @@ var VideoEditorController = (_class6 = class {
|
|
|
2721
2818
|
this.player.subscribe(() => this.notify()),
|
|
2722
2819
|
this.history.subscribe(() => {
|
|
2723
2820
|
if (!this.applying) this.notify();
|
|
2724
|
-
})
|
|
2821
|
+
}),
|
|
2822
|
+
this.effects.subscribe(() => this.notify())
|
|
2725
2823
|
);
|
|
2726
2824
|
}
|
|
2727
2825
|
/** Pauses and stops listening to the player and history. Subscribing again reconnects (React StrictMode). */
|
|
2728
2826
|
destroy() {
|
|
2729
2827
|
this.player.pause();
|
|
2828
|
+
this.effectsEngine.reset();
|
|
2730
2829
|
this.unsubscribers.splice(0).forEach((u) => u());
|
|
2731
2830
|
}
|
|
2732
2831
|
__init44() {this.getState = () => this.state}
|
|
@@ -2746,12 +2845,12 @@ var VideoEditorController = (_class6 = class {
|
|
|
2746
2845
|
const h = this.history.getState();
|
|
2747
2846
|
return {
|
|
2748
2847
|
project: this.project,
|
|
2749
|
-
duration:
|
|
2848
|
+
duration: _chunkIWSMDQE5cjs.videoProjectDuration.call(void 0, this.project),
|
|
2750
2849
|
time: p.time,
|
|
2751
2850
|
playing: p.playing,
|
|
2752
2851
|
loop: p.loop,
|
|
2753
2852
|
selection: this.selection,
|
|
2754
|
-
current:
|
|
2853
|
+
current: _chunkIWSMDQE5cjs.videoClipsAt.call(void 0, this.project, p.time).map((c) => c.clip.id),
|
|
2755
2854
|
issues: this.issues,
|
|
2756
2855
|
readOnly: this.readOnly,
|
|
2757
2856
|
error: this.error,
|
|
@@ -2760,6 +2859,7 @@ var VideoEditorController = (_class6 = class {
|
|
|
2760
2859
|
undoLabel: h.undoName,
|
|
2761
2860
|
redoLabel: h.redoName,
|
|
2762
2861
|
previewScale: this.previewScale,
|
|
2862
|
+
effectsProvider: this.effects.provider,
|
|
2763
2863
|
revision: this.revision
|
|
2764
2864
|
};
|
|
2765
2865
|
}
|
|
@@ -2782,14 +2882,14 @@ var VideoEditorController = (_class6 = class {
|
|
|
2782
2882
|
this.issues = checkVideoProject(project);
|
|
2783
2883
|
const ids = new Set(project.tracks.flatMap((t) => t.clips.map((c) => c.id)));
|
|
2784
2884
|
if (this.selection.some((id) => !ids.has(id))) this.selection = this.selection.filter((id) => ids.has(id));
|
|
2785
|
-
this.player.setDuration(() =>
|
|
2885
|
+
this.player.setDuration(() => _chunkIWSMDQE5cjs.videoProjectDuration.call(void 0, this.project));
|
|
2786
2886
|
} finally {
|
|
2787
2887
|
this.applying = false;
|
|
2788
2888
|
}
|
|
2789
2889
|
this.notify();
|
|
2790
|
-
_optionalChain([this, 'access',
|
|
2890
|
+
_optionalChain([this, 'access', _87 => _87.onChange, 'optionalCall', _88 => _88(project)]);
|
|
2791
2891
|
}
|
|
2792
|
-
commit(label, next) {
|
|
2892
|
+
commit(label, next, merge) {
|
|
2793
2893
|
const before = this.project;
|
|
2794
2894
|
this.error = null;
|
|
2795
2895
|
if (next === before) {
|
|
@@ -2803,7 +2903,8 @@ var VideoEditorController = (_class6 = class {
|
|
|
2803
2903
|
undo: () => this.setProject(before),
|
|
2804
2904
|
redo: () => this.setProject(next)
|
|
2805
2905
|
};
|
|
2806
|
-
this.history.
|
|
2906
|
+
if (merge) this.history.executeMerged(command, { key: merge });
|
|
2907
|
+
else this.history.execute(command);
|
|
2807
2908
|
}
|
|
2808
2909
|
refuse(message) {
|
|
2809
2910
|
this.error = message;
|
|
@@ -2816,14 +2917,15 @@ var VideoEditorController = (_class6 = class {
|
|
|
2816
2917
|
}
|
|
2817
2918
|
/**
|
|
2818
2919
|
* Applies edits as one undo step, all or nothing (see `applyVideoEdits`). With `dryRun` it
|
|
2819
|
-
* reports what would happen and changes nothing.
|
|
2920
|
+
* reports what would happen and changes nothing. Edits with the same `merge` key in a row
|
|
2921
|
+
* (a slider drag) fold into one undo step.
|
|
2820
2922
|
*/
|
|
2821
2923
|
apply(edits, label = "Edit video", options = {}) {
|
|
2822
2924
|
const reason = this.readOnlyReason();
|
|
2823
2925
|
if (reason) return this.refuse(reason);
|
|
2824
2926
|
const result = applyVideoEdits(this.project, edits);
|
|
2825
2927
|
if (!result.ok) return options.dryRun ? result : this.refuse(result.error);
|
|
2826
|
-
if (!options.dryRun) this.commit(label, result.project);
|
|
2928
|
+
if (!options.dryRun) this.commit(label, result.project, options.merge);
|
|
2827
2929
|
return result;
|
|
2828
2930
|
}
|
|
2829
2931
|
/** Opens a project (JSON or object). `clearHistory` drops the undo stack (opening a file); otherwise it is one undo step. */
|
|
@@ -2862,7 +2964,7 @@ var VideoEditorController = (_class6 = class {
|
|
|
2862
2964
|
}
|
|
2863
2965
|
/** Selects clips (unknown ids are dropped). `add` toggles them into the current selection. */
|
|
2864
2966
|
select(clips, options = {}) {
|
|
2865
|
-
const known = _nullishCoalesce(_optionalChain([clips, 'optionalAccess',
|
|
2967
|
+
const known = _nullishCoalesce(_optionalChain([clips, 'optionalAccess', _89 => _89.filter, 'call', _90 => _90((id) => _chunkIWSMDQE5cjs.findVideoClip.call(void 0, this.project, id))]), () => ( []));
|
|
2866
2968
|
let next;
|
|
2867
2969
|
if (options.add) {
|
|
2868
2970
|
next = [...this.selection];
|
|
@@ -2889,7 +2991,7 @@ var VideoEditorController = (_class6 = class {
|
|
|
2889
2991
|
step(frames) {
|
|
2890
2992
|
this.player.pause();
|
|
2891
2993
|
const fps = this.project.fps;
|
|
2892
|
-
this.player.seek(Math.max(0,
|
|
2994
|
+
this.player.seek(Math.max(0, _chunkIWSMDQE5cjs.snapToVideoFrame.call(void 0, this.player.currentTime, fps) + frames * 1e3 / fps));
|
|
2893
2995
|
}
|
|
2894
2996
|
setLoop(loop) {
|
|
2895
2997
|
this.player.setLoop(loop);
|
|
@@ -2906,14 +3008,14 @@ var VideoEditorController = (_class6 = class {
|
|
|
2906
3008
|
*/
|
|
2907
3009
|
snap(time, options = {}) {
|
|
2908
3010
|
const threshold = _nullishCoalesce(options.threshold, () => ( 8 * 1e3 / this.project.fps));
|
|
2909
|
-
const points =
|
|
2910
|
-
const hit =
|
|
2911
|
-
return hit.snapped !== null ? hit : { time: Math.max(0,
|
|
3011
|
+
const points = _chunkIWSMDQE5cjs.videoSnapPoints.call(void 0, this.project, { exclude: options.exclude, playhead: options.playhead === false ? void 0 : this.player.currentTime });
|
|
3012
|
+
const hit = _chunkIWSMDQE5cjs.snapVideoTime.call(void 0, time, points, threshold);
|
|
3013
|
+
return hit.snapped !== null ? hit : { time: Math.max(0, _chunkIWSMDQE5cjs.snapToVideoFrame.call(void 0, time, this.project.fps)), snapped: null };
|
|
2912
3014
|
}
|
|
2913
3015
|
/** Splits the selected clips (or every clip) under the playhead there, as one undo step. */
|
|
2914
3016
|
splitAtPlayhead() {
|
|
2915
|
-
const t =
|
|
2916
|
-
const under =
|
|
3017
|
+
const t = _chunkIWSMDQE5cjs.snapToVideoFrame.call(void 0, this.player.currentTime, this.project.fps);
|
|
3018
|
+
const under = _chunkIWSMDQE5cjs.videoClipsAt.call(void 0, this.project, t).filter(({ clip }) => t > clip.start && t < _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip));
|
|
2917
3019
|
const chosen = this.selection.length ? under.filter(({ clip }) => this.selection.includes(clip.id)) : under;
|
|
2918
3020
|
if (!chosen.length) return this.refuse("No clip is under the playhead to split.");
|
|
2919
3021
|
return this.apply(chosen.map(({ clip }) => ({ op: "split_clip", clip: clip.id, at: t })), "Split");
|
|
@@ -2923,25 +3025,200 @@ var VideoEditorController = (_class6 = class {
|
|
|
2923
3025
|
if (!this.selection.length) return this.refuse("Select clips to delete first.");
|
|
2924
3026
|
return this.apply({ op: "delete_clips", clips: [...this.selection], ripple: options.ripple }, options.ripple ? "Ripple delete" : "Delete clips");
|
|
2925
3027
|
}
|
|
3028
|
+
// -----------------------------------------------------------------------------------------
|
|
3029
|
+
// Effects
|
|
3030
|
+
// -----------------------------------------------------------------------------------------
|
|
3031
|
+
/** The registered effects provider, or `null`. */
|
|
3032
|
+
get effectsProvider() {
|
|
3033
|
+
return this.effects.provider;
|
|
3034
|
+
}
|
|
3035
|
+
/** Registers (or with `null` removes) the effects provider. Not an edit: no undo step. */
|
|
3036
|
+
setEffectsProvider(provider) {
|
|
3037
|
+
this.effects.set(provider);
|
|
3038
|
+
}
|
|
3039
|
+
/** Registers `provider` and returns a function that removes it again (if it is still the one set). */
|
|
3040
|
+
useEffects(provider) {
|
|
3041
|
+
return this.effects.use(provider);
|
|
3042
|
+
}
|
|
3043
|
+
/** The provider's description of an effect, checked for `place` (rejects without a provider or for an unknown id). */
|
|
3044
|
+
async describeEffect(effect, place) {
|
|
3045
|
+
const d = await this.effects.require().describe(effect);
|
|
3046
|
+
if (place) _chunkIWSMDQE5cjs.checkVideoEffectPlace.call(void 0, d, place);
|
|
3047
|
+
return d;
|
|
3048
|
+
}
|
|
3049
|
+
refused(message) {
|
|
3050
|
+
return this.refuse(message);
|
|
3051
|
+
}
|
|
3052
|
+
async effectEdit(run, merge) {
|
|
3053
|
+
const reason = this.readOnlyReason();
|
|
3054
|
+
if (reason) return this.refused(reason);
|
|
3055
|
+
let plan;
|
|
3056
|
+
try {
|
|
3057
|
+
plan = await run();
|
|
3058
|
+
} catch (error) {
|
|
3059
|
+
if (_chunkIOXKXQNWcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refused(error.message);
|
|
3060
|
+
throw error;
|
|
3061
|
+
}
|
|
3062
|
+
const result = this.apply(plan.edit, plan.label, { merge });
|
|
3063
|
+
if (!result.ok) return result;
|
|
3064
|
+
return { ...result, clip: plan.clip, ...plan.effect ? { effect: plan.effect() } : {} };
|
|
3065
|
+
}
|
|
3066
|
+
clipOrThrow(id) {
|
|
3067
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, this.project, id);
|
|
3068
|
+
if (!at) throw new Error(`There is no clip "${id}"; list_applied_effects or get_video_project lists the clips.`);
|
|
3069
|
+
return at.clip;
|
|
3070
|
+
}
|
|
3071
|
+
/**
|
|
3072
|
+
* Adds a filter or overlay effect to a clip's effect stack (at `index`, default the end: applied
|
|
3073
|
+
* last), with `values` over the effect's defaults (numbers may be keyframes). One undo step.
|
|
3074
|
+
* Returns the effect with its new id.
|
|
3075
|
+
*/
|
|
3076
|
+
applyClipEffect(clip, effect, options = {}) {
|
|
3077
|
+
return this.effectEdit(async () => {
|
|
3078
|
+
const current = this.clipOrThrow(clip);
|
|
3079
|
+
const d = await this.describeEffect(effect, "clip");
|
|
3080
|
+
const values = _chunkIWSMDQE5cjs.checkVideoEffectValues.call(void 0, d, options.values, { keyframes: true });
|
|
3081
|
+
const stack = [..._nullishCoalesce(current.effects, () => ( []))];
|
|
3082
|
+
const taken = new Set(stack.map((e) => e.id));
|
|
3083
|
+
let n = 1;
|
|
3084
|
+
while (taken.has(`fx${n}`)) n++;
|
|
3085
|
+
const added = { id: `fx${n}`, effect: d.id, provider: this.effects.require().id, name: d.name, values };
|
|
3086
|
+
if (options.enabled === false) added.enabled = false;
|
|
3087
|
+
if (options.opacity !== void 0) added.opacity = options.opacity;
|
|
3088
|
+
const index = _nullishCoalesce(options.index, () => ( stack.length));
|
|
3089
|
+
if (!(Number.isInteger(index) && index >= 0 && index <= stack.length)) throw new Error(`"index" must be a whole number from 0 to ${stack.length}.`);
|
|
3090
|
+
stack.splice(index, 0, added);
|
|
3091
|
+
return { edit: { op: "update_clip", clip, set: { effects: stack } }, label: `Add effect ${d.name}`, clip, effect: () => added };
|
|
3092
|
+
});
|
|
3093
|
+
}
|
|
3094
|
+
/**
|
|
3095
|
+
* Changes an effect on a clip: `values` (merged over its current ones; numbers may be
|
|
3096
|
+
* keyframes, `null` resets a control to its default), `enabled`, `opacity` or its place in the
|
|
3097
|
+
* stack (`index`). Values are checked against the provider's controls. One undo step.
|
|
3098
|
+
*/
|
|
3099
|
+
updateClipEffect(clip, instance, changes, options = {}) {
|
|
3100
|
+
return this.effectEdit(async () => {
|
|
3101
|
+
const current = this.clipOrThrow(clip);
|
|
3102
|
+
const stack = [..._nullishCoalesce(current.effects, () => ( []))];
|
|
3103
|
+
const i = stack.findIndex((e) => e.id === instance);
|
|
3104
|
+
if (i < 0) throw new Error(`Clip "${clip}" has no effect "${instance}"; its effects are ${stack.map((e) => `"${e.id}" (${_nullishCoalesce(e.name, () => ( e.effect))})`).join(", ") || "none"}.`);
|
|
3105
|
+
const was = stack[i];
|
|
3106
|
+
const next = { ...was };
|
|
3107
|
+
if (changes.values) {
|
|
3108
|
+
const d = await this.describeEffect(was.effect);
|
|
3109
|
+
const reset = Object.keys(changes.values).filter((k) => changes.values[k] === null);
|
|
3110
|
+
const given = Object.fromEntries(Object.entries(changes.values).filter(([, v]) => v !== null));
|
|
3111
|
+
const base = { ..._nullishCoalesce(was.values, () => ( {})) };
|
|
3112
|
+
for (const k of reset) {
|
|
3113
|
+
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(", ")}.`);
|
|
3114
|
+
base[k] = d.defaults[k];
|
|
3115
|
+
}
|
|
3116
|
+
next.values = _chunkIWSMDQE5cjs.checkVideoEffectValues.call(void 0, d, given, { base, keyframes: true });
|
|
3117
|
+
}
|
|
3118
|
+
if (changes.enabled !== void 0) {
|
|
3119
|
+
if (changes.enabled) delete next.enabled;
|
|
3120
|
+
else next.enabled = false;
|
|
3121
|
+
}
|
|
3122
|
+
if (changes.opacity !== void 0) next.opacity = changes.opacity;
|
|
3123
|
+
stack.splice(i, 1);
|
|
3124
|
+
const index = _nullishCoalesce(changes.index, () => ( i));
|
|
3125
|
+
if (!(Number.isInteger(index) && index >= 0 && index <= stack.length)) throw new Error(`"index" must be a whole number from 0 to ${stack.length}.`);
|
|
3126
|
+
stack.splice(index, 0, next);
|
|
3127
|
+
return { edit: { op: "update_clip", clip, set: { effects: stack } }, label: `Change effect ${_nullishCoalesce(was.name, () => ( was.effect))}`, clip, effect: () => next };
|
|
3128
|
+
}, options.merge);
|
|
3129
|
+
}
|
|
3130
|
+
/** Removes an effect from a clip's stack (works without a provider, so placeholders can be cleared). One undo step. */
|
|
3131
|
+
removeClipEffect(clip, instance) {
|
|
3132
|
+
const reason = this.readOnlyReason();
|
|
3133
|
+
if (reason) return this.refused(reason);
|
|
3134
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, this.project, clip);
|
|
3135
|
+
if (!at) return this.refused(`There is no clip "${clip}".`);
|
|
3136
|
+
const stack = _nullishCoalesce(at.clip.effects, () => ( []));
|
|
3137
|
+
const was = stack.find((e) => e.id === instance);
|
|
3138
|
+
if (!was) return this.refused(`Clip "${clip}" has no effect "${instance}"; its effects are ${stack.map((e) => `"${e.id}"`).join(", ") || "none"}.`);
|
|
3139
|
+
const rest = stack.filter((e) => e !== was);
|
|
3140
|
+
const result = rest.length ? this.apply({ op: "update_clip", clip, set: { effects: rest } }, `Remove effect ${_nullishCoalesce(was.name, () => ( was.effect))}`) : this.apply({ op: "update_clip", clip, remove: ["effects"] }, `Remove effect ${_nullishCoalesce(was.name, () => ( was.effect))}`);
|
|
3141
|
+
return result.ok ? { ...result, clip, effect: was } : result;
|
|
3142
|
+
}
|
|
3143
|
+
/**
|
|
3144
|
+
* Sets a provider transition into `clip` from the clip that ends where it starts (centred on the
|
|
3145
|
+
* cut, `duration` ms, default the effect's own length or 1000). One undo step.
|
|
3146
|
+
*/
|
|
3147
|
+
setEffectTransition(clip, effect, options = {}) {
|
|
3148
|
+
return this.effectEdit(async () => {
|
|
3149
|
+
this.clipOrThrow(clip);
|
|
3150
|
+
const d = await this.describeEffect(effect, "transition");
|
|
3151
|
+
const values = _chunkIWSMDQE5cjs.checkVideoEffectValues.call(void 0, d, options.values);
|
|
3152
|
+
const duration = _nullishCoalesce(_nullishCoalesce(options.duration, () => ( d.duration)), () => ( 1e3));
|
|
3153
|
+
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 };
|
|
3154
|
+
});
|
|
3155
|
+
}
|
|
3156
|
+
/**
|
|
3157
|
+
* Adds an effect clip: a generator, title or overlay effect drawn over the whole frame for
|
|
3158
|
+
* `duration` ms (default the effect's own length, else 5 s) at `start` (default the end of the
|
|
3159
|
+
* track). One undo step. Returns the new clip's id.
|
|
3160
|
+
*/
|
|
3161
|
+
addEffectClip(track, effect, options = {}) {
|
|
3162
|
+
return this.effectEdit(async () => {
|
|
3163
|
+
const d = await this.describeEffect(effect, "generator");
|
|
3164
|
+
const values = _chunkIWSMDQE5cjs.checkVideoEffectValues.call(void 0, d, options.values, { keyframes: true });
|
|
3165
|
+
const duration = _nullishCoalesce(_nullishCoalesce(options.duration, () => ( d.duration)), () => ( 5e3));
|
|
3166
|
+
const label = `Add ${d.name}`;
|
|
3167
|
+
const clipId = _nullishCoalesce(options.id, () => ( ""));
|
|
3168
|
+
return {
|
|
3169
|
+
edit: { op: "add_clip", track, mode: options.mode, ripple: options.ripple, clip: { type: "effect", ...options.id ? { id: options.id } : {}, effect: d.id, provider: this.effects.require().id, name: _nullishCoalesce(options.name, () => ( d.name)), values, start: options.start, duration } },
|
|
3170
|
+
label,
|
|
3171
|
+
clip: clipId
|
|
3172
|
+
};
|
|
3173
|
+
}).then((r) => r.ok && !r.clip ? { ...r, clip: _nullishCoalesce(_optionalChain([r, 'access', _91 => _91.outcomes, 'access', _92 => _92[0], 'optionalAccess', _93 => _93.clip]), () => ( "")) } : r);
|
|
3174
|
+
}
|
|
3175
|
+
/**
|
|
3176
|
+
* Changes the values of an effect clip's picture (`target` its id) or of the effect transition
|
|
3177
|
+
* into a clip, merged over the current ones and checked against the provider's controls.
|
|
3178
|
+
* Transition values cannot be keyframed. One undo step.
|
|
3179
|
+
*/
|
|
3180
|
+
updateEffectValues(clip, part, values, options = {}) {
|
|
3181
|
+
return this.effectEdit(async () => {
|
|
3182
|
+
const current = this.clipOrThrow(clip);
|
|
3183
|
+
if (part === "generator") {
|
|
3184
|
+
if (current.type !== "effect") throw new Error(`Clip "${clip}" is not an effect clip.`);
|
|
3185
|
+
const d2 = await this.describeEffect(current.effect);
|
|
3186
|
+
return { edit: { op: "update_clip", clip, set: { values: _chunkIWSMDQE5cjs.checkVideoEffectValues.call(void 0, d2, values, { base: _nullishCoalesce(current.values, () => ( {})), keyframes: true }) } }, label: `Change ${_nullishCoalesce(current.name, () => ( d2.name))}`, clip };
|
|
3187
|
+
}
|
|
3188
|
+
const t = current.transition;
|
|
3189
|
+
if (_optionalChain([t, 'optionalAccess', _94 => _94.type]) !== "effect" || !t.effect) throw new Error(`Clip "${clip}" has no effect transition.`);
|
|
3190
|
+
const d = await this.describeEffect(t.effect.effect);
|
|
3191
|
+
const merged = _chunkIWSMDQE5cjs.checkVideoEffectValues.call(void 0, d, values, { base: _nullishCoalesce(t.effect.values, () => ( {})) });
|
|
3192
|
+
return { edit: { op: "set_transition", clip, transition: { ...t, effect: { ...t.effect, values: merged } } }, label: `Change transition ${d.name}`, clip };
|
|
3193
|
+
}, options.merge);
|
|
3194
|
+
}
|
|
3195
|
+
/** 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). */
|
|
3196
|
+
setClipEffectKeyframes(clip, instance, control, keys) {
|
|
3197
|
+
const current = _optionalChain([_chunkIWSMDQE5cjs.findVideoClip.call(void 0, this.project, clip), 'optionalAccess', _95 => _95.clip]);
|
|
3198
|
+
const was = _optionalChain([current, 'optionalAccess', _96 => _96.effects, 'optionalAccess', _97 => _97.find, 'call', _98 => _98((e) => e.id === instance)]);
|
|
3199
|
+
const value = _optionalChain([was, 'optionalAccess', _99 => _99.values, 'optionalAccess', _100 => _100[control]]);
|
|
3200
|
+
const plain = keys === null ? _chunkIWSMDQE5cjs.isVideoKeyframes.call(void 0, value) ? _optionalChain([value, 'access', _101 => _101.keys, 'access', _102 => _102[0], 'optionalAccess', _103 => _103.v]) : value : { keys: [...keys].sort((a, b) => a.t - b.t) };
|
|
3201
|
+
return this.updateClipEffect(clip, instance, { values: { [control]: _nullishCoalesce(plain, () => ( null)) } });
|
|
3202
|
+
}
|
|
2926
3203
|
/** What plays at `time` (default: the playhead). */
|
|
2927
3204
|
frame(time = this.player.currentTime) {
|
|
2928
|
-
return
|
|
3205
|
+
return _chunkIWSMDQE5cjs.videoFrameAt.call(void 0, this.project, time);
|
|
2929
3206
|
}
|
|
2930
3207
|
/** The frame at `time` (default: the playhead) as SVG. */
|
|
2931
3208
|
toSvg(time = this.player.currentTime, options = {}) {
|
|
2932
|
-
return
|
|
3209
|
+
return _chunkIWSMDQE5cjs.videoProjectSvg.call(void 0, this.project, time, { lutFor: (src) => this.luts.peek(src), ...options });
|
|
2933
3210
|
}
|
|
2934
3211
|
/** The project as an ffmpeg command. */
|
|
2935
3212
|
toFfmpeg(options = {}) {
|
|
2936
|
-
return
|
|
3213
|
+
return _chunkIWSMDQE5cjs.toVideoFfmpeg.call(void 0, this.project, options);
|
|
2937
3214
|
}
|
|
2938
3215
|
/** The ffmpeg command that measures the mix's loudness (see `toVideoLoudnessMeasure`). */
|
|
2939
3216
|
toLoudnessMeasure(options = {}) {
|
|
2940
|
-
return
|
|
3217
|
+
return _chunkIWSMDQE5cjs.toVideoLoudnessMeasure.call(void 0, this.project, options);
|
|
2941
3218
|
}
|
|
2942
3219
|
/** One track as a CMX 3600 EDL. */
|
|
2943
3220
|
toEdl(options = {}) {
|
|
2944
|
-
return
|
|
3221
|
+
return _chunkIWSMDQE5cjs.toVideoEdl.call(void 0, this.project, options);
|
|
2945
3222
|
}
|
|
2946
3223
|
}, _class6);
|
|
2947
3224
|
function checkPreviewScale(scale) {
|
|
@@ -2960,12 +3237,12 @@ function videoRulerTicks(duration, pxPerSecond, fps) {
|
|
|
2960
3237
|
const ticks = [];
|
|
2961
3238
|
for (let t = 0; t <= duration + 1e-6; t += step) {
|
|
2962
3239
|
const isMajor = Math.abs(t / major - Math.round(t / major)) < 1e-9;
|
|
2963
|
-
ticks.push({ time: t, x: t * pxPerMs, major: isMajor, ...isMajor ? { label:
|
|
3240
|
+
ticks.push({ time: t, x: t * pxPerMs, major: isMajor, ...isMajor ? { label: _chunkIWSMDQE5cjs.formatVideoTimecode.call(void 0, t, fps).replace(/^00:/, "") } : {} });
|
|
2964
3241
|
}
|
|
2965
3242
|
return ticks;
|
|
2966
3243
|
}
|
|
2967
3244
|
function videoClipShowsWaveform(clip, asset, mode = "audio") {
|
|
2968
|
-
if (clip.type !== "media" || mode === "none" || !
|
|
3245
|
+
if (clip.type !== "media" || mode === "none" || !_chunkIWSMDQE5cjs.videoAssetHasSound.call(void 0, asset)) return false;
|
|
2969
3246
|
return mode === "all" || asset.kind === "audio";
|
|
2970
3247
|
}
|
|
2971
3248
|
var VIDEO_CLIP_ANIMATION_LABELS = {
|
|
@@ -2983,7 +3260,8 @@ var VIDEO_TRANSITION_LABELS = {
|
|
|
2983
3260
|
wipe: "Wipe",
|
|
2984
3261
|
push: "Push",
|
|
2985
3262
|
slide: "Slide",
|
|
2986
|
-
iris: "Iris"
|
|
3263
|
+
iris: "Iris",
|
|
3264
|
+
effect: "Effect"
|
|
2987
3265
|
};
|
|
2988
3266
|
var videoTransitionHasDirection = (type) => type === "wipe" || type === "push" || type === "slide";
|
|
2989
3267
|
var VIDEO_BLEND_MODE_LABELS = {
|
|
@@ -3012,6 +3290,7 @@ function videoClipTint(clip, asset) {
|
|
|
3012
3290
|
if (clip.type === "text") return "#a855f7";
|
|
3013
3291
|
if (clip.type === "sequence") return "#0d9488";
|
|
3014
3292
|
if (clip.type === "color") return clip.color;
|
|
3293
|
+
if (clip.type === "effect") return "#db2777";
|
|
3015
3294
|
if (!asset) return "#ef4444";
|
|
3016
3295
|
return asset.kind === "audio" ? "#10b981" : asset.kind === "image" ? "#f59e0b" : "#3b82f6";
|
|
3017
3296
|
}
|
|
@@ -3019,13 +3298,14 @@ function videoClipLabel(clip, asset, sequence) {
|
|
|
3019
3298
|
if (clip.name) return clip.name;
|
|
3020
3299
|
if (clip.type === "text") return clip.text.split("\n")[0];
|
|
3021
3300
|
if (clip.type === "color") return clip.color;
|
|
3022
|
-
if (clip.type === "sequence") return `Compound: ${_nullishCoalesce(_optionalChain([sequence, 'optionalAccess',
|
|
3023
|
-
|
|
3024
|
-
const
|
|
3301
|
+
if (clip.type === "sequence") return `Compound: ${_nullishCoalesce(_optionalChain([sequence, 'optionalAccess', _104 => _104.name]), () => ( clip.sequence))}`;
|
|
3302
|
+
if (clip.type === "effect") return `Effect: ${clip.effect}`;
|
|
3303
|
+
const base = _nullishCoalesce(_nullishCoalesce(_optionalChain([asset, 'optionalAccess', _105 => _105.name]), () => ( _optionalChain([asset, 'optionalAccess', _106 => _106.src, 'access', _107 => _107.replace, 'call', _108 => _108(/^.*[\\/]/, "")]))), () => ( clip.asset));
|
|
3304
|
+
const speed = _chunkIWSMDQE5cjs.videoClipSpeed.call(void 0, clip);
|
|
3025
3305
|
return speed !== 1 ? `${base} (${Math.round(speed * 100)}%)` : base;
|
|
3026
3306
|
}
|
|
3027
3307
|
function planVideoClipDrag(project, input) {
|
|
3028
|
-
const at =
|
|
3308
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, project, input.clip);
|
|
3029
3309
|
if (!at) return null;
|
|
3030
3310
|
const { clip, track } = at;
|
|
3031
3311
|
const snap = _nullishCoalesce(input.snap, () => ( ((t) => t)));
|
|
@@ -3042,17 +3322,17 @@ function planVideoClipDrag(project, input) {
|
|
|
3042
3322
|
}
|
|
3043
3323
|
const minimum = 1e3 / project.fps;
|
|
3044
3324
|
if (input.mode === "trim-start") {
|
|
3045
|
-
const to2 = Math.min(snap(Math.max(0, clip.start + input.delta)),
|
|
3325
|
+
const to2 = Math.min(snap(Math.max(0, clip.start + input.delta)), _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip) - minimum);
|
|
3046
3326
|
const changed2 = Math.abs(to2 - clip.start) > 1e-6;
|
|
3047
|
-
const plan = input.ripple ? { start: clip.start, duration: clip.duration - (to2 - clip.start) } : { start: to2, duration:
|
|
3327
|
+
const plan = input.ripple ? { start: clip.start, duration: clip.duration - (to2 - clip.start) } : { start: to2, duration: _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip) - to2 };
|
|
3048
3328
|
return { ...plan, track: track.id, edit: changed2 ? { op: "trim_clip", clip: clip.id, edge: "start", to: to2, ...input.ripple ? { ripple: true } : {} } : null };
|
|
3049
3329
|
}
|
|
3050
|
-
const to = Math.max(snap(
|
|
3051
|
-
const changed = Math.abs(to -
|
|
3330
|
+
const to = Math.max(snap(_chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip) + input.delta), clip.start + minimum);
|
|
3331
|
+
const changed = Math.abs(to - _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, clip)) > 1e-6;
|
|
3052
3332
|
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 };
|
|
3053
3333
|
}
|
|
3054
3334
|
function videoDropTracks(project, clipId) {
|
|
3055
|
-
const at =
|
|
3335
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, project, clipId);
|
|
3056
3336
|
if (!at) return [];
|
|
3057
3337
|
return project.tracks.filter((t) => t.kind === at.track.kind && !t.locked).map((t) => t.id);
|
|
3058
3338
|
}
|
|
@@ -3061,10 +3341,10 @@ function videoDragLabel(edit) {
|
|
|
3061
3341
|
return edit.op === "trim_clip" && edit.ripple ? "Ripple trim" : "Trim clip";
|
|
3062
3342
|
}
|
|
3063
3343
|
function videoAssetDropEdit(project, assetId, options = {}) {
|
|
3064
|
-
const asset =
|
|
3344
|
+
const asset = _chunkIWSMDQE5cjs.videoAssetMap.call(void 0, project).get(assetId);
|
|
3065
3345
|
if (!asset) return null;
|
|
3066
3346
|
const kind = asset.kind === "audio" ? "audio" : "video";
|
|
3067
|
-
const track = _nullishCoalesce(options.track, () => ( _optionalChain([project, 'access',
|
|
3347
|
+
const track = _nullishCoalesce(options.track, () => ( _optionalChain([project, 'access', _109 => _109.tracks, 'access', _110 => _110.find, 'call', _111 => _111((t) => t.kind === kind && !t.locked), 'optionalAccess', _112 => _112.id])));
|
|
3068
3348
|
if (!track) return null;
|
|
3069
3349
|
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 } : {} };
|
|
3070
3350
|
}
|
|
@@ -3113,25 +3393,25 @@ var KEY_LABELS = {
|
|
|
3113
3393
|
scale: { label: "Scale", step: 0.05 },
|
|
3114
3394
|
rotation: { label: "Rotation", step: 1 }
|
|
3115
3395
|
};
|
|
3116
|
-
var animatableOf = (clip, property) =>
|
|
3396
|
+
var animatableOf = (clip, property) => _chunkIWSMDQE5cjs.VIDEO_TRANSFORM_PROPERTIES.includes(property) ? _optionalChain([clip, 'access', _113 => _113.transform, 'optionalAccess', _114 => _114[property]]) : property === "volume" ? clip.type === "media" || clip.type === "sequence" ? clip.volume : void 0 : clip.opacity;
|
|
3117
3397
|
var playheadInClip = (clip, time) => Math.round(Math.min(clip.duration, Math.max(0, time - clip.start)));
|
|
3118
3398
|
function videoKeyframeRows(project, clipId, time) {
|
|
3119
|
-
const at =
|
|
3399
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, project, clipId);
|
|
3120
3400
|
if (!at) return [];
|
|
3121
3401
|
const { clip } = at;
|
|
3122
|
-
const asset = clip.type === "media" ?
|
|
3123
|
-
const visual = !(_optionalChain([asset, 'optionalAccess',
|
|
3124
|
-
const audible = clip.type === "media" &&
|
|
3125
|
-
const properties = [...visual ? ["opacity"] : [], ...audible ? ["volume"] : [], ...visual ?
|
|
3402
|
+
const asset = clip.type === "media" ? _chunkIWSMDQE5cjs.videoAssetMap.call(void 0, project).get(clip.asset) : void 0;
|
|
3403
|
+
const visual = !(_optionalChain([asset, 'optionalAccess', _115 => _115.kind]) === "audio" || at.track.kind === "audio");
|
|
3404
|
+
const audible = clip.type === "media" && _chunkIWSMDQE5cjs.videoAssetHasSound.call(void 0, asset) || clip.type === "sequence";
|
|
3405
|
+
const properties = [...visual ? ["opacity"] : [], ...audible ? ["volume"] : [], ...visual ? _chunkIWSMDQE5cjs.VIDEO_TRANSFORM_PROPERTIES : []];
|
|
3126
3406
|
const clipTime = playheadInClip(clip, time);
|
|
3127
3407
|
return properties.map((property) => {
|
|
3128
3408
|
const prop = animatableOf(clip, property);
|
|
3129
|
-
const keys =
|
|
3130
|
-
const limits =
|
|
3409
|
+
const keys = _chunkIWSMDQE5cjs.isVideoKeyframes.call(void 0, prop) ? prop.keys : [];
|
|
3410
|
+
const limits = _chunkIWSMDQE5cjs.VIDEO_KEYFRAME_LIMITS[property];
|
|
3131
3411
|
return {
|
|
3132
3412
|
property,
|
|
3133
3413
|
...KEY_LABELS[property],
|
|
3134
|
-
value: Math.round(
|
|
3414
|
+
value: Math.round(_chunkIWSMDQE5cjs.videoValueAt.call(void 0, prop, clipTime, limits.default) * 1e3) / 1e3,
|
|
3135
3415
|
keyed: keys.length > 0,
|
|
3136
3416
|
keys: keys.length,
|
|
3137
3417
|
onKey: keys.some((k) => Math.abs(k.t - clipTime) < 0.5),
|
|
@@ -3142,44 +3422,44 @@ function videoKeyframeRows(project, clipId, time) {
|
|
|
3142
3422
|
});
|
|
3143
3423
|
}
|
|
3144
3424
|
function plainValueEdit(clip, property, value) {
|
|
3145
|
-
if (!
|
|
3425
|
+
if (!_chunkIWSMDQE5cjs.VIDEO_TRANSFORM_PROPERTIES.includes(property))
|
|
3146
3426
|
return value === void 0 ? { op: "update_clip", clip: clip.id, remove: [property] } : { op: "update_clip", clip: clip.id, set: { [property]: value } };
|
|
3147
3427
|
const transform = { ...clip.transform, [property]: value };
|
|
3148
3428
|
if (value === void 0) delete transform[property];
|
|
3149
3429
|
return Object.keys(transform).length ? { op: "update_clip", clip: clip.id, set: { transform } } : { op: "update_clip", clip: clip.id, remove: ["transform"] };
|
|
3150
3430
|
}
|
|
3151
3431
|
function videoKeyframeValueEdit(project, clipId, property, time, value) {
|
|
3152
|
-
const at =
|
|
3432
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, project, clipId);
|
|
3153
3433
|
if (!at) return null;
|
|
3154
3434
|
const prop = animatableOf(at.clip, property);
|
|
3155
|
-
if (!
|
|
3435
|
+
if (!_chunkIWSMDQE5cjs.isVideoKeyframes.call(void 0, prop)) return plainValueEdit(at.clip, property, value);
|
|
3156
3436
|
if (value === void 0) return null;
|
|
3157
|
-
return { op: "set_keyframes", clip: clipId, property, keys:
|
|
3437
|
+
return { op: "set_keyframes", clip: clipId, property, keys: _chunkIWSMDQE5cjs.setVideoKey.call(void 0, prop, { t: playheadInClip(at.clip, time), v: value }, _chunkIWSMDQE5cjs.VIDEO_KEYFRAME_LIMITS[property].default).keys };
|
|
3158
3438
|
}
|
|
3159
3439
|
function videoKeyframeToggleEdit(project, clipId, property, time) {
|
|
3160
|
-
const at =
|
|
3440
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, project, clipId);
|
|
3161
3441
|
if (!at) return null;
|
|
3162
3442
|
const prop = animatableOf(at.clip, property);
|
|
3163
3443
|
const t = playheadInClip(at.clip, time);
|
|
3164
|
-
const fallback =
|
|
3165
|
-
if (
|
|
3444
|
+
const fallback = _chunkIWSMDQE5cjs.VIDEO_KEYFRAME_LIMITS[property].default;
|
|
3445
|
+
if (_chunkIWSMDQE5cjs.isVideoKeyframes.call(void 0, prop)) {
|
|
3166
3446
|
const key = prop.keys.find((k) => Math.abs(k.t - t) < 0.5);
|
|
3167
3447
|
if (key) {
|
|
3168
|
-
const rest =
|
|
3169
|
-
return
|
|
3448
|
+
const rest = _chunkIWSMDQE5cjs.removeVideoKey.call(void 0, prop, key.t);
|
|
3449
|
+
return _chunkIWSMDQE5cjs.isVideoKeyframes.call(void 0, rest) ? { op: "set_keyframes", clip: clipId, property, keys: rest.keys } : plainValueEdit(at.clip, property, rest === fallback ? void 0 : rest);
|
|
3170
3450
|
}
|
|
3171
3451
|
}
|
|
3172
|
-
const v =
|
|
3173
|
-
return { op: "set_keyframes", clip: clipId, property, keys:
|
|
3452
|
+
const v = _chunkIWSMDQE5cjs.videoValueAt.call(void 0, prop, t, fallback);
|
|
3453
|
+
return { op: "set_keyframes", clip: clipId, property, keys: _chunkIWSMDQE5cjs.isVideoKeyframes.call(void 0, prop) ? _chunkIWSMDQE5cjs.setVideoKey.call(void 0, prop, { t, v }, fallback).keys : [{ t, v }] };
|
|
3174
3454
|
}
|
|
3175
3455
|
function videoLutEdits(project, clips, lut) {
|
|
3176
3456
|
const edits = [];
|
|
3177
3457
|
for (const id of clips) {
|
|
3178
|
-
const at =
|
|
3458
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, project, id);
|
|
3179
3459
|
if (!at) continue;
|
|
3180
3460
|
const { lut: current, ...rest } = _nullishCoalesce(at.clip.grade, () => ( {}));
|
|
3181
3461
|
if (!lut && !current) continue;
|
|
3182
|
-
const grade =
|
|
3462
|
+
const grade = _chunkIWSMDQE5cjs.normalizeVideoGrade.call(void 0, lut ? { ...rest, lut } : rest);
|
|
3183
3463
|
edits.push(grade ? { op: "update_clip", clip: id, set: { grade } } : { op: "update_clip", clip: id, remove: ["grade"] });
|
|
3184
3464
|
}
|
|
3185
3465
|
return edits;
|
|
@@ -3209,7 +3489,7 @@ var RIPPLE = {
|
|
|
3209
3489
|
};
|
|
3210
3490
|
var MODE = {
|
|
3211
3491
|
type: "string",
|
|
3212
|
-
enum: [...
|
|
3492
|
+
enum: [..._chunkIWSMDQE5cjs.VIDEO_PLACEMENT_MODES],
|
|
3213
3493
|
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.'
|
|
3214
3494
|
};
|
|
3215
3495
|
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.` });
|
|
@@ -3226,11 +3506,11 @@ var TRANSFORM = object(
|
|
|
3226
3506
|
);
|
|
3227
3507
|
var TRANSITION = object(
|
|
3228
3508
|
{
|
|
3229
|
-
type: { type: "string", enum:
|
|
3509
|
+
type: { type: "string", enum: _chunkIWSMDQE5cjs.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." },
|
|
3230
3510
|
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." },
|
|
3231
3511
|
color: COLOR("For dip: the colour passed through (default black)"),
|
|
3232
|
-
direction: { type: "string", enum: [...
|
|
3233
|
-
audioCurve: { type: "string", enum: [...
|
|
3512
|
+
direction: { type: "string", enum: [..._chunkIWSMDQE5cjs.VIDEO_WIPE_DIRECTIONS], description: "For wipe, push and slide: the way the edge or picture travels (default right, coming in from the left)." },
|
|
3513
|
+
audioCurve: { type: "string", enum: [..._chunkIWSMDQE5cjs.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." }
|
|
3234
3514
|
},
|
|
3235
3515
|
["type", "duration"],
|
|
3236
3516
|
"A transition from the clip that ends where this one starts on the same track."
|
|
@@ -3239,7 +3519,7 @@ var LUT_SRC = { type: "string", minLength: 1, description: 'A .cube 3D LUT file
|
|
|
3239
3519
|
var LUT_STRENGTH = { type: "number", minimum: 0, maximum: 1, description: "How much of the LUT's change to apply, 0 (none) to 1 (full, the default); 0.3-0.7 for a subtler look." };
|
|
3240
3520
|
var GRADE = object(
|
|
3241
3521
|
{
|
|
3242
|
-
...Object.fromEntries(
|
|
3522
|
+
...Object.fromEntries(_chunkIWSMDQE5cjs.VIDEO_GRADE_CONTROLS.map((c) => [c.key, { type: "number", minimum: c.min, maximum: c.max, description: c.description }])),
|
|
3243
3523
|
lut: object({ src: LUT_SRC, strength: LUT_STRENGTH, name: { type: "string", minLength: 1, description: "A label for the look." } }, ["src"], "A 3D LUT applied after the other settings (set_video_lut checks the file first).")
|
|
3244
3524
|
},
|
|
3245
3525
|
[],
|
|
@@ -3247,7 +3527,7 @@ var GRADE = object(
|
|
|
3247
3527
|
);
|
|
3248
3528
|
var ANIMATION = (when) => object(
|
|
3249
3529
|
{
|
|
3250
|
-
effect: { type: "string", enum: [...
|
|
3530
|
+
effect: { type: "string", enum: [..._chunkIWSMDQE5cjs.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." },
|
|
3251
3531
|
duration: { type: "number", exclusiveMinimum: 0, description: "Length in ms (default 500)." }
|
|
3252
3532
|
},
|
|
3253
3533
|
["effect"],
|
|
@@ -3257,11 +3537,11 @@ var CLIP_COMMON = {
|
|
|
3257
3537
|
name: { type: "string", description: "A label for the clip." },
|
|
3258
3538
|
opacity: { type: "number", minimum: 0, maximum: 1, description: "Opacity 0\u20131 (default 1). A number replaces any keyframes; set_video_keyframes animates it." },
|
|
3259
3539
|
transform: TRANSFORM,
|
|
3260
|
-
fit: { type: "string", enum: [...
|
|
3540
|
+
fit: { type: "string", enum: [..._chunkIWSMDQE5cjs.VIDEO_FITS], description: "How the picture fits the frame before the transform, as CSS object-fit (default contain for media, fill for colours)." },
|
|
3261
3541
|
grade: GRADE,
|
|
3262
3542
|
animateIn: ANIMATION("How the picture enters, from the clip's start (on top of any fade in). Titles usually rise, pop or fade in."),
|
|
3263
3543
|
animateOut: ANIMATION("How the picture leaves, ending at the clip's end."),
|
|
3264
|
-
blend: { type: "string", enum: [...
|
|
3544
|
+
blend: { type: "string", enum: [..._chunkIWSMDQE5cjs.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." },
|
|
3265
3545
|
fadeIn: MS("Fade up from nothing (picture and sound) over this long"),
|
|
3266
3546
|
fadeOut: MS("Fade down to nothing over this long")
|
|
3267
3547
|
};
|
|
@@ -3270,8 +3550,8 @@ var MEDIA_FIELDS = {
|
|
|
3270
3550
|
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." },
|
|
3271
3551
|
volume: { type: "number", minimum: 0, maximum: 4, description: "Gain (1 = unchanged, default 1). A number replaces any keyframes; set_video_keyframes animates it." },
|
|
3272
3552
|
muted: { type: "boolean", description: "Silence this clip (default false)." },
|
|
3273
|
-
fadeInCurve: { type: "string", enum: [...
|
|
3274
|
-
fadeOutCurve: { type: "string", enum: [...
|
|
3553
|
+
fadeInCurve: { type: "string", enum: [..._chunkIWSMDQE5cjs.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)." },
|
|
3554
|
+
fadeOutCurve: { type: "string", enum: [..._chunkIWSMDQE5cjs.VIDEO_FADE_CURVES], description: "Shape of the sound's fade out (default linear), the same choices as fadeInCurve; exponential sounds natural fading to silence." }
|
|
3275
3555
|
};
|
|
3276
3556
|
var TEXT_FIELDS = {
|
|
3277
3557
|
text: { type: "string", minLength: 1, description: `The title's text ("\\n" breaks lines).` },
|
|
@@ -3320,7 +3600,7 @@ var ASSET_FIELDS = {
|
|
|
3320
3600
|
};
|
|
3321
3601
|
var KEY_PROPERTY = {
|
|
3322
3602
|
type: "string",
|
|
3323
|
-
enum: [...
|
|
3603
|
+
enum: [..._chunkIWSMDQE5cjs.VIDEO_KEYFRAME_PROPERTIES],
|
|
3324
3604
|
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)."
|
|
3325
3605
|
};
|
|
3326
3606
|
var KEYS = {
|
|
@@ -3335,7 +3615,7 @@ var KEYS = {
|
|
|
3335
3615
|
ease: {
|
|
3336
3616
|
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.",
|
|
3337
3617
|
anyOf: [
|
|
3338
|
-
{ type: "string", enum: [...
|
|
3618
|
+
{ type: "string", enum: [..._chunkIWSMDQE5cjs.VIDEO_EASE_NAMES] },
|
|
3339
3619
|
{ type: "array", items: { type: "number" }, minItems: 4, maxItems: 4 }
|
|
3340
3620
|
]
|
|
3341
3621
|
}
|
|
@@ -3364,19 +3644,19 @@ var describeVideoTracks = (tracks) => tracks.map((t, index) => ({
|
|
|
3364
3644
|
...t.locked ? { locked: true } : {},
|
|
3365
3645
|
...t.syncLocked === false ? { syncLocked: false } : {},
|
|
3366
3646
|
...t.volume !== void 0 ? { volume: t.volume } : {},
|
|
3367
|
-
clips:
|
|
3647
|
+
clips: _chunkIWSMDQE5cjs.sortedVideoClips.call(void 0, t).map((c) => ({ ...c, end: _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c), ...c.type === "media" || c.type === "sequence" ? { source: _chunkIWSMDQE5cjs.videoClipSourceRange.call(void 0, c) } : {} }))
|
|
3368
3648
|
}));
|
|
3369
|
-
var videoSequenceUsers = (project, id) =>
|
|
3370
|
-
({ 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:
|
|
3649
|
+
var videoSequenceUsers = (project, id) => _chunkIWSMDQE5cjs.allVideoTracks.call(void 0, project).flatMap(
|
|
3650
|
+
({ 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: _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c), source: _chunkIWSMDQE5cjs.videoClipSourceRange.call(void 0, c) }] : [])
|
|
3371
3651
|
);
|
|
3372
3652
|
function describeVideoSequence(project, sequence, tracks = true) {
|
|
3373
|
-
const cycle =
|
|
3653
|
+
const cycle = _chunkIWSMDQE5cjs.findVideoSequenceCycle.call(void 0, project, sequence.id);
|
|
3374
3654
|
return {
|
|
3375
3655
|
id: sequence.id,
|
|
3376
3656
|
...sequence.name ? { name: sequence.name } : {},
|
|
3377
|
-
duration:
|
|
3657
|
+
duration: _chunkIWSMDQE5cjs.videoSequenceDuration.call(void 0, sequence),
|
|
3378
3658
|
clipCount: sequence.tracks.reduce((n, t) => n + t.clips.length, 0),
|
|
3379
|
-
nests:
|
|
3659
|
+
nests: _chunkIWSMDQE5cjs.videoSequenceChildren.call(void 0, sequence),
|
|
3380
3660
|
usedBy: videoSequenceUsers(project, sequence.id),
|
|
3381
3661
|
...cycle ? { cycle } : {},
|
|
3382
3662
|
...tracks ? { tracks: describeVideoTracks(sequence.tracks) } : { trackCount: sequence.tracks.length }
|
|
@@ -3388,11 +3668,11 @@ function describeVideoProject(project) {
|
|
|
3388
3668
|
width: project.width,
|
|
3389
3669
|
height: project.height,
|
|
3390
3670
|
fps: project.fps,
|
|
3391
|
-
duration:
|
|
3671
|
+
duration: _chunkIWSMDQE5cjs.videoProjectDuration.call(void 0, project),
|
|
3392
3672
|
...project.background ? { background: project.background } : {},
|
|
3393
3673
|
assets: project.assets.map(videoAssetOut),
|
|
3394
3674
|
tracks: describeVideoTracks(project.tracks),
|
|
3395
|
-
..._optionalChain([project, 'access',
|
|
3675
|
+
..._optionalChain([project, 'access', _116 => _116.sequences, 'optionalAccess', _117 => _117.length]) ? { sequences: project.sequences.map((q) => describeVideoSequence(project, q, false)) } : {},
|
|
3396
3676
|
markers: _nullishCoalesce(project.markers, () => ( []))
|
|
3397
3677
|
};
|
|
3398
3678
|
}
|
|
@@ -3405,7 +3685,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3405
3685
|
const project = () => controller.getProject();
|
|
3406
3686
|
const outcome = (result, extra = {}) => {
|
|
3407
3687
|
if (!result.ok) throw new Error(result.error);
|
|
3408
|
-
return { ...extra, duration:
|
|
3688
|
+
return { ...extra, duration: _chunkIWSMDQE5cjs.videoProjectDuration.call(void 0, result.project), issues: issueSummary(result.issues) };
|
|
3409
3689
|
};
|
|
3410
3690
|
const apply = (edits, label, extra) => {
|
|
3411
3691
|
const result = controller.apply(edits, label);
|
|
@@ -3414,19 +3694,19 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3414
3694
|
const clipOut = (p, id) => {
|
|
3415
3695
|
for (const t of p.tracks) {
|
|
3416
3696
|
const c = t.clips.find((x) => x.id === id);
|
|
3417
|
-
if (c) return { track: t.id, ...c, end:
|
|
3697
|
+
if (c) return { track: t.id, ...c, end: _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c), ...c.type === "media" || c.type === "sequence" ? { source: _chunkIWSMDQE5cjs.videoClipSourceRange.call(void 0, c) } : {} };
|
|
3418
3698
|
}
|
|
3419
3699
|
return null;
|
|
3420
3700
|
};
|
|
3421
3701
|
const placed = (o) => ({
|
|
3422
|
-
..._optionalChain([o, 'access',
|
|
3423
|
-
..._optionalChain([o, 'access',
|
|
3424
|
-
..._optionalChain([o, 'access',
|
|
3702
|
+
..._optionalChain([o, 'access', _118 => _118.created, 'optionalAccess', _119 => _119.length]) ? { created: o.created } : {},
|
|
3703
|
+
..._optionalChain([o, 'access', _120 => _120.trimmed, 'optionalAccess', _121 => _121.length]) ? { trimmed: o.trimmed } : {},
|
|
3704
|
+
..._optionalChain([o, 'access', _122 => _122.removed, 'optionalAccess', _123 => _123.length]) ? { removed: o.removed } : {},
|
|
3425
3705
|
...o.rippled ? { rippled: o.rippled } : {}
|
|
3426
3706
|
});
|
|
3427
3707
|
const keysOut = (p, clip, property) => {
|
|
3428
3708
|
const c = clipOut(p, clip);
|
|
3429
|
-
const value =
|
|
3709
|
+
const value = _chunkIWSMDQE5cjs.VIDEO_TRANSFORM_PROPERTIES.includes(property) ? _optionalChain([c, 'optionalAccess', _124 => _124.transform, 'optionalAccess', _125 => _125[property]]) : _optionalChain([c, 'optionalAccess', _126 => _126[property]]);
|
|
3430
3710
|
return typeof value === "object" ? { keys: value.keys } : { keys: [], value: _nullishCoalesce(value, () => ( null)) };
|
|
3431
3711
|
};
|
|
3432
3712
|
const getProject = {
|
|
@@ -3448,8 +3728,8 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3448
3728
|
inputSchema: object({ time: MS("Time from the start (default: the playhead)") }),
|
|
3449
3729
|
annotations: { title: "What plays at a moment", ...READ },
|
|
3450
3730
|
handler: ({ time }) => {
|
|
3451
|
-
const frame =
|
|
3452
|
-
return { ...frame, timecode:
|
|
3731
|
+
const frame = _chunkIWSMDQE5cjs.videoFrameAt.call(void 0, project(), _nullishCoalesce(time, () => ( controller.getState().time)));
|
|
3732
|
+
return { ...frame, timecode: _chunkIWSMDQE5cjs.formatVideoTimecode.call(void 0, frame.time, project().fps) };
|
|
3453
3733
|
}
|
|
3454
3734
|
};
|
|
3455
3735
|
const listSequences = {
|
|
@@ -3477,7 +3757,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3477
3757
|
annotations: { title: "Find gaps", ...READ },
|
|
3478
3758
|
handler: ({ track }) => {
|
|
3479
3759
|
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(", ")}.`);
|
|
3480
|
-
return { gaps:
|
|
3760
|
+
return { gaps: _chunkIWSMDQE5cjs.findVideoGaps.call(void 0, project(), track) };
|
|
3481
3761
|
}
|
|
3482
3762
|
};
|
|
3483
3763
|
const checkProject = {
|
|
@@ -3504,10 +3784,10 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3504
3784
|
annotations: { title: "Render a frame", ...READ },
|
|
3505
3785
|
handler: async ({ time, times, columns, format = "svg" }) => {
|
|
3506
3786
|
const p = project();
|
|
3507
|
-
const lutSrcs = [...new Set(p.tracks.flatMap((t) => t.clips.map((c) => _optionalChain([c, 'access',
|
|
3787
|
+
const lutSrcs = [...new Set(p.tracks.flatMap((t) => t.clips.map((c) => _optionalChain([c, 'access', _127 => _127.grade, 'optionalAccess', _128 => _128.lut, 'optionalAccess', _129 => _129.src])).filter((x) => !!x)))];
|
|
3508
3788
|
const missing = (await Promise.all(lutSrcs.map((src) => controller.luts.load(src).then(() => null, (e) => e.message)))).filter((m) => !!m);
|
|
3509
3789
|
const svgOptions = { lutFor: (src) => controller.luts.peek(src), ...columns ? { columns } : {} };
|
|
3510
|
-
const svg = times ?
|
|
3790
|
+
const svg = times ? _chunkIWSMDQE5cjs.videoContactSheetSvg.call(void 0, p, times, svgOptions) : _chunkIWSMDQE5cjs.videoProjectSvg.call(void 0, p, _nullishCoalesce(time, () => ( controller.getState().time)), svgOptions);
|
|
3511
3791
|
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."] : []];
|
|
3512
3792
|
if (format === "png") {
|
|
3513
3793
|
if (!options.rasterize) throw new Error('This host cannot make PNG images; call render_video_frame with format "svg".');
|
|
@@ -3597,7 +3877,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3597
3877
|
if (play === true) controller.play();
|
|
3598
3878
|
if (play === false) controller.pause();
|
|
3599
3879
|
const state = controller.getState();
|
|
3600
|
-
return { time: state.time, timecode:
|
|
3880
|
+
return { time: state.time, timecode: _chunkIWSMDQE5cjs.formatVideoTimecode.call(void 0, state.time, p.fps), playing: state.playing, clips: state.current };
|
|
3601
3881
|
}
|
|
3602
3882
|
};
|
|
3603
3883
|
const setSettings = {
|
|
@@ -3742,10 +4022,10 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3742
4022
|
const gradeTargets = (ids) => {
|
|
3743
4023
|
const p = project();
|
|
3744
4024
|
for (const id of ids) {
|
|
3745
|
-
const at =
|
|
4025
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, p, id);
|
|
3746
4026
|
if (!at) throw new Error(`There is no clip "${id}"; get_video_project lists the clips.`);
|
|
3747
4027
|
const { clip } = at;
|
|
3748
|
-
if (at.track.kind !== "video" || clip.type === "media" && _optionalChain([p, 'access',
|
|
4028
|
+
if (at.track.kind !== "video" || clip.type === "media" && _optionalChain([p, 'access', _130 => _130.assets, 'access', _131 => _131.find, 'call', _132 => _132((a) => a.id === clip.asset), 'optionalAccess', _133 => _133.kind]) === "audio")
|
|
3749
4029
|
throw new Error(`Clip "${id}" is sound only; grades change pictures. Pass clips on video tracks.`);
|
|
3750
4030
|
}
|
|
3751
4031
|
};
|
|
@@ -3756,7 +4036,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3756
4036
|
inputSchema: object(
|
|
3757
4037
|
{
|
|
3758
4038
|
clips: { type: "array", items: CLIP_ID, minItems: 1, description: "Clips on video tracks to grade." },
|
|
3759
|
-
preset: { type: "string", enum: [...
|
|
4039
|
+
preset: { type: "string", enum: [..._chunkIWSMDQE5cjs.VIDEO_GRADE_PRESET_NAMES], description: "The look." },
|
|
3760
4040
|
amount: { type: "number", minimum: 0, maximum: 1, description: "Strength, 0 (none) to 1 (full, the default); 0.5 is a subtler version." }
|
|
3761
4041
|
},
|
|
3762
4042
|
["clips", "preset"]
|
|
@@ -3765,10 +4045,10 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3765
4045
|
handler: ({ clips, preset, amount }) => {
|
|
3766
4046
|
gradeTargets(clips);
|
|
3767
4047
|
const edits = clips.map((clip) => {
|
|
3768
|
-
const grade =
|
|
4048
|
+
const grade = _chunkIWSMDQE5cjs.videoGradeLook.call(void 0, _chunkIWSMDQE5cjs.findVideoClip.call(void 0, project(), clip).clip.grade, preset, _nullishCoalesce(amount, () => ( 1)));
|
|
3769
4049
|
return grade ? { op: "update_clip", clip, set: { grade } } : { op: "update_clip", clip, remove: ["grade"] };
|
|
3770
4050
|
});
|
|
3771
|
-
return apply(edits, `Apply ${preset} look`, (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([
|
|
4051
|
+
return apply(edits, `Apply ${preset} look`, (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([_chunkIWSMDQE5cjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _134 => _134.clip, 'access', _135 => _135.grade]), () => ( null)) })) }));
|
|
3772
4052
|
}
|
|
3773
4053
|
};
|
|
3774
4054
|
const copyGrade = {
|
|
@@ -3779,7 +4059,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3779
4059
|
annotations: { title: "Copy a colour grade", ...WRITE_IDEMPOTENT },
|
|
3780
4060
|
handler: ({ from, to }) => {
|
|
3781
4061
|
gradeTargets([from, ...to]);
|
|
3782
|
-
const grade =
|
|
4062
|
+
const grade = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, project(), from).clip.grade;
|
|
3783
4063
|
const edits = to.map((clip) => grade ? { op: "update_clip", clip, set: { grade: { ...grade } } } : { op: "update_clip", clip, remove: ["grade"] });
|
|
3784
4064
|
return apply(edits, "Copy grade", () => ({ grade: _nullishCoalesce(grade, () => ( null)), clips: to }));
|
|
3785
4065
|
}
|
|
@@ -3804,7 +4084,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3804
4084
|
const lut = await controller.luts.load(src);
|
|
3805
4085
|
const label = _nullishCoalesce(name, () => ( lut.title));
|
|
3806
4086
|
const setting = { src, ...strength !== void 0 && strength !== 1 ? { strength } : {}, ...label ? { name: label } : {} };
|
|
3807
|
-
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([
|
|
4087
|
+
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([_chunkIWSMDQE5cjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _136 => _136.clip, 'access', _137 => _137.grade]), () => ( null)) })) }));
|
|
3808
4088
|
}
|
|
3809
4089
|
};
|
|
3810
4090
|
const removeLut = {
|
|
@@ -3816,9 +4096,9 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3816
4096
|
handler: ({ clips }) => {
|
|
3817
4097
|
gradeTargets(clips);
|
|
3818
4098
|
const p = project();
|
|
3819
|
-
const withLut = clips.filter((id) => _optionalChain([
|
|
4099
|
+
const withLut = clips.filter((id) => _optionalChain([_chunkIWSMDQE5cjs.findVideoClip.call(void 0, p, id), 'access', _138 => _138.clip, 'access', _139 => _139.grade, 'optionalAccess', _140 => _140.lut]));
|
|
3820
4100
|
if (!withLut.length) throw new Error(`None of ${clips.map((c) => `"${c}"`).join(", ")} has a LUT; get_video_project shows each clip's grade.`);
|
|
3821
|
-
return apply(videoLutEdits(p, withLut, null), "Remove LUT", (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([
|
|
4101
|
+
return apply(videoLutEdits(p, withLut, null), "Remove LUT", (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([_chunkIWSMDQE5cjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _141 => _141.clip, 'access', _142 => _142.grade]), () => ( null)) })) }));
|
|
3822
4102
|
}
|
|
3823
4103
|
};
|
|
3824
4104
|
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." };
|
|
@@ -3876,7 +4156,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3876
4156
|
controller.setPreviewScale(scale);
|
|
3877
4157
|
const s = controller.getState().previewScale;
|
|
3878
4158
|
const fixed = s === "full" ? 1 : typeof s === "number" ? s : null;
|
|
3879
|
-
const plays = fixed === null ? void 0 : project().assets.filter((a) => a.kind === "video").map((a) => ({ asset: a.id, src: _nullishCoalesce(_optionalChain([videoAssetProxy, 'call',
|
|
4159
|
+
const plays = fixed === null ? void 0 : project().assets.filter((a) => a.kind === "video").map((a) => ({ asset: a.id, src: _nullishCoalesce(_optionalChain([videoAssetProxy, 'call', _143 => _143(a, fixed), 'optionalAccess', _144 => _144.src]), () => ( a.src)), proxy: !!videoAssetProxy(a, fixed) }));
|
|
3880
4160
|
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." } };
|
|
3881
4161
|
}
|
|
3882
4162
|
};
|
|
@@ -3927,7 +4207,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3927
4207
|
approximate: parsed.approximate,
|
|
3928
4208
|
first: list[0],
|
|
3929
4209
|
last: list[list.length - 1],
|
|
3930
|
-
...a.duration !== void 0 && list[list.length - 1].end > a.duration +
|
|
4210
|
+
...a.duration !== void 0 && list[list.length - 1].end > a.duration + _chunkIWSMDQE5cjs.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?` } : {}
|
|
3931
4211
|
}));
|
|
3932
4212
|
}
|
|
3933
4213
|
};
|
|
@@ -3945,7 +4225,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3945
4225
|
handler: ({ track, from, to, limit }) => {
|
|
3946
4226
|
const all = timelineWords(track).filter((w) => w.end > (_nullishCoalesce(from, () => ( 0))) && w.start < (_nullishCoalesce(to, () => ( Infinity))));
|
|
3947
4227
|
const words = all.slice(0, _nullishCoalesce(limit, () => ( 1e3)));
|
|
3948
|
-
return { track: _nullishCoalesce(_optionalChain([words, 'access',
|
|
4228
|
+
return { track: _nullishCoalesce(_optionalChain([words, 'access', _145 => _145[0], 'optionalAccess', _146 => _146.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 };
|
|
3949
4229
|
}
|
|
3950
4230
|
};
|
|
3951
4231
|
const findText = {
|
|
@@ -3998,22 +4278,22 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
3998
4278
|
const bad = ranges.findIndex((r) => !(r.to > r.from));
|
|
3999
4279
|
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".`);
|
|
4000
4280
|
const merged = mergeVideoRanges(ranges);
|
|
4001
|
-
const before =
|
|
4002
|
-
return apply(videoRemoveRangesEdits(merged, tracks), merged.length > 1 ? `Cut ${merged.length} stretches` : "Cut stretch", (r) => ({ removed: merged.length, time: round(before -
|
|
4281
|
+
const before = _chunkIWSMDQE5cjs.videoProjectDuration.call(void 0, project());
|
|
4282
|
+
return apply(videoRemoveRangesEdits(merged, tracks), merged.length > 1 ? `Cut ${merged.length} stretches` : "Cut stretch", (r) => ({ removed: merged.length, time: round(before - _chunkIWSMDQE5cjs.videoProjectDuration.call(void 0, r.project)), duration: _chunkIWSMDQE5cjs.videoProjectDuration.call(void 0, r.project) }));
|
|
4003
4283
|
}
|
|
4004
4284
|
};
|
|
4005
4285
|
const rampTarget = (id) => {
|
|
4006
|
-
const at =
|
|
4286
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, project(), id);
|
|
4007
4287
|
if (!at) throw new Error(`There is no clip "${id}"; get_video_project lists the clips.`);
|
|
4008
4288
|
const { clip } = at;
|
|
4009
4289
|
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.`);
|
|
4010
|
-
if (clip.type !== "media") throw new Error(`Clip "${id}" is a ${clip.type === "text" ? "title" : "colour"}, so it has no source to change the speed of; use a video or audio clip.`);
|
|
4011
|
-
if (_optionalChain([project, 'call',
|
|
4290
|
+
if (clip.type !== "media") throw new Error(`Clip "${id}" is a ${clip.type === "text" ? "title" : clip.type === "effect" ? "effect clip" : "colour"}, so it has no source to change the speed of; use a video or audio clip.`);
|
|
4291
|
+
if (_optionalChain([project, 'call', _147 => _147(), 'access', _148 => _148.assets, 'access', _149 => _149.find, 'call', _150 => _150((a) => a.id === clip.asset), 'optionalAccess', _151 => _151.kind]) === "image") throw new Error(`Clip "${id}" is a still, so it has no motion to change the speed of.`);
|
|
4012
4292
|
return clip;
|
|
4013
4293
|
};
|
|
4014
4294
|
const rampOut = (r, id) => {
|
|
4015
4295
|
const outcome2 = r.outcomes[r.outcomes.length - 1];
|
|
4016
|
-
return { clip: clipOut(r.project, id), ...outcome2.rippled ? { rippled: outcome2.rippled } : {}, duration:
|
|
4296
|
+
return { clip: clipOut(r.project, id), ...outcome2.rippled ? { rippled: outcome2.rippled } : {}, duration: _chunkIWSMDQE5cjs.videoProjectDuration.call(void 0, r.project) };
|
|
4017
4297
|
};
|
|
4018
4298
|
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." };
|
|
4019
4299
|
const setSpeedRamp = {
|
|
@@ -4044,8 +4324,8 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4044
4324
|
),
|
|
4045
4325
|
annotations: { title: "Ramp the speed", ...WRITE_IDEMPOTENT },
|
|
4046
4326
|
handler: ({ clip, segments, ripple }) => {
|
|
4047
|
-
const edit =
|
|
4048
|
-
return apply(edit, "Speed ramp", (r) => ({ ...rampOut(r, clip), source: Math.round(
|
|
4327
|
+
const edit = _chunkIWSMDQE5cjs.videoSpeedRampEdit.call(void 0, rampTarget(clip), segments, _nullishCoalesce(ripple, () => ( true)));
|
|
4328
|
+
return apply(edit, "Speed ramp", (r) => ({ ...rampOut(r, clip), source: Math.round(_chunkIWSMDQE5cjs.videoSpeedRampKeys.call(void 0, segments).source) }));
|
|
4049
4329
|
}
|
|
4050
4330
|
};
|
|
4051
4331
|
const addFreeze = {
|
|
@@ -4065,8 +4345,8 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4065
4345
|
handler: ({ clip, at, duration, ripple }) => {
|
|
4066
4346
|
const c = rampTarget(clip);
|
|
4067
4347
|
const t = at - c.start;
|
|
4068
|
-
if (t < 0 || t > c.duration) throw new Error(`${
|
|
4069
|
-
return apply(
|
|
4348
|
+
if (t < 0 || t > c.duration) throw new Error(`${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, at)} is outside clip "${clip}" (${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, c.start)}\u2013${_chunkIWSMDQE5cjs.formatVideoSeconds.call(void 0, _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c))}); pick a time inside it.`);
|
|
4349
|
+
return apply(_chunkIWSMDQE5cjs.videoFreezeFrameEdit.call(void 0, c, t, duration, _nullishCoalesce(ripple, () => ( true))), "Freeze frame", (r) => rampOut(r, clip));
|
|
4070
4350
|
}
|
|
4071
4351
|
};
|
|
4072
4352
|
const removeRamp = {
|
|
@@ -4239,7 +4519,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4239
4519
|
let from;
|
|
4240
4520
|
let to;
|
|
4241
4521
|
if (args.clip !== void 0) {
|
|
4242
|
-
const found =
|
|
4522
|
+
const found = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, p, args.clip);
|
|
4243
4523
|
if (!found) throw new Error(`There is no clip "${args.clip}"; get_video_project lists the clips.`);
|
|
4244
4524
|
const c = found.clip;
|
|
4245
4525
|
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).`);
|
|
@@ -4249,7 +4529,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4249
4529
|
toSource = (t) => (_nullishCoalesce(c.in, () => ( 0))) + (t - c.start) * speed;
|
|
4250
4530
|
toOut = (s) => c.start + (s - (_nullishCoalesce(c.in, () => ( 0)))) / speed;
|
|
4251
4531
|
from = Math.max(c.start, _nullishCoalesce(args.from, () => ( c.start)));
|
|
4252
|
-
to = Math.min(
|
|
4532
|
+
to = Math.min(_chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c), _nullishCoalesce(args.to, () => ( _chunkIWSMDQE5cjs.videoClipEnd.call(void 0, c))));
|
|
4253
4533
|
} else {
|
|
4254
4534
|
asset = p.assets.find((a) => a.id === args.asset);
|
|
4255
4535
|
if (!asset) throw new Error(`There is no asset "${args.asset}"; the assets are ${p.assets.map((a) => `"${a.id}"`).join(", ") || "none"}.`);
|
|
@@ -4330,11 +4610,11 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4330
4610
|
annotations: { title: "Measure a frame with scopes", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
4331
4611
|
handler: async ({ time, bins, columns }) => {
|
|
4332
4612
|
const p = project();
|
|
4333
|
-
const end =
|
|
4613
|
+
const end = _chunkIWSMDQE5cjs.videoProjectDuration.call(void 0, p);
|
|
4334
4614
|
const t = _nullishCoalesce(time, () => ( controller.getState().time));
|
|
4335
4615
|
if (time !== void 0 && time > end) throw new Error(`Time ${time} ms is past the end of the project (${end} ms).`);
|
|
4336
4616
|
const pixels = await pixelsAt(t);
|
|
4337
|
-
return { time: t, timecode:
|
|
4617
|
+
return { time: t, timecode: _chunkIWSMDQE5cjs.formatVideoTimecode.call(void 0, t, p.fps), width: pixels.width, height: pixels.height, ...summarizeVideoScopes(pixels, { bins, columns }) };
|
|
4338
4618
|
}
|
|
4339
4619
|
};
|
|
4340
4620
|
const reads = [getProject, listSequences, getFrame, getTranscript, findText, findFillers, findPauses, findGaps, checkProject, renderFrame, getScopes, previewCache, planProxies, exportFfmpeg, exportLoudnessMeasure, exportEdl, audioLevels, findSilences, seek, setPreviewScale];
|
|
@@ -4356,6 +4636,198 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4356
4636
|
};
|
|
4357
4637
|
}
|
|
4358
4638
|
|
|
4639
|
+
// src/video-editor/effect-tools.ts
|
|
4640
|
+
function videoClipAppliedEffects(clip) {
|
|
4641
|
+
const out = [];
|
|
4642
|
+
const ref = (r) => ({ effect: r.effect, ...r.name ? { name: r.name } : {}, ...r.provider ? { provider: r.provider } : {} });
|
|
4643
|
+
if (clip.type === "effect") out.push({ id: "generator", ...ref(clip), role: "effect clip", enabled: true, values: _nullishCoalesce(clip.values, () => ( {})) });
|
|
4644
|
+
if (_optionalChain([clip, 'access', _152 => _152.transition, 'optionalAccess', _153 => _153.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 });
|
|
4645
|
+
(_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 }));
|
|
4646
|
+
return out;
|
|
4647
|
+
}
|
|
4648
|
+
var MS2 = (what) => ({ type: "number", minimum: 0, description: `${what}, in milliseconds.` });
|
|
4649
|
+
var KEYS2 = {
|
|
4650
|
+
type: "array",
|
|
4651
|
+
minItems: 1,
|
|
4652
|
+
items: {
|
|
4653
|
+
type: "object",
|
|
4654
|
+
properties: {
|
|
4655
|
+
t: { type: "number", description: "Clip-relative time in ms (0 = the clip's start)." },
|
|
4656
|
+
v: { type: "number", description: "The control's value at t, within its range from describe_effect." },
|
|
4657
|
+
ease: { anyOf: [{ type: "string", enum: [..._chunkIWSMDQE5cjs.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]." }
|
|
4658
|
+
},
|
|
4659
|
+
required: ["t", "v"],
|
|
4660
|
+
additionalProperties: false
|
|
4661
|
+
},
|
|
4662
|
+
description: "Keys in any order (sorted for you), one per time."
|
|
4663
|
+
};
|
|
4664
|
+
function createVideoEffectsToolProvider(controller, options = {}) {
|
|
4665
|
+
const readOnlyReason = () => {
|
|
4666
|
+
const ro = typeof options.readOnly === "function" ? options.readOnly() : options.readOnly;
|
|
4667
|
+
if (ro) return typeof ro === "string" ? ro : "The video project is read-only.";
|
|
4668
|
+
return controller.readOnlyReason();
|
|
4669
|
+
};
|
|
4670
|
+
const clipOf = (id) => {
|
|
4671
|
+
const at = _chunkIWSMDQE5cjs.findVideoClip.call(void 0, controller.getProject(), id);
|
|
4672
|
+
if (!at) {
|
|
4673
|
+
const ids = controller.getProject().tracks.flatMap((t) => t.clips.map((c) => c.id));
|
|
4674
|
+
throw new Error(`There is no clip "${id}"; the clips are ${ids.map((c) => `"${c}"`).join(", ") || "none"} (get_video_project lists them).`);
|
|
4675
|
+
}
|
|
4676
|
+
return at.clip;
|
|
4677
|
+
};
|
|
4678
|
+
const result = (r, target, instance, extra = {}) => {
|
|
4679
|
+
if (!r.ok) throw new Error(r.error);
|
|
4680
|
+
const effects = videoClipAppliedEffects(clipOf(target));
|
|
4681
|
+
const effect = _nullishCoalesce(effects.find((e) => e.id === (_nullishCoalesce(instance, () => ( _optionalChain([r, 'access', _154 => _154.effect, 'optionalAccess', _155 => _155.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])));
|
|
4682
|
+
return { target, effect, effects, ...extra };
|
|
4683
|
+
};
|
|
4684
|
+
return _chunkTK53AB4Qcjs.createEffectToolProvider.call(void 0, {
|
|
4685
|
+
id: _nullishCoalesce(options.id, () => ( "video-effects")),
|
|
4686
|
+
namespace: options.namespace,
|
|
4687
|
+
target: { noun: "clip", id: 'A clip id from get_video_project (e.g. "c1").' },
|
|
4688
|
+
applyUses: ["filter", "overlay"],
|
|
4689
|
+
applyDetails: "Filters change the clip's picture and overlays draw over it, in stack order, on the picture as it comes from the source, before the clip's grade, placement, opacity and blend; numbers may be keyframed (clip-relative ms). Transitions go through set_video_effect_transition and generators or titles through add_video_effect_clip. The preview renders them frame by frame; the ffmpeg export then needs rendered frames (see export_video_ffmpeg).",
|
|
4690
|
+
provider: () => controller.effectsProvider,
|
|
4691
|
+
readOnlyReason,
|
|
4692
|
+
list: (target) => {
|
|
4693
|
+
const clips = target ? [clipOf(target)] : controller.getProject().tracks.flatMap((t) => t.clips);
|
|
4694
|
+
return clips.map((c) => ({ target: c.id, ...c.name ? { name: c.name } : {}, effects: videoClipAppliedEffects(c) })).filter((t) => target || t.effects.length);
|
|
4695
|
+
},
|
|
4696
|
+
apply: async (target, effect, args) => {
|
|
4697
|
+
clipOf(target);
|
|
4698
|
+
return result(await controller.applyClipEffect(target, effect, { values: args.values, index: args.index, enabled: args.enabled, opacity: args.opacity }), target);
|
|
4699
|
+
},
|
|
4700
|
+
update: async (target, instance, changes) => {
|
|
4701
|
+
clipOf(target);
|
|
4702
|
+
if (instance === "generator" || instance === "transition") {
|
|
4703
|
+
const extra = ["enabled", "opacity", "index"].filter((k) => changes[k] !== void 0);
|
|
4704
|
+
if (extra.length) throw new Error(`An ${instance === "generator" ? "effect clip" : "effect transition"} only takes values; change its ${extra.join(", ")} with update_video_clip${instance === "transition" ? " or set_video_effect_transition" : ""}.`);
|
|
4705
|
+
const values = Object.fromEntries(Object.entries(_nullishCoalesce(changes.values, () => ( {}))).filter(([, v]) => v !== null));
|
|
4706
|
+
return result(await controller.updateEffectValues(target, instance, values), target, instance);
|
|
4707
|
+
}
|
|
4708
|
+
return result(await controller.updateClipEffect(target, instance, changes), target, instance);
|
|
4709
|
+
},
|
|
4710
|
+
remove: async (target, instance) => {
|
|
4711
|
+
const clip = clipOf(target);
|
|
4712
|
+
const was = videoClipAppliedEffects(clip).find((e) => e.id === instance);
|
|
4713
|
+
if (!was) throw new Error(`Clip "${target}" has no effect "${instance}"; its effects are ${videoClipAppliedEffects(clip).map((e) => `"${e.id}"`).join(", ") || "none"}.`);
|
|
4714
|
+
if (instance === "generator") throw new Error(`"${target}" is an effect clip: its effect is the clip itself. Delete the clip with delete_video_clips.`);
|
|
4715
|
+
if (instance === "transition") {
|
|
4716
|
+
const r2 = controller.apply({ op: "set_transition", clip: target, transition: null }, "Remove transition");
|
|
4717
|
+
if (!r2.ok) throw new Error(r2.error);
|
|
4718
|
+
return { target, effect: was, effects: videoClipAppliedEffects(clipOf(target)) };
|
|
4719
|
+
}
|
|
4720
|
+
const r = controller.removeClipEffect(target, instance);
|
|
4721
|
+
if (!r.ok) throw new Error(r.error);
|
|
4722
|
+
return { target, effect: was, effects: videoClipAppliedEffects(clipOf(target)) };
|
|
4723
|
+
},
|
|
4724
|
+
subscribe: (notify) => controller.subscribe(() => notify()),
|
|
4725
|
+
extraTools: (ctx) => [
|
|
4726
|
+
{
|
|
4727
|
+
name: "add_video_effect_clip",
|
|
4728
|
+
title: "Add an effect clip",
|
|
4729
|
+
description: "Adds a clip drawn by a provider generator, title or overlay effect (search_effects with use generator, title or overlay), filling the frame like a colour clip; transparent effects show the tracks beneath. It can be moved, trimmed, faded, graded and given clip effects like any clip. One undo step. Returns the new clip id and its effect. The ffmpeg export then needs rendered frames.",
|
|
4730
|
+
inputSchema: {
|
|
4731
|
+
type: "object",
|
|
4732
|
+
properties: {
|
|
4733
|
+
track: { type: "string", minLength: 1, description: 'A video track id from get_video_project (e.g. "v1"); earlier tracks draw on top.' },
|
|
4734
|
+
effect: ctx.effectIdSchema(["generator", "title", "overlay"]),
|
|
4735
|
+
start: MS2("Where it starts on the timeline (default: the end of the track)"),
|
|
4736
|
+
duration: { type: "number", exclusiveMinimum: 0, description: "Length in ms (default: the effect's own length, else 5000)." },
|
|
4737
|
+
values: ctx.valuesSchema("Control values over the effect's defaults", true),
|
|
4738
|
+
name: { type: "string", minLength: 1, description: "A label for the clip (default: the effect's name)." },
|
|
4739
|
+
mode: { type: "string", enum: [..._chunkIWSMDQE5cjs.VIDEO_PLACEMENT_MODES], description: "What to do with clips already there: refuse (default), overwrite or insert." }
|
|
4740
|
+
},
|
|
4741
|
+
required: ["track", "effect"],
|
|
4742
|
+
additionalProperties: false
|
|
4743
|
+
},
|
|
4744
|
+
annotations: { title: "Add an effect clip", ...ctx.annotations.write },
|
|
4745
|
+
handler: async (args) => {
|
|
4746
|
+
ctx.requireProvider();
|
|
4747
|
+
const r = await controller.addEffectClip(args.track, args.effect, { start: args.start, duration: args.duration, values: args.values, name: args.name, mode: args.mode });
|
|
4748
|
+
if (!r.ok) throw new Error(r.error);
|
|
4749
|
+
return { clip: r.clip, track: args.track, effects: videoClipAppliedEffects(clipOf(r.clip)) };
|
|
4750
|
+
}
|
|
4751
|
+
},
|
|
4752
|
+
{
|
|
4753
|
+
name: "set_video_effect_transition",
|
|
4754
|
+
title: "Set an effect transition",
|
|
4755
|
+
description: `Sets a provider transition effect (search_effects with use transition) into a clip from the clip that ends where it starts on the same track, centred on the cut; like a crossfade it needs half its length in media past the cut on both sides. Replaces any transition there. One undo step. Returns the clip's effects. Remove it with remove_effect (effect "transition") or set_video_transition null.`,
|
|
4756
|
+
inputSchema: {
|
|
4757
|
+
type: "object",
|
|
4758
|
+
properties: {
|
|
4759
|
+
clip: { type: "string", minLength: 1, description: "The incoming clip (the one after the cut), from get_video_project." },
|
|
4760
|
+
effect: ctx.effectIdSchema(["transition"]),
|
|
4761
|
+
duration: { type: "number", exclusiveMinimum: 0, description: "Length in ms, centred on the cut (default: the effect's own length, else 1000)." },
|
|
4762
|
+
values: ctx.valuesSchema("Control values over the effect's defaults (plain values; transitions cannot be keyframed)")
|
|
4763
|
+
},
|
|
4764
|
+
required: ["clip", "effect"],
|
|
4765
|
+
additionalProperties: false
|
|
4766
|
+
},
|
|
4767
|
+
annotations: { title: "Set an effect transition", ...ctx.annotations.writeIdempotent },
|
|
4768
|
+
handler: async (args) => {
|
|
4769
|
+
ctx.requireProvider();
|
|
4770
|
+
const r = await controller.setEffectTransition(args.clip, args.effect, { duration: args.duration, values: args.values });
|
|
4771
|
+
if (!r.ok) throw new Error(r.error);
|
|
4772
|
+
return { clip: args.clip, transition: clipOf(args.clip).transition, effects: videoClipAppliedEffects(clipOf(args.clip)) };
|
|
4773
|
+
}
|
|
4774
|
+
},
|
|
4775
|
+
{
|
|
4776
|
+
name: "set_video_effect_keyframes",
|
|
4777
|
+
title: "Keyframe an effect control",
|
|
4778
|
+
description: "Animates one number control of a clip effect or an effect clip with keys at clip-relative times (ms), or with keys null stops animating it, keeping its value at the clip's start. Values are checked against the control's range from describe_effect. One undo step. Returns the effect.",
|
|
4779
|
+
inputSchema: {
|
|
4780
|
+
type: "object",
|
|
4781
|
+
properties: {
|
|
4782
|
+
clip: { type: "string", minLength: 1, description: "A clip id from list_applied_effects." },
|
|
4783
|
+
effect: { type: "string", minLength: 1, description: `The effect's id on the clip ("fx1", or "generator" for an effect clip's own effect).` },
|
|
4784
|
+
control: { type: "string", minLength: 1, description: "A number control name from describe_effect." },
|
|
4785
|
+
keys: { anyOf: [KEYS2, { type: "null" }], description: "The keys, or null to stop animating the control." }
|
|
4786
|
+
},
|
|
4787
|
+
required: ["clip", "effect", "control", "keys"],
|
|
4788
|
+
additionalProperties: false
|
|
4789
|
+
},
|
|
4790
|
+
annotations: { title: "Keyframe an effect control", ...ctx.annotations.writeIdempotent },
|
|
4791
|
+
handler: async (args) => {
|
|
4792
|
+
ctx.requireProvider();
|
|
4793
|
+
const keys = args.keys;
|
|
4794
|
+
let r;
|
|
4795
|
+
if (args.effect === "generator") {
|
|
4796
|
+
const clip = clipOf(args.clip);
|
|
4797
|
+
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).`);
|
|
4798
|
+
const was = _optionalChain([clip, 'access', _156 => _156.values, 'optionalAccess', _157 => _157[args.control]]);
|
|
4799
|
+
const plain = keys === null ? _chunkIWSMDQE5cjs.isVideoKeyframes.call(void 0, was) ? _optionalChain([was, 'access', _158 => _158.keys, 'access', _159 => _159[0], 'optionalAccess', _160 => _160.v]) : was : { keys: [...keys].sort((a, b) => a.t - b.t) };
|
|
4800
|
+
if (plain === void 0) throw new Error(`"${args.control}" has no value to keep; give keys instead.`);
|
|
4801
|
+
r = await controller.updateEffectValues(args.clip, "generator", { [args.control]: plain });
|
|
4802
|
+
} else r = await controller.setClipEffectKeyframes(args.clip, args.effect, args.control, keys);
|
|
4803
|
+
if (!r.ok) throw new Error(r.error);
|
|
4804
|
+
return { clip: args.clip, effect: videoClipAppliedEffects(clipOf(args.clip)).find((e) => e.id === args.effect) };
|
|
4805
|
+
}
|
|
4806
|
+
}
|
|
4807
|
+
]
|
|
4808
|
+
});
|
|
4809
|
+
}
|
|
4810
|
+
|
|
4811
|
+
|
|
4812
|
+
|
|
4813
|
+
|
|
4814
|
+
|
|
4815
|
+
|
|
4816
|
+
|
|
4817
|
+
|
|
4818
|
+
|
|
4819
|
+
|
|
4820
|
+
|
|
4821
|
+
|
|
4822
|
+
|
|
4823
|
+
|
|
4824
|
+
|
|
4825
|
+
|
|
4826
|
+
|
|
4827
|
+
|
|
4828
|
+
|
|
4829
|
+
|
|
4830
|
+
|
|
4359
4831
|
|
|
4360
4832
|
|
|
4361
4833
|
|
|
@@ -4587,5 +5059,5 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4587
5059
|
|
|
4588
5060
|
|
|
4589
5061
|
|
|
4590
|
-
exports.VIDEO_BLEND_MODES = _chunkSMJGE7HMcjs.VIDEO_BLEND_MODES; exports.VIDEO_BLEND_MODE_LABELS = VIDEO_BLEND_MODE_LABELS; exports.VIDEO_CLIP_ANIMATION_DURATION = _chunkSMJGE7HMcjs.VIDEO_CLIP_ANIMATION_DURATION; exports.VIDEO_CLIP_ANIMATION_EFFECTS = _chunkSMJGE7HMcjs.VIDEO_CLIP_ANIMATION_EFFECTS; exports.VIDEO_CLIP_ANIMATION_LABELS = VIDEO_CLIP_ANIMATION_LABELS; exports.VIDEO_CLIP_TYPES = _chunkSMJGE7HMcjs.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_EASE_NAMES = _chunkSMJGE7HMcjs.VIDEO_EASE_NAMES; exports.VIDEO_EDIT_OPS = VIDEO_EDIT_OPS; exports.VIDEO_FADE_CURVES = _chunkSMJGE7HMcjs.VIDEO_FADE_CURVES; exports.VIDEO_FADE_CURVE_LABELS = VIDEO_FADE_CURVE_LABELS; exports.VIDEO_FITS = _chunkSMJGE7HMcjs.VIDEO_FITS; exports.VIDEO_GRADE_CONTROLS = _chunkSMJGE7HMcjs.VIDEO_GRADE_CONTROLS; exports.VIDEO_GRADE_PRESETS = _chunkSMJGE7HMcjs.VIDEO_GRADE_PRESETS; exports.VIDEO_GRADE_PRESET_NAMES = _chunkSMJGE7HMcjs.VIDEO_GRADE_PRESET_NAMES; exports.VIDEO_ISSUE_CODES = VIDEO_ISSUE_CODES; exports.VIDEO_KEYFRAME_LIMITS = _chunkSMJGE7HMcjs.VIDEO_KEYFRAME_LIMITS; exports.VIDEO_KEYFRAME_PROPERTIES = _chunkSMJGE7HMcjs.VIDEO_KEYFRAME_PROPERTIES; exports.VIDEO_LUT_MAX_SIZE = _chunkSMJGE7HMcjs.VIDEO_LUT_MAX_SIZE; exports.VIDEO_PEAK_BLOCK = VIDEO_PEAK_BLOCK; exports.VIDEO_PLACEMENT_MODES = _chunkSMJGE7HMcjs.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 = _chunkSMJGE7HMcjs.VIDEO_TIME_EPSILON; exports.VIDEO_TRANSFORM_PROPERTIES = _chunkSMJGE7HMcjs.VIDEO_TRANSFORM_PROPERTIES; exports.VIDEO_TRANSITION_LABELS = VIDEO_TRANSITION_LABELS; exports.VIDEO_TRANSITION_TYPES = _chunkSMJGE7HMcjs.VIDEO_TRANSITION_TYPES; exports.VIDEO_VECTORSCOPE_TARGETS = VIDEO_VECTORSCOPE_TARGETS; exports.VIDEO_WIPE_DIRECTIONS = _chunkSMJGE7HMcjs.VIDEO_WIPE_DIRECTIONS; exports.VideoAudioPeaksCache = VideoAudioPeaksCache; exports.VideoEditorController = VideoEditorController; exports.VideoFrameCache = VideoFrameCache; exports.VideoLutCache = _chunkSMJGE7HMcjs.VideoLutCache; exports.VideoPreviewEngine = VideoPreviewEngine; exports.VideoPreviewPixels = VideoPreviewPixels; exports.allVideoClipIds = _chunkSMJGE7HMcjs.allVideoClipIds; exports.allVideoTracks = _chunkSMJGE7HMcjs.allVideoTracks; exports.applyVideoEdits = applyVideoEdits; exports.applyVideoGrade = _chunkSMJGE7HMcjs.applyVideoGrade; exports.applyVideoLut = _chunkSMJGE7HMcjs.applyVideoLut; exports.applyVideoLutToPixels = _chunkSMJGE7HMcjs.applyVideoLutToPixels; exports.buildVideoAudioPeaks = buildVideoAudioPeaks; exports.checkVideoProject = checkVideoProject; exports.checkVideoTimeRemap = _chunkSMJGE7HMcjs.checkVideoTimeRemap; exports.createVideoEditorToolProvider = createVideoEditorToolProvider; exports.createVideoElementDecoder = createVideoElementDecoder; exports.createVideoProject = createVideoProject; exports.decodeVideoAudioPeaks = decodeVideoAudioPeaks; exports.describeVideoProject = describeVideoProject; exports.describeVideoSequence = describeVideoSequence; exports.drawVideoFrame = _chunkSMJGE7HMcjs.drawVideoFrame; exports.ffmpegFilterValue = _chunkSMJGE7HMcjs.ffmpegFilterValue; exports.findVideoAudioSilences = findVideoAudioSilences; exports.findVideoClip = _chunkSMJGE7HMcjs.findVideoClip; exports.findVideoFillers = findVideoFillers; exports.findVideoGaps = _chunkSMJGE7HMcjs.findVideoGaps; exports.findVideoSequenceClip = _chunkSMJGE7HMcjs.findVideoSequenceClip; exports.findVideoSequenceCycle = _chunkSMJGE7HMcjs.findVideoSequenceCycle; exports.findVideoTranscriptPauses = findVideoTranscriptPauses; exports.findVideoTranscriptText = findVideoTranscriptText; exports.formatVideoSeconds = _chunkSMJGE7HMcjs.formatVideoSeconds; exports.formatVideoTimecode = _chunkSMJGE7HMcjs.formatVideoTimecode; exports.formatVideoTimecodeFrames = _chunkSMJGE7HMcjs.formatVideoTimecodeFrames; exports.isVideoDropFrameRate = _chunkSMJGE7HMcjs.isVideoDropFrameRate; exports.isVideoKeyframes = _chunkSMJGE7HMcjs.isVideoKeyframes; exports.mergeVideoRanges = mergeVideoRanges; exports.nextFreeVideoSlot = _chunkSMJGE7HMcjs.nextFreeVideoSlot; exports.normalizeVideoGrade = _chunkSMJGE7HMcjs.normalizeVideoGrade; exports.normalizeVideoGradeLut = _chunkSMJGE7HMcjs.normalizeVideoGradeLut; exports.normalizeVideoWord = normalizeVideoWord; exports.parseVideoAnimatable = parseVideoAnimatable; exports.parseVideoAsset = parseVideoAsset; exports.parseVideoAssetProxies = parseVideoAssetProxies; exports.parseVideoClip = parseVideoClip; exports.parseVideoClipAnimation = parseVideoClipAnimation; exports.parseVideoCubeLut = _chunkSMJGE7HMcjs.parseVideoCubeLut; exports.parseVideoGrade = parseVideoGrade; exports.parseVideoGradeLut = parseVideoGradeLut; exports.parseVideoKeyframes = parseVideoKeyframes; exports.parseVideoLoudnessMeasurement = _chunkSMJGE7HMcjs.parseVideoLoudnessMeasurement; exports.parseVideoMarker = parseVideoMarker; exports.parseVideoPreviewScale = parseVideoPreviewScale; exports.parseVideoProject = parseVideoProject; exports.parseVideoSequence = parseVideoSequence; exports.parseVideoTimeRemap = parseVideoTimeRemap; exports.parseVideoTrack = parseVideoTrack; exports.parseVideoTranscript = parseVideoTranscript; exports.parseVideoTranscriptWords = parseVideoTranscriptWords; exports.parseVideoTransform = parseVideoTransform; exports.parseVideoTransition = parseVideoTransition; exports.placeVideoRect = _chunkSMJGE7HMcjs.placeVideoRect; exports.planVideoClipDrag = planVideoClipDrag; exports.planVideoPrefetch = planVideoPrefetch; exports.probeVideoMedia = probeVideoMedia; exports.readVideoScopesPanel = readVideoScopesPanel; exports.removeVideoKey = _chunkSMJGE7HMcjs.removeVideoKey; exports.resolveVideoPreviewScale = resolveVideoPreviewScale; exports.retimeVideoAnimatable = _chunkSMJGE7HMcjs.retimeVideoAnimatable; exports.setVideoKey = _chunkSMJGE7HMcjs.setVideoKey; exports.snapToVideoFrame = _chunkSMJGE7HMcjs.snapToVideoFrame; exports.snapVideoTime = _chunkSMJGE7HMcjs.snapVideoTime; exports.sortVideoKeys = _chunkSMJGE7HMcjs.sortVideoKeys; exports.sortedVideoClips = _chunkSMJGE7HMcjs.sortedVideoClips; exports.splitVideoAnimatable = _chunkSMJGE7HMcjs.splitVideoAnimatable; exports.summarizeVideoScopes = summarizeVideoScopes; exports.toVideoEdl = _chunkSMJGE7HMcjs.toVideoEdl; exports.toVideoFfmpeg = _chunkSMJGE7HMcjs.toVideoFfmpeg; exports.toVideoLoudnessMeasure = _chunkSMJGE7HMcjs.toVideoLoudnessMeasure; exports.videoAssetDropEdit = videoAssetDropEdit; exports.videoAssetHasSound = _chunkSMJGE7HMcjs.videoAssetHasSound; exports.videoAssetKindOf = videoAssetKindOf; exports.videoAssetMap = _chunkSMJGE7HMcjs.videoAssetMap; exports.videoAssetProxy = videoAssetProxy; exports.videoAudioLevels = videoAudioLevels; exports.videoAudioPeakRange = videoAudioPeakRange; exports.videoAudioPeakSpans = videoAudioPeakSpans; exports.videoAudioPeaksDuration = videoAudioPeaksDuration; exports.videoCacheEvictions = videoCacheEvictions; exports.videoChroma = videoChroma; exports.videoClipAfter = _chunkSMJGE7HMcjs.videoClipAfter; exports.videoClipAnimated = _chunkSMJGE7HMcjs.videoClipAnimated; exports.videoClipAnimationProperties = _chunkSMJGE7HMcjs.videoClipAnimationProperties; exports.videoClipAnimationSpans = _chunkSMJGE7HMcjs.videoClipAnimationSpans; exports.videoClipBefore = _chunkSMJGE7HMcjs.videoClipBefore; exports.videoClipEnd = _chunkSMJGE7HMcjs.videoClipEnd; exports.videoClipHandles = _chunkSMJGE7HMcjs.videoClipHandles; exports.videoClipKeyframes = videoClipKeyframes; exports.videoClipLabel = videoClipLabel; exports.videoClipOverhang = _chunkSMJGE7HMcjs.videoClipOverhang; exports.videoClipShowsWaveform = videoClipShowsWaveform; exports.videoClipSoundGain = _chunkSMJGE7HMcjs.videoClipSoundGain; exports.videoClipSourceRange = _chunkSMJGE7HMcjs.videoClipSourceRange; exports.videoClipSourceTime = _chunkSMJGE7HMcjs.videoClipSourceTime; exports.videoClipSpeed = _chunkSMJGE7HMcjs.videoClipSpeed; exports.videoClipSpeedAt = _chunkSMJGE7HMcjs.videoClipSpeedAt; exports.videoClipTint = videoClipTint; exports.videoClipWaveform = videoClipWaveform; exports.videoClipWaveformPath = videoClipWaveformPath; exports.videoClipsAt = _chunkSMJGE7HMcjs.videoClipsAt; exports.videoContactSheetSvg = _chunkSMJGE7HMcjs.videoContactSheetSvg; exports.videoDragLabel = videoDragLabel; exports.videoDropTracks = videoDropTracks; exports.videoEaseBezier = _chunkSMJGE7HMcjs.videoEaseBezier; exports.videoEaseProgress = _chunkSMJGE7HMcjs.videoEaseProgress; exports.videoExposureNotes = videoExposureNotes; exports.videoExposureStats = videoExposureStats; exports.videoFadeCurveGain = _chunkSMJGE7HMcjs.videoFadeCurveGain; exports.videoFrameAt = _chunkSMJGE7HMcjs.videoFrameAt; exports.videoFrameCacheKey = videoFrameCacheKey; exports.videoFrameDuration = _chunkSMJGE7HMcjs.videoFrameDuration; exports.videoFrameLeafLayers = _chunkSMJGE7HMcjs.videoFrameLeafLayers; exports.videoFrameRequestsAt = videoFrameRequestsAt; exports.videoFrameToSvg = _chunkSMJGE7HMcjs.videoFrameToSvg; exports.videoFrames = _chunkSMJGE7HMcjs.videoFrames; exports.videoFreezeFrameEdit = _chunkSMJGE7HMcjs.videoFreezeFrameEdit; exports.videoGradeCssFilter = _chunkSMJGE7HMcjs.videoGradeCssFilter; exports.videoGradeFfmpegFilters = _chunkSMJGE7HMcjs.videoGradeFfmpegFilters; exports.videoGradeGainsFilterId = _chunkSMJGE7HMcjs.videoGradeGainsFilterId; exports.videoGradeLook = _chunkSMJGE7HMcjs.videoGradeLook; exports.videoGradePreset = _chunkSMJGE7HMcjs.videoGradePreset; exports.videoGradeStepMatrix = _chunkSMJGE7HMcjs.videoGradeStepMatrix; exports.videoGradeStepSvgValues = _chunkSMJGE7HMcjs.videoGradeStepSvgValues; exports.videoGradeSteps = _chunkSMJGE7HMcjs.videoGradeSteps; exports.videoGradeSvgDefs = _chunkSMJGE7HMcjs.videoGradeSvgDefs; exports.videoGradeSvgFilter = _chunkSMJGE7HMcjs.videoGradeSvgFilter; exports.videoHistogram = videoHistogram; exports.videoHistogramImage = videoHistogramImage; exports.videoHourFrames = _chunkSMJGE7HMcjs.videoHourFrames; exports.videoIrisRadius = _chunkSMJGE7HMcjs.videoIrisRadius; exports.videoIssueKey = videoIssueKey; exports.videoKeyframeBreakpoints = _chunkSMJGE7HMcjs.videoKeyframeBreakpoints; exports.videoKeyframeFfmpegExpr = _chunkSMJGE7HMcjs.videoKeyframeFfmpegExpr; exports.videoKeyframeRows = videoKeyframeRows; exports.videoKeyframeToggleEdit = videoKeyframeToggleEdit; exports.videoKeyframeValueEdit = videoKeyframeValueEdit; exports.videoKeysOf = _chunkSMJGE7HMcjs.videoKeysOf; exports.videoLuma = videoLuma; exports.videoLumaWaveform = videoLumaWaveform; exports.videoLutEdits = videoLutEdits; exports.videoLutFromFunction = _chunkSMJGE7HMcjs.videoLutFromFunction; exports.videoLutSvgApproximation = _chunkSMJGE7HMcjs.videoLutSvgApproximation; exports.videoLutSvgPrimitives = _chunkSMJGE7HMcjs.videoLutSvgPrimitives; exports.videoLutToCube = _chunkSMJGE7HMcjs.videoLutToCube; exports.videoOverlap = _chunkSMJGE7HMcjs.videoOverlap; exports.videoPeakDb = videoPeakDb; exports.videoPreviewSrc = videoPreviewSrc; exports.videoProjectDuration = _chunkSMJGE7HMcjs.videoProjectDuration; exports.videoProjectHasProxies = videoProjectHasProxies; exports.videoProjectSvg = _chunkSMJGE7HMcjs.videoProjectSvg; exports.videoProxyFfmpeg = videoProxyFfmpeg; exports.videoProxyName = videoProxyName; exports.videoProxyPlan = videoProxyPlan; exports.videoRemoveRangesEdits = videoRemoveRangesEdits; exports.videoRulerTicks = videoRulerTicks; exports.videoScopeImage = videoScopeImage; exports.videoSequenceChildren = _chunkSMJGE7HMcjs.videoSequenceChildren; exports.videoSequenceDuration = _chunkSMJGE7HMcjs.videoSequenceDuration; exports.videoSequenceMap = _chunkSMJGE7HMcjs.videoSequenceMap; exports.videoShellQuote = _chunkSMJGE7HMcjs.videoShellQuote; exports.videoSlowMotionRamp = _chunkSMJGE7HMcjs.videoSlowMotionRamp; exports.videoSnapPoints = _chunkSMJGE7HMcjs.videoSnapPoints; exports.videoSourceFrame = videoSourceFrame; exports.videoSourceFrameTime = videoSourceFrameTime; exports.videoSpeedRampEdit = _chunkSMJGE7HMcjs.videoSpeedRampEdit; exports.videoSpeedRampKeys = _chunkSMJGE7HMcjs.videoSpeedRampKeys; exports.videoTextStyle = _chunkSMJGE7HMcjs.videoTextStyle; exports.videoTimeRemapBreakpoints = _chunkSMJGE7HMcjs.videoTimeRemapBreakpoints; exports.videoTimeRemapSpan = _chunkSMJGE7HMcjs.videoTimeRemapSpan; exports.videoTimecodeFrames = _chunkSMJGE7HMcjs.videoTimecodeFrames; exports.videoTimelineTranscript = videoTimelineTranscript; exports.videoTitleFrame = _chunkSMJGE7HMcjs.videoTitleFrame; exports.videoTrackSyncLocked = _chunkSMJGE7HMcjs.videoTrackSyncLocked; exports.videoTranscriptEdit = videoTranscriptEdit; exports.videoTranscriptTrack = videoTranscriptTrack; exports.videoTransformAt = _chunkSMJGE7HMcjs.videoTransformAt; exports.videoTransitionAudioCurve = _chunkSMJGE7HMcjs.videoTransitionAudioCurve; exports.videoTransitionEase = _chunkSMJGE7HMcjs.videoTransitionEase; exports.videoTransitionHasDirection = videoTransitionHasDirection; exports.videoValueAt = _chunkSMJGE7HMcjs.videoValueAt; exports.videoVectorscope = videoVectorscope; exports.videoVectorscopeAngle = videoVectorscopeAngle; exports.videoVectorscopeImage = videoVectorscopeImage; exports.videoVectorscopePoint = videoVectorscopePoint; exports.videoWaveformImage = videoWaveformImage; exports.videoWaveformPath = videoWaveformPath; exports.videoWipeRect = _chunkSMJGE7HMcjs.videoWipeRect; exports.videoWordAt = videoWordAt; exports.videoWordsRange = videoWordsRange;
|
|
5062
|
+
exports.VIDEO_BLEND_MODES = _chunkIWSMDQE5cjs.VIDEO_BLEND_MODES; exports.VIDEO_BLEND_MODE_LABELS = VIDEO_BLEND_MODE_LABELS; exports.VIDEO_CLIP_ANIMATION_DURATION = _chunkIWSMDQE5cjs.VIDEO_CLIP_ANIMATION_DURATION; exports.VIDEO_CLIP_ANIMATION_EFFECTS = _chunkIWSMDQE5cjs.VIDEO_CLIP_ANIMATION_EFFECTS; exports.VIDEO_CLIP_ANIMATION_LABELS = VIDEO_CLIP_ANIMATION_LABELS; exports.VIDEO_CLIP_TYPES = _chunkIWSMDQE5cjs.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_EASE_NAMES = _chunkIWSMDQE5cjs.VIDEO_EASE_NAMES; exports.VIDEO_EDIT_OPS = VIDEO_EDIT_OPS; exports.VIDEO_EFFECT_PLACES = _chunkIWSMDQE5cjs.VIDEO_EFFECT_PLACES; exports.VIDEO_FADE_CURVES = _chunkIWSMDQE5cjs.VIDEO_FADE_CURVES; exports.VIDEO_FADE_CURVE_LABELS = VIDEO_FADE_CURVE_LABELS; exports.VIDEO_FITS = _chunkIWSMDQE5cjs.VIDEO_FITS; exports.VIDEO_GRADE_CONTROLS = _chunkIWSMDQE5cjs.VIDEO_GRADE_CONTROLS; exports.VIDEO_GRADE_PRESETS = _chunkIWSMDQE5cjs.VIDEO_GRADE_PRESETS; exports.VIDEO_GRADE_PRESET_NAMES = _chunkIWSMDQE5cjs.VIDEO_GRADE_PRESET_NAMES; exports.VIDEO_ISSUE_CODES = VIDEO_ISSUE_CODES; exports.VIDEO_KEYFRAME_LIMITS = _chunkIWSMDQE5cjs.VIDEO_KEYFRAME_LIMITS; exports.VIDEO_KEYFRAME_PROPERTIES = _chunkIWSMDQE5cjs.VIDEO_KEYFRAME_PROPERTIES; exports.VIDEO_LUT_MAX_SIZE = _chunkIWSMDQE5cjs.VIDEO_LUT_MAX_SIZE; exports.VIDEO_PEAK_BLOCK = VIDEO_PEAK_BLOCK; exports.VIDEO_PLACEMENT_MODES = _chunkIWSMDQE5cjs.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 = _chunkIWSMDQE5cjs.VIDEO_TIME_EPSILON; exports.VIDEO_TRANSFORM_PROPERTIES = _chunkIWSMDQE5cjs.VIDEO_TRANSFORM_PROPERTIES; exports.VIDEO_TRANSITION_LABELS = VIDEO_TRANSITION_LABELS; exports.VIDEO_TRANSITION_TYPES = _chunkIWSMDQE5cjs.VIDEO_TRANSITION_TYPES; exports.VIDEO_VECTORSCOPE_TARGETS = VIDEO_VECTORSCOPE_TARGETS; exports.VIDEO_WIPE_DIRECTIONS = _chunkIWSMDQE5cjs.VIDEO_WIPE_DIRECTIONS; exports.VideoAudioPeaksCache = VideoAudioPeaksCache; exports.VideoEditorController = VideoEditorController; exports.VideoEffectsEngine = _chunkIWSMDQE5cjs.VideoEffectsEngine; exports.VideoFrameCache = VideoFrameCache; exports.VideoLutCache = _chunkIWSMDQE5cjs.VideoLutCache; exports.VideoPreviewEngine = VideoPreviewEngine; exports.VideoPreviewPixels = VideoPreviewPixels; exports.allVideoClipIds = _chunkIWSMDQE5cjs.allVideoClipIds; exports.allVideoTracks = _chunkIWSMDQE5cjs.allVideoTracks; exports.applyVideoEdits = applyVideoEdits; exports.applyVideoGrade = _chunkIWSMDQE5cjs.applyVideoGrade; exports.applyVideoLut = _chunkIWSMDQE5cjs.applyVideoLut; exports.applyVideoLutToPixels = _chunkIWSMDQE5cjs.applyVideoLutToPixels; exports.buildVideoAudioPeaks = buildVideoAudioPeaks; exports.checkVideoEffectPlace = _chunkIWSMDQE5cjs.checkVideoEffectPlace; exports.checkVideoEffectValues = _chunkIWSMDQE5cjs.checkVideoEffectValues; exports.checkVideoProject = checkVideoProject; exports.checkVideoTimeRemap = _chunkIWSMDQE5cjs.checkVideoTimeRemap; exports.createVideoEditorToolProvider = createVideoEditorToolProvider; exports.createVideoEffectsToolProvider = createVideoEffectsToolProvider; exports.createVideoElementDecoder = createVideoElementDecoder; exports.createVideoProject = createVideoProject; exports.decodeVideoAudioPeaks = decodeVideoAudioPeaks; exports.describeVideoProject = describeVideoProject; exports.describeVideoSequence = describeVideoSequence; exports.drawVideoFrame = _chunkIWSMDQE5cjs.drawVideoFrame; exports.ffmpegFilterValue = _chunkIWSMDQE5cjs.ffmpegFilterValue; exports.findVideoAudioSilences = findVideoAudioSilences; exports.findVideoClip = _chunkIWSMDQE5cjs.findVideoClip; exports.findVideoFillers = findVideoFillers; exports.findVideoGaps = _chunkIWSMDQE5cjs.findVideoGaps; exports.findVideoSequenceClip = _chunkIWSMDQE5cjs.findVideoSequenceClip; exports.findVideoSequenceCycle = _chunkIWSMDQE5cjs.findVideoSequenceCycle; exports.findVideoTranscriptPauses = findVideoTranscriptPauses; exports.findVideoTranscriptText = findVideoTranscriptText; exports.formatVideoSeconds = _chunkIWSMDQE5cjs.formatVideoSeconds; exports.formatVideoTimecode = _chunkIWSMDQE5cjs.formatVideoTimecode; exports.formatVideoTimecodeFrames = _chunkIWSMDQE5cjs.formatVideoTimecodeFrames; exports.isVideoDropFrameRate = _chunkIWSMDQE5cjs.isVideoDropFrameRate; exports.isVideoKeyframes = _chunkIWSMDQE5cjs.isVideoKeyframes; exports.mergeVideoRanges = mergeVideoRanges; exports.mixEffectPixels = _chunkIWSMDQE5cjs.mixEffectPixels; exports.nextFreeVideoSlot = _chunkIWSMDQE5cjs.nextFreeVideoSlot; exports.normalizeVideoGrade = _chunkIWSMDQE5cjs.normalizeVideoGrade; exports.normalizeVideoGradeLut = _chunkIWSMDQE5cjs.normalizeVideoGradeLut; exports.normalizeVideoWord = normalizeVideoWord; exports.overEffectPixels = _chunkIWSMDQE5cjs.overEffectPixels; exports.parseVideoAnimatable = parseVideoAnimatable; exports.parseVideoAsset = parseVideoAsset; exports.parseVideoAssetProxies = parseVideoAssetProxies; exports.parseVideoClip = parseVideoClip; exports.parseVideoClipAnimation = parseVideoClipAnimation; exports.parseVideoClipEffects = parseVideoClipEffects; exports.parseVideoCubeLut = _chunkIWSMDQE5cjs.parseVideoCubeLut; exports.parseVideoEffectRef = parseVideoEffectRef; exports.parseVideoEffectValues = parseVideoEffectValues; exports.parseVideoGrade = parseVideoGrade; exports.parseVideoGradeLut = parseVideoGradeLut; exports.parseVideoKeyframes = parseVideoKeyframes; exports.parseVideoLoudnessMeasurement = _chunkIWSMDQE5cjs.parseVideoLoudnessMeasurement; exports.parseVideoMarker = parseVideoMarker; exports.parseVideoPreviewScale = parseVideoPreviewScale; exports.parseVideoProject = parseVideoProject; exports.parseVideoSequence = parseVideoSequence; exports.parseVideoTimeRemap = parseVideoTimeRemap; exports.parseVideoTrack = parseVideoTrack; exports.parseVideoTranscript = parseVideoTranscript; exports.parseVideoTranscriptWords = parseVideoTranscriptWords; exports.parseVideoTransform = parseVideoTransform; exports.parseVideoTransition = parseVideoTransition; exports.placeVideoRect = _chunkIWSMDQE5cjs.placeVideoRect; exports.planVideoClipDrag = planVideoClipDrag; exports.planVideoPrefetch = planVideoPrefetch; exports.probeVideoMedia = probeVideoMedia; exports.readVideoScopesPanel = readVideoScopesPanel; exports.removeVideoKey = _chunkIWSMDQE5cjs.removeVideoKey; exports.renderVideoFrameExact = _chunkIWSMDQE5cjs.renderVideoFrameExact; exports.resolveVideoPreviewScale = resolveVideoPreviewScale; exports.retimeVideoAnimatable = _chunkIWSMDQE5cjs.retimeVideoAnimatable; exports.setVideoKey = _chunkIWSMDQE5cjs.setVideoKey; exports.snapToVideoFrame = _chunkIWSMDQE5cjs.snapToVideoFrame; exports.snapVideoTime = _chunkIWSMDQE5cjs.snapVideoTime; exports.sortVideoKeys = _chunkIWSMDQE5cjs.sortVideoKeys; exports.sortedVideoClips = _chunkIWSMDQE5cjs.sortedVideoClips; exports.splitVideoAnimatable = _chunkIWSMDQE5cjs.splitVideoAnimatable; exports.summarizeVideoScopes = summarizeVideoScopes; exports.toVideoEdl = _chunkIWSMDQE5cjs.toVideoEdl; exports.toVideoFfmpeg = _chunkIWSMDQE5cjs.toVideoFfmpeg; exports.toVideoLoudnessMeasure = _chunkIWSMDQE5cjs.toVideoLoudnessMeasure; exports.videoAssetDropEdit = videoAssetDropEdit; exports.videoAssetHasSound = _chunkIWSMDQE5cjs.videoAssetHasSound; exports.videoAssetKindOf = videoAssetKindOf; exports.videoAssetMap = _chunkIWSMDQE5cjs.videoAssetMap; exports.videoAssetProxy = videoAssetProxy; exports.videoAudioLevels = videoAudioLevels; exports.videoAudioPeakRange = videoAudioPeakRange; exports.videoAudioPeakSpans = videoAudioPeakSpans; exports.videoAudioPeaksDuration = videoAudioPeaksDuration; exports.videoCacheEvictions = videoCacheEvictions; exports.videoChroma = videoChroma; exports.videoClipAfter = _chunkIWSMDQE5cjs.videoClipAfter; exports.videoClipAnimated = _chunkIWSMDQE5cjs.videoClipAnimated; exports.videoClipAnimationProperties = _chunkIWSMDQE5cjs.videoClipAnimationProperties; exports.videoClipAnimationSpans = _chunkIWSMDQE5cjs.videoClipAnimationSpans; exports.videoClipAppliedEffects = videoClipAppliedEffects; exports.videoClipBefore = _chunkIWSMDQE5cjs.videoClipBefore; exports.videoClipEffectUses = _chunkIWSMDQE5cjs.videoClipEffectUses; exports.videoClipEnd = _chunkIWSMDQE5cjs.videoClipEnd; exports.videoClipHandles = _chunkIWSMDQE5cjs.videoClipHandles; exports.videoClipKeyframes = videoClipKeyframes; exports.videoClipLabel = videoClipLabel; exports.videoClipOverhang = _chunkIWSMDQE5cjs.videoClipOverhang; exports.videoClipShowsWaveform = videoClipShowsWaveform; exports.videoClipSoundGain = _chunkIWSMDQE5cjs.videoClipSoundGain; exports.videoClipSourceRange = _chunkIWSMDQE5cjs.videoClipSourceRange; exports.videoClipSourceTime = _chunkIWSMDQE5cjs.videoClipSourceTime; exports.videoClipSpeed = _chunkIWSMDQE5cjs.videoClipSpeed; exports.videoClipSpeedAt = _chunkIWSMDQE5cjs.videoClipSpeedAt; exports.videoClipTint = videoClipTint; exports.videoClipWaveform = videoClipWaveform; exports.videoClipWaveformPath = videoClipWaveformPath; exports.videoClipsAt = _chunkIWSMDQE5cjs.videoClipsAt; exports.videoContactSheetSvg = _chunkIWSMDQE5cjs.videoContactSheetSvg; exports.videoDragLabel = videoDragLabel; exports.videoDropTracks = videoDropTracks; exports.videoEaseBezier = _chunkIWSMDQE5cjs.videoEaseBezier; exports.videoEaseProgress = _chunkIWSMDQE5cjs.videoEaseProgress; exports.videoEffectFrameTime = _chunkIWSMDQE5cjs.videoEffectFrameTime; exports.videoEffectLayerKey = _chunkIWSMDQE5cjs.videoEffectLayerKey; exports.videoEffectValuesAt = _chunkIWSMDQE5cjs.videoEffectValuesAt; exports.videoExposureNotes = videoExposureNotes; exports.videoExposureStats = videoExposureStats; exports.videoFadeCurveGain = _chunkIWSMDQE5cjs.videoFadeCurveGain; exports.videoFfmpegUnsupportedEffects = _chunkIWSMDQE5cjs.videoFfmpegUnsupportedEffects; exports.videoFrameAt = _chunkIWSMDQE5cjs.videoFrameAt; exports.videoFrameCacheKey = videoFrameCacheKey; exports.videoFrameDuration = _chunkIWSMDQE5cjs.videoFrameDuration; exports.videoFrameLeafLayers = _chunkIWSMDQE5cjs.videoFrameLeafLayers; exports.videoFrameRequestsAt = videoFrameRequestsAt; exports.videoFrameToSvg = _chunkIWSMDQE5cjs.videoFrameToSvg; exports.videoFrames = _chunkIWSMDQE5cjs.videoFrames; exports.videoFreezeFrameEdit = _chunkIWSMDQE5cjs.videoFreezeFrameEdit; exports.videoGradeCssFilter = _chunkIWSMDQE5cjs.videoGradeCssFilter; exports.videoGradeFfmpegFilters = _chunkIWSMDQE5cjs.videoGradeFfmpegFilters; exports.videoGradeGainsFilterId = _chunkIWSMDQE5cjs.videoGradeGainsFilterId; exports.videoGradeLook = _chunkIWSMDQE5cjs.videoGradeLook; exports.videoGradePreset = _chunkIWSMDQE5cjs.videoGradePreset; exports.videoGradeStepMatrix = _chunkIWSMDQE5cjs.videoGradeStepMatrix; exports.videoGradeStepSvgValues = _chunkIWSMDQE5cjs.videoGradeStepSvgValues; exports.videoGradeSteps = _chunkIWSMDQE5cjs.videoGradeSteps; exports.videoGradeSvgDefs = _chunkIWSMDQE5cjs.videoGradeSvgDefs; exports.videoGradeSvgFilter = _chunkIWSMDQE5cjs.videoGradeSvgFilter; exports.videoHistogram = videoHistogram; exports.videoHistogramImage = videoHistogramImage; exports.videoHourFrames = _chunkIWSMDQE5cjs.videoHourFrames; exports.videoIrisRadius = _chunkIWSMDQE5cjs.videoIrisRadius; exports.videoIssueKey = videoIssueKey; exports.videoKeyframeBreakpoints = _chunkIWSMDQE5cjs.videoKeyframeBreakpoints; exports.videoKeyframeFfmpegExpr = _chunkIWSMDQE5cjs.videoKeyframeFfmpegExpr; exports.videoKeyframeRows = videoKeyframeRows; exports.videoKeyframeToggleEdit = videoKeyframeToggleEdit; exports.videoKeyframeValueEdit = videoKeyframeValueEdit; exports.videoKeysOf = _chunkIWSMDQE5cjs.videoKeysOf; exports.videoLayersUseEffects = _chunkIWSMDQE5cjs.videoLayersUseEffects; exports.videoLayersWithoutTransitionEffects = _chunkIWSMDQE5cjs.videoLayersWithoutTransitionEffects; exports.videoLuma = videoLuma; exports.videoLumaWaveform = videoLumaWaveform; exports.videoLutEdits = videoLutEdits; exports.videoLutFromFunction = _chunkIWSMDQE5cjs.videoLutFromFunction; exports.videoLutSvgApproximation = _chunkIWSMDQE5cjs.videoLutSvgApproximation; exports.videoLutSvgPrimitives = _chunkIWSMDQE5cjs.videoLutSvgPrimitives; exports.videoLutToCube = _chunkIWSMDQE5cjs.videoLutToCube; exports.videoOverlap = _chunkIWSMDQE5cjs.videoOverlap; exports.videoPeakDb = videoPeakDb; exports.videoPreviewSrc = videoPreviewSrc; exports.videoProjectDuration = _chunkIWSMDQE5cjs.videoProjectDuration; exports.videoProjectEffects = _chunkIWSMDQE5cjs.videoProjectEffects; exports.videoProjectHasProxies = videoProjectHasProxies; exports.videoProjectSvg = _chunkIWSMDQE5cjs.videoProjectSvg; exports.videoProxyFfmpeg = videoProxyFfmpeg; exports.videoProxyName = videoProxyName; exports.videoProxyPlan = videoProxyPlan; exports.videoRemoveRangesEdits = videoRemoveRangesEdits; exports.videoRulerTicks = videoRulerTicks; exports.videoScopeImage = videoScopeImage; exports.videoSequenceChildren = _chunkIWSMDQE5cjs.videoSequenceChildren; exports.videoSequenceDuration = _chunkIWSMDQE5cjs.videoSequenceDuration; exports.videoSequenceMap = _chunkIWSMDQE5cjs.videoSequenceMap; exports.videoShellQuote = _chunkIWSMDQE5cjs.videoShellQuote; exports.videoSlowMotionRamp = _chunkIWSMDQE5cjs.videoSlowMotionRamp; exports.videoSnapPoints = _chunkIWSMDQE5cjs.videoSnapPoints; exports.videoSourceFrame = videoSourceFrame; exports.videoSourceFrameTime = videoSourceFrameTime; exports.videoSpeedRampEdit = _chunkIWSMDQE5cjs.videoSpeedRampEdit; exports.videoSpeedRampKeys = _chunkIWSMDQE5cjs.videoSpeedRampKeys; exports.videoTextStyle = _chunkIWSMDQE5cjs.videoTextStyle; exports.videoTimeRemapBreakpoints = _chunkIWSMDQE5cjs.videoTimeRemapBreakpoints; exports.videoTimeRemapSpan = _chunkIWSMDQE5cjs.videoTimeRemapSpan; exports.videoTimecodeFrames = _chunkIWSMDQE5cjs.videoTimecodeFrames; exports.videoTimelineTranscript = videoTimelineTranscript; exports.videoTitleFrame = _chunkIWSMDQE5cjs.videoTitleFrame; exports.videoTrackSyncLocked = _chunkIWSMDQE5cjs.videoTrackSyncLocked; exports.videoTranscriptEdit = videoTranscriptEdit; exports.videoTranscriptTrack = videoTranscriptTrack; exports.videoTransformAt = _chunkIWSMDQE5cjs.videoTransformAt; exports.videoTransitionAudioCurve = _chunkIWSMDQE5cjs.videoTransitionAudioCurve; exports.videoTransitionEase = _chunkIWSMDQE5cjs.videoTransitionEase; exports.videoTransitionHasDirection = videoTransitionHasDirection; exports.videoValueAt = _chunkIWSMDQE5cjs.videoValueAt; exports.videoVectorscope = videoVectorscope; exports.videoVectorscopeAngle = videoVectorscopeAngle; exports.videoVectorscopeImage = videoVectorscopeImage; exports.videoVectorscopePoint = videoVectorscopePoint; exports.videoWaveformImage = videoWaveformImage; exports.videoWaveformPath = videoWaveformPath; exports.videoWipeRect = _chunkIWSMDQE5cjs.videoWipeRect; exports.videoWordAt = videoWordAt; exports.videoWordsRange = videoWordsRange;
|
|
4591
5063
|
//# sourceMappingURL=index.cjs.map
|