@pixerate/editor 0.230.0 → 0.231.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/{chunk-A57ZQDNN.cjs → chunk-5T3H7CGG.cjs} +14 -4
- package/dist/{chunk-ONNNNGNS.js → chunk-CSM5T6SE.js} +13 -3
- package/dist/paint-editor/index.cjs +2 -2
- package/dist/paint-editor/index.js +1 -1
- package/dist/video-editor/camera-tools.d.cts +10 -0
- package/dist/video-editor/camera-tools.d.ts +10 -0
- package/dist/video-editor/camera.d.cts +47 -0
- package/dist/video-editor/camera.d.ts +47 -0
- package/dist/video-editor/check.d.cts +1 -1
- package/dist/video-editor/check.d.ts +1 -1
- package/dist/video-editor/controller.d.cts +37 -2
- package/dist/video-editor/controller.d.ts +37 -2
- package/dist/video-editor/effect-tools.d.cts +2 -1
- package/dist/video-editor/effect-tools.d.ts +2 -1
- package/dist/video-editor/index.cjs +690 -375
- package/dist/video-editor/index.d.cts +2 -0
- package/dist/video-editor/index.d.ts +2 -0
- package/dist/video-editor/index.js +331 -16
- package/dist/video-editor/keyframes.d.cts +10 -3
- package/dist/video-editor/keyframes.d.ts +10 -3
- package/dist/video-editor/parse.d.cts +5 -3
- package/dist/video-editor/parse.d.ts +5 -3
- package/dist/video-editor/tools.d.cts +18 -0
- package/dist/video-editor/tools.d.ts +18 -0
- package/dist/video-editor/types.d.cts +37 -1
- package/dist/video-editor/types.d.ts +37 -1
- package/package.json +1 -1
|
@@ -148,7 +148,8 @@ var _chunkC73U5UI3cjs = require('../chunk-C73U5UI3.cjs');
|
|
|
148
148
|
|
|
149
149
|
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
|
|
152
|
+
var _chunk5T3H7CGGcjs = require('../chunk-5T3H7CGG.cjs');
|
|
152
153
|
require('../chunk-PY4GWSE2.cjs');
|
|
153
154
|
|
|
154
155
|
|
|
@@ -157,6 +158,11 @@ var _chunkERJA5CGTcjs = require('../chunk-ERJA5CGT.cjs');
|
|
|
157
158
|
|
|
158
159
|
|
|
159
160
|
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
160
166
|
var _chunkOPSK22DLcjs = require('../chunk-OPSK22DL.cjs');
|
|
161
167
|
require('../chunk-WOFXZ3XU.cjs');
|
|
162
168
|
|
|
@@ -216,7 +222,7 @@ function parseVideoEase(v, path) {
|
|
|
216
222
|
if (v[0] < 0 || v[0] > 1 || v[2] < 0 || v[2] > 1) fail(path, "must have x1 and x2 between 0 and 1");
|
|
217
223
|
return [v[0], v[1], v[2], v[3]];
|
|
218
224
|
}
|
|
219
|
-
return oneOf(v,
|
|
225
|
+
return oneOf(v, _chunk5T3H7CGGcjs.VIDEO_EASE_NAMES, path);
|
|
220
226
|
}
|
|
221
227
|
function parseVideoKeyframes(v, path, { min, max } = {}) {
|
|
222
228
|
if (!isObject(v)) return fail(path, "must be a number or keyframes { keys: [{ t, v, ease }] }");
|
|
@@ -228,7 +234,10 @@ function parseVideoKeyframes(v, path, { min, max } = {}) {
|
|
|
228
234
|
for (const key of Object.keys(k)) if (!["t", "v", "ease"].includes(key)) fail(`${at}.${key}`, "is not a key field (t, v, ease)");
|
|
229
235
|
return compact({ t: num(k.t, `${at}.t`), v: num(k.v, `${at}.v`, { min, max }), ease: parseVideoEase(k.ease, `${at}.ease`) });
|
|
230
236
|
});
|
|
231
|
-
for (let i = 1; i < keys.length; i++)
|
|
237
|
+
for (let i = 1; i < keys.length; i++) {
|
|
238
|
+
if (keys[i].t < keys[i - 1].t) fail(`${path}.keys[${i}].t`, `must not be before the key before (${keys[i - 1].t} ms); keys go in time order`);
|
|
239
|
+
if (i >= 2 && keys[i].t === keys[i - 2].t) fail(`${path}.keys[${i}].t`, `is the third key at ${keys[i].t} ms; a time takes one key, or two for a jump (the value just before, then the value after)`);
|
|
240
|
+
}
|
|
232
241
|
return { keys };
|
|
233
242
|
}
|
|
234
243
|
function parseVideoAnimatable(v, path, range = {}) {
|
|
@@ -253,8 +262,9 @@ function parseVideoTimeRemap(v, speed, path) {
|
|
|
253
262
|
const remap = parseVideoAnimatable(v, path, { optional: true, min: 0 });
|
|
254
263
|
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)");
|
|
255
264
|
if (speed !== void 0 && speed !== 1) fail(path, 'cannot be used with a speed; a ramp sets the speed itself (remove "speed")');
|
|
265
|
+
for (let i = 1; i < remap.keys.length; i++) if (remap.keys[i].t === remap.keys[i - 1].t) fail(`${path}.keys[${i}].t`, `must be later than the key before (${remap.keys[i - 1].t} ms); a speed ramp has one key per time`);
|
|
256
266
|
try {
|
|
257
|
-
|
|
267
|
+
_chunk5T3H7CGGcjs.checkVideoTimeRemap.call(void 0, remap, path);
|
|
258
268
|
} catch (e) {
|
|
259
269
|
throw new Error(e.message.replace(/\.?$/, "."));
|
|
260
270
|
}
|
|
@@ -264,17 +274,17 @@ function parseVideoClipAnimation(v, path) {
|
|
|
264
274
|
if (v === void 0) return void 0;
|
|
265
275
|
if (!isObject(v)) return fail(path, "must be an object { effect, duration }");
|
|
266
276
|
return compact({
|
|
267
|
-
effect: oneOf(v.effect,
|
|
277
|
+
effect: oneOf(v.effect, _chunk5T3H7CGGcjs.VIDEO_CLIP_ANIMATION_EFFECTS, `${path}.effect`, false),
|
|
268
278
|
duration: num(v.duration, `${path}.duration`, { optional: true, positive: true })
|
|
269
279
|
});
|
|
270
280
|
}
|
|
271
281
|
function parseVideoGrade(v, path) {
|
|
272
282
|
if (v === void 0) return void 0;
|
|
273
283
|
if (!isObject(v)) return fail(path, "must be an object such as { exposure, contrast, saturation }");
|
|
274
|
-
const known = /* @__PURE__ */ new Set([...
|
|
284
|
+
const known = /* @__PURE__ */ new Set([..._chunk5T3H7CGGcjs.VIDEO_GRADE_CONTROLS.map((c) => c.key), "lut"]);
|
|
275
285
|
const unknown = Object.keys(v).find((k) => !known.has(k));
|
|
276
286
|
if (unknown) fail(`${path}.${unknown}`, `is not a grade setting; use ${[...known].join(", ")}`);
|
|
277
|
-
return compact({ ...Object.fromEntries(
|
|
287
|
+
return compact({ ...Object.fromEntries(_chunk5T3H7CGGcjs.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`) });
|
|
278
288
|
}
|
|
279
289
|
function parseVideoGradeLut(v, path) {
|
|
280
290
|
if (v === void 0) return void 0;
|
|
@@ -289,7 +299,7 @@ function parseVideoClipMask(v, path) {
|
|
|
289
299
|
if (!isObject(v)) return fail(path, 'must be an object such as { shape: "ellipse", x: 0.5, y: 0.5, width: 0.4, height: 0.6, feather: 20 }');
|
|
290
300
|
const unknown = Object.keys(v).find((k) => !MASK_KEYS.includes(k));
|
|
291
301
|
if (unknown) fail(`${path}.${unknown}`, `is not a mask setting; use ${MASK_KEYS.join(", ")}`);
|
|
292
|
-
const shape = oneOf(v.shape,
|
|
302
|
+
const shape = oneOf(v.shape, _chunk5T3H7CGGcjs.VIDEO_MASK_SHAPES, `${path}.shape`, false);
|
|
293
303
|
let points;
|
|
294
304
|
if (v.points !== void 0) {
|
|
295
305
|
if (shape !== "polygon") fail(`${path}.points`, "is only for polygon masks");
|
|
@@ -315,15 +325,15 @@ function parseVideoClipMask(v, path) {
|
|
|
315
325
|
function parseVideoTransition(v, path) {
|
|
316
326
|
if (v === void 0) return void 0;
|
|
317
327
|
if (!isObject(v)) return fail(path, "must be an object { type, duration }");
|
|
318
|
-
const type = oneOf(v.type,
|
|
328
|
+
const type = oneOf(v.type, _chunk5T3H7CGGcjs.VIDEO_TRANSITION_TYPES, `${path}.type`, false);
|
|
319
329
|
if (type === "effect" && v.effect === void 0) fail(`${path}.effect`, 'is required for an effect transition: { effect: "<effect id>", values }');
|
|
320
330
|
if (type !== "effect" && v.effect !== void 0) fail(`${path}.effect`, 'is only for transitions of type "effect"');
|
|
321
331
|
return compact({
|
|
322
332
|
type,
|
|
323
333
|
duration: num(v.duration, `${path}.duration`, { positive: true }),
|
|
324
334
|
color: str(v.color, `${path}.color`, true),
|
|
325
|
-
direction: oneOf(v.direction,
|
|
326
|
-
audioCurve: oneOf(v.audioCurve,
|
|
335
|
+
direction: oneOf(v.direction, _chunk5T3H7CGGcjs.VIDEO_WIPE_DIRECTIONS, `${path}.direction`),
|
|
336
|
+
audioCurve: oneOf(v.audioCurve, _chunk5T3H7CGGcjs.VIDEO_FADE_CURVES, `${path}.audioCurve`),
|
|
327
337
|
effect: v.effect === void 0 ? void 0 : parseVideoEffectRef(v.effect, `${path}.effect`, false)
|
|
328
338
|
});
|
|
329
339
|
}
|
|
@@ -414,9 +424,45 @@ function parseVideoAssetProxies(v, path) {
|
|
|
414
424
|
}
|
|
415
425
|
return out.length ? out : void 0;
|
|
416
426
|
}
|
|
427
|
+
var CAMERA_KEYS = ["in", "during", "from", "framing", "base"];
|
|
428
|
+
function parseCameraFraming(v, path) {
|
|
429
|
+
if (v === void 0) return void 0;
|
|
430
|
+
if (!isObject(v)) return fail(path, "must be an object { zoom, x, y }");
|
|
431
|
+
const unknown = Object.keys(v).find((k) => !["zoom", "x", "y"].includes(k));
|
|
432
|
+
if (unknown) fail(`${path}.${unknown}`, "is not a framing field (zoom, x, y)");
|
|
433
|
+
return compact({ zoom: num(v.zoom, `${path}.zoom`, { optional: true, positive: true }), x: num(v.x, `${path}.x`, { optional: true }), y: num(v.y, `${path}.y`, { optional: true }) });
|
|
434
|
+
}
|
|
435
|
+
function parseCameraMove(v, path, hold) {
|
|
436
|
+
if (v === void 0) return void 0;
|
|
437
|
+
if (typeof v === "string" && v) return v;
|
|
438
|
+
if (!isObject(v) || typeof v.move !== "string" || !v.move) return fail(path, "must be a camera move's id, or { move, ms, preset, values }");
|
|
439
|
+
const unknown = Object.keys(v).find((k) => !["move", "ms", "preset", "values"].includes(k));
|
|
440
|
+
if (unknown) fail(`${path}.${unknown}`, "is not a camera move field (move, ms, preset, values)");
|
|
441
|
+
if (hold && v.ms !== void 0) fail(`${path}.ms`, "is not for a hold move, which plays across the rest of the clip");
|
|
442
|
+
if (v.values !== void 0 && !isObject(v.values)) fail(`${path}.values`, "must be an object of the move's control values");
|
|
443
|
+
return compact({ move: v.move, ms: num(v.ms, `${path}.ms`, { optional: true, min: 0 }), preset: str(v.preset, `${path}.preset`, true), values: v.values });
|
|
444
|
+
}
|
|
445
|
+
function parseVideoClipCamera(v, path) {
|
|
446
|
+
if (v === void 0) return void 0;
|
|
447
|
+
if (!isObject(v)) return fail(path, "must be an object { in, during, from, framing, base }");
|
|
448
|
+
const unknown = Object.keys(v).find((k) => !CAMERA_KEYS.includes(k));
|
|
449
|
+
if (unknown) fail(`${path}.${unknown}`, `is not a camera field; use ${CAMERA_KEYS.join(", ")}`);
|
|
450
|
+
if (v.in === void 0 && v.during === void 0) fail(path, 'names no move: give "in", "during" or both, or remove the camera');
|
|
451
|
+
if (!isObject(v.base)) fail(`${path}.base`, "must be the clip's transform before the moves were baked, { x, y, scale, rotation } as numbers");
|
|
452
|
+
const base = v.base;
|
|
453
|
+
const extra = Object.keys(base).find((k) => !["x", "y", "scale", "rotation"].includes(k));
|
|
454
|
+
if (extra) fail(`${path}.base.${extra}`, "is not a transform field (x, y, scale, rotation)");
|
|
455
|
+
return compact({
|
|
456
|
+
in: parseCameraMove(v.in, `${path}.in`, false),
|
|
457
|
+
during: parseCameraMove(v.during, `${path}.during`, true),
|
|
458
|
+
from: parseCameraFraming(v.from, `${path}.from`),
|
|
459
|
+
framing: parseCameraFraming(v.framing, `${path}.framing`),
|
|
460
|
+
base: compact({ x: num(base.x, `${path}.base.x`, { optional: true }), y: num(base.y, `${path}.base.y`, { optional: true }), scale: num(base.scale, `${path}.base.scale`, { optional: true, min: 0 }), rotation: num(base.rotation, `${path}.base.rotation`, { optional: true }) })
|
|
461
|
+
});
|
|
462
|
+
}
|
|
417
463
|
function parseVideoClip(v, path = "clip") {
|
|
418
464
|
if (!isObject(v)) return fail(path, "must be an object");
|
|
419
|
-
const type = oneOf(_nullishCoalesce(v.type, () => ( "media")),
|
|
465
|
+
const type = oneOf(_nullishCoalesce(v.type, () => ( "media")), _chunk5T3H7CGGcjs.VIDEO_CLIP_TYPES, `${path}.type`, false);
|
|
420
466
|
const base = {
|
|
421
467
|
id: str(v.id, `${path}.id`),
|
|
422
468
|
name: str(v.name, `${path}.name`, true),
|
|
@@ -424,8 +470,8 @@ function parseVideoClip(v, path = "clip") {
|
|
|
424
470
|
duration: num(v.duration, `${path}.duration`, { positive: true }),
|
|
425
471
|
opacity: parseVideoAnimatable(v.opacity, `${path}.opacity`, { optional: true, min: 0, max: 1 }),
|
|
426
472
|
transform: parseVideoTransform(v.transform, `${path}.transform`),
|
|
427
|
-
fit: oneOf(v.fit,
|
|
428
|
-
blend: oneOf(v.blend,
|
|
473
|
+
fit: oneOf(v.fit, _chunk5T3H7CGGcjs.VIDEO_FITS, `${path}.fit`),
|
|
474
|
+
blend: oneOf(v.blend, _chunk5T3H7CGGcjs.VIDEO_BLEND_MODES, `${path}.blend`),
|
|
429
475
|
grade: parseVideoGrade(v.grade, `${path}.grade`),
|
|
430
476
|
animateIn: parseVideoClipAnimation(v.animateIn, `${path}.animateIn`),
|
|
431
477
|
animateOut: parseVideoClipAnimation(v.animateOut, `${path}.animateOut`),
|
|
@@ -433,7 +479,8 @@ function parseVideoClip(v, path = "clip") {
|
|
|
433
479
|
fadeOut: num(v.fadeOut, `${path}.fadeOut`, { optional: true, min: 0 }),
|
|
434
480
|
transition: parseVideoTransition(v.transition, `${path}.transition`),
|
|
435
481
|
effects: parseVideoClipEffects(v.effects, `${path}.effects`),
|
|
436
|
-
mask: parseVideoClipMask(v.mask, `${path}.mask`)
|
|
482
|
+
mask: parseVideoClipMask(v.mask, `${path}.mask`),
|
|
483
|
+
camera: parseVideoClipCamera(v.camera, `${path}.camera`)
|
|
437
484
|
};
|
|
438
485
|
if (type === "media")
|
|
439
486
|
return compact({
|
|
@@ -445,8 +492,8 @@ function parseVideoClip(v, path = "clip") {
|
|
|
445
492
|
volume: parseVideoAnimatable(v.volume, `${path}.volume`, { optional: true, min: 0, max: 4 }),
|
|
446
493
|
muted: bool(v.muted, `${path}.muted`),
|
|
447
494
|
timeRemap: parseVideoTimeRemap(v.timeRemap, v.speed, `${path}.timeRemap`),
|
|
448
|
-
fadeInCurve: oneOf(v.fadeInCurve,
|
|
449
|
-
fadeOutCurve: oneOf(v.fadeOutCurve,
|
|
495
|
+
fadeInCurve: oneOf(v.fadeInCurve, _chunk5T3H7CGGcjs.VIDEO_FADE_CURVES, `${path}.fadeInCurve`),
|
|
496
|
+
fadeOutCurve: oneOf(v.fadeOutCurve, _chunk5T3H7CGGcjs.VIDEO_FADE_CURVES, `${path}.fadeOutCurve`)
|
|
450
497
|
});
|
|
451
498
|
if (type === "sequence") {
|
|
452
499
|
for (const key of ["speed", "timeRemap"])
|
|
@@ -458,8 +505,8 @@ function parseVideoClip(v, path = "clip") {
|
|
|
458
505
|
in: num(v.in, `${path}.in`, { optional: true, min: 0 }),
|
|
459
506
|
volume: parseVideoAnimatable(v.volume, `${path}.volume`, { optional: true, min: 0, max: 4 }),
|
|
460
507
|
muted: bool(v.muted, `${path}.muted`),
|
|
461
|
-
fadeInCurve: oneOf(v.fadeInCurve,
|
|
462
|
-
fadeOutCurve: oneOf(v.fadeOutCurve,
|
|
508
|
+
fadeInCurve: oneOf(v.fadeInCurve, _chunk5T3H7CGGcjs.VIDEO_FADE_CURVES, `${path}.fadeInCurve`),
|
|
509
|
+
fadeOutCurve: oneOf(v.fadeOutCurve, _chunk5T3H7CGGcjs.VIDEO_FADE_CURVES, `${path}.fadeOutCurve`)
|
|
463
510
|
});
|
|
464
511
|
}
|
|
465
512
|
if (type === "text")
|
|
@@ -474,7 +521,7 @@ function parseVideoClip(v, path = "clip") {
|
|
|
474
521
|
background: str(v.background, `${path}.background`, true)
|
|
475
522
|
});
|
|
476
523
|
if (type === "adjustment") {
|
|
477
|
-
const scope = oneOf(v.scope,
|
|
524
|
+
const scope = oneOf(v.scope, _chunk5T3H7CGGcjs.VIDEO_ADJUSTMENT_SCOPES, `${path}.scope`);
|
|
478
525
|
const targetTrack = str(v.targetTrack, `${path}.targetTrack`, true);
|
|
479
526
|
if (scope === "track" && !targetTrack) fail(`${path}.targetTrack`, 'is required when scope is "track": the id of the track whose pictures the adjustment changes');
|
|
480
527
|
if (targetTrack !== void 0 && scope !== "track") fail(`${path}.targetTrack`, 'is only for scope "track"');
|
|
@@ -577,9 +624,9 @@ function createVideoProject(options = {}) {
|
|
|
577
624
|
// src/video-editor/check.ts
|
|
578
625
|
function videoClipKeyframes(clip) {
|
|
579
626
|
const out = [
|
|
580
|
-
{ property: "opacity", keys:
|
|
581
|
-
{ property: "volume", keys: clip.type === "media" || clip.type === "sequence" ?
|
|
582
|
-
...
|
|
627
|
+
{ property: "opacity", keys: _chunk5T3H7CGGcjs.videoKeysOf.call(void 0, clip.opacity) },
|
|
628
|
+
{ property: "volume", keys: clip.type === "media" || clip.type === "sequence" ? _chunk5T3H7CGGcjs.videoKeysOf.call(void 0, clip.volume) : [] },
|
|
629
|
+
..._chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES.map((p) => ({ property: p, keys: _chunk5T3H7CGGcjs.videoKeysOf.call(void 0, _optionalChain([clip, 'access', _2 => _2.transform, 'optionalAccess', _3 => _3[p]])) }))
|
|
583
630
|
];
|
|
584
631
|
return out.filter((o) => o.keys.length);
|
|
585
632
|
}
|
|
@@ -597,6 +644,7 @@ var VIDEO_ISSUE_CODES = [
|
|
|
597
644
|
"animations-too-long",
|
|
598
645
|
"animation-keyed",
|
|
599
646
|
"keyframes-outside-clip",
|
|
647
|
+
"camera-stale",
|
|
600
648
|
"unknown-duration",
|
|
601
649
|
"unused-asset",
|
|
602
650
|
"unused-sequence",
|
|
@@ -607,8 +655,8 @@ var VIDEO_ISSUE_CODES = [
|
|
|
607
655
|
var videoIssueKey = (i) => [i.code, _nullishCoalesce(i.sequence, () => ( "")), _nullishCoalesce(i.track, () => ( "")), _nullishCoalesce(i.clip, () => ( "")), _nullishCoalesce(i.asset, () => ( "")), _nullishCoalesce(i.marker, () => ( ""))].join("|");
|
|
608
656
|
function checkVideoProject(project) {
|
|
609
657
|
const issues = [];
|
|
610
|
-
const assets =
|
|
611
|
-
const sequences =
|
|
658
|
+
const assets = _chunk5T3H7CGGcjs.videoAssetMap.call(void 0, project);
|
|
659
|
+
const sequences = _chunk5T3H7CGGcjs.videoSequenceMap.call(void 0, project);
|
|
612
660
|
const used = /* @__PURE__ */ new Set();
|
|
613
661
|
const usedSequences = /* @__PURE__ */ new Set();
|
|
614
662
|
const cycles = /* @__PURE__ */ new Map();
|
|
@@ -616,7 +664,7 @@ function checkVideoProject(project) {
|
|
|
616
664
|
if ((asset.kind === "video" || asset.kind === "audio") && asset.duration === void 0)
|
|
617
665
|
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.` });
|
|
618
666
|
const checkTrack = (track, sequence) => {
|
|
619
|
-
const clips =
|
|
667
|
+
const clips = _chunk5T3H7CGGcjs.sortedVideoClips.call(void 0, track);
|
|
620
668
|
const where = sequence ? ` in sequence "${sequence}"` : "";
|
|
621
669
|
for (let i = 0; i < clips.length; i++) {
|
|
622
670
|
const clip = clips[i];
|
|
@@ -626,13 +674,13 @@ function checkVideoProject(project) {
|
|
|
626
674
|
const seq = sequences.get(clip.sequence);
|
|
627
675
|
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.` });
|
|
628
676
|
else {
|
|
629
|
-
if (!cycles.has(seq.id)) cycles.set(seq.id,
|
|
677
|
+
if (!cycles.has(seq.id)) cycles.set(seq.id, _chunk5T3H7CGGcjs.findVideoSequenceCycle.call(void 0, project, seq.id));
|
|
630
678
|
const cycle = cycles.get(seq.id);
|
|
631
679
|
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.` });
|
|
632
|
-
const length =
|
|
633
|
-
const range =
|
|
634
|
-
if (range.out > length +
|
|
635
|
-
issues.push({ code: "source-overrun", severity: "error", ...at, message: `Compound clip "${clip.id}" plays to ${
|
|
680
|
+
const length = _chunk5T3H7CGGcjs.videoSequenceDuration.call(void 0, seq);
|
|
681
|
+
const range = _chunk5T3H7CGGcjs.videoClipSourceRange.call(void 0, clip);
|
|
682
|
+
if (range.out > length + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON)
|
|
683
|
+
issues.push({ code: "source-overrun", severity: "error", ...at, message: `Compound clip "${clip.id}" plays to ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, range.out)} of sequence "${seq.id}", which is only ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, length)} long; shorten the clip or move its in point.` });
|
|
636
684
|
}
|
|
637
685
|
} else if (clip.type === "media") {
|
|
638
686
|
used.add(clip.asset);
|
|
@@ -641,30 +689,41 @@ function checkVideoProject(project) {
|
|
|
641
689
|
else {
|
|
642
690
|
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.` });
|
|
643
691
|
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.` });
|
|
644
|
-
const range =
|
|
645
|
-
if (asset.duration !== void 0 && range.out > asset.duration +
|
|
646
|
-
issues.push({ code: "source-overrun", severity: "error", ...at, message: `Clip "${clip.id}" plays to ${
|
|
692
|
+
const range = _chunk5T3H7CGGcjs.videoClipSourceRange.call(void 0, clip);
|
|
693
|
+
if (asset.duration !== void 0 && range.out > asset.duration + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON)
|
|
694
|
+
issues.push({ code: "source-overrun", severity: "error", ...at, message: `Clip "${clip.id}" plays to ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, range.out)} of "${asset.id}", which is only ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, asset.duration)} long; shorten the clip or move its in point.` });
|
|
647
695
|
}
|
|
648
696
|
} 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.` });
|
|
649
697
|
if (clip.type === "adjustment" && (_nullishCoalesce(clip.scope, () => ( "underneath"))) === "track" && !(sequence ? _nullishCoalesce(_optionalChain([sequences, 'access', _4 => _4.get, 'call', _5 => _5(sequence), 'optionalAccess', _6 => _6.tracks]), () => ( [])) : project.tracks).some((t) => t.id === clip.targetTrack))
|
|
650
698
|
issues.push({ code: "missing-target-track", severity: "warning", ...at, message: `Adjustment clip "${clip.id}" changes track "${clip.targetTrack}", which is not ${sequence ? `in sequence "${sequence}"` : "in the project"}, so it changes nothing; set its targetTrack to a track beside it or change its scope.` });
|
|
651
699
|
const next = clips[i + 1];
|
|
652
|
-
if (next && next.start <
|
|
653
|
-
issues.push({ code: "overlap", severity: "error", ...at, message: `Clips "${clip.id}" and "${next.id}" overlap on track "${track.id}"${where} from ${
|
|
654
|
-
if ((_nullishCoalesce(clip.fadeIn, () => ( 0))) + (_nullishCoalesce(clip.fadeOut, () => ( 0))) > clip.duration +
|
|
700
|
+
if (next && next.start < _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip) - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON)
|
|
701
|
+
issues.push({ code: "overlap", severity: "error", ...at, message: `Clips "${clip.id}" and "${next.id}" overlap on track "${track.id}"${where} from ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, next.start)}; move one of them.` });
|
|
702
|
+
if ((_nullishCoalesce(clip.fadeIn, () => ( 0))) + (_nullishCoalesce(clip.fadeOut, () => ( 0))) > clip.duration + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON)
|
|
655
703
|
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.` });
|
|
656
|
-
const anim = (clip.animateIn ? _nullishCoalesce(clip.animateIn.duration, () => (
|
|
657
|
-
if (anim > clip.duration +
|
|
704
|
+
const anim = (clip.animateIn ? _nullishCoalesce(clip.animateIn.duration, () => ( _chunk5T3H7CGGcjs.VIDEO_CLIP_ANIMATION_DURATION)) : 0) + (clip.animateOut ? _nullishCoalesce(clip.animateOut.duration, () => ( _chunk5T3H7CGGcjs.VIDEO_CLIP_ANIMATION_DURATION)) : 0);
|
|
705
|
+
if (anim > clip.duration + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON)
|
|
658
706
|
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.` });
|
|
659
707
|
for (const which of ["animateIn", "animateOut"]) {
|
|
660
708
|
const a = clip[which];
|
|
661
709
|
if (!a) continue;
|
|
662
|
-
const keyed =
|
|
710
|
+
const keyed = _chunk5T3H7CGGcjs.videoClipAnimationProperties.call(void 0, a).filter((p) => _chunk5T3H7CGGcjs.videoKeysOf.call(void 0, p === "opacity" ? clip.opacity : _optionalChain([clip, 'access', _7 => _7.transform, 'optionalAccess', _8 => _8[p]])).length);
|
|
663
711
|
if (keyed.length)
|
|
664
712
|
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.` });
|
|
665
713
|
}
|
|
714
|
+
if (clip.camera) {
|
|
715
|
+
const last = Math.max(0, ..._chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES.flatMap((p) => _chunk5T3H7CGGcjs.videoKeysOf.call(void 0, _optionalChain([clip, 'access', _9 => _9.transform, 'optionalAccess', _10 => _10[p]])).map((k) => k.t)));
|
|
716
|
+
const frame = 1e3 / (project.fps || 30);
|
|
717
|
+
if (last > 0 && Math.abs(last - clip.duration) > frame + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON)
|
|
718
|
+
issues.push({
|
|
719
|
+
code: "camera-stale",
|
|
720
|
+
severity: "warning",
|
|
721
|
+
...at,
|
|
722
|
+
message: `Clip "${clip.id}"'s camera moves were baked for ${Math.round(last)} ms but the clip is ${Math.round(clip.duration)} ms, so ${last < clip.duration ? "the camera stops early" : "the end of the move is cut off"}; set the move again (set_clip_camera_move) to re-bake it.`
|
|
723
|
+
});
|
|
724
|
+
}
|
|
666
725
|
for (const { property, keys } of videoClipKeyframes(clip)) {
|
|
667
|
-
const outside = keys.filter((k) => k.t < -
|
|
726
|
+
const outside = keys.filter((k) => k.t < -_chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON || k.t > clip.duration + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON);
|
|
668
727
|
if (outside.length)
|
|
669
728
|
issues.push({
|
|
670
729
|
code: "keyframes-outside-clip",
|
|
@@ -675,20 +734,20 @@ function checkVideoProject(project) {
|
|
|
675
734
|
}
|
|
676
735
|
if (clip.transition) {
|
|
677
736
|
const d = clip.transition.duration;
|
|
678
|
-
const before =
|
|
737
|
+
const before = _chunk5T3H7CGGcjs.videoClipBefore.call(void 0, track, clip);
|
|
679
738
|
if (!before) {
|
|
680
739
|
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.` });
|
|
681
740
|
continue;
|
|
682
741
|
}
|
|
683
|
-
if (d > clip.duration +
|
|
742
|
+
if (d > clip.duration + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON || d > before.duration + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) {
|
|
684
743
|
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.` });
|
|
685
744
|
continue;
|
|
686
745
|
}
|
|
687
746
|
if (clip.transition.type === "dip") continue;
|
|
688
|
-
const outgoing =
|
|
689
|
-
const incoming =
|
|
747
|
+
const outgoing = _chunk5T3H7CGGcjs.videoClipHandles.call(void 0, before, assets, sequences).after;
|
|
748
|
+
const incoming = _chunk5T3H7CGGcjs.videoClipHandles.call(void 0, clip, assets, sequences).before;
|
|
690
749
|
const half = d / 2;
|
|
691
|
-
if (outgoing < half -
|
|
750
|
+
if (outgoing < half - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON || incoming < half - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) {
|
|
692
751
|
const fits = 2 * Math.min(outgoing, incoming);
|
|
693
752
|
issues.push({
|
|
694
753
|
code: "transition-handles",
|
|
@@ -705,9 +764,9 @@ function checkVideoProject(project) {
|
|
|
705
764
|
for (const sequence of _nullishCoalesce(project.sequences, () => ( [])))
|
|
706
765
|
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.` });
|
|
707
766
|
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.` });
|
|
708
|
-
const end =
|
|
767
|
+
const end = _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, project);
|
|
709
768
|
for (const marker of _nullishCoalesce(project.markers, () => ( [])))
|
|
710
|
-
if (marker.time > end +
|
|
769
|
+
if (marker.time > end + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) issues.push({ code: "marker-past-end", severity: "note", marker: marker.id, message: `Marker "${marker.id}" at ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, marker.time)} is past the end (${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, end)}).` });
|
|
711
770
|
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." });
|
|
712
771
|
const rank = { error: 0, warning: 1, note: 2 };
|
|
713
772
|
return issues.sort((a, b) => rank[a.severity] - rank[b.severity]);
|
|
@@ -761,7 +820,7 @@ function mergeSpans(spans) {
|
|
|
761
820
|
const out = [];
|
|
762
821
|
for (const [from, to] of [...spans].sort((a, b) => a[0] - b[0])) {
|
|
763
822
|
const last = out[out.length - 1];
|
|
764
|
-
if (last && from <= last[1] +
|
|
823
|
+
if (last && from <= last[1] + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) last[1] = Math.max(last[1], to);
|
|
765
824
|
else out.push([from, to]);
|
|
766
825
|
}
|
|
767
826
|
return out;
|
|
@@ -775,16 +834,16 @@ function clipAnimatables(clip) {
|
|
|
775
834
|
// A speed ramp is keys in clip time too, so trims and splits keep it on the same frames of source.
|
|
776
835
|
{ get: () => c.timeRemap, set: (v) => c.timeRemap = v }
|
|
777
836
|
];
|
|
778
|
-
for (const p of
|
|
837
|
+
for (const p of _chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES) out.push({ get: () => _optionalChain([c, 'access', _11 => _11.transform, 'optionalAccess', _12 => _12[p]]), set: (v) => c.transform && (c.transform[p] = v) });
|
|
779
838
|
return out;
|
|
780
839
|
}
|
|
781
840
|
function retimeClipKeys(clip, fn) {
|
|
782
841
|
for (const a of clipAnimatables(clip)) {
|
|
783
842
|
const v = a.get();
|
|
784
|
-
if (
|
|
843
|
+
if (_chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, v)) a.set(fn(v));
|
|
785
844
|
}
|
|
786
845
|
}
|
|
787
|
-
var OPTIONAL_CLIP_FIELDS = ["name", "effects", "mask", "scope", "targetTrack", "values", "provider", "opacity", "transform", "fit", "blend", "grade", "animateIn", "animateOut", "fadeIn", "fadeOut", "fadeInCurve", "fadeOutCurve", "transition", "in", "speed", "timeRemap", "volume", "muted", "color", "fontSize", "fontFamily", "fontWeight", "background"];
|
|
846
|
+
var OPTIONAL_CLIP_FIELDS = ["name", "effects", "mask", "camera", "scope", "targetTrack", "values", "provider", "opacity", "transform", "fit", "blend", "grade", "animateIn", "animateOut", "fadeIn", "fadeOut", "fadeInCurve", "fadeOutCurve", "transition", "in", "speed", "timeRemap", "volume", "muted", "color", "fontSize", "fontFamily", "fontWeight", "background"];
|
|
788
847
|
var TIME_FIELDS = { slip_clip: ["delta"], roll_edit: ["delta"], slide_clip: ["delta"], lift_range: ["from", "to"], extract_range: ["from", "to"], split_at: ["at"] };
|
|
789
848
|
var Editor = (_class = class {
|
|
790
849
|
constructor(p) {;_class.prototype.__init.call(this);
|
|
@@ -798,8 +857,8 @@ var Editor = (_class = class {
|
|
|
798
857
|
return t;
|
|
799
858
|
}
|
|
800
859
|
clip(id) {
|
|
801
|
-
const at =
|
|
802
|
-
const nested = at ? null :
|
|
860
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, this.p, id);
|
|
861
|
+
const nested = at ? null : _chunk5T3H7CGGcjs.findVideoSequenceClip.call(void 0, this.p, id);
|
|
803
862
|
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).`);
|
|
804
863
|
if (!at) {
|
|
805
864
|
const ids = this.p.tracks.flatMap((t) => t.clips.map((c) => c.id));
|
|
@@ -816,16 +875,16 @@ var Editor = (_class = class {
|
|
|
816
875
|
return a;
|
|
817
876
|
}
|
|
818
877
|
fits(track, start, duration, ignore, what) {
|
|
819
|
-
const hit =
|
|
878
|
+
const hit = _chunk5T3H7CGGcjs.videoOverlap.call(void 0, track, start, start + duration, ignore);
|
|
820
879
|
if (hit) {
|
|
821
|
-
const free =
|
|
822
|
-
refuse(`${what} at ${
|
|
880
|
+
const free = _chunk5T3H7CGGcjs.nextFreeVideoSlot.call(void 0, track, start, duration, ignore);
|
|
881
|
+
refuse(`${what} at ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, start)}\u2013${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, start + duration)} would overlap clip "${hit.id}" (${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, hit.start)}\u2013${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, hit))}) on track "${track.id}"; the next free place is ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, free)}, or use mode "insert" to push later clips along or "overwrite" to replace what is there.`);
|
|
823
882
|
}
|
|
824
883
|
}
|
|
825
884
|
/** An adjustment clip's target track must exist. */
|
|
826
885
|
adjustmentTarget(clip) {
|
|
827
886
|
if (clip.type !== "adjustment" || clip.targetTrack === void 0) return;
|
|
828
|
-
const ids =
|
|
887
|
+
const ids = _chunk5T3H7CGGcjs.allVideoTracks.call(void 0, this.p).map(({ track }) => track.id);
|
|
829
888
|
if (!ids.includes(clip.targetTrack)) refuse(`Adjustment clip "${clip.id}" targets track ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, clip.targetTrack, ids)}, which does not exist; the tracks are ${ids.map((t) => `"${t}"`).join(", ")}.`);
|
|
830
889
|
}
|
|
831
890
|
kindFits(track, clip) {
|
|
@@ -836,19 +895,19 @@ var Editor = (_class = class {
|
|
|
836
895
|
return;
|
|
837
896
|
}
|
|
838
897
|
if (track.kind === "audio" && (clip.type !== "media" || asset.kind === "image")) refuse(`Track "${track.id}" is an audio track; ${clip.type === "media" ? "images" : `${clip.type} clips`} go on a video track.`);
|
|
839
|
-
if (track.kind === "video" && _optionalChain([asset, 'optionalAccess',
|
|
898
|
+
if (track.kind === "video" && _optionalChain([asset, 'optionalAccess', _13 => _13.kind]) === "audio") refuse(`Track "${track.id}" is a video track; audio asset "${asset.id}" goes on an audio track.`);
|
|
840
899
|
}
|
|
841
900
|
/** Moves every clip on `track` starting at or after `from` by `delta`. */
|
|
842
901
|
shift(track, from, delta, except = /* @__PURE__ */ new Set()) {
|
|
843
902
|
if (!delta) return;
|
|
844
|
-
for (const c of track.clips) if (!except.has(c.id) && c.start >= from -
|
|
903
|
+
for (const c of track.clips) if (!except.has(c.id) && c.start >= from - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) c.start = Math.max(0, c.start + delta);
|
|
845
904
|
track.clips.sort((a, b) => a.start - b.start);
|
|
846
905
|
}
|
|
847
906
|
get frame() {
|
|
848
907
|
return 1e3 / this.p.fps;
|
|
849
908
|
}
|
|
850
909
|
ids() {
|
|
851
|
-
return
|
|
910
|
+
return _chunk5T3H7CGGcjs.allVideoClipIds.call(void 0, this.p);
|
|
852
911
|
}
|
|
853
912
|
/**
|
|
854
913
|
* The tracks a ripple on `sources` moves, top to bottom: the sources, and every unlocked
|
|
@@ -856,8 +915,8 @@ var Editor = (_class = class {
|
|
|
856
915
|
*/
|
|
857
916
|
rippleTracks(sources) {
|
|
858
917
|
const set = new Set(sources);
|
|
859
|
-
if ([...set].some(
|
|
860
|
-
for (const t of this.p.tracks) if (
|
|
918
|
+
if ([...set].some(_chunk5T3H7CGGcjs.videoTrackSyncLocked)) {
|
|
919
|
+
for (const t of this.p.tracks) if (_chunk5T3H7CGGcjs.videoTrackSyncLocked.call(void 0, t) && !t.locked) set.add(t);
|
|
861
920
|
}
|
|
862
921
|
return this.p.tracks.filter((t) => set.has(t));
|
|
863
922
|
}
|
|
@@ -874,7 +933,7 @@ var Editor = (_class = class {
|
|
|
874
933
|
return open;
|
|
875
934
|
}
|
|
876
935
|
range(from, to) {
|
|
877
|
-
if (!(to - from >
|
|
936
|
+
if (!(to - from > _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON)) refuse(`"to" (${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, to)}) must be after "from" (${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, from)}).`);
|
|
878
937
|
}
|
|
879
938
|
/** Moves a media or compound clip's in point by `delta` of timeline time (stills, titles and colours have none). */
|
|
880
939
|
moveIn(clip, delta) {
|
|
@@ -883,18 +942,18 @@ var Editor = (_class = class {
|
|
|
883
942
|
if (clip.in < 1e-9) delete clip.in;
|
|
884
943
|
return;
|
|
885
944
|
}
|
|
886
|
-
if (clip.type !== "media" || _optionalChain([
|
|
887
|
-
clip.in = Math.max(0, (_nullishCoalesce(clip.in, () => ( 0))) + delta *
|
|
945
|
+
if (clip.type !== "media" || _optionalChain([_chunk5T3H7CGGcjs.videoAssetMap.call(void 0, this.p), 'access', _14 => _14.get, 'call', _15 => _15(clip.asset), 'optionalAccess', _16 => _16.kind]) === "image") return;
|
|
946
|
+
clip.in = Math.max(0, (_nullishCoalesce(clip.in, () => ( 0))) + delta * _chunk5T3H7CGGcjs.videoClipSpeed.call(void 0, clip));
|
|
888
947
|
if (clip.in < 1e-9) delete clip.in;
|
|
889
948
|
}
|
|
890
949
|
/** Moves a clip's head `delta` later in time (start, in point and keys); the caller sets start and duration. */
|
|
891
950
|
trimHead(clip, delta) {
|
|
892
951
|
if (!isRamped(clip)) this.moveIn(clip, delta);
|
|
893
|
-
retimeClipKeys(clip, (v) =>
|
|
952
|
+
retimeClipKeys(clip, (v) => _chunk5T3H7CGGcjs.retimeVideoAnimatable.call(void 0, v, -delta));
|
|
894
953
|
}
|
|
895
954
|
/** Cuts `clip` at `at` (inside it): the left part keeps the id, the right part is returned. */
|
|
896
955
|
cut(track, clip, at, id) {
|
|
897
|
-
const end =
|
|
956
|
+
const end = _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip);
|
|
898
957
|
const right = { ...structuredClone(clip), id: _nullishCoalesce(id, () => ( freshId(`${clip.id}-`, this.ids()))), start: at, duration: end - at };
|
|
899
958
|
delete right.transition;
|
|
900
959
|
delete right.fadeIn;
|
|
@@ -902,9 +961,9 @@ var Editor = (_class = class {
|
|
|
902
961
|
delete right.animateIn;
|
|
903
962
|
const leftValues = clipAnimatables(clip);
|
|
904
963
|
clipAnimatables(right).forEach((r, i) => {
|
|
905
|
-
const [l, rr] =
|
|
906
|
-
if (
|
|
907
|
-
if (
|
|
964
|
+
const [l, rr] = _chunk5T3H7CGGcjs.splitVideoAnimatable.call(void 0, leftValues[i].get(), at - clip.start);
|
|
965
|
+
if (_chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, l)) leftValues[i].set(l);
|
|
966
|
+
if (_chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, rr)) r.set(rr);
|
|
908
967
|
});
|
|
909
968
|
if (!isRamped(right)) this.moveIn(right, at - clip.start);
|
|
910
969
|
clip.duration = at - clip.start;
|
|
@@ -918,7 +977,7 @@ var Editor = (_class = class {
|
|
|
918
977
|
/** Cuts every clip on `tracks` that runs across `at`; returns the new right-hand parts. */
|
|
919
978
|
cutAcross(tracks, at) {
|
|
920
979
|
const made = [];
|
|
921
|
-
for (const t of tracks) for (const c of [...t.clips]) if (c.start < at -
|
|
980
|
+
for (const t of tracks) for (const c of [...t.clips]) if (c.start < at - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON && _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c) > at + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) made.push(this.cut(t, c, at));
|
|
922
981
|
return made;
|
|
923
982
|
}
|
|
924
983
|
/**
|
|
@@ -936,10 +995,10 @@ var Editor = (_class = class {
|
|
|
936
995
|
*/
|
|
937
996
|
close(tracks, from, to) {
|
|
938
997
|
for (const t of tracks) {
|
|
939
|
-
const hit =
|
|
998
|
+
const hit = _chunk5T3H7CGGcjs.videoOverlap.call(void 0, t, from, to);
|
|
940
999
|
if (hit)
|
|
941
1000
|
refuse(
|
|
942
|
-
`Rippling out ${
|
|
1001
|
+
`Rippling out ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, from)}\u2013${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, to)} would pull track "${t.id}" out of sync: clip "${hit.id}" (${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, hit.start)}\u2013${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, _chunk5T3H7CGGcjs.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.`
|
|
943
1002
|
);
|
|
944
1003
|
}
|
|
945
1004
|
for (const t of tracks) this.shift(t, to, from - to);
|
|
@@ -951,10 +1010,10 @@ var Editor = (_class = class {
|
|
|
951
1010
|
clear(track, from, to, report) {
|
|
952
1011
|
for (const c of [...track.clips]) {
|
|
953
1012
|
const start = c.start;
|
|
954
|
-
const end =
|
|
955
|
-
if (end <= from +
|
|
956
|
-
const coversHead = start >= from -
|
|
957
|
-
const coversTail = end <= to +
|
|
1013
|
+
const end = _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c);
|
|
1014
|
+
if (end <= from + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON || start >= to - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) continue;
|
|
1015
|
+
const coversHead = start >= from - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON;
|
|
1016
|
+
const coversTail = end <= to + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON;
|
|
958
1017
|
if (coversHead && coversTail) {
|
|
959
1018
|
track.clips = track.clips.filter((x) => x !== c);
|
|
960
1019
|
report.removed.push(c.id);
|
|
@@ -977,8 +1036,8 @@ var Editor = (_class = class {
|
|
|
977
1036
|
/** Clamps a slip, roll or slide to `[lo, hi]`, refusing when it cannot move that way at all. */
|
|
978
1037
|
clamp(delta, lo, hi, why) {
|
|
979
1038
|
const applied = Math.min(Math.max(delta, Math.min(0, lo)), Math.max(0, hi));
|
|
980
|
-
if (Math.abs(delta) >
|
|
981
|
-
return Math.abs(applied) <=
|
|
1039
|
+
if (Math.abs(delta) > _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON && Math.abs(applied) <= _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) refuse(why());
|
|
1040
|
+
return Math.abs(applied) <= _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON ? 0 : applied;
|
|
982
1041
|
}
|
|
983
1042
|
/** Places a clip on a track by `mode`, returning what it cut, trimmed, removed and rippled. */
|
|
984
1043
|
place(track, clip, mode, outcome) {
|
|
@@ -988,14 +1047,14 @@ var Editor = (_class = class {
|
|
|
988
1047
|
outcome.rippled = tracks.map((t) => t.id);
|
|
989
1048
|
} else if (mode === "overwrite") {
|
|
990
1049
|
const report = { removed: [], trimmed: [], created: [] };
|
|
991
|
-
this.clear(track, clip.start,
|
|
1050
|
+
this.clear(track, clip.start, _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip), report);
|
|
992
1051
|
Object.assign(outcome, report);
|
|
993
1052
|
} else this.fits(track, clip.start, clip.duration, /* @__PURE__ */ new Set([clip.id]), `Clip "${clip.id}"`);
|
|
994
1053
|
track.clips.push(clip);
|
|
995
1054
|
track.clips.sort((a, b) => a.start - b.start);
|
|
996
1055
|
}
|
|
997
1056
|
placement(mode, ripple) {
|
|
998
|
-
if (mode !== void 0 && !
|
|
1057
|
+
if (mode !== void 0 && !_chunk5T3H7CGGcjs.VIDEO_PLACEMENT_MODES.includes(mode)) refuse(`"mode" must be ${_chunk5T3H7CGGcjs.VIDEO_PLACEMENT_MODES.map((m) => `"${m}"`).join(", ")}.`);
|
|
999
1058
|
if (ripple && mode !== void 0 && mode !== "insert") refuse(`"ripple" means mode "insert", so it cannot go with mode "${mode}"; pass one or the other.`);
|
|
1000
1059
|
return _nullishCoalesce(mode, () => ( (ripple ? "insert" : "refuse")));
|
|
1001
1060
|
}
|
|
@@ -1032,7 +1091,7 @@ var Editor = (_class = class {
|
|
|
1032
1091
|
}
|
|
1033
1092
|
case "remove_asset": {
|
|
1034
1093
|
const asset = this.asset(e.asset);
|
|
1035
|
-
const users =
|
|
1094
|
+
const users = _chunk5T3H7CGGcjs.allVideoTracks.call(void 0, this.p).flatMap(({ track: t }) => t.clips.filter((c) => c.type === "media" && c.asset === asset.id).map((c) => c.id));
|
|
1036
1095
|
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.`);
|
|
1037
1096
|
this.p.assets = this.p.assets.filter((a) => a !== asset);
|
|
1038
1097
|
return this.outcomes.push({ op: e.op, asset: asset.id });
|
|
@@ -1085,12 +1144,12 @@ var Editor = (_class = class {
|
|
|
1085
1144
|
else draft.duration = (asset.duration - (_nullishCoalesce(draft.in, () => ( 0)))) / (_nullishCoalesce(draft.speed, () => ( 1)));
|
|
1086
1145
|
if (!(draft.duration > 0)) refuse(`"in" (${draft.in} ms) is at or past the end of "${asset.id}" (${asset.duration} ms).`);
|
|
1087
1146
|
} else if (draft.type === "sequence") {
|
|
1088
|
-
const length =
|
|
1147
|
+
const length = _chunk5T3H7CGGcjs.videoSequenceDuration.call(void 0, _chunk5T3H7CGGcjs.videoSequenceMap.call(void 0, this.p).get(draft.sequence)) - (_nullishCoalesce(draft.in, () => ( 0)));
|
|
1089
1148
|
if (!(length > 0)) refuse(`"in" (${_nullishCoalesce(draft.in, () => ( 0))} ms) is at or past the end of sequence "${draft.sequence}".`);
|
|
1090
1149
|
draft.duration = length;
|
|
1091
1150
|
} else draft.duration = VIDEO_DEFAULT_TITLE_DURATION;
|
|
1092
1151
|
}
|
|
1093
|
-
const end =
|
|
1152
|
+
const end = _chunk5T3H7CGGcjs.sortedVideoClips.call(void 0, track).reduce((m, c) => Math.max(m, _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c)), 0);
|
|
1094
1153
|
draft.start ??= end;
|
|
1095
1154
|
const clip = parseVideoClip(draft, "clip");
|
|
1096
1155
|
this.adjustmentTarget(clip);
|
|
@@ -1116,20 +1175,20 @@ var Editor = (_class = class {
|
|
|
1116
1175
|
case "trim_clip": {
|
|
1117
1176
|
const { track, clip } = this.clip(e.clip);
|
|
1118
1177
|
this.unlocked(track);
|
|
1119
|
-
const speed =
|
|
1120
|
-
const end =
|
|
1178
|
+
const speed = _chunk5T3H7CGGcjs.videoClipSpeed.call(void 0, clip);
|
|
1179
|
+
const end = _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip);
|
|
1121
1180
|
const minimum = 1e3 / this.p.fps;
|
|
1122
|
-
const assets =
|
|
1181
|
+
const assets = _chunk5T3H7CGGcjs.videoAssetMap.call(void 0, this.p);
|
|
1123
1182
|
if (e.edge === "start") {
|
|
1124
1183
|
const delta = e.to - clip.start;
|
|
1125
|
-
if (clip.duration - delta < minimum -
|
|
1184
|
+
if (clip.duration - delta < minimum - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) refuse(`Trimming the start to ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, e.to)} would leave "${clip.id}" shorter than a frame; it ends at ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, end)}.`);
|
|
1126
1185
|
if (clip.type === "media" && !isRamped(clip) || clip.type === "sequence") {
|
|
1127
1186
|
const sourceIn = (_nullishCoalesce(clip.in, () => ( 0))) + delta * speed;
|
|
1128
|
-
if (sourceIn < -
|
|
1187
|
+
if (sourceIn < -_chunk5T3H7CGGcjs.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 ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, clip.start - (_nullishCoalesce(clip.in, () => ( 0))) / speed)}).`);
|
|
1129
1188
|
clip.in = Math.max(0, sourceIn);
|
|
1130
1189
|
if (clip.in === 0) delete clip.in;
|
|
1131
1190
|
}
|
|
1132
|
-
retimeClipKeys(clip, (v) =>
|
|
1191
|
+
retimeClipKeys(clip, (v) => _chunk5T3H7CGGcjs.retimeVideoAnimatable.call(void 0, v, -delta));
|
|
1133
1192
|
if (e.ripple) {
|
|
1134
1193
|
const tracks = this.rippleTracks([track]);
|
|
1135
1194
|
if (delta > 0) {
|
|
@@ -1150,17 +1209,17 @@ var Editor = (_class = class {
|
|
|
1150
1209
|
}
|
|
1151
1210
|
} else {
|
|
1152
1211
|
const duration = e.to - clip.start;
|
|
1153
|
-
if (duration < minimum -
|
|
1212
|
+
if (duration < minimum - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) refuse(`Trimming the end to ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, e.to)} would leave "${clip.id}" shorter than a frame; it starts at ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, clip.start)}.`);
|
|
1154
1213
|
if (clip.type === "media" && !isRamped(clip)) {
|
|
1155
1214
|
const asset = assets.get(clip.asset);
|
|
1156
1215
|
const out = (_nullishCoalesce(clip.in, () => ( 0))) + duration * speed;
|
|
1157
|
-
if (_optionalChain([asset, 'optionalAccess',
|
|
1158
|
-
refuse(`"${clip.id}" can end at most at ${
|
|
1216
|
+
if (_optionalChain([asset, 'optionalAccess', _17 => _17.duration]) !== void 0 && out > asset.duration + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON)
|
|
1217
|
+
refuse(`"${clip.id}" can end at most at ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, clip.start + (asset.duration - (_nullishCoalesce(clip.in, () => ( 0)))) / speed)}, where "${asset.id}" runs out.`);
|
|
1159
1218
|
}
|
|
1160
1219
|
if (clip.type === "sequence") {
|
|
1161
|
-
const seq =
|
|
1162
|
-
const length = seq ?
|
|
1163
|
-
if ((_nullishCoalesce(clip.in, () => ( 0))) + duration > length +
|
|
1220
|
+
const seq = _chunk5T3H7CGGcjs.videoSequenceMap.call(void 0, this.p).get(clip.sequence);
|
|
1221
|
+
const length = seq ? _chunk5T3H7CGGcjs.videoSequenceDuration.call(void 0, seq) : Infinity;
|
|
1222
|
+
if ((_nullishCoalesce(clip.in, () => ( 0))) + duration > length + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) refuse(`"${clip.id}" can end at most at ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, clip.start + length - (_nullishCoalesce(clip.in, () => ( 0))))}, where sequence "${clip.sequence}" ends.`);
|
|
1164
1223
|
}
|
|
1165
1224
|
if (e.ripple) {
|
|
1166
1225
|
const tracks = this.rippleTracks([track]);
|
|
@@ -1182,9 +1241,9 @@ var Editor = (_class = class {
|
|
|
1182
1241
|
case "split_clip": {
|
|
1183
1242
|
const { track, clip } = this.clip(e.clip);
|
|
1184
1243
|
this.unlocked(track);
|
|
1185
|
-
const end =
|
|
1244
|
+
const end = _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip);
|
|
1186
1245
|
const minimum = 1e3 / this.p.fps;
|
|
1187
|
-
if (e.at < clip.start + minimum -
|
|
1246
|
+
if (e.at < clip.start + minimum - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON || e.at > end - minimum + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) refuse(`${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, e.at)} is not inside "${clip.id}" (${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, clip.start)}\u2013${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, end)}), at least a frame from either end.`);
|
|
1188
1247
|
if (e.id !== void 0 && this.ids().includes(e.id)) refuse(`There is already a clip "${e.id}".`);
|
|
1189
1248
|
const right = this.cut(track, clip, e.at, e.id);
|
|
1190
1249
|
return this.outcomes.push({ op: e.op, clips: [clip.id, right.id], clip: right.id, track: track.id });
|
|
@@ -1195,12 +1254,12 @@ var Editor = (_class = class {
|
|
|
1195
1254
|
for (const track of new Set(found.map((f) => f.track))) track.clips = track.clips.filter((c) => !found.some((f) => f.clip === c));
|
|
1196
1255
|
if (!e.ripple) return this.outcomes.push({ op: e.op, clips: found.map((f) => f.clip.id) });
|
|
1197
1256
|
const rippled = /* @__PURE__ */ new Set();
|
|
1198
|
-
const groups = [...new Set(found.map((f) => f.track))].filter((t) => !
|
|
1199
|
-
if (found.some((f) =>
|
|
1257
|
+
const groups = [...new Set(found.map((f) => f.track))].filter((t) => !_chunk5T3H7CGGcjs.videoTrackSyncLocked.call(void 0, t)).map((t) => [t]);
|
|
1258
|
+
if (found.some((f) => _chunk5T3H7CGGcjs.videoTrackSyncLocked.call(void 0, f.track))) groups.push(found.filter((f) => _chunk5T3H7CGGcjs.videoTrackSyncLocked.call(void 0, f.track)).map((f) => f.track));
|
|
1200
1259
|
for (const sources of groups) {
|
|
1201
1260
|
const tracks = this.rippleTracks(sources);
|
|
1202
1261
|
tracks.forEach((t) => rippled.add(t));
|
|
1203
|
-
const spans = mergeSpans(found.filter((f) => sources.includes(f.track)).map((f) => [f.clip.start,
|
|
1262
|
+
const spans = mergeSpans(found.filter((f) => sources.includes(f.track)).map((f) => [f.clip.start, _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, f.clip)]));
|
|
1204
1263
|
for (const [from, to] of spans.reverse()) this.close(tracks, from, to);
|
|
1205
1264
|
}
|
|
1206
1265
|
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) });
|
|
@@ -1216,15 +1275,15 @@ var Editor = (_class = class {
|
|
|
1216
1275
|
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.");
|
|
1217
1276
|
let stretch = 1;
|
|
1218
1277
|
if (at.clip.type === "media" && !("duration" in set)) {
|
|
1219
|
-
const was =
|
|
1220
|
-
const now = "speed" in set ? set.speed : _optionalChain([e, 'access',
|
|
1278
|
+
const was = _chunk5T3H7CGGcjs.videoClipSpeed.call(void 0, at.clip);
|
|
1279
|
+
const now = "speed" in set ? set.speed : _optionalChain([e, 'access', _18 => _18.remove, 'optionalAccess', _19 => _19.includes, 'call', _20 => _20("speed")]) ? 1 : was;
|
|
1221
1280
|
if (now !== was) {
|
|
1222
1281
|
set.duration = at.clip.duration * was / now;
|
|
1223
1282
|
stretch = was / now;
|
|
1224
1283
|
}
|
|
1225
1284
|
}
|
|
1226
1285
|
const next = { ...structuredClone(at.clip), ...set };
|
|
1227
|
-
if (stretch !== 1) retimeClipKeys(next, (v) =>
|
|
1286
|
+
if (stretch !== 1) retimeClipKeys(next, (v) => _chunk5T3H7CGGcjs.retimeVideoAnimatable.call(void 0, v, 0, stretch));
|
|
1228
1287
|
for (const k of _nullishCoalesce(e.remove, () => ( []))) delete next[k];
|
|
1229
1288
|
const clip = parseVideoClip(next, "set");
|
|
1230
1289
|
this.adjustmentTarget(clip);
|
|
@@ -1238,17 +1297,17 @@ var Editor = (_class = class {
|
|
|
1238
1297
|
const { track, clip } = this.clip(e.clip);
|
|
1239
1298
|
this.unlocked(track);
|
|
1240
1299
|
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.`);
|
|
1241
|
-
if (clip.type !== "media") refuse(`Clip "${clip.id}" is a ${
|
|
1300
|
+
if (clip.type !== "media") refuse(`Clip "${clip.id}" is a ${_chunk5T3H7CGGcjs.videoClipTypeLabel.call(void 0, clip)}, so it has no source to ramp; only video and audio clips change speed.`);
|
|
1242
1301
|
const asset = this.asset(clip.asset);
|
|
1243
1302
|
if (asset.kind === "image") refuse(`Clip "${clip.id}" is a still ("${asset.id}"), so it has no motion to ramp.`);
|
|
1244
1303
|
const media = clip;
|
|
1245
|
-
const end =
|
|
1304
|
+
const end = _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, media);
|
|
1246
1305
|
const duration = _nullishCoalesce(e.duration, () => ( media.duration));
|
|
1247
|
-
if (!(duration >= 1e3 / this.p.fps -
|
|
1306
|
+
if (!(duration >= 1e3 / this.p.fps - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON)) refuse(`"duration" must be at least a frame (${Math.ceil(1e3 / this.p.fps)} ms).`);
|
|
1248
1307
|
if (e.keys === null) {
|
|
1249
1308
|
if (!media.timeRemap) refuse(`Clip "${clip.id}" has no speed ramp to remove.`);
|
|
1250
1309
|
const from = (_nullishCoalesce(media.in, () => ( 0))) + media.timeRemap.keys[0].v;
|
|
1251
|
-
if (asset.duration !== void 0 && from + duration > asset.duration +
|
|
1310
|
+
if (asset.duration !== void 0 && from + duration > asset.duration + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON)
|
|
1252
1311
|
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.`);
|
|
1253
1312
|
delete media.timeRemap;
|
|
1254
1313
|
media.in = from;
|
|
@@ -1256,17 +1315,17 @@ var Editor = (_class = class {
|
|
|
1256
1315
|
} else {
|
|
1257
1316
|
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).');
|
|
1258
1317
|
const remap = parseVideoTimeRemap({ keys: e.keys }, void 0, "keys");
|
|
1259
|
-
remap.keys =
|
|
1260
|
-
|
|
1261
|
-
const span =
|
|
1262
|
-
if (asset.duration !== void 0 && (_nullishCoalesce(media.in, () => ( 0))) + span.to > asset.duration +
|
|
1318
|
+
remap.keys = _chunk5T3H7CGGcjs.sortVideoKeys.call(void 0, remap.keys, { jumps: false });
|
|
1319
|
+
_chunk5T3H7CGGcjs.checkVideoTimeRemap.call(void 0, remap, "keys");
|
|
1320
|
+
const span = _chunk5T3H7CGGcjs.videoTimeRemapSpan.call(void 0, remap);
|
|
1321
|
+
if (asset.duration !== void 0 && (_nullishCoalesce(media.in, () => ( 0))) + span.to > asset.duration + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON)
|
|
1263
1322
|
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.`);
|
|
1264
1323
|
media.timeRemap = remap;
|
|
1265
1324
|
delete media.speed;
|
|
1266
1325
|
}
|
|
1267
1326
|
const newEnd = media.start + duration;
|
|
1268
1327
|
const outcome = { op: e.op, clip: clip.id, track: track.id };
|
|
1269
|
-
if (Math.abs(newEnd - end) >
|
|
1328
|
+
if (Math.abs(newEnd - end) > _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) {
|
|
1270
1329
|
if (e.ripple) {
|
|
1271
1330
|
const tracks = this.rippleTracks([track]);
|
|
1272
1331
|
if (newEnd < end) {
|
|
@@ -1295,11 +1354,11 @@ var Editor = (_class = class {
|
|
|
1295
1354
|
case "slip_clip": {
|
|
1296
1355
|
const { track, clip } = this.clip(e.clip);
|
|
1297
1356
|
this.unlocked(track);
|
|
1298
|
-
if (clip.type !== "media" && clip.type !== "sequence") refuse(`Clip "${clip.id}" is a ${
|
|
1357
|
+
if (clip.type !== "media" && clip.type !== "sequence") refuse(`Clip "${clip.id}" is a ${_chunk5T3H7CGGcjs.videoClipTypeLabel.call(void 0, clip)}, so it has no source to slip; only video, audio and compound clips slip.`);
|
|
1299
1358
|
const source = clip.type === "sequence" ? `sequence "${clip.sequence}"` : `"${this.asset(clip.asset).id}"`;
|
|
1300
1359
|
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.`);
|
|
1301
|
-
const handles =
|
|
1302
|
-
const { lead, tail } =
|
|
1360
|
+
const handles = _chunk5T3H7CGGcjs.videoClipHandles.call(void 0, clip, _chunk5T3H7CGGcjs.videoAssetMap.call(void 0, this.p), _chunk5T3H7CGGcjs.videoSequenceMap.call(void 0, this.p));
|
|
1361
|
+
const { lead, tail } = _chunk5T3H7CGGcjs.videoClipOverhang.call(void 0, track, clip);
|
|
1303
1362
|
const delta = this.clamp(
|
|
1304
1363
|
e.delta,
|
|
1305
1364
|
lead - handles.before,
|
|
@@ -1317,13 +1376,13 @@ var Editor = (_class = class {
|
|
|
1317
1376
|
this.unlocked(track);
|
|
1318
1377
|
const L = left.clip;
|
|
1319
1378
|
const R = right.clip;
|
|
1320
|
-
if (Math.abs(
|
|
1321
|
-
if (Math.abs(
|
|
1322
|
-
refuse(`"${L.id}" ends at ${
|
|
1379
|
+
if (Math.abs(_chunk5T3H7CGGcjs.videoClipEnd.call(void 0, L) - R.start) > _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) {
|
|
1380
|
+
if (Math.abs(_chunk5T3H7CGGcjs.videoClipEnd.call(void 0, R) - L.start) <= _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) refuse(`"${R.id}" comes before "${L.id}"; pass left "${R.id}" and right "${L.id}".`);
|
|
1381
|
+
refuse(`"${L.id}" ends at ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, L))} but "${R.id}" starts at ${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, R.start)}; a roll needs two clips that meet at a cut (use trim_clip to move one edge).`);
|
|
1323
1382
|
}
|
|
1324
|
-
const assets =
|
|
1325
|
-
const lo = Math.max(-(L.duration - this.frame), -(
|
|
1326
|
-
const hi = Math.min(R.duration - this.frame,
|
|
1383
|
+
const assets = _chunk5T3H7CGGcjs.videoAssetMap.call(void 0, this.p);
|
|
1384
|
+
const lo = Math.max(-(L.duration - this.frame), -(_chunk5T3H7CGGcjs.videoClipHandles.call(void 0, R, assets, _chunk5T3H7CGGcjs.videoSequenceMap.call(void 0, this.p)).before - _chunk5T3H7CGGcjs.videoClipOverhang.call(void 0, track, R).lead));
|
|
1385
|
+
const hi = Math.min(R.duration - this.frame, _chunk5T3H7CGGcjs.videoClipHandles.call(void 0, L, assets, _chunk5T3H7CGGcjs.videoSequenceMap.call(void 0, this.p)).after - _chunk5T3H7CGGcjs.videoClipOverhang.call(void 0, track, L).tail);
|
|
1327
1386
|
const delta = this.clamp(
|
|
1328
1387
|
e.delta,
|
|
1329
1388
|
lo,
|
|
@@ -1339,18 +1398,18 @@ var Editor = (_class = class {
|
|
|
1339
1398
|
case "slide_clip": {
|
|
1340
1399
|
const { track, clip } = this.clip(e.clip);
|
|
1341
1400
|
this.unlocked(track);
|
|
1342
|
-
const before =
|
|
1343
|
-
const after =
|
|
1401
|
+
const before = _chunk5T3H7CGGcjs.videoClipBefore.call(void 0, track, clip);
|
|
1402
|
+
const after = _chunk5T3H7CGGcjs.videoClipAfter.call(void 0, track, clip);
|
|
1344
1403
|
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.`);
|
|
1345
|
-
const assets =
|
|
1346
|
-
const end =
|
|
1404
|
+
const assets = _chunk5T3H7CGGcjs.videoAssetMap.call(void 0, this.p);
|
|
1405
|
+
const end = _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip);
|
|
1347
1406
|
const others = track.clips.filter((c) => c !== clip);
|
|
1348
1407
|
const room = {
|
|
1349
|
-
earlier: before ? before.duration - this.frame : clip.start - others.filter((c) =>
|
|
1350
|
-
later: after ? after.duration - this.frame : others.filter((c) => c.start >= end -
|
|
1408
|
+
earlier: before ? before.duration - this.frame : clip.start - others.filter((c) => _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c) <= clip.start + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON).reduce((m, c) => Math.max(m, _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c)), 0),
|
|
1409
|
+
later: after ? after.duration - this.frame : others.filter((c) => c.start >= end - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON).reduce((m, c) => Math.min(m, c.start - end), Infinity)
|
|
1351
1410
|
};
|
|
1352
|
-
const lo = -Math.min(room.earlier, after ?
|
|
1353
|
-
const hi = Math.min(room.later, before ?
|
|
1411
|
+
const lo = -Math.min(room.earlier, after ? _chunk5T3H7CGGcjs.videoClipHandles.call(void 0, after, assets, _chunk5T3H7CGGcjs.videoSequenceMap.call(void 0, this.p)).before - _chunk5T3H7CGGcjs.videoClipOverhang.call(void 0, track, after).lead : Infinity);
|
|
1412
|
+
const hi = Math.min(room.later, before ? _chunk5T3H7CGGcjs.videoClipHandles.call(void 0, before, assets, _chunk5T3H7CGGcjs.videoSequenceMap.call(void 0, this.p)).after - _chunk5T3H7CGGcjs.videoClipOverhang.call(void 0, track, before).tail : Infinity);
|
|
1354
1413
|
const delta = this.clamp(
|
|
1355
1414
|
e.delta,
|
|
1356
1415
|
lo,
|
|
@@ -1365,7 +1424,7 @@ var Editor = (_class = class {
|
|
|
1365
1424
|
this.trimHead(after, delta);
|
|
1366
1425
|
}
|
|
1367
1426
|
track.clips.sort((a, b) => a.start - b.start);
|
|
1368
|
-
return this.outcomes.push({ op: e.op, clip: clip.id, clips: [_optionalChain([before, 'optionalAccess',
|
|
1427
|
+
return this.outcomes.push({ op: e.op, clip: clip.id, clips: [_optionalChain([before, 'optionalAccess', _21 => _21.id]), clip.id, _optionalChain([after, 'optionalAccess', _22 => _22.id])].filter((x) => !!x), track: track.id, delta });
|
|
1369
1428
|
}
|
|
1370
1429
|
case "lift_range":
|
|
1371
1430
|
case "extract_range": {
|
|
@@ -1383,29 +1442,29 @@ var Editor = (_class = class {
|
|
|
1383
1442
|
}
|
|
1384
1443
|
case "split_at": {
|
|
1385
1444
|
const tracks = this.rangeTracks(e.tracks);
|
|
1386
|
-
const lefts = tracks.flatMap((t) => t.clips.filter((c) => c.start < e.at -
|
|
1387
|
-
if (!lefts.length) refuse(`No clip runs across ${
|
|
1445
|
+
const lefts = tracks.flatMap((t) => t.clips.filter((c) => c.start < e.at - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON && _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c) > e.at + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON).map((c) => c.id));
|
|
1446
|
+
if (!lefts.length) refuse(`No clip runs across ${_chunk5T3H7CGGcjs.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.`);
|
|
1388
1447
|
const created = this.cutAcross(tracks, e.at).map((c) => c.id);
|
|
1389
1448
|
return this.outcomes.push({ op: e.op, clips: lefts, created });
|
|
1390
1449
|
}
|
|
1391
1450
|
case "set_keyframes": {
|
|
1392
1451
|
const { track, clip } = this.clip(e.clip);
|
|
1393
1452
|
this.unlocked(track);
|
|
1394
|
-
if (!
|
|
1453
|
+
if (!_chunk5T3H7CGGcjs.VIDEO_KEYFRAME_PROPERTIES.includes(e.property)) refuse(`"${e.property}" cannot be keyframed; use one of ${_chunk5T3H7CGGcjs.VIDEO_KEYFRAME_PROPERTIES.join(", ")}.`);
|
|
1395
1454
|
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.`);
|
|
1396
|
-
const limits =
|
|
1397
|
-
const transform =
|
|
1455
|
+
const limits = _chunk5T3H7CGGcjs.VIDEO_KEYFRAME_LIMITS[e.property];
|
|
1456
|
+
const transform = _chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES.includes(e.property);
|
|
1398
1457
|
const c = clip;
|
|
1399
|
-
const current = transform ? _optionalChain([c, 'access',
|
|
1458
|
+
const current = transform ? _optionalChain([c, 'access', _23 => _23.transform, 'optionalAccess', _24 => _24[e.property]]) : c[e.property];
|
|
1400
1459
|
let value;
|
|
1401
1460
|
if (e.keys === null) {
|
|
1402
|
-
const v =
|
|
1403
|
-
value =
|
|
1461
|
+
const v = _chunk5T3H7CGGcjs.videoValueAt.call(void 0, current, 0, limits.default);
|
|
1462
|
+
value = _chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, current) ? v === limits.default ? void 0 : v : current;
|
|
1404
1463
|
} else {
|
|
1405
1464
|
if (!Array.isArray(e.keys) || !e.keys.length) refuse('"keys" must list at least one key { t, v }; pass null to remove the keyframes.');
|
|
1406
1465
|
let sorted = [];
|
|
1407
1466
|
try {
|
|
1408
|
-
sorted =
|
|
1467
|
+
sorted = _chunk5T3H7CGGcjs.sortVideoKeys.call(void 0, e.keys);
|
|
1409
1468
|
} catch (error) {
|
|
1410
1469
|
refuse(error.message);
|
|
1411
1470
|
}
|
|
@@ -1424,12 +1483,12 @@ var Editor = (_class = class {
|
|
|
1424
1483
|
this.unlocked(track);
|
|
1425
1484
|
let at = 0;
|
|
1426
1485
|
const moved = [];
|
|
1427
|
-
for (const clip of
|
|
1428
|
-
if (clip.start >= (_nullishCoalesce(e.from, () => ( 0))) -
|
|
1486
|
+
for (const clip of _chunk5T3H7CGGcjs.sortedVideoClips.call(void 0, track)) {
|
|
1487
|
+
if (clip.start >= (_nullishCoalesce(e.from, () => ( 0))) - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON && clip.start > at + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) {
|
|
1429
1488
|
clip.start = Math.max(at, _nullishCoalesce(e.from, () => ( 0)));
|
|
1430
1489
|
moved.push(clip.id);
|
|
1431
1490
|
}
|
|
1432
|
-
at = Math.max(at,
|
|
1491
|
+
at = Math.max(at, _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip));
|
|
1433
1492
|
}
|
|
1434
1493
|
return this.outcomes.push({ op: e.op, track: track.id, clips: moved });
|
|
1435
1494
|
}
|
|
@@ -1478,7 +1537,7 @@ function applyVideoEdits(project, edits) {
|
|
|
1478
1537
|
editor.run(edit);
|
|
1479
1538
|
} catch (error) {
|
|
1480
1539
|
const message = error.message;
|
|
1481
|
-
return { ok: false, error: `${list.length > 1 ? `op ${i + 1} (${_optionalChain([edit, 'optionalAccess',
|
|
1540
|
+
return { ok: false, error: `${list.length > 1 ? `op ${i + 1} (${_optionalChain([edit, 'optionalAccess', _25 => _25.op])}): ` : ""}${message}${/Nothing was changed\.$/.test(message) ? "" : " Nothing was changed."}` };
|
|
1482
1541
|
}
|
|
1483
1542
|
}
|
|
1484
1543
|
let next;
|
|
@@ -1559,24 +1618,24 @@ function videoTranscriptTrack(project, track) {
|
|
|
1559
1618
|
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(", ")}.`);
|
|
1560
1619
|
return track;
|
|
1561
1620
|
}
|
|
1562
|
-
const assets =
|
|
1563
|
-
const transcribed = (t) => t.clips.some((c) => c.type === "media" && _optionalChain([assets, 'access',
|
|
1564
|
-
return _nullishCoalesce(_optionalChain([(_nullishCoalesce(project.tracks.find((t) => t.kind === "audio" && transcribed(t)), () => ( project.tracks.find(transcribed)))), 'optionalAccess',
|
|
1621
|
+
const assets = _chunk5T3H7CGGcjs.videoAssetMap.call(void 0, project);
|
|
1622
|
+
const transcribed = (t) => t.clips.some((c) => c.type === "media" && _optionalChain([assets, 'access', _26 => _26.get, 'call', _27 => _27(c.asset), 'optionalAccess', _28 => _28.transcript, 'optionalAccess', _29 => _29.length]));
|
|
1623
|
+
return _nullishCoalesce(_optionalChain([(_nullishCoalesce(project.tracks.find((t) => t.kind === "audio" && transcribed(t)), () => ( project.tracks.find(transcribed)))), 'optionalAccess', _30 => _30.id]), () => ( null));
|
|
1565
1624
|
}
|
|
1566
1625
|
function videoTimelineTranscript(project, options = {}) {
|
|
1567
1626
|
const id = videoTranscriptTrack(project, options.track);
|
|
1568
1627
|
if (!id) return [];
|
|
1569
1628
|
const track = project.tracks.find((t) => t.id === id);
|
|
1570
|
-
const assets =
|
|
1629
|
+
const assets = _chunk5T3H7CGGcjs.videoAssetMap.call(void 0, project);
|
|
1571
1630
|
const out = [];
|
|
1572
|
-
for (const clip of
|
|
1631
|
+
for (const clip of _chunk5T3H7CGGcjs.sortedVideoClips.call(void 0, track)) {
|
|
1573
1632
|
if (clip.type !== "media") continue;
|
|
1574
|
-
const words = _optionalChain([assets, 'access',
|
|
1575
|
-
if (!_optionalChain([words, 'optionalAccess',
|
|
1576
|
-
const speed =
|
|
1633
|
+
const words = _optionalChain([assets, 'access', _31 => _31.get, 'call', _32 => _32(clip.asset), 'optionalAccess', _33 => _33.transcript]);
|
|
1634
|
+
if (!_optionalChain([words, 'optionalAccess', _34 => _34.length])) continue;
|
|
1635
|
+
const speed = _chunk5T3H7CGGcjs.videoClipSpeed.call(void 0, clip);
|
|
1577
1636
|
const from = _nullishCoalesce(clip.in, () => ( 0));
|
|
1578
1637
|
const to = from + clip.duration * speed;
|
|
1579
|
-
const toTimeline = (s) => Math.min(
|
|
1638
|
+
const toTimeline = (s) => Math.min(_chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip), Math.max(clip.start, clip.start + (s - from) / speed));
|
|
1580
1639
|
words.forEach((w, index) => {
|
|
1581
1640
|
const mid = (w.start + w.end) / 2;
|
|
1582
1641
|
if (mid < from || mid >= to) return;
|
|
@@ -1621,19 +1680,19 @@ function findVideoTranscriptPauses(words, options = {}) {
|
|
|
1621
1680
|
let to = b.start - keep;
|
|
1622
1681
|
if (options.fps) {
|
|
1623
1682
|
const f = 1e3 / options.fps;
|
|
1624
|
-
from =
|
|
1625
|
-
to =
|
|
1683
|
+
from = _chunk5T3H7CGGcjs.snapToVideoFrame.call(void 0, Math.ceil(from / f - 1e-9) * f, options.fps);
|
|
1684
|
+
to = _chunk5T3H7CGGcjs.snapToVideoFrame.call(void 0, Math.floor(to / f + 1e-9) * f, options.fps);
|
|
1626
1685
|
}
|
|
1627
|
-
if (to - from >
|
|
1686
|
+
if (to - from > _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) out.push({ from, to, text: `(pause after "${a.word}")` });
|
|
1628
1687
|
}
|
|
1629
1688
|
return out;
|
|
1630
1689
|
}
|
|
1631
1690
|
function mergeVideoRanges(ranges) {
|
|
1632
|
-
const sorted = ranges.filter((r) => r.to - r.from >
|
|
1691
|
+
const sorted = ranges.filter((r) => r.to - r.from > _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON).map((r) => ({ from: r.from, to: r.to })).sort((a, b) => a.from - b.from);
|
|
1633
1692
|
const out = [];
|
|
1634
1693
|
for (const r of sorted) {
|
|
1635
1694
|
const last = out[out.length - 1];
|
|
1636
|
-
if (last && r.from <= last.to +
|
|
1695
|
+
if (last && r.from <= last.to + _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) last.to = Math.max(last.to, r.to);
|
|
1637
1696
|
else out.push(r);
|
|
1638
1697
|
}
|
|
1639
1698
|
return out;
|
|
@@ -1679,7 +1738,7 @@ function findVideoRepetitions(words, options = {}) {
|
|
|
1679
1738
|
var VIDEO_DISFLUENCY_KINDS = ["filler", "pause", "repetition"];
|
|
1680
1739
|
function detectVideoDisfluencies(words, options = {}) {
|
|
1681
1740
|
const kinds = new Set(_nullishCoalesce(options.kinds, () => ( VIDEO_DISFLUENCY_KINDS)));
|
|
1682
|
-
const startIndex = (time) => Math.max(0, words.findIndex((w) => w.start >= time -
|
|
1741
|
+
const startIndex = (time) => Math.max(0, words.findIndex((w) => w.start >= time - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON));
|
|
1683
1742
|
const out = [];
|
|
1684
1743
|
if (kinds.has("filler"))
|
|
1685
1744
|
for (const r of findVideoFillers(words, options.fillers)) {
|
|
@@ -1693,13 +1752,13 @@ function detectVideoDisfluencies(words, options = {}) {
|
|
|
1693
1752
|
}
|
|
1694
1753
|
if (kinds.has("pause"))
|
|
1695
1754
|
for (const r of findVideoTranscriptPauses(words, options.pauses)) {
|
|
1696
|
-
const after = words.findIndex((w) => w.start >= r.to -
|
|
1755
|
+
const after = words.findIndex((w) => w.start >= r.to - _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON);
|
|
1697
1756
|
out.push({ ...r, kind: "pause", words: [Math.max(0, after - 1), Math.max(0, after)] });
|
|
1698
1757
|
}
|
|
1699
1758
|
return out.sort((a, b) => a.from - b.from || a.to - b.to);
|
|
1700
1759
|
}
|
|
1701
1760
|
function videoCutsWithMargin(ranges, keep) {
|
|
1702
|
-
return ranges.map((r) => ({ ...r, from: r.from + keep, to: r.to - keep })).filter((r) => r.to - r.from >
|
|
1761
|
+
return ranges.map((r) => ({ ...r, from: r.from + keep, to: r.to - keep })).filter((r) => r.to - r.from > _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON);
|
|
1703
1762
|
}
|
|
1704
1763
|
|
|
1705
1764
|
// src/video-editor/mix.ts
|
|
@@ -1805,7 +1864,7 @@ function videoDuckingKeys(clip, speech, options = {}) {
|
|
|
1805
1864
|
const gap = Math.max(_nullishCoalesce(options.mergeGap, () => ( 600)), attack + release);
|
|
1806
1865
|
const base = _nullishCoalesce(options.base, () => ( 1));
|
|
1807
1866
|
const low = Math.round(base * 10 ** (duckDb / 20) * 1e4) / 1e4;
|
|
1808
|
-
const end =
|
|
1867
|
+
const end = _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip);
|
|
1809
1868
|
const ranges = [];
|
|
1810
1869
|
for (const r of mergeVideoRanges(speech)) {
|
|
1811
1870
|
if (r.to <= clip.start - release || r.from >= end + attack) continue;
|
|
@@ -2010,7 +2069,7 @@ function videoClipWaveform(clip, peaks, columns) {
|
|
|
2010
2069
|
const step = clip.duration / Math.max(1, n);
|
|
2011
2070
|
for (let c = 0; c < n; c++) {
|
|
2012
2071
|
const { min, max } = videoAudioPeakRange(peaks, start + c * step * speed, start + (c + 1) * step * speed);
|
|
2013
|
-
const gain =
|
|
2072
|
+
const gain = _chunk5T3H7CGGcjs.videoClipSoundGain.call(void 0, clip, (c + 0.5) * step);
|
|
2014
2073
|
out[2 * c] = min * gain;
|
|
2015
2074
|
out[2 * c + 1] = max * gain;
|
|
2016
2075
|
}
|
|
@@ -2141,7 +2200,7 @@ var VideoAudioPeaksCache = (_class2 = class {
|
|
|
2141
2200
|
// src/video-editor/plan.ts
|
|
2142
2201
|
function clipIndex(project) {
|
|
2143
2202
|
const out = /* @__PURE__ */ new Map();
|
|
2144
|
-
for (const { track } of
|
|
2203
|
+
for (const { track } of _chunk5T3H7CGGcjs.allVideoTracks.call(void 0, project)) for (const c of track.clips) out.set(c.id, c);
|
|
2145
2204
|
return out;
|
|
2146
2205
|
}
|
|
2147
2206
|
function diffVideoProjects(before, after) {
|
|
@@ -2150,32 +2209,32 @@ function diffVideoProjects(before, after) {
|
|
|
2150
2209
|
const clipsAdded = [...b.keys()].filter((id) => !a.has(id));
|
|
2151
2210
|
const clipsRemoved = [...a.keys()].filter((id) => !b.has(id));
|
|
2152
2211
|
const clipsChanged = [...b.keys()].filter((id) => a.has(id) && JSON.stringify(a.get(id)) !== JSON.stringify(b.get(id)));
|
|
2153
|
-
const durationBefore =
|
|
2154
|
-
const durationAfter =
|
|
2212
|
+
const durationBefore = _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, before);
|
|
2213
|
+
const durationAfter = _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, after);
|
|
2155
2214
|
return { durationBefore, durationAfter, durationDelta: durationAfter - durationBefore, clipsAdded, clipsRemoved, clipsChanged };
|
|
2156
2215
|
}
|
|
2157
2216
|
function planVideoEdits(project, input) {
|
|
2158
|
-
if (!_optionalChain([input, 'access',
|
|
2217
|
+
if (!_optionalChain([input, 'access', _35 => _35.title, 'optionalAccess', _36 => _36.trim, 'call', _37 => _37()])) return { ok: false, error: 'A plan needs a title saying what it does (e.g. "Remove 12 filler words").' };
|
|
2159
2218
|
if (!input.edits.length) return { ok: false, error: "The plan has no edits; there is nothing to propose." };
|
|
2160
2219
|
const result = applyVideoEdits(project, input.edits);
|
|
2161
2220
|
if (!result.ok) return { ok: false, error: result.error };
|
|
2162
2221
|
const known = new Set(checkVideoProject(project).map(videoIssueKey));
|
|
2163
|
-
const
|
|
2222
|
+
const summary2 = { ...diffVideoProjects(project, result.project), newIssues: result.issues.filter((i) => !known.has(videoIssueKey(i))), edits: input.edits.length };
|
|
2164
2223
|
const plan = {
|
|
2165
2224
|
id: _nullishCoalesce(input.id, () => ( "plan")),
|
|
2166
2225
|
title: input.title.trim(),
|
|
2167
2226
|
...input.description ? { description: input.description } : {},
|
|
2168
2227
|
...input.source ? { source: input.source } : {},
|
|
2169
2228
|
edits: structuredClone([...input.edits]),
|
|
2170
|
-
..._optionalChain([input, 'access',
|
|
2171
|
-
summary
|
|
2229
|
+
..._optionalChain([input, 'access', _38 => _38.ranges, 'optionalAccess', _39 => _39.length]) ? { ranges: input.ranges.map((r) => ({ ...r })) } : {},
|
|
2230
|
+
summary: summary2
|
|
2172
2231
|
};
|
|
2173
2232
|
return { ok: true, plan, project: result.project };
|
|
2174
2233
|
}
|
|
2175
2234
|
function describeVideoEditPlan(plan) {
|
|
2176
2235
|
const s = plan.summary;
|
|
2177
2236
|
const parts = [];
|
|
2178
|
-
if (_optionalChain([plan, 'access',
|
|
2237
|
+
if (_optionalChain([plan, 'access', _40 => _40.ranges, 'optionalAccess', _41 => _41.length])) parts.push(`${plan.ranges.length} stretch${plan.ranges.length > 1 ? "es" : ""}`);
|
|
2179
2238
|
const delta = s.durationDelta;
|
|
2180
2239
|
const length = Math.abs(delta) < 0.5 ? "same length" : `${(Math.abs(delta) / 1e3).toFixed(1)} s ${delta < 0 ? "shorter" : "longer"}`;
|
|
2181
2240
|
const clips = [s.clipsAdded.length && `${s.clipsAdded.length} added`, s.clipsChanged.length && `${s.clipsChanged.length} changed`, s.clipsRemoved.length && `${s.clipsRemoved.length} removed`].filter(Boolean).join(", ");
|
|
@@ -2514,23 +2573,23 @@ var VideoPreviewPixels = (_class3 = class {constructor() { _class3.prototype.__i
|
|
|
2514
2573
|
next(time, timeout = 5e3) {
|
|
2515
2574
|
const matches = () => this.drawnAt && this.drawnAt.complete && Math.abs(this.drawnAt.time - time) < 0.5;
|
|
2516
2575
|
return new Promise((resolve, reject) => {
|
|
2517
|
-
const
|
|
2576
|
+
const done2 = (fn) => {
|
|
2518
2577
|
clearTimeout(timer);
|
|
2519
2578
|
off();
|
|
2520
2579
|
fn();
|
|
2521
2580
|
};
|
|
2522
2581
|
const check = () => {
|
|
2523
|
-
if (!this.reader) return
|
|
2582
|
+
if (!this.reader) return done2(() => reject(new Error("The preview was closed before it drew the frame.")));
|
|
2524
2583
|
if (!matches()) return;
|
|
2525
2584
|
try {
|
|
2526
2585
|
const snap = this.read();
|
|
2527
|
-
|
|
2586
|
+
done2(() => snap ? resolve(snap) : reject(new Error("The preview has no pixels to read.")));
|
|
2528
2587
|
} catch (e) {
|
|
2529
|
-
|
|
2588
|
+
done2(() => reject(e));
|
|
2530
2589
|
}
|
|
2531
2590
|
};
|
|
2532
2591
|
const off = this.subscribe(check);
|
|
2533
|
-
const timer = setTimeout(() =>
|
|
2592
|
+
const timer = setTimeout(() => done2(() => reject(new Error(`The preview did not finish drawing ${Math.round(time)} ms within ${timeout} ms; its media may still be loading or may have failed to load. Try again, or check the asset sources.`))), timeout);
|
|
2534
2593
|
check();
|
|
2535
2594
|
});
|
|
2536
2595
|
}
|
|
@@ -2555,6 +2614,88 @@ function readVideoScopesPanel(feed, kinds = VIDEO_SCOPE_KINDS, options = {}) {
|
|
|
2555
2614
|
return { ok: true, time: snap.time, complete: snap.complete, images, stats, notes: videoExposureNotes(stats) };
|
|
2556
2615
|
}
|
|
2557
2616
|
|
|
2617
|
+
// src/video-editor/camera.ts
|
|
2618
|
+
function videoCameraView(framing, stage) {
|
|
2619
|
+
const zoom = _nullishCoalesce(_optionalChain([framing, 'optionalAccess', _42 => _42.zoom]), () => ( 1));
|
|
2620
|
+
return { zoom, scrollX: stage.width / (2 * zoom) - (stage.width / 2 + (_nullishCoalesce(_optionalChain([framing, 'optionalAccess', _43 => _43.x]), () => ( 0)))), scrollY: stage.height / (2 * zoom) - (stage.height / 2 + (_nullishCoalesce(_optionalChain([framing, 'optionalAccess', _44 => _44.y]), () => ( 0)))) };
|
|
2621
|
+
}
|
|
2622
|
+
function videoTransformOfView(view, base, stage) {
|
|
2623
|
+
const cx = stage.width / 2;
|
|
2624
|
+
const cy = stage.height / 2;
|
|
2625
|
+
const px = (cx + (_nullishCoalesce(base.x, () => ( 0))) + view.scrollX) * view.zoom - cx;
|
|
2626
|
+
const py = (cy + (_nullishCoalesce(base.y, () => ( 0))) + view.scrollY) * view.zoom - cy;
|
|
2627
|
+
const roll = _nullishCoalesce(view.roll, () => ( 0));
|
|
2628
|
+
const a = roll * Math.PI / 180;
|
|
2629
|
+
const tidy = (n) => Math.round(n * 1e3) / 1e3 || 0;
|
|
2630
|
+
return {
|
|
2631
|
+
x: tidy(px * Math.cos(a) - py * Math.sin(a)),
|
|
2632
|
+
y: tidy(px * Math.sin(a) + py * Math.cos(a)),
|
|
2633
|
+
scale: tidy((_nullishCoalesce(base.scale, () => ( 1))) * view.zoom),
|
|
2634
|
+
rotation: tidy((_nullishCoalesce(base.rotation, () => ( 0))) + roll)
|
|
2635
|
+
};
|
|
2636
|
+
}
|
|
2637
|
+
function videoCameraBase(clip) {
|
|
2638
|
+
if (clip.camera) return clip.camera.base;
|
|
2639
|
+
const t = _nullishCoalesce(clip.transform, () => ( {}));
|
|
2640
|
+
const keyed = _chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES.filter((p) => _chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, t[p]));
|
|
2641
|
+
if (keyed.length)
|
|
2642
|
+
throw new Error(`Clip "${clip.id}" keys its ${keyed.join(", ")}, which a camera move would replace; remove those keyframes first (set_video_keyframes with keys null).`);
|
|
2643
|
+
return Object.fromEntries(_chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES.flatMap((p) => typeof t[p] === "number" ? [[p, t[p]]] : []));
|
|
2644
|
+
}
|
|
2645
|
+
async function bakeVideoClipCamera(clip, camera, project, provider) {
|
|
2646
|
+
const stage = { width: project.width, height: project.height };
|
|
2647
|
+
const fps = project.fps > 0 ? project.fps : 30;
|
|
2648
|
+
const to = videoCameraView(camera.framing, stage);
|
|
2649
|
+
const notes = [];
|
|
2650
|
+
const cuts = [];
|
|
2651
|
+
const windows = {};
|
|
2652
|
+
let keys = [];
|
|
2653
|
+
let inMs = 0;
|
|
2654
|
+
const moveIn = _chunkOPSK22DLcjs.cameraMoveParts.call(void 0, camera.in);
|
|
2655
|
+
if (moveIn) {
|
|
2656
|
+
const { description } = await _chunkOPSK22DLcjs.resolveCameraMoveSpec.call(void 0, provider, moveIn, "transition");
|
|
2657
|
+
inMs = _nullishCoalesce(moveIn.ms, () => ( description.camera.durationMs));
|
|
2658
|
+
if (inMs > clip.duration) throw new Error(`The move into clip "${clip.id}" takes ${inMs} ms, longer than the clip (${clip.duration} ms); give a shorter "ms" or lengthen the clip.`);
|
|
2659
|
+
const sample = await _chunkOPSK22DLcjs.sampleEffectCameraMove.call(void 0, provider, moveIn.move, { from: videoCameraView(camera.from, stage), to, ms: inMs, stage, fps, values: moveIn.values });
|
|
2660
|
+
keys.push(...sample.keys);
|
|
2661
|
+
if (sample.cut !== void 0) cuts.push(sample.cut);
|
|
2662
|
+
windows.in = { start: 0, end: inMs };
|
|
2663
|
+
}
|
|
2664
|
+
const moveDuring = _chunkOPSK22DLcjs.cameraMoveParts.call(void 0, camera.during);
|
|
2665
|
+
const holdMs = clip.duration - inMs;
|
|
2666
|
+
if (moveDuring && holdMs > 0) {
|
|
2667
|
+
await _chunkOPSK22DLcjs.resolveCameraMoveSpec.call(void 0, provider, moveDuring, "hold");
|
|
2668
|
+
const at = keys.length ? keys[keys.length - 1].view : to;
|
|
2669
|
+
const sample = await _chunkOPSK22DLcjs.sampleEffectCameraMove.call(void 0, provider, moveDuring.move, { from: at, to: at, ms: holdMs, stage, fps, values: moveDuring.values });
|
|
2670
|
+
const shifted = sample.keys.map((k) => ({ t: k.t + inMs, view: k.view }));
|
|
2671
|
+
if (keys.length && shifted.length && sameView(keys[keys.length - 1].view, shifted[0].view)) shifted.shift();
|
|
2672
|
+
keys.push(...shifted);
|
|
2673
|
+
if (sample.cut !== void 0) cuts.push(sample.cut + inMs);
|
|
2674
|
+
windows.during = { start: inMs, end: clip.duration };
|
|
2675
|
+
} else if (moveDuring) notes.push(`The move into the clip fills it, so the hold move "${moveDuring.move}" has no time to play; shorten the move in or lengthen the clip.`);
|
|
2676
|
+
if (!keys.length) keys = [{ t: 0, view: to }];
|
|
2677
|
+
const flat = keys.some((k) => k.view.tilt || k.view.turn || k.view.blur && k.view.blur > 0);
|
|
2678
|
+
if (flat) notes.push("A clip transform has no tilt, turn or motion blur, so those parts of the move are left out; the zoom, pan and roll are kept.");
|
|
2679
|
+
const base = videoCameraBase(clip);
|
|
2680
|
+
const transforms = keys.map((k) => ({ t: Math.round(k.t * 1e3) / 1e3, value: videoTransformOfView(k.view, base, stage) }));
|
|
2681
|
+
const transform = {};
|
|
2682
|
+
for (const p of _chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES) {
|
|
2683
|
+
const out = [];
|
|
2684
|
+
for (const { t, value } of transforms) {
|
|
2685
|
+
const last = out[out.length - 1];
|
|
2686
|
+
const prev = out[out.length - 2];
|
|
2687
|
+
if (last && prev && last.v === value[p] && prev.v === value[p] && prev.t !== last.t) out[out.length - 1] = { t, v: value[p] };
|
|
2688
|
+
else out.push({ t, v: value[p] });
|
|
2689
|
+
}
|
|
2690
|
+
transform[p] = out.length > 1 && out.some((k) => k.v !== out[0].v) ? { keys: out } : out[0].v;
|
|
2691
|
+
}
|
|
2692
|
+
return { transform, cuts, windows, notes };
|
|
2693
|
+
}
|
|
2694
|
+
var sameView = (a, b) => ["zoom", "scrollX", "scrollY", "tilt", "turn", "roll", "blur"].every((k) => Math.abs((_nullishCoalesce(a[k], () => ( 0))) - (_nullishCoalesce(b[k], () => ( 0)))) < 1e-9);
|
|
2695
|
+
function videoClipCameraMove(clip, role) {
|
|
2696
|
+
return _chunkOPSK22DLcjs.cameraMoveParts.call(void 0, _optionalChain([clip, 'optionalAccess', _45 => _45.camera, 'optionalAccess', _46 => _46[role === "transition" ? "in" : "during"]]));
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2558
2699
|
// src/video-editor/transcript-controller.ts
|
|
2559
2700
|
var TranscriptVideoController = (_class4 = class {
|
|
2560
2701
|
constructor(controller, options = {}) {;_class4.prototype.__init9.call(this);_class4.prototype.__init10.call(this);_class4.prototype.__init11.call(this);_class4.prototype.__init12.call(this);_class4.prototype.__init13.call(this);_class4.prototype.__init14.call(this);_class4.prototype.__init15.call(this);
|
|
@@ -2590,7 +2731,7 @@ var TranscriptVideoController = (_class4 = class {
|
|
|
2590
2731
|
}}
|
|
2591
2732
|
/** Stops following the editor. */
|
|
2592
2733
|
destroy() {
|
|
2593
|
-
_optionalChain([this, 'access',
|
|
2734
|
+
_optionalChain([this, 'access', _47 => _47.unsubscribe, 'optionalCall', _48 => _48()]);
|
|
2594
2735
|
this.unsubscribe = null;
|
|
2595
2736
|
this.listeners.clear();
|
|
2596
2737
|
}
|
|
@@ -2604,7 +2745,7 @@ var TranscriptVideoController = (_class4 = class {
|
|
|
2604
2745
|
words = videoTimelineTranscript(project, { track: this.track });
|
|
2605
2746
|
} catch (e4) {
|
|
2606
2747
|
}
|
|
2607
|
-
const disfluencies = detectVideoDisfluencies(words, { ...this.options.disfluencies, pauses: { fps: project.fps, ..._optionalChain([this, 'access',
|
|
2748
|
+
const disfluencies = detectVideoDisfluencies(words, { ...this.options.disfluencies, pauses: { fps: project.fps, ..._optionalChain([this, 'access', _49 => _49.options, 'access', _50 => _50.disfluencies, 'optionalAccess', _51 => _51.pauses]) } });
|
|
2608
2749
|
const flags = {};
|
|
2609
2750
|
for (const d of disfluencies)
|
|
2610
2751
|
for (let i = d.words[0]; i <= d.words[1]; i++) {
|
|
@@ -2727,12 +2868,12 @@ var TranscriptVideoController = (_class4 = class {
|
|
|
2727
2868
|
// src/video-editor/proxy.ts
|
|
2728
2869
|
var VIDEO_PROXY_SCALES = [0.5, 0.25];
|
|
2729
2870
|
function videoAssetProxy(asset, scale) {
|
|
2730
|
-
if (!_optionalChain([asset, 'optionalAccess',
|
|
2871
|
+
if (!_optionalChain([asset, 'optionalAccess', _52 => _52.proxies, 'optionalAccess', _53 => _53.length]) || !(scale > 0) || scale >= 1) return null;
|
|
2731
2872
|
let best = null;
|
|
2732
2873
|
for (const p of asset.proxies) if (p.scale >= scale - 1e-9 && p.scale < 1 && (!best || p.scale < best.scale)) best = p;
|
|
2733
2874
|
return best;
|
|
2734
2875
|
}
|
|
2735
|
-
var videoPreviewSrc = (asset, scale, fallback = _nullishCoalesce(_optionalChain([asset, 'optionalAccess',
|
|
2876
|
+
var videoPreviewSrc = (asset, scale, fallback = _nullishCoalesce(_optionalChain([asset, 'optionalAccess', _54 => _54.src]), () => ( ""))) => _nullishCoalesce(_optionalChain([videoAssetProxy, 'call', _55 => _55(asset, scale), 'optionalAccess', _56 => _56.src]), () => ( fallback));
|
|
2736
2877
|
function resolveVideoPreviewScale(scale, shown) {
|
|
2737
2878
|
if (scale === void 0 || scale === "auto") return Math.min(1, Math.max(0, shown));
|
|
2738
2879
|
if (scale === "full") return 1;
|
|
@@ -2781,7 +2922,7 @@ function videoProxyFfmpeg(asset, options = {}) {
|
|
|
2781
2922
|
output
|
|
2782
2923
|
];
|
|
2783
2924
|
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 } : {} };
|
|
2784
|
-
return { asset: asset.id, args, command: ["ffmpeg", ...args].map(
|
|
2925
|
+
return { asset: asset.id, args, command: ["ffmpeg", ...args].map(_chunk5T3H7CGGcjs.videoShellQuote).join(" "), proxy };
|
|
2785
2926
|
}
|
|
2786
2927
|
function videoProxyPlan(project, options = {}) {
|
|
2787
2928
|
const scale = _nullishCoalesce(options.scale, () => ( 0.5));
|
|
@@ -2791,7 +2932,7 @@ function videoProxyPlan(project, options = {}) {
|
|
|
2791
2932
|
if (!a) throw new Error(`There is no asset "${id}"; the assets are ${project.assets.map((x) => `"${x.id}"`).join(", ") || "none"}.`);
|
|
2792
2933
|
if (a.kind !== "video") throw new Error(`Asset "${id}" is ${a.kind === "image" ? "an image" : "audio"}; only video assets have proxies.`);
|
|
2793
2934
|
}
|
|
2794
|
-
return project.assets.filter((a) => a.kind === "video" && (!wanted || wanted.has(a.id)) && !_optionalChain([a, 'access',
|
|
2935
|
+
return project.assets.filter((a) => a.kind === "video" && (!wanted || wanted.has(a.id)) && !_optionalChain([a, 'access', _57 => _57.proxies, 'optionalAccess', _58 => _58.some, 'call', _59 => _59((p) => Math.abs(p.scale - scale) < 1e-9)])).map((a) => videoProxyFfmpeg(a, { ...options, scale }));
|
|
2795
2936
|
}
|
|
2796
2937
|
var VIDEO_PREVIEW_SCALE_OPTIONS = [
|
|
2797
2938
|
{ value: "auto", label: "Auto", scale: "auto" },
|
|
@@ -2799,7 +2940,7 @@ var VIDEO_PREVIEW_SCALE_OPTIONS = [
|
|
|
2799
2940
|
...VIDEO_PROXY_SCALES.map((s) => ({ value: String(s), label: s === 0.5 ? "\xBD" : s === 0.25 ? "\xBC" : `${s * 100}%`, scale: s }))
|
|
2800
2941
|
];
|
|
2801
2942
|
var parseVideoPreviewScale = (value) => value === "full" ? "full" : Number(value) > 0 && Number(value) <= 1 ? Number(value) : "auto";
|
|
2802
|
-
var videoProjectHasProxies = (project) => project.assets.some((a) => !!_optionalChain([a, 'access',
|
|
2943
|
+
var videoProjectHasProxies = (project) => project.assets.some((a) => !!_optionalChain([a, 'access', _60 => _60.proxies, 'optionalAccess', _61 => _61.length]));
|
|
2803
2944
|
|
|
2804
2945
|
// src/video-editor/frame-cache.ts
|
|
2805
2946
|
var videoSourceFrame = (sourceTime, fps) => Math.max(0, Math.floor(sourceTime * fps / 1e3 + 1e-6));
|
|
@@ -2807,7 +2948,7 @@ var videoSourceFrameTime = (frame, fps) => (frame + 0.5) * 1e3 / fps;
|
|
|
2807
2948
|
var videoFrameCacheKey = (src, frame) => `${frame}@${src}`;
|
|
2808
2949
|
function videoFrameRequestsAt(project, time, srcFor = (l) => l.src) {
|
|
2809
2950
|
const out = [];
|
|
2810
|
-
for (const layer of
|
|
2951
|
+
for (const layer of _chunk5T3H7CGGcjs.videoFrameLeafLayers.call(void 0, _chunk5T3H7CGGcjs.videoFrameAt.call(void 0, project, time).layers)) {
|
|
2811
2952
|
if (layer.type !== "media" || layer.assetKind !== "video") continue;
|
|
2812
2953
|
const src = srcFor(layer);
|
|
2813
2954
|
if (!src) continue;
|
|
@@ -2843,7 +2984,7 @@ function videoCacheEvictions(entries, options) {
|
|
|
2843
2984
|
return d >= 0 ? d : -d * behind;
|
|
2844
2985
|
};
|
|
2845
2986
|
const out = [];
|
|
2846
|
-
for (const e of entries.filter((x) => !_optionalChain([options, 'access',
|
|
2987
|
+
for (const e of entries.filter((x) => !_optionalChain([options, 'access', _62 => _62.protect, 'optionalAccess', _63 => _63.has, 'call', _64 => _64(x.key)])).sort((a, b) => cost(b) - cost(a))) {
|
|
2847
2988
|
if (total <= options.maxBytes) break;
|
|
2848
2989
|
out.push(e.key);
|
|
2849
2990
|
total -= e.bytes;
|
|
@@ -2884,7 +3025,7 @@ var VideoFrameCache = (_class5 = class {
|
|
|
2884
3025
|
const entry = this.entries.get(videoFrameCacheKey(src, videoSourceFrame(sourceTime, fps)));
|
|
2885
3026
|
if (entry) this.hits++;
|
|
2886
3027
|
else this.misses++;
|
|
2887
|
-
return _optionalChain([entry, 'optionalAccess',
|
|
3028
|
+
return _optionalChain([entry, 'optionalAccess', _65 => _65.frame, 'access', _66 => _66.image]);
|
|
2888
3029
|
}
|
|
2889
3030
|
/** Whether a frame is cached, without counting it. */
|
|
2890
3031
|
has(src, sourceTime, fps) {
|
|
@@ -2892,7 +3033,7 @@ var VideoFrameCache = (_class5 = class {
|
|
|
2892
3033
|
}
|
|
2893
3034
|
/** Keeps a decoded frame (replacing any with the same key), then evicts to the budget. */
|
|
2894
3035
|
put(request, frame) {
|
|
2895
|
-
if (this.destroyed) return void _optionalChain([frame, 'access',
|
|
3036
|
+
if (this.destroyed) return void _optionalChain([frame, 'access', _67 => _67.image, 'access', _68 => _68.close, 'optionalCall', _69 => _69()]);
|
|
2896
3037
|
const old = this.entries.get(request.key);
|
|
2897
3038
|
if (old) this.drop(old);
|
|
2898
3039
|
const bytes = Math.max(1, frame.width * frame.height * 4);
|
|
@@ -2991,7 +3132,7 @@ var VideoFrameCache = (_class5 = class {
|
|
|
2991
3132
|
(frame) => {
|
|
2992
3133
|
this.inFlight.delete(r.key);
|
|
2993
3134
|
if (generation === this.generation || this.bytes + frame.width * frame.height * 4 <= this.maxBytes) this.put(r, frame);
|
|
2994
|
-
else _optionalChain([frame, 'access',
|
|
3135
|
+
else _optionalChain([frame, 'access', _70 => _70.image, 'access', _71 => _71.close, 'optionalCall', _72 => _72()]);
|
|
2995
3136
|
},
|
|
2996
3137
|
() => this.inFlight.delete(r.key)
|
|
2997
3138
|
).finally(() => this.pump());
|
|
@@ -3004,7 +3145,7 @@ var VideoFrameCache = (_class5 = class {
|
|
|
3004
3145
|
drop(e) {
|
|
3005
3146
|
this.entries.delete(e.key);
|
|
3006
3147
|
this.bytes -= e.bytes;
|
|
3007
|
-
_optionalChain([e, 'access',
|
|
3148
|
+
_optionalChain([e, 'access', _73 => _73.frame, 'access', _74 => _74.image, 'access', _75 => _75.close, 'optionalCall', _76 => _76()]);
|
|
3008
3149
|
}
|
|
3009
3150
|
emit() {
|
|
3010
3151
|
for (const l of [...this.listeners]) l();
|
|
@@ -3056,7 +3197,7 @@ var VideoPreviewEngine = (_class6 = class {
|
|
|
3056
3197
|
this.source = source;
|
|
3057
3198
|
this.options = options;
|
|
3058
3199
|
this.canvas = canvas2;
|
|
3059
|
-
this.ctx = options.context !== void 0 ? options.context : _nullishCoalesce(_optionalChain([canvas2, 'access',
|
|
3200
|
+
this.ctx = options.context !== void 0 ? options.context : _nullishCoalesce(_optionalChain([canvas2, 'access', _81 => _81.getContext, 'optionalCall', _82 => _82("2d")]), () => ( null));
|
|
3060
3201
|
this.unsubscribe = source.subscribe(() => this.update());
|
|
3061
3202
|
this.lutCache = options.luts !== void 0 ? options.luts : _nullishCoalesce(source.luts, () => ( null));
|
|
3062
3203
|
this.unsubscribeLuts = this.lutCache ? this.lutCache.subscribe(() => this.redraw()) : () => {
|
|
@@ -3101,7 +3242,7 @@ var VideoPreviewEngine = (_class6 = class {
|
|
|
3101
3242
|
/** The canvas's pixels and the frame they show, or `null` when its context cannot be read. */
|
|
3102
3243
|
readPixels() {
|
|
3103
3244
|
const ctx = this.ctx;
|
|
3104
|
-
if (!_optionalChain([ctx, 'optionalAccess',
|
|
3245
|
+
if (!_optionalChain([ctx, 'optionalAccess', _83 => _83.getImageData]) || !this.drawn) return null;
|
|
3105
3246
|
return { ...this.drawn, pixels: ctx.getImageData(0, 0, this.canvas.width, this.canvas.height) };
|
|
3106
3247
|
}
|
|
3107
3248
|
createMedia(kind) {
|
|
@@ -3139,8 +3280,8 @@ var VideoPreviewEngine = (_class6 = class {
|
|
|
3139
3280
|
entry.media.pause();
|
|
3140
3281
|
entry.media.removeEventListener("seeked", entry.onReady);
|
|
3141
3282
|
entry.media.removeEventListener("loadeddata", entry.onReady);
|
|
3142
|
-
_optionalChain([entry, 'access',
|
|
3143
|
-
_optionalChain([entry, 'access',
|
|
3283
|
+
_optionalChain([entry, 'access', _84 => _84.media, 'access', _85 => _85.removeAttribute, 'optionalCall', _86 => _86("src")]);
|
|
3284
|
+
_optionalChain([entry, 'access', _87 => _87.media, 'access', _88 => _88.load, 'optionalCall', _89 => _89()]);
|
|
3144
3285
|
this.media.delete(entry.clip);
|
|
3145
3286
|
}
|
|
3146
3287
|
/** Brings the media elements in step with the editor and draws the frame. */
|
|
@@ -3148,13 +3289,13 @@ var VideoPreviewEngine = (_class6 = class {
|
|
|
3148
3289
|
if (this.destroyed) return;
|
|
3149
3290
|
const state = this.source.getState();
|
|
3150
3291
|
const { project, time, playing } = state;
|
|
3151
|
-
const frame =
|
|
3292
|
+
const frame = _chunk5T3H7CGGcjs.videoFrameAt.call(void 0, project, time);
|
|
3152
3293
|
const scale = resolveVideoPreviewScale(_nullishCoalesce(this.options.previewScale, () => ( state.previewScale)), this.resolutionFor(project.width));
|
|
3153
3294
|
const assets = new Map(project.assets.map((a) => [a.id, a]));
|
|
3154
3295
|
this.srcFor = (layer) => videoPreviewSrc(assets.get(_nullishCoalesce(layer.asset, () => ( ""))), scale, layer.src);
|
|
3155
3296
|
this.playing = playing;
|
|
3156
3297
|
this.fps = project.fps;
|
|
3157
|
-
_optionalChain([this, 'access',
|
|
3298
|
+
_optionalChain([this, 'access', _90 => _90.frameCache, 'optionalAccess', _91 => _91.update, 'call', _92 => _92(project, time, { playing, srcFor: this.srcFor })]);
|
|
3158
3299
|
const tolerance = (_nullishCoalesce(this.options.tolerance, () => ( 200))) / 1e3;
|
|
3159
3300
|
const active = /* @__PURE__ */ new Set();
|
|
3160
3301
|
const sync = (clip, src, kind, sourceTime, speed, gain) => {
|
|
@@ -3178,10 +3319,10 @@ var VideoPreviewEngine = (_class6 = class {
|
|
|
3178
3319
|
}
|
|
3179
3320
|
};
|
|
3180
3321
|
const sounding = new Map(frame.audio.map((a) => [a.clip, a]));
|
|
3181
|
-
for (const layer of
|
|
3322
|
+
for (const layer of _chunk5T3H7CGGcjs.videoFrameLeafLayers.call(void 0, frame.layers)) {
|
|
3182
3323
|
if (layer.type !== "media" || layer.assetKind !== "video" || !layer.src) continue;
|
|
3183
3324
|
const sound = sounding.get(layer.clip);
|
|
3184
|
-
sync(layer.clip, this.srcFor(layer), "video", _nullishCoalesce(layer.sourceTime, () => ( 0)), _nullishCoalesce(_optionalChain([sound, 'optionalAccess',
|
|
3325
|
+
sync(layer.clip, this.srcFor(layer), "video", _nullishCoalesce(layer.sourceTime, () => ( 0)), _nullishCoalesce(_optionalChain([sound, 'optionalAccess', _93 => _93.speed]), () => ( 1)), sound ? sound.gain : null);
|
|
3185
3326
|
sounding.delete(layer.clip);
|
|
3186
3327
|
}
|
|
3187
3328
|
for (const a of sounding.values()) sync(a.clip, a.src, "audio", a.sourceTime, a.speed, a.gain);
|
|
@@ -3190,9 +3331,9 @@ var VideoPreviewEngine = (_class6 = class {
|
|
|
3190
3331
|
}
|
|
3191
3332
|
/** With effects, the frame is drawn at the start of its frame, so effect pictures are cached once per frame. */
|
|
3192
3333
|
drawable(project, frame) {
|
|
3193
|
-
if (!_optionalChain([this, 'access',
|
|
3194
|
-
const at =
|
|
3195
|
-
return at === frame.time ? frame : { ...
|
|
3334
|
+
if (!_optionalChain([this, 'access', _94 => _94.effects, 'optionalAccess', _95 => _95.available]) || !_chunk5T3H7CGGcjs.videoLayersUseEffects.call(void 0, frame.layers)) return frame;
|
|
3335
|
+
const at = _chunk5T3H7CGGcjs.videoEffectFrameTime.call(void 0, frame.time, project.fps);
|
|
3336
|
+
return at === frame.time ? frame : { ..._chunk5T3H7CGGcjs.videoFrameAt.call(void 0, project, at), time: frame.time };
|
|
3196
3337
|
}
|
|
3197
3338
|
redraw() {
|
|
3198
3339
|
if (this.scheduled || this.destroyed) return;
|
|
@@ -3201,7 +3342,7 @@ var VideoPreviewEngine = (_class6 = class {
|
|
|
3201
3342
|
this.scheduled = false;
|
|
3202
3343
|
if (this.destroyed) return;
|
|
3203
3344
|
const { project, time } = this.source.getState();
|
|
3204
|
-
this.draw(this.drawable(project,
|
|
3345
|
+
this.draw(this.drawable(project, _chunk5T3H7CGGcjs.videoFrameAt.call(void 0, project, time)));
|
|
3205
3346
|
});
|
|
3206
3347
|
}
|
|
3207
3348
|
__init40() {this.sourceFor = (layer) => {
|
|
@@ -3212,7 +3353,7 @@ var VideoPreviewEngine = (_class6 = class {
|
|
|
3212
3353
|
const entry = this.media.get(layer.clip);
|
|
3213
3354
|
const ready = !!entry && entry.media.readyState >= 2;
|
|
3214
3355
|
const cache = this.frameCache;
|
|
3215
|
-
const src = _nullishCoalesce(_optionalChain([entry, 'optionalAccess',
|
|
3356
|
+
const src = _nullishCoalesce(_optionalChain([entry, 'optionalAccess', _96 => _96.src]), () => ( this.srcFor(layer)));
|
|
3216
3357
|
const sourceTime = _nullishCoalesce(layer.sourceTime, () => ( 0));
|
|
3217
3358
|
if (cache && src && (!this.playing || !ready || entry.media.seeking)) {
|
|
3218
3359
|
const hit = cache.get(src, sourceTime, this.fps);
|
|
@@ -3244,7 +3385,7 @@ var VideoPreviewEngine = (_class6 = class {
|
|
|
3244
3385
|
if (!source) this.complete = false;
|
|
3245
3386
|
return source;
|
|
3246
3387
|
};
|
|
3247
|
-
|
|
3388
|
+
_chunk5T3H7CGGcjs.drawVideoFrame.call(void 0, this.ctx, frame, sourceFor, resolution, {
|
|
3248
3389
|
defineSvgFilter: this.defineSvgFilter,
|
|
3249
3390
|
lutFor: this.lutFor,
|
|
3250
3391
|
scratch: this.scratch,
|
|
@@ -3254,12 +3395,12 @@ var VideoPreviewEngine = (_class6 = class {
|
|
|
3254
3395
|
}
|
|
3255
3396
|
});
|
|
3256
3397
|
this.drawn = { time: frame.time, complete: this.complete };
|
|
3257
|
-
_optionalChain([this, 'access',
|
|
3258
|
-
_optionalChain([this, 'access',
|
|
3398
|
+
_optionalChain([this, 'access', _97 => _97.options, 'access', _98 => _98.onFrame, 'optionalCall', _99 => _99(frame)]);
|
|
3399
|
+
_optionalChain([this, 'access', _100 => _100.pixelsTarget, 'optionalAccess', _101 => _101.drawn, 'call', _102 => _102(frame.time, this.complete)]);
|
|
3259
3400
|
}
|
|
3260
3401
|
/** A grade's LUT once loaded; while it loads (or if it fails) the frame is drawn without it and counts as incomplete. */
|
|
3261
3402
|
__init41() {this.lutFor = (src) => {
|
|
3262
|
-
const lut = _optionalChain([this, 'access',
|
|
3403
|
+
const lut = _optionalChain([this, 'access', _103 => _103.lutCache, 'optionalAccess', _104 => _104.get, 'call', _105 => _105(src)]);
|
|
3263
3404
|
if (!lut) this.complete = false;
|
|
3264
3405
|
return lut;
|
|
3265
3406
|
}}
|
|
@@ -3304,7 +3445,7 @@ var VideoPreviewEngine = (_class6 = class {
|
|
|
3304
3445
|
this.unsubscribeLuts();
|
|
3305
3446
|
this.unsubscribeFrames();
|
|
3306
3447
|
this.unsubscribeEffects();
|
|
3307
|
-
_optionalChain([this, 'access',
|
|
3448
|
+
_optionalChain([this, 'access', _106 => _106.filterHost, 'optionalAccess', _107 => _107.remove, 'call', _108 => _108()]);
|
|
3308
3449
|
this.filterHost = null;
|
|
3309
3450
|
this.filters.clear();
|
|
3310
3451
|
this.unsubscribe();
|
|
@@ -3348,17 +3489,17 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3348
3489
|
constructor(options = {}) {;_class7.prototype.__init44.call(this);_class7.prototype.__init45.call(this);_class7.prototype.__init46.call(this);_class7.prototype.__init47.call(this);_class7.prototype.__init48.call(this);_class7.prototype.__init49.call(this);_class7.prototype.__init50.call(this);_class7.prototype.__init51.call(this);_class7.prototype.__init52.call(this);_class7.prototype.__init53.call(this);_class7.prototype.__init54.call(this);_class7.prototype.__init55.call(this);
|
|
3349
3490
|
this.history = _nullishCoalesce(options.history, () => ( new (0, _chunkFJ2MSI43cjs.HistoryManager)()));
|
|
3350
3491
|
this.audioPeaks = options.audioPeaks instanceof VideoAudioPeaksCache ? options.audioPeaks : new VideoAudioPeaksCache(options.audioPeaks);
|
|
3351
|
-
this.luts = options.luts instanceof
|
|
3492
|
+
this.luts = options.luts instanceof _chunk5T3H7CGGcjs.VideoLutCache ? options.luts : new (0, _chunk5T3H7CGGcjs.VideoLutCache)(options.luts);
|
|
3352
3493
|
this.frameCache = _nullishCoalesce(options.frameCache, () => ( null));
|
|
3353
3494
|
this.effects = new (0, _chunkOPSK22DLcjs.EffectsSlot)();
|
|
3354
3495
|
if (options.effects) this.effects.set(options.effects);
|
|
3355
|
-
this.effectsEngine = new (0,
|
|
3496
|
+
this.effectsEngine = new (0, _chunk5T3H7CGGcjs.VideoEffectsEngine)({ slot: this.effects });
|
|
3356
3497
|
this.project = options.project ? parseVideoProject(options.project) : createVideoProject();
|
|
3357
3498
|
this.issues = checkVideoProject(this.project);
|
|
3358
3499
|
this.readOnly = _nullishCoalesce(options.readOnly, () => ( false));
|
|
3359
3500
|
this.previewScale = checkPreviewScale(_nullishCoalesce(options.previewScale, () => ( "auto")));
|
|
3360
3501
|
this.onChange = options.onChange;
|
|
3361
|
-
this.player = new (0, _chunkM5GLQQWGcjs.AnimationPlayer)({ clock: options.clock, duration: () =>
|
|
3502
|
+
this.player = new (0, _chunkM5GLQQWGcjs.AnimationPlayer)({ clock: options.clock, duration: () => _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, this.project), loop: "none" });
|
|
3362
3503
|
this.state = this.computeState();
|
|
3363
3504
|
this.connect();
|
|
3364
3505
|
}
|
|
@@ -3395,12 +3536,12 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3395
3536
|
const h = this.history.getState();
|
|
3396
3537
|
return {
|
|
3397
3538
|
project: this.project,
|
|
3398
|
-
duration:
|
|
3539
|
+
duration: _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, this.project),
|
|
3399
3540
|
time: p.time,
|
|
3400
3541
|
playing: p.playing,
|
|
3401
3542
|
loop: p.loop,
|
|
3402
3543
|
selection: this.selection,
|
|
3403
|
-
current:
|
|
3544
|
+
current: _chunk5T3H7CGGcjs.videoClipsAt.call(void 0, this.project, p.time).map((c) => c.clip.id),
|
|
3404
3545
|
issues: this.issues,
|
|
3405
3546
|
readOnly: this.readOnly,
|
|
3406
3547
|
error: this.error,
|
|
@@ -3433,12 +3574,12 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3433
3574
|
this.issues = checkVideoProject(project);
|
|
3434
3575
|
const ids = new Set(project.tracks.flatMap((t) => t.clips.map((c) => c.id)));
|
|
3435
3576
|
if (this.selection.some((id) => !ids.has(id))) this.selection = this.selection.filter((id) => ids.has(id));
|
|
3436
|
-
this.player.setDuration(() =>
|
|
3577
|
+
this.player.setDuration(() => _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, this.project));
|
|
3437
3578
|
} finally {
|
|
3438
3579
|
this.applying = false;
|
|
3439
3580
|
}
|
|
3440
3581
|
this.notify();
|
|
3441
|
-
_optionalChain([this, 'access',
|
|
3582
|
+
_optionalChain([this, 'access', _109 => _109.onChange, 'optionalCall', _110 => _110(project)]);
|
|
3442
3583
|
}
|
|
3443
3584
|
commit(label, next, merge) {
|
|
3444
3585
|
const before = this.project;
|
|
@@ -3595,7 +3736,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3595
3736
|
}
|
|
3596
3737
|
/** Selects clips (unknown ids are dropped). `add` toggles them into the current selection. */
|
|
3597
3738
|
select(clips, options = {}) {
|
|
3598
|
-
const known = _nullishCoalesce(_optionalChain([clips, 'optionalAccess',
|
|
3739
|
+
const known = _nullishCoalesce(_optionalChain([clips, 'optionalAccess', _111 => _111.filter, 'call', _112 => _112((id) => _chunk5T3H7CGGcjs.findVideoClip.call(void 0, this.project, id))]), () => ( []));
|
|
3599
3740
|
let next;
|
|
3600
3741
|
if (options.add) {
|
|
3601
3742
|
next = [...this.selection];
|
|
@@ -3622,7 +3763,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3622
3763
|
step(frames) {
|
|
3623
3764
|
this.player.pause();
|
|
3624
3765
|
const fps = this.project.fps;
|
|
3625
|
-
this.player.seek(Math.max(0,
|
|
3766
|
+
this.player.seek(Math.max(0, _chunk5T3H7CGGcjs.snapToVideoFrame.call(void 0, this.player.currentTime, fps) + frames * 1e3 / fps));
|
|
3626
3767
|
}
|
|
3627
3768
|
setLoop(loop) {
|
|
3628
3769
|
this.player.setLoop(loop);
|
|
@@ -3639,14 +3780,14 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3639
3780
|
*/
|
|
3640
3781
|
snap(time, options = {}) {
|
|
3641
3782
|
const threshold = _nullishCoalesce(options.threshold, () => ( 8 * 1e3 / this.project.fps));
|
|
3642
|
-
const points =
|
|
3643
|
-
const hit =
|
|
3644
|
-
return hit.snapped !== null ? hit : { time: Math.max(0,
|
|
3783
|
+
const points = _chunk5T3H7CGGcjs.videoSnapPoints.call(void 0, this.project, { exclude: options.exclude, playhead: options.playhead === false ? void 0 : this.player.currentTime });
|
|
3784
|
+
const hit = _chunk5T3H7CGGcjs.snapVideoTime.call(void 0, time, points, threshold);
|
|
3785
|
+
return hit.snapped !== null ? hit : { time: Math.max(0, _chunk5T3H7CGGcjs.snapToVideoFrame.call(void 0, time, this.project.fps)), snapped: null };
|
|
3645
3786
|
}
|
|
3646
3787
|
/** Splits the selected clips (or every clip) under the playhead there, as one undo step. */
|
|
3647
3788
|
splitAtPlayhead() {
|
|
3648
|
-
const t =
|
|
3649
|
-
const under =
|
|
3789
|
+
const t = _chunk5T3H7CGGcjs.snapToVideoFrame.call(void 0, this.player.currentTime, this.project.fps);
|
|
3790
|
+
const under = _chunk5T3H7CGGcjs.videoClipsAt.call(void 0, this.project, t).filter(({ clip }) => t > clip.start && t < _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip));
|
|
3650
3791
|
const chosen = this.selection.length ? under.filter(({ clip }) => this.selection.includes(clip.id)) : under;
|
|
3651
3792
|
if (!chosen.length) return this.refuse("No clip is under the playhead to split.");
|
|
3652
3793
|
return this.apply(chosen.map(({ clip }) => ({ op: "split_clip", clip: clip.id, at: t })), "Split");
|
|
@@ -3674,7 +3815,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3674
3815
|
/** The provider's description of an effect, checked for `place` (rejects without a provider or for an unknown id). */
|
|
3675
3816
|
async describeEffect(effect, place) {
|
|
3676
3817
|
const d = await this.effects.require().describe(effect);
|
|
3677
|
-
if (place)
|
|
3818
|
+
if (place) _chunk5T3H7CGGcjs.checkVideoEffectPlace.call(void 0, d, place);
|
|
3678
3819
|
return d;
|
|
3679
3820
|
}
|
|
3680
3821
|
refused(message) {
|
|
@@ -3695,7 +3836,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3695
3836
|
return { ...result, clip: plan.clip, ...plan.effect ? { effect: plan.effect() } : {} };
|
|
3696
3837
|
}
|
|
3697
3838
|
clipOrThrow(id) {
|
|
3698
|
-
const at =
|
|
3839
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, this.project, id);
|
|
3699
3840
|
if (!at) throw new Error(`There is no clip "${id}"; list_applied_effects or get_video_project lists the clips.`);
|
|
3700
3841
|
return at.clip;
|
|
3701
3842
|
}
|
|
@@ -3708,7 +3849,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3708
3849
|
return this.effectEdit(async () => {
|
|
3709
3850
|
const current = this.clipOrThrow(clip);
|
|
3710
3851
|
const d = await this.describeEffect(effect, "clip");
|
|
3711
|
-
const values =
|
|
3852
|
+
const values = _chunk5T3H7CGGcjs.checkVideoEffectValues.call(void 0, d, options.values, { keyframes: true });
|
|
3712
3853
|
const stack = [..._nullishCoalesce(current.effects, () => ( []))];
|
|
3713
3854
|
const taken = new Set(stack.map((e) => e.id));
|
|
3714
3855
|
let n = 1;
|
|
@@ -3744,7 +3885,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3744
3885
|
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(", ")}.`);
|
|
3745
3886
|
base[k] = d.defaults[k];
|
|
3746
3887
|
}
|
|
3747
|
-
next.values =
|
|
3888
|
+
next.values = _chunk5T3H7CGGcjs.checkVideoEffectValues.call(void 0, d, given, { base, keyframes: true });
|
|
3748
3889
|
}
|
|
3749
3890
|
if (changes.enabled !== void 0) {
|
|
3750
3891
|
if (changes.enabled) delete next.enabled;
|
|
@@ -3758,11 +3899,92 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3758
3899
|
return { edit: { op: "update_clip", clip, set: { effects: stack } }, label: `Change effect ${_nullishCoalesce(was.name, () => ( was.effect))}`, clip, effect: () => next };
|
|
3759
3900
|
}, options.merge);
|
|
3760
3901
|
}
|
|
3902
|
+
/** The provider's camera moves for a role (`transition` into a clip, `hold` while it plays), or all of them. Empty without camera support. */
|
|
3903
|
+
async cameraMoves(role) {
|
|
3904
|
+
const provider = this.effects.provider;
|
|
3905
|
+
if (!_optionalChain([provider, 'optionalAccess', _113 => _113.capabilities, 'access', _114 => _114.supportsCamera]) || !provider.cameraView) return [];
|
|
3906
|
+
return (await provider.list({ kind: "camera" })).filter((e) => e.kind === "camera" && e.camera && (!role || e.camera.role === role));
|
|
3907
|
+
}
|
|
3908
|
+
cameraClip(id) {
|
|
3909
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, this.project, id);
|
|
3910
|
+
if (!at) {
|
|
3911
|
+
const ids = this.project.tracks.flatMap((t) => t.clips.map((c) => c.id));
|
|
3912
|
+
throw new Error(`There is no clip "${id}"; the clips are ${ids.map((c) => `"${c}"`).join(", ") || "none"} (get_video_project lists them).`);
|
|
3913
|
+
}
|
|
3914
|
+
if (at.track.kind === "audio") throw new Error(`Clip "${id}" is on audio track "${at.track.id}" and has no picture for a camera to move over.`);
|
|
3915
|
+
if (at.clip.type === "adjustment") throw new Error(`Clip "${id}" is an adjustment clip, which has no picture of its own for a camera to move over.`);
|
|
3916
|
+
return at.clip;
|
|
3917
|
+
}
|
|
3918
|
+
async cameraEdit(clipId, camera, label, merge) {
|
|
3919
|
+
const clip = this.cameraClip(clipId);
|
|
3920
|
+
const base = videoCameraBase(clip);
|
|
3921
|
+
if (!camera) {
|
|
3922
|
+
const restored = Object.keys(base).length ? { transform: base } : {};
|
|
3923
|
+
const r2 = this.apply({ op: "update_clip", clip: clipId, set: restored, remove: ["camera", ...Object.keys(base).length ? [] : ["transform"]] }, label, { merge });
|
|
3924
|
+
if (!r2.ok) return r2;
|
|
3925
|
+
return { ok: true, clip: clipId, camera: null, keys: { x: 0, y: 0, scale: 0, rotation: 0 }, cuts: [], windows: {}, notes: [] };
|
|
3926
|
+
}
|
|
3927
|
+
const bake = await bakeVideoClipCamera(clip, camera, this.project, this.effects.require());
|
|
3928
|
+
const r = this.apply({ op: "update_clip", clip: clipId, set: { camera, transform: bake.transform } }, label, { merge });
|
|
3929
|
+
if (!r.ok) return r;
|
|
3930
|
+
const keys = Object.fromEntries(_chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES.map((p) => [p, _chunk5T3H7CGGcjs.videoKeysOf.call(void 0, bake.transform[p]).length]));
|
|
3931
|
+
return { ok: true, clip: clipId, camera, keys, cuts: bake.cuts, windows: bake.windows, notes: bake.notes };
|
|
3932
|
+
}
|
|
3933
|
+
/**
|
|
3934
|
+
* Sets the camera move a clip plays into (`transition`: from `from` to `framing` from the
|
|
3935
|
+
* clip's start) or while it holds (`hold`: across the rest of the clip at `framing`), and bakes
|
|
3936
|
+
* the clip's moves into its x, y, scale and rotation keys at the project's frame rate, keeping a
|
|
3937
|
+
* cut's two keys. The move is checked first (role, preset, values; a preset's values and a move
|
|
3938
|
+
* in's length are written out). A clip whose transform is keyed by hand is refused. One undo step.
|
|
3939
|
+
*/
|
|
3940
|
+
async setClipCameraMove(clip, role, spec, options = {}) {
|
|
3941
|
+
const reason = this.readOnlyReason();
|
|
3942
|
+
if (reason) return this.refused(reason);
|
|
3943
|
+
try {
|
|
3944
|
+
const current = this.cameraClip(clip);
|
|
3945
|
+
const { spec: parts, description } = await _chunkOPSK22DLcjs.resolveCameraMoveSpec.call(void 0, this.effects.require(), spec, role);
|
|
3946
|
+
const move = role === "transition" && parts.ms === void 0 ? { ...parts, ms: description.camera.durationMs } : parts;
|
|
3947
|
+
const simple = move.ms === void 0 && move.preset === void 0 && move.values === void 0;
|
|
3948
|
+
const camera = { ..._nullishCoalesce(current.camera, () => ( { base: videoCameraBase(current) })), [_chunkOPSK22DLcjs.cameraMoveField.call(void 0, role)]: simple ? move.move : move };
|
|
3949
|
+
for (const key of ["from", "framing"]) {
|
|
3950
|
+
if (options[key] === null) delete camera[key];
|
|
3951
|
+
else if (options[key] !== void 0) camera[key] = options[key];
|
|
3952
|
+
}
|
|
3953
|
+
if (camera.from && !camera.in) throw new Error('"from" is where a move in starts; set a transition move too, or leave "from" out.');
|
|
3954
|
+
return await this.cameraEdit(clip, camera, `${role === "hold" ? "Hold move" : "Camera move"} ${description.name}`, options.merge);
|
|
3955
|
+
} catch (error) {
|
|
3956
|
+
if (_chunkOPSK22DLcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refused(error.message);
|
|
3957
|
+
throw error;
|
|
3958
|
+
}
|
|
3959
|
+
}
|
|
3960
|
+
/**
|
|
3961
|
+
* Removes a clip's camera move for a role and bakes what is left (which needs the provider);
|
|
3962
|
+
* with no move left the transform goes back to what it was before the moves. One undo step.
|
|
3963
|
+
*/
|
|
3964
|
+
async clearClipCameraMove(clip, role) {
|
|
3965
|
+
const reason = this.readOnlyReason();
|
|
3966
|
+
if (reason) return this.refused(reason);
|
|
3967
|
+
try {
|
|
3968
|
+
const current = this.cameraClip(clip);
|
|
3969
|
+
const field = _chunkOPSK22DLcjs.cameraMoveField.call(void 0, role);
|
|
3970
|
+
const other = field === "in" ? "during" : "in";
|
|
3971
|
+
if (_optionalChain([current, 'access', _115 => _115.camera, 'optionalAccess', _116 => _116[field]]) === void 0)
|
|
3972
|
+
throw new Error(`Clip "${clip}" has no camera "${field}" move to clear${_optionalChain([current, 'access', _117 => _117.camera, 'optionalAccess', _118 => _118[other]]) !== void 0 ? `; it has a "${other}" move (role ${role === "hold" ? "transition" : "hold"})` : ""}.`);
|
|
3973
|
+
const camera = { ...current.camera };
|
|
3974
|
+
delete camera[field];
|
|
3975
|
+
if (field === "in") delete camera.from;
|
|
3976
|
+
const left = camera.in !== void 0 || camera.during !== void 0;
|
|
3977
|
+
return await this.cameraEdit(clip, left ? camera : null, role === "hold" ? "Clear hold move" : "Clear camera move");
|
|
3978
|
+
} catch (error) {
|
|
3979
|
+
if (_chunkOPSK22DLcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refused(error.message);
|
|
3980
|
+
throw error;
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3761
3983
|
/** Removes an effect from a clip's stack (works without a provider, so placeholders can be cleared). One undo step. */
|
|
3762
3984
|
removeClipEffect(clip, instance) {
|
|
3763
3985
|
const reason = this.readOnlyReason();
|
|
3764
3986
|
if (reason) return this.refused(reason);
|
|
3765
|
-
const at =
|
|
3987
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, this.project, clip);
|
|
3766
3988
|
if (!at) return this.refused(`There is no clip "${clip}".`);
|
|
3767
3989
|
const stack = _nullishCoalesce(at.clip.effects, () => ( []));
|
|
3768
3990
|
const was = stack.find((e) => e.id === instance);
|
|
@@ -3779,7 +4001,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3779
4001
|
return this.effectEdit(async () => {
|
|
3780
4002
|
this.clipOrThrow(clip);
|
|
3781
4003
|
const d = await this.describeEffect(effect, "transition");
|
|
3782
|
-
const values =
|
|
4004
|
+
const values = _chunk5T3H7CGGcjs.checkVideoEffectValues.call(void 0, d, options.values);
|
|
3783
4005
|
const duration = _nullishCoalesce(_nullishCoalesce(options.duration, () => ( d.duration)), () => ( 1e3));
|
|
3784
4006
|
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 };
|
|
3785
4007
|
});
|
|
@@ -3792,7 +4014,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3792
4014
|
addEffectClip(track, effect, options = {}) {
|
|
3793
4015
|
return this.effectEdit(async () => {
|
|
3794
4016
|
const d = await this.describeEffect(effect, "generator");
|
|
3795
|
-
const values =
|
|
4017
|
+
const values = _chunk5T3H7CGGcjs.checkVideoEffectValues.call(void 0, d, options.values, { keyframes: true });
|
|
3796
4018
|
const duration = _nullishCoalesce(_nullishCoalesce(options.duration, () => ( d.duration)), () => ( 5e3));
|
|
3797
4019
|
const label = `Add ${d.name}`;
|
|
3798
4020
|
const clipId = _nullishCoalesce(options.id, () => ( ""));
|
|
@@ -3801,7 +4023,7 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3801
4023
|
label,
|
|
3802
4024
|
clip: clipId
|
|
3803
4025
|
};
|
|
3804
|
-
}).then((r) => r.ok && !r.clip ? { ...r, clip: _nullishCoalesce(_optionalChain([r, 'access',
|
|
4026
|
+
}).then((r) => r.ok && !r.clip ? { ...r, clip: _nullishCoalesce(_optionalChain([r, 'access', _119 => _119.outcomes, 'access', _120 => _120[0], 'optionalAccess', _121 => _121.clip]), () => ( "")) } : r);
|
|
3805
4027
|
}
|
|
3806
4028
|
/**
|
|
3807
4029
|
* Changes the values of an effect clip's picture (`target` its id) or of the effect transition
|
|
@@ -3814,42 +4036,42 @@ var VideoEditorController = (_class7 = class _VideoEditorController {
|
|
|
3814
4036
|
if (part === "generator") {
|
|
3815
4037
|
if (current.type !== "effect") throw new Error(`Clip "${clip}" is not an effect clip.`);
|
|
3816
4038
|
const d2 = await this.describeEffect(current.effect);
|
|
3817
|
-
return { edit: { op: "update_clip", clip, set: { values:
|
|
4039
|
+
return { edit: { op: "update_clip", clip, set: { values: _chunk5T3H7CGGcjs.checkVideoEffectValues.call(void 0, d2, values, { base: _nullishCoalesce(current.values, () => ( {})), keyframes: true }) } }, label: `Change ${_nullishCoalesce(current.name, () => ( d2.name))}`, clip };
|
|
3818
4040
|
}
|
|
3819
4041
|
const t = current.transition;
|
|
3820
|
-
if (_optionalChain([t, 'optionalAccess',
|
|
4042
|
+
if (_optionalChain([t, 'optionalAccess', _122 => _122.type]) !== "effect" || !t.effect) throw new Error(`Clip "${clip}" has no effect transition.`);
|
|
3821
4043
|
const d = await this.describeEffect(t.effect.effect);
|
|
3822
|
-
const merged =
|
|
4044
|
+
const merged = _chunk5T3H7CGGcjs.checkVideoEffectValues.call(void 0, d, values, { base: _nullishCoalesce(t.effect.values, () => ( {})) });
|
|
3823
4045
|
return { edit: { op: "set_transition", clip, transition: { ...t, effect: { ...t.effect, values: merged } } }, label: `Change transition ${d.name}`, clip };
|
|
3824
4046
|
}, options.merge);
|
|
3825
4047
|
}
|
|
3826
4048
|
/** 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). */
|
|
3827
4049
|
setClipEffectKeyframes(clip, instance, control, keys) {
|
|
3828
|
-
const current = _optionalChain([
|
|
3829
|
-
const was = _optionalChain([current, 'optionalAccess',
|
|
3830
|
-
const value = _optionalChain([was, 'optionalAccess',
|
|
3831
|
-
const plain = keys === null ?
|
|
4050
|
+
const current = _optionalChain([_chunk5T3H7CGGcjs.findVideoClip.call(void 0, this.project, clip), 'optionalAccess', _123 => _123.clip]);
|
|
4051
|
+
const was = _optionalChain([current, 'optionalAccess', _124 => _124.effects, 'optionalAccess', _125 => _125.find, 'call', _126 => _126((e) => e.id === instance)]);
|
|
4052
|
+
const value = _optionalChain([was, 'optionalAccess', _127 => _127.values, 'optionalAccess', _128 => _128[control]]);
|
|
4053
|
+
const plain = keys === null ? _chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, value) ? _optionalChain([value, 'access', _129 => _129.keys, 'access', _130 => _130[0], 'optionalAccess', _131 => _131.v]) : value : { keys: [...keys].sort((a, b) => a.t - b.t) };
|
|
3832
4054
|
return this.updateClipEffect(clip, instance, { values: { [control]: _nullishCoalesce(plain, () => ( null)) } });
|
|
3833
4055
|
}
|
|
3834
4056
|
/** What plays at `time` (default: the playhead). */
|
|
3835
4057
|
frame(time = this.player.currentTime) {
|
|
3836
|
-
return
|
|
4058
|
+
return _chunk5T3H7CGGcjs.videoFrameAt.call(void 0, this.project, time);
|
|
3837
4059
|
}
|
|
3838
4060
|
/** The frame at `time` (default: the playhead) as SVG. */
|
|
3839
4061
|
toSvg(time = this.player.currentTime, options = {}) {
|
|
3840
|
-
return
|
|
4062
|
+
return _chunk5T3H7CGGcjs.videoProjectSvg.call(void 0, this.project, time, { lutFor: (src) => this.luts.peek(src), ...options });
|
|
3841
4063
|
}
|
|
3842
4064
|
/** The project as an ffmpeg command. */
|
|
3843
4065
|
toFfmpeg(options = {}) {
|
|
3844
|
-
return
|
|
4066
|
+
return _chunk5T3H7CGGcjs.toVideoFfmpeg.call(void 0, this.project, options);
|
|
3845
4067
|
}
|
|
3846
4068
|
/** The ffmpeg command that measures the mix's loudness (see `toVideoLoudnessMeasure`). */
|
|
3847
4069
|
toLoudnessMeasure(options = {}) {
|
|
3848
|
-
return
|
|
4070
|
+
return _chunk5T3H7CGGcjs.toVideoLoudnessMeasure.call(void 0, this.project, options);
|
|
3849
4071
|
}
|
|
3850
4072
|
/** One track as a CMX 3600 EDL. */
|
|
3851
4073
|
toEdl(options = {}) {
|
|
3852
|
-
return
|
|
4074
|
+
return _chunk5T3H7CGGcjs.toVideoEdl.call(void 0, this.project, options);
|
|
3853
4075
|
}
|
|
3854
4076
|
}, _class7.__initStatic(), _class7);
|
|
3855
4077
|
function checkPreviewScale(scale) {
|
|
@@ -3883,7 +4105,7 @@ function planVideoToolPlayback(tool, args) {
|
|
|
3883
4105
|
const clips = clipsOf(args);
|
|
3884
4106
|
const track = str2(args.track) ? args.track : void 0;
|
|
3885
4107
|
const newClip = args.clip && typeof args.clip === "object" ? args.clip : null;
|
|
3886
|
-
const time = [args.start, args.at, args.time, args.to, _optionalChain([newClip, 'optionalAccess',
|
|
4108
|
+
const time = [args.start, args.at, args.time, args.to, _optionalChain([newClip, 'optionalAccess', _132 => _132.start])].find(num2);
|
|
3887
4109
|
const click = (ref) => [{ type: "target", ref }, { type: "press" }, { type: "release" }];
|
|
3888
4110
|
if (clips.length === 1 && (time !== void 0 || track) && tool !== "split_video_clip") {
|
|
3889
4111
|
const clip = clips[0];
|
|
@@ -3917,12 +4139,12 @@ function videoRulerTicks(duration, pxPerSecond, fps) {
|
|
|
3917
4139
|
const ticks = [];
|
|
3918
4140
|
for (let t = 0; t <= duration + 1e-6; t += step) {
|
|
3919
4141
|
const isMajor = Math.abs(t / major - Math.round(t / major)) < 1e-9;
|
|
3920
|
-
ticks.push({ time: t, x: t * pxPerMs, major: isMajor, ...isMajor ? { label:
|
|
4142
|
+
ticks.push({ time: t, x: t * pxPerMs, major: isMajor, ...isMajor ? { label: _chunk5T3H7CGGcjs.formatVideoTimecode.call(void 0, t, fps).replace(/^00:/, "") } : {} });
|
|
3921
4143
|
}
|
|
3922
4144
|
return ticks;
|
|
3923
4145
|
}
|
|
3924
4146
|
function videoClipShowsWaveform(clip, asset, mode = "audio") {
|
|
3925
|
-
if (clip.type !== "media" || mode === "none" || !
|
|
4147
|
+
if (clip.type !== "media" || mode === "none" || !_chunk5T3H7CGGcjs.videoAssetHasSound.call(void 0, asset)) return false;
|
|
3926
4148
|
return mode === "all" || asset.kind === "audio";
|
|
3927
4149
|
}
|
|
3928
4150
|
var VIDEO_CLIP_ANIMATION_LABELS = {
|
|
@@ -3979,15 +4201,15 @@ function videoClipLabel(clip, asset, sequence) {
|
|
|
3979
4201
|
if (clip.name) return clip.name;
|
|
3980
4202
|
if (clip.type === "text") return clip.text.split("\n")[0];
|
|
3981
4203
|
if (clip.type === "color") return clip.color;
|
|
3982
|
-
if (clip.type === "sequence") return `Compound: ${_nullishCoalesce(_optionalChain([sequence, 'optionalAccess',
|
|
4204
|
+
if (clip.type === "sequence") return `Compound: ${_nullishCoalesce(_optionalChain([sequence, 'optionalAccess', _133 => _133.name]), () => ( clip.sequence))}`;
|
|
3983
4205
|
if (clip.type === "effect") return `Effect: ${clip.effect}`;
|
|
3984
4206
|
if (clip.type === "adjustment") return `Adjustment${clip.scope === "all" ? " (all tracks)" : clip.scope === "track" ? ` (${clip.targetTrack})` : ""}`;
|
|
3985
|
-
const base = _nullishCoalesce(_nullishCoalesce(_optionalChain([asset, 'optionalAccess',
|
|
3986
|
-
const speed =
|
|
4207
|
+
const base = _nullishCoalesce(_nullishCoalesce(_optionalChain([asset, 'optionalAccess', _134 => _134.name]), () => ( _optionalChain([asset, 'optionalAccess', _135 => _135.src, 'access', _136 => _136.replace, 'call', _137 => _137(/^.*[\\/]/, "")]))), () => ( clip.asset));
|
|
4208
|
+
const speed = _chunk5T3H7CGGcjs.videoClipSpeed.call(void 0, clip);
|
|
3987
4209
|
return speed !== 1 ? `${base} (${Math.round(speed * 100)}%)` : base;
|
|
3988
4210
|
}
|
|
3989
4211
|
function planVideoClipDrag(project, input) {
|
|
3990
|
-
const at =
|
|
4212
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, project, input.clip);
|
|
3991
4213
|
if (!at) return null;
|
|
3992
4214
|
const { clip, track } = at;
|
|
3993
4215
|
const snap = _nullishCoalesce(input.snap, () => ( ((t) => t)));
|
|
@@ -4004,17 +4226,17 @@ function planVideoClipDrag(project, input) {
|
|
|
4004
4226
|
}
|
|
4005
4227
|
const minimum = 1e3 / project.fps;
|
|
4006
4228
|
if (input.mode === "trim-start") {
|
|
4007
|
-
const to2 = Math.min(snap(Math.max(0, clip.start + input.delta)),
|
|
4229
|
+
const to2 = Math.min(snap(Math.max(0, clip.start + input.delta)), _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip) - minimum);
|
|
4008
4230
|
const changed2 = Math.abs(to2 - clip.start) > 1e-6;
|
|
4009
|
-
const plan = input.ripple ? { start: clip.start, duration: clip.duration - (to2 - clip.start) } : { start: to2, duration:
|
|
4231
|
+
const plan = input.ripple ? { start: clip.start, duration: clip.duration - (to2 - clip.start) } : { start: to2, duration: _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip) - to2 };
|
|
4010
4232
|
return { ...plan, track: track.id, edit: changed2 ? { op: "trim_clip", clip: clip.id, edge: "start", to: to2, ...input.ripple ? { ripple: true } : {} } : null };
|
|
4011
4233
|
}
|
|
4012
|
-
const to = Math.max(snap(
|
|
4013
|
-
const changed = Math.abs(to -
|
|
4234
|
+
const to = Math.max(snap(_chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip) + input.delta), clip.start + minimum);
|
|
4235
|
+
const changed = Math.abs(to - _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip)) > 1e-6;
|
|
4014
4236
|
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 };
|
|
4015
4237
|
}
|
|
4016
4238
|
function videoDropTracks(project, clipId) {
|
|
4017
|
-
const at =
|
|
4239
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, project, clipId);
|
|
4018
4240
|
if (!at) return [];
|
|
4019
4241
|
return project.tracks.filter((t) => t.kind === at.track.kind && !t.locked).map((t) => t.id);
|
|
4020
4242
|
}
|
|
@@ -4023,10 +4245,10 @@ function videoDragLabel(edit) {
|
|
|
4023
4245
|
return edit.op === "trim_clip" && edit.ripple ? "Ripple trim" : "Trim clip";
|
|
4024
4246
|
}
|
|
4025
4247
|
function videoAssetDropEdit(project, assetId, options = {}) {
|
|
4026
|
-
const asset =
|
|
4248
|
+
const asset = _chunk5T3H7CGGcjs.videoAssetMap.call(void 0, project).get(assetId);
|
|
4027
4249
|
if (!asset) return null;
|
|
4028
4250
|
const kind = asset.kind === "audio" ? "audio" : "video";
|
|
4029
|
-
const track = _nullishCoalesce(options.track, () => ( _optionalChain([project, 'access',
|
|
4251
|
+
const track = _nullishCoalesce(options.track, () => ( _optionalChain([project, 'access', _138 => _138.tracks, 'access', _139 => _139.find, 'call', _140 => _140((t) => t.kind === kind && !t.locked), 'optionalAccess', _141 => _141.id])));
|
|
4030
4252
|
if (!track) return null;
|
|
4031
4253
|
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 } : {} };
|
|
4032
4254
|
}
|
|
@@ -4041,7 +4263,7 @@ function probeVideoMedia(src, kind, timeout = 15e3) {
|
|
|
4041
4263
|
return new Promise((resolve, reject) => {
|
|
4042
4264
|
if (typeof document === "undefined") return reject(new Error("Media can only be probed in a browser."));
|
|
4043
4265
|
const timer = setTimeout(() => reject(new Error(`"${src}" took too long to load.`)), timeout);
|
|
4044
|
-
const
|
|
4266
|
+
const done2 = (probe) => {
|
|
4045
4267
|
clearTimeout(timer);
|
|
4046
4268
|
resolve(probe);
|
|
4047
4269
|
};
|
|
@@ -4051,7 +4273,7 @@ function probeVideoMedia(src, kind, timeout = 15e3) {
|
|
|
4051
4273
|
};
|
|
4052
4274
|
if (kind === "image") {
|
|
4053
4275
|
const img = new Image();
|
|
4054
|
-
img.onload = () =>
|
|
4276
|
+
img.onload = () => done2({ kind, width: img.naturalWidth, height: img.naturalHeight });
|
|
4055
4277
|
img.onerror = failed;
|
|
4056
4278
|
img.src = src;
|
|
4057
4279
|
return;
|
|
@@ -4061,7 +4283,7 @@ function probeVideoMedia(src, kind, timeout = 15e3) {
|
|
|
4061
4283
|
el.onloadedmetadata = () => {
|
|
4062
4284
|
const duration = Number.isFinite(el.duration) ? Math.round(el.duration * 1e3) : void 0;
|
|
4063
4285
|
const v = el;
|
|
4064
|
-
|
|
4286
|
+
done2({ kind, ...duration ? { duration } : {}, ...kind === "video" && v.videoWidth ? { width: v.videoWidth, height: v.videoHeight } : {} });
|
|
4065
4287
|
};
|
|
4066
4288
|
el.onerror = failed;
|
|
4067
4289
|
el.src = src;
|
|
@@ -4075,25 +4297,25 @@ var KEY_LABELS = {
|
|
|
4075
4297
|
scale: { label: "Scale", step: 0.05 },
|
|
4076
4298
|
rotation: { label: "Rotation", step: 1 }
|
|
4077
4299
|
};
|
|
4078
|
-
var animatableOf = (clip, property) =>
|
|
4300
|
+
var animatableOf = (clip, property) => _chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES.includes(property) ? _optionalChain([clip, 'access', _142 => _142.transform, 'optionalAccess', _143 => _143[property]]) : property === "volume" ? clip.type === "media" || clip.type === "sequence" ? clip.volume : void 0 : clip.opacity;
|
|
4079
4301
|
var playheadInClip = (clip, time) => Math.round(Math.min(clip.duration, Math.max(0, time - clip.start)));
|
|
4080
4302
|
function videoKeyframeRows(project, clipId, time) {
|
|
4081
|
-
const at =
|
|
4303
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, project, clipId);
|
|
4082
4304
|
if (!at) return [];
|
|
4083
4305
|
const { clip } = at;
|
|
4084
|
-
const asset = clip.type === "media" ?
|
|
4085
|
-
const visual = !(_optionalChain([asset, 'optionalAccess',
|
|
4086
|
-
const audible = clip.type === "media" &&
|
|
4087
|
-
const properties = [...visual ? ["opacity"] : [], ...audible ? ["volume"] : [], ...visual ?
|
|
4306
|
+
const asset = clip.type === "media" ? _chunk5T3H7CGGcjs.videoAssetMap.call(void 0, project).get(clip.asset) : void 0;
|
|
4307
|
+
const visual = !(_optionalChain([asset, 'optionalAccess', _144 => _144.kind]) === "audio" || at.track.kind === "audio");
|
|
4308
|
+
const audible = clip.type === "media" && _chunk5T3H7CGGcjs.videoAssetHasSound.call(void 0, asset) || clip.type === "sequence";
|
|
4309
|
+
const properties = [...visual ? ["opacity"] : [], ...audible ? ["volume"] : [], ...visual ? _chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES : []];
|
|
4088
4310
|
const clipTime = playheadInClip(clip, time);
|
|
4089
4311
|
return properties.map((property) => {
|
|
4090
4312
|
const prop = animatableOf(clip, property);
|
|
4091
|
-
const keys =
|
|
4092
|
-
const limits =
|
|
4313
|
+
const keys = _chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, prop) ? prop.keys : [];
|
|
4314
|
+
const limits = _chunk5T3H7CGGcjs.VIDEO_KEYFRAME_LIMITS[property];
|
|
4093
4315
|
return {
|
|
4094
4316
|
property,
|
|
4095
4317
|
...KEY_LABELS[property],
|
|
4096
|
-
value: Math.round(
|
|
4318
|
+
value: Math.round(_chunk5T3H7CGGcjs.videoValueAt.call(void 0, prop, clipTime, limits.default) * 1e3) / 1e3,
|
|
4097
4319
|
keyed: keys.length > 0,
|
|
4098
4320
|
keys: keys.length,
|
|
4099
4321
|
onKey: keys.some((k) => Math.abs(k.t - clipTime) < 0.5),
|
|
@@ -4104,44 +4326,44 @@ function videoKeyframeRows(project, clipId, time) {
|
|
|
4104
4326
|
});
|
|
4105
4327
|
}
|
|
4106
4328
|
function plainValueEdit(clip, property, value) {
|
|
4107
|
-
if (!
|
|
4329
|
+
if (!_chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES.includes(property))
|
|
4108
4330
|
return value === void 0 ? { op: "update_clip", clip: clip.id, remove: [property] } : { op: "update_clip", clip: clip.id, set: { [property]: value } };
|
|
4109
4331
|
const transform = { ...clip.transform, [property]: value };
|
|
4110
4332
|
if (value === void 0) delete transform[property];
|
|
4111
4333
|
return Object.keys(transform).length ? { op: "update_clip", clip: clip.id, set: { transform } } : { op: "update_clip", clip: clip.id, remove: ["transform"] };
|
|
4112
4334
|
}
|
|
4113
4335
|
function videoKeyframeValueEdit(project, clipId, property, time, value) {
|
|
4114
|
-
const at =
|
|
4336
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, project, clipId);
|
|
4115
4337
|
if (!at) return null;
|
|
4116
4338
|
const prop = animatableOf(at.clip, property);
|
|
4117
|
-
if (!
|
|
4339
|
+
if (!_chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, prop)) return plainValueEdit(at.clip, property, value);
|
|
4118
4340
|
if (value === void 0) return null;
|
|
4119
|
-
return { op: "set_keyframes", clip: clipId, property, keys:
|
|
4341
|
+
return { op: "set_keyframes", clip: clipId, property, keys: _chunk5T3H7CGGcjs.setVideoKey.call(void 0, prop, { t: playheadInClip(at.clip, time), v: value }, _chunk5T3H7CGGcjs.VIDEO_KEYFRAME_LIMITS[property].default).keys };
|
|
4120
4342
|
}
|
|
4121
4343
|
function videoKeyframeToggleEdit(project, clipId, property, time) {
|
|
4122
|
-
const at =
|
|
4344
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, project, clipId);
|
|
4123
4345
|
if (!at) return null;
|
|
4124
4346
|
const prop = animatableOf(at.clip, property);
|
|
4125
4347
|
const t = playheadInClip(at.clip, time);
|
|
4126
|
-
const fallback =
|
|
4127
|
-
if (
|
|
4348
|
+
const fallback = _chunk5T3H7CGGcjs.VIDEO_KEYFRAME_LIMITS[property].default;
|
|
4349
|
+
if (_chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, prop)) {
|
|
4128
4350
|
const key = prop.keys.find((k) => Math.abs(k.t - t) < 0.5);
|
|
4129
4351
|
if (key) {
|
|
4130
|
-
const rest =
|
|
4131
|
-
return
|
|
4352
|
+
const rest = _chunk5T3H7CGGcjs.removeVideoKey.call(void 0, prop, key.t);
|
|
4353
|
+
return _chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, rest) ? { op: "set_keyframes", clip: clipId, property, keys: rest.keys } : plainValueEdit(at.clip, property, rest === fallback ? void 0 : rest);
|
|
4132
4354
|
}
|
|
4133
4355
|
}
|
|
4134
|
-
const v =
|
|
4135
|
-
return { op: "set_keyframes", clip: clipId, property, keys:
|
|
4356
|
+
const v = _chunk5T3H7CGGcjs.videoValueAt.call(void 0, prop, t, fallback);
|
|
4357
|
+
return { op: "set_keyframes", clip: clipId, property, keys: _chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, prop) ? _chunk5T3H7CGGcjs.setVideoKey.call(void 0, prop, { t, v }, fallback).keys : [{ t, v }] };
|
|
4136
4358
|
}
|
|
4137
4359
|
function videoLutEdits(project, clips, lut) {
|
|
4138
4360
|
const edits = [];
|
|
4139
4361
|
for (const id of clips) {
|
|
4140
|
-
const at =
|
|
4362
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, project, id);
|
|
4141
4363
|
if (!at) continue;
|
|
4142
4364
|
const { lut: current, ...rest } = _nullishCoalesce(at.clip.grade, () => ( {}));
|
|
4143
4365
|
if (!lut && !current) continue;
|
|
4144
|
-
const grade =
|
|
4366
|
+
const grade = _chunk5T3H7CGGcjs.normalizeVideoGrade.call(void 0, lut ? { ...rest, lut } : rest);
|
|
4145
4367
|
edits.push(grade ? { op: "update_clip", clip: id, set: { grade } } : { op: "update_clip", clip: id, remove: ["grade"] });
|
|
4146
4368
|
}
|
|
4147
4369
|
return edits;
|
|
@@ -4162,9 +4384,9 @@ function videoAddAdjustmentEdits(project, time, options = {}) {
|
|
|
4162
4384
|
const duration = _nullishCoalesce(options.duration, () => ( 3e3));
|
|
4163
4385
|
const start = Math.max(0, time);
|
|
4164
4386
|
const top = project.tracks[0];
|
|
4165
|
-
const free = top && top.kind === "video" && !top.locked && !top.clips.some((c) => c.start < start + duration &&
|
|
4387
|
+
const free = top && top.kind === "video" && !top.locked && !top.clips.some((c) => c.start < start + duration && _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c) > start);
|
|
4166
4388
|
const edits = [];
|
|
4167
|
-
let track = _optionalChain([top, 'optionalAccess',
|
|
4389
|
+
let track = _optionalChain([top, 'optionalAccess', _145 => _145.id]);
|
|
4168
4390
|
if (!free) {
|
|
4169
4391
|
const ids = new Set(project.tracks.map((t) => t.id));
|
|
4170
4392
|
let n = 1;
|
|
@@ -4181,8 +4403,8 @@ function videoMaskEdit(clip, mask) {
|
|
|
4181
4403
|
function videoSkinProtectionEdits(project, clips, amount) {
|
|
4182
4404
|
const edits = [];
|
|
4183
4405
|
for (const id of clips) {
|
|
4184
|
-
const clip = _optionalChain([
|
|
4185
|
-
const lut = _optionalChain([clip, 'optionalAccess',
|
|
4406
|
+
const clip = _optionalChain([_chunk5T3H7CGGcjs.findVideoClip.call(void 0, project, id), 'optionalAccess', _146 => _146.clip]);
|
|
4407
|
+
const lut = _optionalChain([clip, 'optionalAccess', _147 => _147.grade, 'optionalAccess', _148 => _148.lut]);
|
|
4186
4408
|
if (!clip || !lut) continue;
|
|
4187
4409
|
const { preserveSkinTones: _p, ...rest } = lut;
|
|
4188
4410
|
const k = Math.min(1, Math.max(0, amount));
|
|
@@ -4215,7 +4437,7 @@ var RIPPLE = {
|
|
|
4215
4437
|
};
|
|
4216
4438
|
var MODE = {
|
|
4217
4439
|
type: "string",
|
|
4218
|
-
enum: [...
|
|
4440
|
+
enum: [..._chunk5T3H7CGGcjs.VIDEO_PLACEMENT_MODES],
|
|
4219
4441
|
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.'
|
|
4220
4442
|
};
|
|
4221
4443
|
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.` });
|
|
@@ -4232,11 +4454,11 @@ var TRANSFORM = object(
|
|
|
4232
4454
|
);
|
|
4233
4455
|
var TRANSITION = object(
|
|
4234
4456
|
{
|
|
4235
|
-
type: { type: "string", enum:
|
|
4457
|
+
type: { type: "string", enum: _chunk5T3H7CGGcjs.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." },
|
|
4236
4458
|
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." },
|
|
4237
4459
|
color: COLOR("For dip: the colour passed through (default black)"),
|
|
4238
|
-
direction: { type: "string", enum: [...
|
|
4239
|
-
audioCurve: { type: "string", enum: [...
|
|
4460
|
+
direction: { type: "string", enum: [..._chunk5T3H7CGGcjs.VIDEO_WIPE_DIRECTIONS], description: "For wipe, push and slide: the way the edge or picture travels (default right, coming in from the left)." },
|
|
4461
|
+
audioCurve: { type: "string", enum: [..._chunk5T3H7CGGcjs.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." }
|
|
4240
4462
|
},
|
|
4241
4463
|
["type", "duration"],
|
|
4242
4464
|
"A transition from the clip that ends where this one starts on the same track."
|
|
@@ -4246,7 +4468,7 @@ var LUT_STRENGTH = { type: "number", minimum: 0, maximum: 1, description: "How m
|
|
|
4246
4468
|
var SKIN = { type: "number", minimum: 0, maximum: 1, description: "How much of the LUT's change to hold back on skin tones, 0 (none, the default) to 1 (skin keeps its colour); 0.5-0.8 keeps faces natural under a heavy look. Applied in the preview and frame renders; ffmpeg's lut3d cannot, so the export notes it." };
|
|
4247
4469
|
var GRADE = object(
|
|
4248
4470
|
{
|
|
4249
|
-
...Object.fromEntries(
|
|
4471
|
+
...Object.fromEntries(_chunk5T3H7CGGcjs.VIDEO_GRADE_CONTROLS.map((c) => [c.key, { type: "number", minimum: c.min, maximum: c.max, description: c.description }])),
|
|
4250
4472
|
lut: object({ src: LUT_SRC, strength: LUT_STRENGTH, name: { type: "string", minLength: 1, description: "A label for the look." }, preserveSkinTones: SKIN }, ["src"], "A 3D LUT applied after the other settings (set_video_lut checks the file first).")
|
|
4251
4473
|
},
|
|
4252
4474
|
[],
|
|
@@ -4254,7 +4476,7 @@ var GRADE = object(
|
|
|
4254
4476
|
);
|
|
4255
4477
|
var ANIMATION = (when) => object(
|
|
4256
4478
|
{
|
|
4257
|
-
effect: { type: "string", enum: [...
|
|
4479
|
+
effect: { type: "string", enum: [..._chunk5T3H7CGGcjs.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." },
|
|
4258
4480
|
duration: { type: "number", exclusiveMinimum: 0, description: "Length in ms (default 500)." }
|
|
4259
4481
|
},
|
|
4260
4482
|
["effect"],
|
|
@@ -4264,11 +4486,11 @@ var CLIP_COMMON = {
|
|
|
4264
4486
|
name: { type: "string", description: "A label for the clip." },
|
|
4265
4487
|
opacity: { type: "number", minimum: 0, maximum: 1, description: "Opacity 0\u20131 (default 1). A number replaces any keyframes; set_video_keyframes animates it." },
|
|
4266
4488
|
transform: TRANSFORM,
|
|
4267
|
-
fit: { type: "string", enum: [...
|
|
4489
|
+
fit: { type: "string", enum: [..._chunk5T3H7CGGcjs.VIDEO_FITS], description: "How the picture fits the frame before the transform, as CSS object-fit (default contain for media, fill for colours)." },
|
|
4268
4490
|
grade: GRADE,
|
|
4269
4491
|
animateIn: ANIMATION("How the picture enters, from the clip's start (on top of any fade in). Titles usually rise, pop or fade in."),
|
|
4270
4492
|
animateOut: ANIMATION("How the picture leaves, ending at the clip's end."),
|
|
4271
|
-
blend: { type: "string", enum: [...
|
|
4493
|
+
blend: { type: "string", enum: [..._chunk5T3H7CGGcjs.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." },
|
|
4272
4494
|
fadeIn: MS("Fade up from nothing (picture and sound) over this long"),
|
|
4273
4495
|
fadeOut: MS("Fade down to nothing over this long")
|
|
4274
4496
|
};
|
|
@@ -4277,8 +4499,8 @@ var MEDIA_FIELDS = {
|
|
|
4277
4499
|
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." },
|
|
4278
4500
|
volume: { type: "number", minimum: 0, maximum: 4, description: "Gain (1 = unchanged, default 1). A number replaces any keyframes; set_video_keyframes animates it." },
|
|
4279
4501
|
muted: { type: "boolean", description: "Silence this clip (default false)." },
|
|
4280
|
-
fadeInCurve: { type: "string", enum: [...
|
|
4281
|
-
fadeOutCurve: { type: "string", enum: [...
|
|
4502
|
+
fadeInCurve: { type: "string", enum: [..._chunk5T3H7CGGcjs.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)." },
|
|
4503
|
+
fadeOutCurve: { type: "string", enum: [..._chunk5T3H7CGGcjs.VIDEO_FADE_CURVES], description: "Shape of the sound's fade out (default linear), the same choices as fadeInCurve; exponential sounds natural fading to silence." }
|
|
4282
4504
|
};
|
|
4283
4505
|
var TEXT_FIELDS = {
|
|
4284
4506
|
text: { type: "string", minLength: 1, description: `The title's text ("\\n" breaks lines).` },
|
|
@@ -4327,7 +4549,7 @@ var ASSET_FIELDS = {
|
|
|
4327
4549
|
};
|
|
4328
4550
|
var KEY_PROPERTY = {
|
|
4329
4551
|
type: "string",
|
|
4330
|
-
enum: [...
|
|
4552
|
+
enum: [..._chunk5T3H7CGGcjs.VIDEO_KEYFRAME_PROPERTIES],
|
|
4331
4553
|
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)."
|
|
4332
4554
|
};
|
|
4333
4555
|
var KEYS = {
|
|
@@ -4342,7 +4564,7 @@ var KEYS = {
|
|
|
4342
4564
|
ease: {
|
|
4343
4565
|
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.",
|
|
4344
4566
|
anyOf: [
|
|
4345
|
-
{ type: "string", enum: [...
|
|
4567
|
+
{ type: "string", enum: [..._chunk5T3H7CGGcjs.VIDEO_EASE_NAMES] },
|
|
4346
4568
|
{ type: "array", items: { type: "number" }, minItems: 4, maxItems: 4 }
|
|
4347
4569
|
]
|
|
4348
4570
|
}
|
|
@@ -4371,19 +4593,19 @@ var describeVideoTracks = (tracks) => tracks.map((t, index) => ({
|
|
|
4371
4593
|
...t.locked ? { locked: true } : {},
|
|
4372
4594
|
...t.syncLocked === false ? { syncLocked: false } : {},
|
|
4373
4595
|
...t.volume !== void 0 ? { volume: t.volume } : {},
|
|
4374
|
-
clips:
|
|
4596
|
+
clips: _chunk5T3H7CGGcjs.sortedVideoClips.call(void 0, t).map((c) => ({ ...c, end: _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c), ...c.type === "media" || c.type === "sequence" ? { source: _chunk5T3H7CGGcjs.videoClipSourceRange.call(void 0, c) } : {} }))
|
|
4375
4597
|
}));
|
|
4376
|
-
var videoSequenceUsers = (project, id) =>
|
|
4377
|
-
({ 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:
|
|
4598
|
+
var videoSequenceUsers = (project, id) => _chunk5T3H7CGGcjs.allVideoTracks.call(void 0, project).flatMap(
|
|
4599
|
+
({ 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: _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c), source: _chunk5T3H7CGGcjs.videoClipSourceRange.call(void 0, c) }] : [])
|
|
4378
4600
|
);
|
|
4379
4601
|
function describeVideoSequence(project, sequence, tracks = true) {
|
|
4380
|
-
const cycle =
|
|
4602
|
+
const cycle = _chunk5T3H7CGGcjs.findVideoSequenceCycle.call(void 0, project, sequence.id);
|
|
4381
4603
|
return {
|
|
4382
4604
|
id: sequence.id,
|
|
4383
4605
|
...sequence.name ? { name: sequence.name } : {},
|
|
4384
|
-
duration:
|
|
4606
|
+
duration: _chunk5T3H7CGGcjs.videoSequenceDuration.call(void 0, sequence),
|
|
4385
4607
|
clipCount: sequence.tracks.reduce((n, t) => n + t.clips.length, 0),
|
|
4386
|
-
nests:
|
|
4608
|
+
nests: _chunk5T3H7CGGcjs.videoSequenceChildren.call(void 0, sequence),
|
|
4387
4609
|
usedBy: videoSequenceUsers(project, sequence.id),
|
|
4388
4610
|
...cycle ? { cycle } : {},
|
|
4389
4611
|
...tracks ? { tracks: describeVideoTracks(sequence.tracks) } : { trackCount: sequence.tracks.length }
|
|
@@ -4395,11 +4617,11 @@ function describeVideoProject(project) {
|
|
|
4395
4617
|
width: project.width,
|
|
4396
4618
|
height: project.height,
|
|
4397
4619
|
fps: project.fps,
|
|
4398
|
-
duration:
|
|
4620
|
+
duration: _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, project),
|
|
4399
4621
|
...project.background ? { background: project.background } : {},
|
|
4400
4622
|
assets: project.assets.map(videoAssetOut),
|
|
4401
4623
|
tracks: describeVideoTracks(project.tracks),
|
|
4402
|
-
..._optionalChain([project, 'access',
|
|
4624
|
+
..._optionalChain([project, 'access', _149 => _149.sequences, 'optionalAccess', _150 => _150.length]) ? { sequences: project.sequences.map((q) => describeVideoSequence(project, q, false)) } : {},
|
|
4403
4625
|
markers: _nullishCoalesce(project.markers, () => ( []))
|
|
4404
4626
|
};
|
|
4405
4627
|
}
|
|
@@ -4412,7 +4634,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4412
4634
|
const project = () => controller.getProject();
|
|
4413
4635
|
const outcome = (result, extra = {}) => {
|
|
4414
4636
|
if (!result.ok) throw new Error(result.error);
|
|
4415
|
-
return { ...extra, duration:
|
|
4637
|
+
return { ...extra, duration: _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, result.project), issues: issueSummary(result.issues) };
|
|
4416
4638
|
};
|
|
4417
4639
|
const apply = (edits, label, extra) => {
|
|
4418
4640
|
const result = controller.apply(edits, label);
|
|
@@ -4421,19 +4643,19 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4421
4643
|
const clipOut = (p, id) => {
|
|
4422
4644
|
for (const t of p.tracks) {
|
|
4423
4645
|
const c = t.clips.find((x) => x.id === id);
|
|
4424
|
-
if (c) return { track: t.id, ...c, end:
|
|
4646
|
+
if (c) return { track: t.id, ...c, end: _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c), ...c.type === "media" || c.type === "sequence" ? { source: _chunk5T3H7CGGcjs.videoClipSourceRange.call(void 0, c) } : {} };
|
|
4425
4647
|
}
|
|
4426
4648
|
return null;
|
|
4427
4649
|
};
|
|
4428
4650
|
const placed = (o) => ({
|
|
4429
|
-
..._optionalChain([o, 'access',
|
|
4430
|
-
..._optionalChain([o, 'access',
|
|
4431
|
-
..._optionalChain([o, 'access',
|
|
4651
|
+
..._optionalChain([o, 'access', _151 => _151.created, 'optionalAccess', _152 => _152.length]) ? { created: o.created } : {},
|
|
4652
|
+
..._optionalChain([o, 'access', _153 => _153.trimmed, 'optionalAccess', _154 => _154.length]) ? { trimmed: o.trimmed } : {},
|
|
4653
|
+
..._optionalChain([o, 'access', _155 => _155.removed, 'optionalAccess', _156 => _156.length]) ? { removed: o.removed } : {},
|
|
4432
4654
|
...o.rippled ? { rippled: o.rippled } : {}
|
|
4433
4655
|
});
|
|
4434
4656
|
const keysOut = (p, clip, property) => {
|
|
4435
4657
|
const c = clipOut(p, clip);
|
|
4436
|
-
const value =
|
|
4658
|
+
const value = _chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES.includes(property) ? _optionalChain([c, 'optionalAccess', _157 => _157.transform, 'optionalAccess', _158 => _158[property]]) : _optionalChain([c, 'optionalAccess', _159 => _159[property]]);
|
|
4437
4659
|
return typeof value === "object" ? { keys: value.keys } : { keys: [], value: _nullishCoalesce(value, () => ( null)) };
|
|
4438
4660
|
};
|
|
4439
4661
|
const getProject = {
|
|
@@ -4455,8 +4677,8 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4455
4677
|
inputSchema: object({ time: MS("Time from the start (default: the playhead)") }),
|
|
4456
4678
|
annotations: { title: "What plays at a moment", ...READ },
|
|
4457
4679
|
handler: ({ time }) => {
|
|
4458
|
-
const frame =
|
|
4459
|
-
return { ...frame, timecode:
|
|
4680
|
+
const frame = _chunk5T3H7CGGcjs.videoFrameAt.call(void 0, project(), _nullishCoalesce(time, () => ( controller.getState().time)));
|
|
4681
|
+
return { ...frame, timecode: _chunk5T3H7CGGcjs.formatVideoTimecode.call(void 0, frame.time, project().fps) };
|
|
4460
4682
|
}
|
|
4461
4683
|
};
|
|
4462
4684
|
const listSequences = {
|
|
@@ -4484,7 +4706,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4484
4706
|
annotations: { title: "Find gaps", ...READ },
|
|
4485
4707
|
handler: ({ track }) => {
|
|
4486
4708
|
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(", ")}.`);
|
|
4487
|
-
return { gaps:
|
|
4709
|
+
return { gaps: _chunk5T3H7CGGcjs.findVideoGaps.call(void 0, project(), track) };
|
|
4488
4710
|
}
|
|
4489
4711
|
};
|
|
4490
4712
|
const checkProject = {
|
|
@@ -4511,10 +4733,10 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4511
4733
|
annotations: { title: "Render a frame", ...READ },
|
|
4512
4734
|
handler: async ({ time, times, columns, format = "svg" }) => {
|
|
4513
4735
|
const p = project();
|
|
4514
|
-
const lutSrcs = [...new Set(p.tracks.flatMap((t) => t.clips.map((c) => _optionalChain([c, 'access',
|
|
4736
|
+
const lutSrcs = [...new Set(p.tracks.flatMap((t) => t.clips.map((c) => _optionalChain([c, 'access', _160 => _160.grade, 'optionalAccess', _161 => _161.lut, 'optionalAccess', _162 => _162.src])).filter((x) => !!x)))];
|
|
4515
4737
|
const missing = (await Promise.all(lutSrcs.map((src) => controller.luts.load(src).then(() => null, (e) => e.message)))).filter((m) => !!m);
|
|
4516
4738
|
const svgOptions = { lutFor: (src) => controller.luts.peek(src), ...columns ? { columns } : {} };
|
|
4517
|
-
const svg = times ?
|
|
4739
|
+
const svg = times ? _chunk5T3H7CGGcjs.videoContactSheetSvg.call(void 0, p, times, svgOptions) : _chunk5T3H7CGGcjs.videoProjectSvg.call(void 0, p, _nullishCoalesce(time, () => ( controller.getState().time)), svgOptions);
|
|
4518
4740
|
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."] : []];
|
|
4519
4741
|
if (format === "png") {
|
|
4520
4742
|
if (!options.rasterize) throw new Error('This host cannot make PNG images; call render_video_frame with format "svg".');
|
|
@@ -4604,7 +4826,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4604
4826
|
if (play === true) controller.play();
|
|
4605
4827
|
if (play === false) controller.pause();
|
|
4606
4828
|
const state = controller.getState();
|
|
4607
|
-
return { time: state.time, timecode:
|
|
4829
|
+
return { time: state.time, timecode: _chunk5T3H7CGGcjs.formatVideoTimecode.call(void 0, state.time, p.fps), playing: state.playing, clips: state.current };
|
|
4608
4830
|
}
|
|
4609
4831
|
};
|
|
4610
4832
|
const setSettings = {
|
|
@@ -4730,7 +4952,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4730
4952
|
inputSchema: object(
|
|
4731
4953
|
{
|
|
4732
4954
|
clip: CLIP_ID,
|
|
4733
|
-
set: object({ ...CLIP_COMMON, ...MEDIA_FIELDS, asset: { ...ASSET_ID, description: "For media: play another asset (same in point)." }, ...TEXT_FIELDS, color: COLOR("Text colour, or a colour clip's fill"), scope: { type: "string", enum: [...
|
|
4955
|
+
set: object({ ...CLIP_COMMON, ...MEDIA_FIELDS, asset: { ...ASSET_ID, description: "For media: play another asset (same in point)." }, ...TEXT_FIELDS, color: COLOR("Text colour, or a colour clip's fill"), scope: { type: "string", enum: [..._chunk5T3H7CGGcjs.VIDEO_ADJUSTMENT_SCOPES], description: "For adjustment clips: which pictures it changes, underneath (default), all or track." }, targetTrack: { ...TRACK_ID, description: 'For adjustment clips with scope "track": the track whose pictures it changes.' } }, [], "Fields to replace (only those that fit the clip's type)."),
|
|
4734
4956
|
remove: { type: "array", items: { type: "string", enum: ["name", "opacity", "transform", "fit", "blend", "grade", "animateIn", "animateOut", "fadeIn", "fadeOut", "fadeInCurve", "fadeOutCurve", "in", "speed", "volume", "muted", "fontSize", "fontFamily", "fontWeight", "background", "scope", "targetTrack"] }, description: 'Fields to reset to their defaults (an adjustment clip going from scope "track" to another scope must also remove targetTrack).' }
|
|
4735
4957
|
},
|
|
4736
4958
|
["clip"]
|
|
@@ -4749,10 +4971,10 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4749
4971
|
const gradeTargets = (ids) => {
|
|
4750
4972
|
const p = project();
|
|
4751
4973
|
for (const id of ids) {
|
|
4752
|
-
const at =
|
|
4974
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, p, id);
|
|
4753
4975
|
if (!at) throw new Error(`There is no clip "${id}"; get_video_project lists the clips.`);
|
|
4754
4976
|
const { clip } = at;
|
|
4755
|
-
if (at.track.kind !== "video" || clip.type === "media" && _optionalChain([p, 'access',
|
|
4977
|
+
if (at.track.kind !== "video" || clip.type === "media" && _optionalChain([p, 'access', _163 => _163.assets, 'access', _164 => _164.find, 'call', _165 => _165((a) => a.id === clip.asset), 'optionalAccess', _166 => _166.kind]) === "audio")
|
|
4756
4978
|
throw new Error(`Clip "${id}" is sound only; grades change pictures. Pass clips on video tracks.`);
|
|
4757
4979
|
}
|
|
4758
4980
|
};
|
|
@@ -4763,7 +4985,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4763
4985
|
inputSchema: object(
|
|
4764
4986
|
{
|
|
4765
4987
|
clips: { type: "array", items: CLIP_ID, minItems: 1, description: "Clips on video tracks to grade." },
|
|
4766
|
-
preset: { type: "string", enum: [...
|
|
4988
|
+
preset: { type: "string", enum: [..._chunk5T3H7CGGcjs.VIDEO_GRADE_PRESET_NAMES], description: "The look." },
|
|
4767
4989
|
amount: { type: "number", minimum: 0, maximum: 1, description: "Strength, 0 (none) to 1 (full, the default); 0.5 is a subtler version." }
|
|
4768
4990
|
},
|
|
4769
4991
|
["clips", "preset"]
|
|
@@ -4772,10 +4994,10 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4772
4994
|
handler: ({ clips, preset, amount }) => {
|
|
4773
4995
|
gradeTargets(clips);
|
|
4774
4996
|
const edits = clips.map((clip) => {
|
|
4775
|
-
const grade =
|
|
4997
|
+
const grade = _chunk5T3H7CGGcjs.videoGradeLook.call(void 0, _chunk5T3H7CGGcjs.findVideoClip.call(void 0, project(), clip).clip.grade, preset, _nullishCoalesce(amount, () => ( 1)));
|
|
4776
4998
|
return grade ? { op: "update_clip", clip, set: { grade } } : { op: "update_clip", clip, remove: ["grade"] };
|
|
4777
4999
|
});
|
|
4778
|
-
return apply(edits, `Apply ${preset} look`, (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([
|
|
5000
|
+
return apply(edits, `Apply ${preset} look`, (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([_chunk5T3H7CGGcjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _167 => _167.clip, 'access', _168 => _168.grade]), () => ( null)) })) }));
|
|
4779
5001
|
}
|
|
4780
5002
|
};
|
|
4781
5003
|
const copyGrade = {
|
|
@@ -4786,7 +5008,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4786
5008
|
annotations: { title: "Copy a colour grade", ...WRITE_IDEMPOTENT },
|
|
4787
5009
|
handler: ({ from, to }) => {
|
|
4788
5010
|
gradeTargets([from, ...to]);
|
|
4789
|
-
const grade =
|
|
5011
|
+
const grade = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, project(), from).clip.grade;
|
|
4790
5012
|
const edits = to.map((clip) => grade ? { op: "update_clip", clip, set: { grade: { ...grade } } } : { op: "update_clip", clip, remove: ["grade"] });
|
|
4791
5013
|
return apply(edits, "Copy grade", () => ({ grade: _nullishCoalesce(grade, () => ( null)), clips: to }));
|
|
4792
5014
|
}
|
|
@@ -4812,7 +5034,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4812
5034
|
const lut = await controller.luts.load(src);
|
|
4813
5035
|
const label = _nullishCoalesce(name, () => ( lut.title));
|
|
4814
5036
|
const setting = { src, ...strength !== void 0 && strength !== 1 ? { strength } : {}, ...label ? { name: label } : {}, ...preserve_skin_tones ? { preserveSkinTones: preserve_skin_tones } : {} };
|
|
4815
|
-
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([
|
|
5037
|
+
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([_chunk5T3H7CGGcjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _169 => _169.clip, 'access', _170 => _170.grade]), () => ( null)) })) }));
|
|
4816
5038
|
}
|
|
4817
5039
|
};
|
|
4818
5040
|
const removeLut = {
|
|
@@ -4824,9 +5046,9 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4824
5046
|
handler: ({ clips }) => {
|
|
4825
5047
|
gradeTargets(clips);
|
|
4826
5048
|
const p = project();
|
|
4827
|
-
const withLut = clips.filter((id) => _optionalChain([
|
|
5049
|
+
const withLut = clips.filter((id) => _optionalChain([_chunk5T3H7CGGcjs.findVideoClip.call(void 0, p, id), 'access', _171 => _171.clip, 'access', _172 => _172.grade, 'optionalAccess', _173 => _173.lut]));
|
|
4828
5050
|
if (!withLut.length) throw new Error(`None of ${clips.map((c) => `"${c}"`).join(", ")} has a LUT; get_video_project shows each clip's grade.`);
|
|
4829
|
-
return apply(videoLutEdits(p, withLut, null), "Remove LUT", (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([
|
|
5051
|
+
return apply(videoLutEdits(p, withLut, null), "Remove LUT", (r) => ({ clips: clips.map((id) => ({ id, grade: _nullishCoalesce(_optionalChain([_chunk5T3H7CGGcjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _174 => _174.clip, 'access', _175 => _175.grade]), () => ( null)) })) }));
|
|
4830
5052
|
}
|
|
4831
5053
|
};
|
|
4832
5054
|
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." };
|
|
@@ -4884,7 +5106,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4884
5106
|
controller.setPreviewScale(scale);
|
|
4885
5107
|
const s = controller.getState().previewScale;
|
|
4886
5108
|
const fixed = s === "full" ? 1 : typeof s === "number" ? s : null;
|
|
4887
|
-
const plays = fixed === null ? void 0 : project().assets.filter((a) => a.kind === "video").map((a) => ({ asset: a.id, src: _nullishCoalesce(_optionalChain([videoAssetProxy, 'call',
|
|
5109
|
+
const plays = fixed === null ? void 0 : project().assets.filter((a) => a.kind === "video").map((a) => ({ asset: a.id, src: _nullishCoalesce(_optionalChain([videoAssetProxy, 'call', _176 => _176(a, fixed), 'optionalAccess', _177 => _177.src]), () => ( a.src)), proxy: !!videoAssetProxy(a, fixed) }));
|
|
4888
5110
|
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." } };
|
|
4889
5111
|
}
|
|
4890
5112
|
};
|
|
@@ -4935,7 +5157,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4935
5157
|
approximate: parsed.approximate,
|
|
4936
5158
|
first: list[0],
|
|
4937
5159
|
last: list[list.length - 1],
|
|
4938
|
-
...a.duration !== void 0 && list[list.length - 1].end > a.duration +
|
|
5160
|
+
...a.duration !== void 0 && list[list.length - 1].end > a.duration + _chunk5T3H7CGGcjs.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?` } : {}
|
|
4939
5161
|
}));
|
|
4940
5162
|
}
|
|
4941
5163
|
};
|
|
@@ -4953,7 +5175,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
4953
5175
|
handler: ({ track, from, to, limit }) => {
|
|
4954
5176
|
const all = timelineWords(track).filter((w) => w.end > (_nullishCoalesce(from, () => ( 0))) && w.start < (_nullishCoalesce(to, () => ( Infinity))));
|
|
4955
5177
|
const words = all.slice(0, _nullishCoalesce(limit, () => ( 1e3)));
|
|
4956
|
-
return { track: _nullishCoalesce(_optionalChain([words, 'access',
|
|
5178
|
+
return { track: _nullishCoalesce(_optionalChain([words, 'access', _178 => _178[0], 'optionalAccess', _179 => _179.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 };
|
|
4957
5179
|
}
|
|
4958
5180
|
};
|
|
4959
5181
|
const findText = {
|
|
@@ -5006,22 +5228,22 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
5006
5228
|
const bad = ranges.findIndex((r) => !(r.to > r.from));
|
|
5007
5229
|
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".`);
|
|
5008
5230
|
const merged = mergeVideoRanges(ranges);
|
|
5009
|
-
const before =
|
|
5010
|
-
return apply(videoRemoveRangesEdits(merged, tracks), merged.length > 1 ? `Cut ${merged.length} stretches` : "Cut stretch", (r) => ({ removed: merged.length, time: round(before -
|
|
5231
|
+
const before = _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, project());
|
|
5232
|
+
return apply(videoRemoveRangesEdits(merged, tracks), merged.length > 1 ? `Cut ${merged.length} stretches` : "Cut stretch", (r) => ({ removed: merged.length, time: round(before - _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, r.project)), duration: _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, r.project) }));
|
|
5011
5233
|
}
|
|
5012
5234
|
};
|
|
5013
5235
|
const rampTarget = (id) => {
|
|
5014
|
-
const at =
|
|
5236
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, project(), id);
|
|
5015
5237
|
if (!at) throw new Error(`There is no clip "${id}"; get_video_project lists the clips.`);
|
|
5016
5238
|
const { clip } = at;
|
|
5017
5239
|
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.`);
|
|
5018
|
-
if (clip.type !== "media") throw new Error(`Clip "${id}" is a ${
|
|
5019
|
-
if (_optionalChain([project, 'call',
|
|
5240
|
+
if (clip.type !== "media") throw new Error(`Clip "${id}" is a ${_chunk5T3H7CGGcjs.videoClipTypeLabel.call(void 0, clip)}, so it has no source to change the speed of; use a video or audio clip.`);
|
|
5241
|
+
if (_optionalChain([project, 'call', _180 => _180(), 'access', _181 => _181.assets, 'access', _182 => _182.find, 'call', _183 => _183((a) => a.id === clip.asset), 'optionalAccess', _184 => _184.kind]) === "image") throw new Error(`Clip "${id}" is a still, so it has no motion to change the speed of.`);
|
|
5020
5242
|
return clip;
|
|
5021
5243
|
};
|
|
5022
5244
|
const rampOut = (r, id) => {
|
|
5023
5245
|
const outcome2 = r.outcomes[r.outcomes.length - 1];
|
|
5024
|
-
return { clip: clipOut(r.project, id), ...outcome2.rippled ? { rippled: outcome2.rippled } : {}, duration:
|
|
5246
|
+
return { clip: clipOut(r.project, id), ...outcome2.rippled ? { rippled: outcome2.rippled } : {}, duration: _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, r.project) };
|
|
5025
5247
|
};
|
|
5026
5248
|
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." };
|
|
5027
5249
|
const setSpeedRamp = {
|
|
@@ -5052,8 +5274,8 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
5052
5274
|
),
|
|
5053
5275
|
annotations: { title: "Ramp the speed", ...WRITE_IDEMPOTENT },
|
|
5054
5276
|
handler: ({ clip, segments, ripple }) => {
|
|
5055
|
-
const edit =
|
|
5056
|
-
return apply(edit, "Speed ramp", (r) => ({ ...rampOut(r, clip), source: Math.round(
|
|
5277
|
+
const edit = _chunk5T3H7CGGcjs.videoSpeedRampEdit.call(void 0, rampTarget(clip), segments, _nullishCoalesce(ripple, () => ( true)));
|
|
5278
|
+
return apply(edit, "Speed ramp", (r) => ({ ...rampOut(r, clip), source: Math.round(_chunk5T3H7CGGcjs.videoSpeedRampKeys.call(void 0, segments).source) }));
|
|
5057
5279
|
}
|
|
5058
5280
|
};
|
|
5059
5281
|
const addFreeze = {
|
|
@@ -5073,8 +5295,8 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
5073
5295
|
handler: ({ clip, at, duration, ripple }) => {
|
|
5074
5296
|
const c = rampTarget(clip);
|
|
5075
5297
|
const t = at - c.start;
|
|
5076
|
-
if (t < 0 || t > c.duration) throw new Error(`${
|
|
5077
|
-
return apply(
|
|
5298
|
+
if (t < 0 || t > c.duration) throw new Error(`${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, at)} is outside clip "${clip}" (${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, c.start)}\u2013${_chunk5T3H7CGGcjs.formatVideoSeconds.call(void 0, _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c))}); pick a time inside it.`);
|
|
5299
|
+
return apply(_chunk5T3H7CGGcjs.videoFreezeFrameEdit.call(void 0, c, t, duration, _nullishCoalesce(ripple, () => ( true))), "Freeze frame", (r) => rampOut(r, clip));
|
|
5078
5300
|
}
|
|
5079
5301
|
};
|
|
5080
5302
|
const removeRamp = {
|
|
@@ -5247,7 +5469,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
5247
5469
|
let from;
|
|
5248
5470
|
let to;
|
|
5249
5471
|
if (args.clip !== void 0) {
|
|
5250
|
-
const found =
|
|
5472
|
+
const found = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, p, args.clip);
|
|
5251
5473
|
if (!found) throw new Error(`There is no clip "${args.clip}"; get_video_project lists the clips.`);
|
|
5252
5474
|
const c = found.clip;
|
|
5253
5475
|
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).`);
|
|
@@ -5257,7 +5479,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
5257
5479
|
toSource = (t) => (_nullishCoalesce(c.in, () => ( 0))) + (t - c.start) * speed;
|
|
5258
5480
|
toOut = (s) => c.start + (s - (_nullishCoalesce(c.in, () => ( 0)))) / speed;
|
|
5259
5481
|
from = Math.max(c.start, _nullishCoalesce(args.from, () => ( c.start)));
|
|
5260
|
-
to = Math.min(
|
|
5482
|
+
to = Math.min(_chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c), _nullishCoalesce(args.to, () => ( _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c))));
|
|
5261
5483
|
} else {
|
|
5262
5484
|
asset = p.assets.find((a) => a.id === args.asset);
|
|
5263
5485
|
if (!asset) throw new Error(`There is no asset "${args.asset}"; the assets are ${p.assets.map((a) => `"${a.id}"`).join(", ") || "none"}.`);
|
|
@@ -5338,15 +5560,15 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
5338
5560
|
annotations: { title: "Measure a frame with scopes", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
5339
5561
|
handler: async ({ time, bins, columns }) => {
|
|
5340
5562
|
const p = project();
|
|
5341
|
-
const end =
|
|
5563
|
+
const end = _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, p);
|
|
5342
5564
|
const t = _nullishCoalesce(time, () => ( controller.getState().time));
|
|
5343
5565
|
if (time !== void 0 && time > end) throw new Error(`Time ${time} ms is past the end of the project (${end} ms).`);
|
|
5344
5566
|
const pixels = await pixelsAt(t);
|
|
5345
|
-
return { time: t, timecode:
|
|
5567
|
+
return { time: t, timecode: _chunk5T3H7CGGcjs.formatVideoTimecode.call(void 0, t, p.fps), width: pixels.width, height: pixels.height, ...summarizeVideoScopes(pixels, { bins, columns }) };
|
|
5346
5568
|
}
|
|
5347
5569
|
};
|
|
5348
5570
|
const MASK_FIELDS = {
|
|
5349
|
-
shape: { type: "string", enum: [...
|
|
5571
|
+
shape: { type: "string", enum: [..._chunk5T3H7CGGcjs.VIDEO_MASK_SHAPES], description: "rectangle (with corner_radius), ellipse, linear (a straight split: the side above the line at rotation 0 shows) or polygon (points)." },
|
|
5350
5572
|
x: { type: "number", description: "Centre across the clip's picture, 0 (left edge) to 1 (right edge); default 0.5." },
|
|
5351
5573
|
y: { type: "number", description: "Centre down the clip's picture, 0 (top) to 1 (bottom); default 0.5." },
|
|
5352
5574
|
width: { type: "number", minimum: 0, description: "Width as a fraction of the picture's width (default 0.5). Unused by linear." },
|
|
@@ -5366,10 +5588,10 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
5366
5588
|
track: { ...TRACK_ID, description: 'A video track to put it on; tracks below it are "underneath".' },
|
|
5367
5589
|
start: MS("Where it starts on the timeline (default: the end of the track)"),
|
|
5368
5590
|
duration: { type: "number", exclusiveMinimum: 0, description: "How long it lasts, in ms (default 3000)." },
|
|
5369
|
-
scope: { type: "string", enum: [...
|
|
5591
|
+
scope: { type: "string", enum: [..._chunk5T3H7CGGcjs.VIDEO_ADJUSTMENT_SCOPES], description: "Which pictures it changes: underneath (default), all or track." },
|
|
5370
5592
|
target_track: { ...TRACK_ID, description: 'For scope "track" (required then): the track whose pictures it changes.' },
|
|
5371
5593
|
grade: GRADE,
|
|
5372
|
-
preset: { type: "string", enum: [...
|
|
5594
|
+
preset: { type: "string", enum: [..._chunk5T3H7CGGcjs.VIDEO_GRADE_PRESET_NAMES], description: "A named look to start from (grade settings given override it)." },
|
|
5373
5595
|
amount: { type: "number", minimum: 0, maximum: 1, description: "Strength of the preset, 0\u20131 (default 1)." },
|
|
5374
5596
|
name: { type: "string", minLength: 1, description: 'A label for the clip (e.g. "Night look").' },
|
|
5375
5597
|
id: { type: "string", minLength: 1, description: 'Your own id for the clip (default: a fresh one such as "c7").' },
|
|
@@ -5383,13 +5605,13 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
5383
5605
|
if (t && t.kind !== "video") throw new Error(`Track "${track}" is an audio track; adjustment clips change pictures, so put it on a video track.`);
|
|
5384
5606
|
if (scope === "track" && !target_track) throw new Error('Scope "track" needs target_track: the id of the track whose pictures it changes.');
|
|
5385
5607
|
if (target_track !== void 0 && scope !== "track") throw new Error('target_track is only for scope "track"; leave it out or set scope to "track".');
|
|
5386
|
-
const look = { ...preset ?
|
|
5608
|
+
const look = { ...preset ? _chunk5T3H7CGGcjs.videoGradePreset.call(void 0, preset, _nullishCoalesce(amount, () => ( 1))) : {}, ..._nullishCoalesce(grade, () => ( {})) };
|
|
5387
5609
|
const clip = { type: "adjustment", ...id ? { id } : {}, ...name ? { name } : {}, ...start !== void 0 ? { start } : {}, duration: _nullishCoalesce(duration, () => ( 3e3)), ...scope ? { scope } : {}, ...target_track ? { targetTrack: target_track } : {}, ...Object.keys(look).length ? { grade: look } : {} };
|
|
5388
5610
|
return apply({ op: "add_clip", track, clip, mode }, "Add adjustment clip", (r) => ({ clip: clipOut(r.project, r.outcomes[0].clip), ...placed(r.outcomes[0]), ...Object.keys(look).length ? {} : { hint: "It changes nothing yet: give it a grade (update_video_clip), effects (apply_effect) or a mask." } }));
|
|
5389
5611
|
}
|
|
5390
5612
|
};
|
|
5391
5613
|
const maskTarget = (id) => {
|
|
5392
|
-
const at =
|
|
5614
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, project(), id);
|
|
5393
5615
|
if (!at) throw new Error(`There is no clip "${id}"; get_video_project lists the clips.`);
|
|
5394
5616
|
if (at.track.kind !== "video") throw new Error(`Clip "${id}" is on audio track "${at.track.id}"; masks cut pictures, so pass a clip on a video track.`);
|
|
5395
5617
|
return at;
|
|
@@ -5431,13 +5653,13 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
5431
5653
|
gradeTargets(clips);
|
|
5432
5654
|
const edits = [];
|
|
5433
5655
|
for (const id of clips) {
|
|
5434
|
-
const clip =
|
|
5435
|
-
const lut = _optionalChain([clip, 'access',
|
|
5656
|
+
const clip = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, project(), id).clip;
|
|
5657
|
+
const lut = _optionalChain([clip, 'access', _185 => _185.grade, 'optionalAccess', _186 => _186.lut]);
|
|
5436
5658
|
if (!lut) throw new Error(`Clip "${id}" has no LUT to protect skin from; add one with set_video_lut first.`);
|
|
5437
5659
|
const { preserveSkinTones: _p, ...rest } = lut;
|
|
5438
5660
|
edits.push({ op: "update_clip", clip: id, set: { grade: { ...clip.grade, lut: amount > 0 ? { ...rest, preserveSkinTones: amount } : rest } } });
|
|
5439
5661
|
}
|
|
5440
|
-
return apply(edits, amount > 0 ? "Protect skin tones" : "Stop protecting skin tones", (r) => ({ clips: clips.map((id) => ({ id, lut: _nullishCoalesce(_optionalChain([
|
|
5662
|
+
return apply(edits, amount > 0 ? "Protect skin tones" : "Stop protecting skin tones", (r) => ({ clips: clips.map((id) => ({ id, lut: _nullishCoalesce(_optionalChain([_chunk5T3H7CGGcjs.findVideoClip.call(void 0, r.project, id), 'optionalAccess', _187 => _187.clip, 'access', _188 => _188.grade, 'optionalAccess', _189 => _189.lut]), () => ( null)) })) }));
|
|
5441
5663
|
}
|
|
5442
5664
|
};
|
|
5443
5665
|
const planOut = (plan) => ({
|
|
@@ -5490,7 +5712,7 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
5490
5712
|
handler: ({ plan }) => {
|
|
5491
5713
|
const r = controller.applyPlan(plan);
|
|
5492
5714
|
if (!r.ok) throw new Error(r.error);
|
|
5493
|
-
return { plan: r.plan.id, title: r.plan.title, stale: r.stale, outcomes: r.outcomes, duration:
|
|
5715
|
+
return { plan: r.plan.id, title: r.plan.title, stale: r.stale, outcomes: r.outcomes, duration: _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, r.project), issues: issueSummary(r.issues) };
|
|
5494
5716
|
}
|
|
5495
5717
|
};
|
|
5496
5718
|
const discardPlan = {
|
|
@@ -5526,12 +5748,96 @@ function createVideoEditorToolProvider(controller, options = {}) {
|
|
|
5526
5748
|
}, options.playbackSurface);
|
|
5527
5749
|
}
|
|
5528
5750
|
|
|
5751
|
+
// src/video-editor/camera-tools.ts
|
|
5752
|
+
var ROLE = {
|
|
5753
|
+
type: "string",
|
|
5754
|
+
enum: ["transition", "hold"],
|
|
5755
|
+
description: 'transition: the move the camera makes into the clip from its start (a glide, whip pan, punch zoom, cut), from "from" to "framing". hold: the move it makes across the rest of the clip (a Ken Burns drift, a crash zoom), at "framing".'
|
|
5756
|
+
};
|
|
5757
|
+
var FRAMING = (what) => ({
|
|
5758
|
+
anyOf: [
|
|
5759
|
+
{
|
|
5760
|
+
type: "object",
|
|
5761
|
+
properties: {
|
|
5762
|
+
zoom: { type: "number", exclusiveMinimum: 0, description: "Zoom on the picture as placed (1 = the whole picture, 2 = half of it fills the frame). Default 1." },
|
|
5763
|
+
x: { type: "number", description: "Point the camera centres on, pixels right of the frame's centre. Default 0." },
|
|
5764
|
+
y: { type: "number", description: "Point the camera centres on, pixels below the frame's centre. Default 0." }
|
|
5765
|
+
},
|
|
5766
|
+
additionalProperties: false
|
|
5767
|
+
},
|
|
5768
|
+
{ type: "null" }
|
|
5769
|
+
],
|
|
5770
|
+
description: `${what} null removes it (the whole picture). Left out, the clip keeps the one it has.`
|
|
5771
|
+
});
|
|
5772
|
+
var summary = (e) => ({ id: e.id, name: e.name, role: e.camera.role, durationMs: e.camera.durationMs, ...e.camera.cut !== void 0 ? { cut: e.camera.cut } : {}, ...e.description ? { description: e.description } : {} });
|
|
5773
|
+
var done = (r) => {
|
|
5774
|
+
if (!r.ok) throw new Error(r.error);
|
|
5775
|
+
const { ok: _ok, ...rest } = r;
|
|
5776
|
+
return { ...rest, ...rest.notes.length ? {} : { notes: void 0 } };
|
|
5777
|
+
};
|
|
5778
|
+
function videoCameraMoveTools(controller, ctx) {
|
|
5779
|
+
return [
|
|
5780
|
+
{
|
|
5781
|
+
name: "list_video_camera_moves",
|
|
5782
|
+
title: "List camera moves for clips",
|
|
5783
|
+
description: "Lists the effects provider's camera moves, for a role or both: { available, moves: [{ id, name, role, durationMs, cut (0\u20131 of the way through where the view jumps), description }] }. Give an id to set_clip_camera_move; describe_effect gives a move's controls and presets. Without a provider that has camera moves it returns available: false and the reason.",
|
|
5784
|
+
inputSchema: { type: "object", properties: { role: ROLE }, additionalProperties: false },
|
|
5785
|
+
annotations: { title: "List camera moves for clips", ...ctx.annotations.read },
|
|
5786
|
+
handler: async (args) => {
|
|
5787
|
+
const provider = controller.effectsProvider;
|
|
5788
|
+
if (!_optionalChain([provider, 'optionalAccess', _190 => _190.capabilities, 'access', _191 => _191.supportsCamera]) || !provider.cameraView)
|
|
5789
|
+
return { available: false, reason: provider ? `${provider.name} has no camera moves (capabilities.supportsCamera is not set).` : "No effects provider is registered, so there are no camera moves.", moves: [] };
|
|
5790
|
+
return { available: true, provider: provider.name, moves: (await controller.cameraMoves(args.role)).map(summary) };
|
|
5791
|
+
}
|
|
5792
|
+
},
|
|
5793
|
+
{
|
|
5794
|
+
name: "set_clip_camera_move",
|
|
5795
|
+
title: "Set a clip's camera move",
|
|
5796
|
+
description: `Plays a camera move from list_video_camera_moves on a clip's picture, the clip being the shot: role transition moves from "from" to "framing" over "ms" from the clip's start; role hold plays across the rest of the clip at "framing". The clip's moves are baked into its x, y, scale and rotation keys, one per frame at the project's fps, and a move that cuts keeps two keys at the cut so nothing tweens across it. A clip whose transform is keyed by hand is refused (clear those keys first). The move is checked first: a wrong-role id, an unknown preset or values outside its controls are refused with the moves or presets that fit. One undo step. Returns { clip, camera, keys (per property), cuts (clip ms), windows ({ in, during }: when each move plays), notes (what a clip transform cannot show: tilt, turn, blur) }. After trimming the clip, set the move again to re-bake it.`,
|
|
5797
|
+
inputSchema: {
|
|
5798
|
+
type: "object",
|
|
5799
|
+
properties: {
|
|
5800
|
+
clip: { type: "string", minLength: 1, description: "A clip id with a picture, from get_video_project." },
|
|
5801
|
+
role: ROLE,
|
|
5802
|
+
move: { type: "string", minLength: 1, description: "A camera move id of that role from list_video_camera_moves." },
|
|
5803
|
+
ms: { type: "number", minimum: 0, maximum: _chunkOPSK22DLcjs.CAMERA_MOVE_MAX_MS, description: `How long a transition takes, ms (default the move's durationMs; at most the clip's length). Not for a hold, which plays across the rest of the clip.` },
|
|
5804
|
+
preset: { type: "string", minLength: 1, description: "A preset of the move by name, from describe_effect." },
|
|
5805
|
+
values: ctx.valuesSchema("Control values over the move's defaults (and the preset's), from describe_effect"),
|
|
5806
|
+
from: FRAMING("Where a transition starts."),
|
|
5807
|
+
framing: FRAMING("Where a transition arrives and a hold plays.")
|
|
5808
|
+
},
|
|
5809
|
+
required: ["clip", "role", "move"],
|
|
5810
|
+
additionalProperties: false
|
|
5811
|
+
},
|
|
5812
|
+
annotations: { title: "Set a clip's camera move", ...ctx.annotations.writeIdempotent },
|
|
5813
|
+
handler: async (args) => {
|
|
5814
|
+
ctx.requireProvider();
|
|
5815
|
+
const spec = { move: args.move, ...args.ms !== void 0 ? { ms: args.ms } : {}, ...args.preset !== void 0 ? { preset: args.preset } : {}, ...args.values !== void 0 ? { values: args.values } : {} };
|
|
5816
|
+
return done(await controller.setClipCameraMove(args.clip, args.role, spec, { from: args.from, framing: args.framing }));
|
|
5817
|
+
}
|
|
5818
|
+
},
|
|
5819
|
+
{
|
|
5820
|
+
name: "clear_clip_camera_move",
|
|
5821
|
+
title: "Clear a clip's camera move",
|
|
5822
|
+
description: "Removes a clip's camera move for a role and re-bakes the other one (which needs the provider); with no move left the clip's transform goes back to what it was before the moves. One undo step. Returns { clip, camera (null when none is left), keys, cuts, windows }.",
|
|
5823
|
+
inputSchema: {
|
|
5824
|
+
type: "object",
|
|
5825
|
+
properties: { clip: { type: "string", minLength: 1, description: "A clip id from get_video_project." }, role: ROLE },
|
|
5826
|
+
required: ["clip", "role"],
|
|
5827
|
+
additionalProperties: false
|
|
5828
|
+
},
|
|
5829
|
+
annotations: { title: "Clear a clip's camera move", ...ctx.annotations.destructive },
|
|
5830
|
+
handler: async (args) => done(await controller.clearClipCameraMove(args.clip, args.role))
|
|
5831
|
+
}
|
|
5832
|
+
];
|
|
5833
|
+
}
|
|
5834
|
+
|
|
5529
5835
|
// src/video-editor/effect-tools.ts
|
|
5530
5836
|
function videoClipAppliedEffects(clip) {
|
|
5531
5837
|
const out = [];
|
|
5532
5838
|
const ref = (r) => ({ effect: r.effect, ...r.name ? { name: r.name } : {}, ...r.provider ? { provider: r.provider } : {} });
|
|
5533
5839
|
if (clip.type === "effect") out.push({ id: "generator", ...ref(clip), role: "effect clip", enabled: true, values: _nullishCoalesce(clip.values, () => ( {})) });
|
|
5534
|
-
if (_optionalChain([clip, 'access',
|
|
5840
|
+
if (_optionalChain([clip, 'access', _192 => _192.transition, 'optionalAccess', _193 => _193.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 });
|
|
5535
5841
|
(_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 }));
|
|
5536
5842
|
return out;
|
|
5537
5843
|
}
|
|
@@ -5544,7 +5850,7 @@ var KEYS2 = {
|
|
|
5544
5850
|
properties: {
|
|
5545
5851
|
t: { type: "number", description: "Clip-relative time in ms (0 = the clip's start)." },
|
|
5546
5852
|
v: { type: "number", description: "The control's value at t, within its range from describe_effect." },
|
|
5547
|
-
ease: { anyOf: [{ type: "string", enum: [...
|
|
5853
|
+
ease: { anyOf: [{ type: "string", enum: [..._chunk5T3H7CGGcjs.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]." }
|
|
5548
5854
|
},
|
|
5549
5855
|
required: ["t", "v"],
|
|
5550
5856
|
additionalProperties: false
|
|
@@ -5558,7 +5864,7 @@ function createVideoEffectsToolProvider(controller, options = {}) {
|
|
|
5558
5864
|
return controller.readOnlyReason();
|
|
5559
5865
|
};
|
|
5560
5866
|
const clipOf = (id) => {
|
|
5561
|
-
const at =
|
|
5867
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, controller.getProject(), id);
|
|
5562
5868
|
if (!at) {
|
|
5563
5869
|
const ids = controller.getProject().tracks.flatMap((t) => t.clips.map((c) => c.id));
|
|
5564
5870
|
throw new Error(`There is no clip "${id}"; the clips are ${ids.map((c) => `"${c}"`).join(", ") || "none"} (get_video_project lists them).`);
|
|
@@ -5568,7 +5874,7 @@ function createVideoEffectsToolProvider(controller, options = {}) {
|
|
|
5568
5874
|
const result = (r, target, instance, extra = {}) => {
|
|
5569
5875
|
if (!r.ok) throw new Error(r.error);
|
|
5570
5876
|
const effects = videoClipAppliedEffects(clipOf(target));
|
|
5571
|
-
const effect = _nullishCoalesce(effects.find((e) => e.id === (_nullishCoalesce(instance, () => ( _optionalChain([r, 'access',
|
|
5877
|
+
const effect = _nullishCoalesce(effects.find((e) => e.id === (_nullishCoalesce(instance, () => ( _optionalChain([r, 'access', _194 => _194.effect, 'optionalAccess', _195 => _195.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])));
|
|
5572
5878
|
return { target, effect, effects, ...extra };
|
|
5573
5879
|
};
|
|
5574
5880
|
return withVideoPlayback(_chunkOPSK22DLcjs.createEffectToolProvider.call(void 0, {
|
|
@@ -5616,6 +5922,7 @@ function createVideoEffectsToolProvider(controller, options = {}) {
|
|
|
5616
5922
|
},
|
|
5617
5923
|
subscribe: (notify) => controller.subscribe(() => notify()),
|
|
5618
5924
|
extraTools: (ctx) => [
|
|
5925
|
+
...videoCameraMoveTools(controller, ctx),
|
|
5619
5926
|
{
|
|
5620
5927
|
name: "add_video_effect_clip",
|
|
5621
5928
|
title: "Add an effect clip",
|
|
@@ -5629,7 +5936,7 @@ function createVideoEffectsToolProvider(controller, options = {}) {
|
|
|
5629
5936
|
duration: { type: "number", exclusiveMinimum: 0, description: "Length in ms (default: the effect's own length, else 5000)." },
|
|
5630
5937
|
values: ctx.valuesSchema("Control values over the effect's defaults", true),
|
|
5631
5938
|
name: { type: "string", minLength: 1, description: "A label for the clip (default: the effect's name)." },
|
|
5632
|
-
mode: { type: "string", enum: [...
|
|
5939
|
+
mode: { type: "string", enum: [..._chunk5T3H7CGGcjs.VIDEO_PLACEMENT_MODES], description: "What to do with clips already there: refuse (default), overwrite or insert." }
|
|
5633
5940
|
},
|
|
5634
5941
|
required: ["track", "effect"],
|
|
5635
5942
|
additionalProperties: false
|
|
@@ -5688,8 +5995,8 @@ function createVideoEffectsToolProvider(controller, options = {}) {
|
|
|
5688
5995
|
if (args.effect === "generator") {
|
|
5689
5996
|
const clip = clipOf(args.clip);
|
|
5690
5997
|
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).`);
|
|
5691
|
-
const was = _optionalChain([clip, 'access',
|
|
5692
|
-
const plain = keys === null ?
|
|
5998
|
+
const was = _optionalChain([clip, 'access', _196 => _196.values, 'optionalAccess', _197 => _197[args.control]]);
|
|
5999
|
+
const plain = keys === null ? _chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, was) ? _optionalChain([was, 'access', _198 => _198.keys, 'access', _199 => _199[0], 'optionalAccess', _200 => _200.v]) : was : { keys: [...keys].sort((a, b) => a.t - b.t) };
|
|
5693
6000
|
if (plain === void 0) throw new Error(`"${args.control}" has no value to keep; give keys instead.`);
|
|
5694
6001
|
r = await controller.updateEffectValues(args.clip, "generator", { [args.control]: plain });
|
|
5695
6002
|
} else r = await controller.setClipEffectKeyframes(args.clip, args.effect, args.control, keys);
|
|
@@ -5767,7 +6074,7 @@ function createVideoDialogueToolProvider(controller, options = {}) {
|
|
|
5767
6074
|
const r = controller.proposePlan({ title, description: "Cuts fillers, long pauses and stutters found in the transcript, closing up every sync-locked track.", edits: videoRemoveRangesEdits(cuts), ranges: cuts.map((d) => ({ from: d.from, to: d.to, text: d.text, reason: d.kind })), source: "plan_video_dialogue_cleanup" });
|
|
5768
6075
|
if (!r.ok) throw new Error(r.error);
|
|
5769
6076
|
const p = r.plan;
|
|
5770
|
-
return { plan: { id: p.id, title: p.title, summary: p.summary, text: describeVideoEditPlan(p), cuts: cuts.length }, durationNow:
|
|
6077
|
+
return { plan: { id: p.id, title: p.title, summary: p.summary, text: describeVideoEditPlan(p), cuts: cuts.length }, durationNow: _chunk5T3H7CGGcjs.videoProjectDuration.call(void 0, controller.getProject()), hint: `Nothing changed yet. Show the user the plan, then call apply_video_edit_plan with plan "${p.id}" (or discard_video_edit_plan).` };
|
|
5771
6078
|
}
|
|
5772
6079
|
};
|
|
5773
6080
|
return withVideoPlayback(
|
|
@@ -5814,7 +6121,7 @@ function createVideoMusicToolProvider(controller, options = {}) {
|
|
|
5814
6121
|
};
|
|
5815
6122
|
const project = () => controller.getProject();
|
|
5816
6123
|
const soundClip = (p, id) => {
|
|
5817
|
-
const at =
|
|
6124
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, p, id);
|
|
5818
6125
|
if (!at) throw new Error(`There is no clip "${id}"; get_video_project lists the clips.`);
|
|
5819
6126
|
const c = at.clip;
|
|
5820
6127
|
if (c.type !== "media") throw new Error(`Clip "${id}" is a ${c.type} clip and has no sound of its own; pass a video or audio clip.`);
|
|
@@ -5830,8 +6137,8 @@ function createVideoMusicToolProvider(controller, options = {}) {
|
|
|
5830
6137
|
const { clip, asset: asset2 } = soundClip(p, args.clip);
|
|
5831
6138
|
const speed = _nullishCoalesce(clip.speed, () => ( 1));
|
|
5832
6139
|
const from2 = Math.max(clip.start, _nullishCoalesce(args.from, () => ( clip.start)));
|
|
5833
|
-
const to2 = Math.min(
|
|
5834
|
-
if (!(to2 > from2)) throw new Error(`The stretch is empty (${from2}\u2013${to2} ms); "from" and "to" must be inside the clip (${clip.start}\u2013${
|
|
6140
|
+
const to2 = Math.min(_chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip), _nullishCoalesce(args.to, () => ( _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip))));
|
|
6141
|
+
if (!(to2 > from2)) throw new Error(`The stretch is empty (${from2}\u2013${to2} ms); "from" and "to" must be inside the clip (${clip.start}\u2013${_chunk5T3H7CGGcjs.videoClipEnd.call(void 0, clip)} ms) with "to" after "from".`);
|
|
5835
6142
|
return { asset: asset2, from: (_nullishCoalesce(clip.in, () => ( 0))) + (from2 - clip.start) * speed, to: (_nullishCoalesce(clip.in, () => ( 0))) + (to2 - clip.start) * speed, out: (s) => clip.start + (s - (_nullishCoalesce(clip.in, () => ( 0)))) / speed };
|
|
5836
6143
|
}
|
|
5837
6144
|
const asset = p.assets.find((a) => a.id === args.asset);
|
|
@@ -5873,7 +6180,7 @@ function createVideoMusicToolProvider(controller, options = {}) {
|
|
|
5873
6180
|
handler: async ({ clips, target, ceiling, replace }) => {
|
|
5874
6181
|
const p = project();
|
|
5875
6182
|
const targets = clips.map((id) => soundClip(p, id));
|
|
5876
|
-
for (const t of targets) if (
|
|
6183
|
+
for (const t of targets) if (_chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, t.clip.volume) && !replace) throw new Error(`Clip "${t.clip.id}" has volume keyframes, which a constant gain would replace; pass replace: true, or remove them first.`);
|
|
5877
6184
|
const results = [];
|
|
5878
6185
|
const edits = [];
|
|
5879
6186
|
for (const { clip, asset } of targets) {
|
|
@@ -5918,7 +6225,7 @@ function createVideoMusicToolProvider(controller, options = {}) {
|
|
|
5918
6225
|
handler: async (args) => {
|
|
5919
6226
|
const p = project();
|
|
5920
6227
|
const music = args.music.map((id) => soundClip(p, id));
|
|
5921
|
-
for (const m of music) if (
|
|
6228
|
+
for (const m of music) if (_chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, m.clip.volume) && !args.replace) throw new Error(`Music clip "${m.clip.id}" already has volume keyframes; pass replace: true to replace them, or remove them first.`);
|
|
5922
6229
|
const transcriptTrack = videoTranscriptTrack(p, args.dialogue_track);
|
|
5923
6230
|
const mode = _nullishCoalesce(args.speech, () => ( (transcriptTrack && videoTimelineTranscript(p, { track: transcriptTrack }).length ? "transcript" : "audio")));
|
|
5924
6231
|
let ranges = [];
|
|
@@ -5931,7 +6238,7 @@ function createVideoMusicToolProvider(controller, options = {}) {
|
|
|
5931
6238
|
const track = p.tracks.find((t) => t.id === args.dialogue_track);
|
|
5932
6239
|
if (!track) throw new Error(`There is no track "${args.dialogue_track}".`);
|
|
5933
6240
|
const musicIds = new Set(music.map((m) => m.clip.id));
|
|
5934
|
-
for (const c of
|
|
6241
|
+
for (const c of _chunk5T3H7CGGcjs.sortedVideoClips.call(void 0, track)) {
|
|
5935
6242
|
if (c.type !== "media" || musicIds.has(c.id)) continue;
|
|
5936
6243
|
const asset = p.assets.find((a) => a.id === c.asset);
|
|
5937
6244
|
if (!asset || asset.kind === "image" || asset.hasAudio === false) continue;
|
|
@@ -5942,10 +6249,10 @@ function createVideoMusicToolProvider(controller, options = {}) {
|
|
|
5942
6249
|
let at = c.start;
|
|
5943
6250
|
for (const s of silences) {
|
|
5944
6251
|
const a = c.start + (s.start - src0) / speed;
|
|
5945
|
-
if (a - at >
|
|
6252
|
+
if (a - at > _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) ranges.push({ from: at, to: a });
|
|
5946
6253
|
at = c.start + (s.end - src0) / speed;
|
|
5947
6254
|
}
|
|
5948
|
-
if (
|
|
6255
|
+
if (_chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c) - at > _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) ranges.push({ from: at, to: _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, c) });
|
|
5949
6256
|
}
|
|
5950
6257
|
if (!ranges.length) throw new Error(`Track "${args.dialogue_track}" has no sound above -40 dBFS, so there is no speech to duck under.`);
|
|
5951
6258
|
}
|
|
@@ -6008,7 +6315,7 @@ function createVideoMusicToolProvider(controller, options = {}) {
|
|
|
6008
6315
|
if (!beats.length) throw new Error(`No beats were found in "${args.music}"; try a lower sensitivity, or pass beats.`);
|
|
6009
6316
|
} else beats = [...args.beats].sort((a, b) => a - b);
|
|
6010
6317
|
const tolerance = _nullishCoalesce(args.tolerance, () => ( 150));
|
|
6011
|
-
const clips =
|
|
6318
|
+
const clips = _chunk5T3H7CGGcjs.sortedVideoClips.call(void 0, track);
|
|
6012
6319
|
const edits = [];
|
|
6013
6320
|
const ranges = [];
|
|
6014
6321
|
const skipped = [];
|
|
@@ -6016,8 +6323,8 @@ function createVideoMusicToolProvider(controller, options = {}) {
|
|
|
6016
6323
|
for (let i = 0; i + 1 < clips.length; i++) {
|
|
6017
6324
|
const left = clips[i];
|
|
6018
6325
|
const right = clips[i + 1];
|
|
6019
|
-
const cut =
|
|
6020
|
-
if (Math.abs(right.start - cut) >
|
|
6326
|
+
const cut = _chunk5T3H7CGGcjs.videoClipEnd.call(void 0, left);
|
|
6327
|
+
if (Math.abs(right.start - cut) > _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON) continue;
|
|
6021
6328
|
const beat = nearestVideoBeat(beats, cut, tolerance);
|
|
6022
6329
|
if (beat === null) {
|
|
6023
6330
|
skipped.push({ cut: round4(cut), reason: `no beat within ${tolerance} ms` });
|
|
@@ -6092,7 +6399,7 @@ function videoClipEffectDocument(clip, instance, providerId) {
|
|
|
6092
6399
|
const values = {};
|
|
6093
6400
|
const tracks = {};
|
|
6094
6401
|
for (const [control, v] of Object.entries(_nullishCoalesce(effect.values, () => ( {})))) {
|
|
6095
|
-
if (
|
|
6402
|
+
if (_chunk5T3H7CGGcjs.isVideoKeyframes.call(void 0, v)) {
|
|
6096
6403
|
values[control] = v.keys[0].v;
|
|
6097
6404
|
tracks[control] = v.keys.map((k) => ({ time: k.t, value: k.v, ...k.ease && k.ease !== "linear" ? { easing: videoEaseToAnimationEasing(k.ease) } : {} }));
|
|
6098
6405
|
} else values[control] = v;
|
|
@@ -6133,7 +6440,7 @@ function videoEffectValuesFromDocument(doc) {
|
|
|
6133
6440
|
async function openVideoClipEffectAuthoring(controller, clip, instance, options = {}) {
|
|
6134
6441
|
const provider = controller.effectsProvider;
|
|
6135
6442
|
if (!provider) throw new Error("No effects provider is registered, so the effect cannot be opened for authoring; register one with setEffectsProvider.");
|
|
6136
|
-
const at =
|
|
6443
|
+
const at = _chunk5T3H7CGGcjs.findVideoClip.call(void 0, controller.getProject(), clip);
|
|
6137
6444
|
if (!at) throw new Error(`There is no clip "${clip}".`);
|
|
6138
6445
|
const doc = videoClipEffectDocument(at.clip, instance, provider.id);
|
|
6139
6446
|
const session = await _chunkC73U5UI3cjs.createEffectAuthoringSession.call(void 0, { document: doc }, { ...options, provider });
|
|
@@ -6477,4 +6784,12 @@ function createVideoEditorDocument(controller) {
|
|
|
6477
6784
|
|
|
6478
6785
|
|
|
6479
6786
|
|
|
6480
|
-
exports.TranscriptVideoController = TranscriptVideoController; exports.VIDEO_ADJUSTMENT_SCOPES = _chunkA57ZQDNNcjs.VIDEO_ADJUSTMENT_SCOPES; exports.VIDEO_ADJUSTMENT_SCOPE_LABELS = VIDEO_ADJUSTMENT_SCOPE_LABELS; exports.VIDEO_BLEND_MODES = _chunkA57ZQDNNcjs.VIDEO_BLEND_MODES; exports.VIDEO_BLEND_MODE_LABELS = VIDEO_BLEND_MODE_LABELS; exports.VIDEO_CLIP_ANIMATION_DURATION = _chunkA57ZQDNNcjs.VIDEO_CLIP_ANIMATION_DURATION; exports.VIDEO_CLIP_ANIMATION_EFFECTS = _chunkA57ZQDNNcjs.VIDEO_CLIP_ANIMATION_EFFECTS; exports.VIDEO_CLIP_ANIMATION_LABELS = VIDEO_CLIP_ANIMATION_LABELS; exports.VIDEO_CLIP_TYPES = _chunkA57ZQDNNcjs.VIDEO_CLIP_TYPES; exports.VIDEO_DEFAULT_FILLERS = VIDEO_DEFAULT_FILLERS; exports.VIDEO_DEFAULT_STILL_DURATION = VIDEO_DEFAULT_STILL_DURATION; exports.VIDEO_DEFAULT_TITLE_DURATION = VIDEO_DEFAULT_TITLE_DURATION; exports.VIDEO_DISFLUENCY_KINDS = VIDEO_DISFLUENCY_KINDS; exports.VIDEO_EASE_NAMES = _chunkA57ZQDNNcjs.VIDEO_EASE_NAMES; exports.VIDEO_EDIT_OPS = VIDEO_EDIT_OPS; exports.VIDEO_EFFECT_PLACES = _chunkA57ZQDNNcjs.VIDEO_EFFECT_PLACES; exports.VIDEO_FADE_CURVES = _chunkA57ZQDNNcjs.VIDEO_FADE_CURVES; exports.VIDEO_FADE_CURVE_LABELS = VIDEO_FADE_CURVE_LABELS; exports.VIDEO_FITS = _chunkA57ZQDNNcjs.VIDEO_FITS; exports.VIDEO_GRADE_CONTROLS = _chunkA57ZQDNNcjs.VIDEO_GRADE_CONTROLS; exports.VIDEO_GRADE_PRESETS = _chunkA57ZQDNNcjs.VIDEO_GRADE_PRESETS; exports.VIDEO_GRADE_PRESET_NAMES = _chunkA57ZQDNNcjs.VIDEO_GRADE_PRESET_NAMES; exports.VIDEO_ISSUE_CODES = VIDEO_ISSUE_CODES; exports.VIDEO_KEYFRAME_LIMITS = _chunkA57ZQDNNcjs.VIDEO_KEYFRAME_LIMITS; exports.VIDEO_KEYFRAME_PROPERTIES = _chunkA57ZQDNNcjs.VIDEO_KEYFRAME_PROPERTIES; exports.VIDEO_LOUDNESS_HOP = VIDEO_LOUDNESS_HOP; exports.VIDEO_LUT_MAX_SIZE = _chunkA57ZQDNNcjs.VIDEO_LUT_MAX_SIZE; exports.VIDEO_MASK_DEFAULTS = _chunkA57ZQDNNcjs.VIDEO_MASK_DEFAULTS; exports.VIDEO_MASK_SHAPES = _chunkA57ZQDNNcjs.VIDEO_MASK_SHAPES; exports.VIDEO_MASK_SHAPE_LABELS = VIDEO_MASK_SHAPE_LABELS; exports.VIDEO_PEAK_BLOCK = VIDEO_PEAK_BLOCK; exports.VIDEO_PLACEMENT_MODES = _chunkA57ZQDNNcjs.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 = _chunkA57ZQDNNcjs.VIDEO_TIME_EPSILON; exports.VIDEO_TRANSFORM_PROPERTIES = _chunkA57ZQDNNcjs.VIDEO_TRANSFORM_PROPERTIES; exports.VIDEO_TRANSITION_LABELS = VIDEO_TRANSITION_LABELS; exports.VIDEO_TRANSITION_TYPES = _chunkA57ZQDNNcjs.VIDEO_TRANSITION_TYPES; exports.VIDEO_VECTORSCOPE_TARGETS = VIDEO_VECTORSCOPE_TARGETS; exports.VIDEO_WIPE_DIRECTIONS = _chunkA57ZQDNNcjs.VIDEO_WIPE_DIRECTIONS; exports.VideoAudioPeaksCache = VideoAudioPeaksCache; exports.VideoEditorController = VideoEditorController; exports.VideoEffectsEngine = _chunkA57ZQDNNcjs.VideoEffectsEngine; exports.VideoFrameCache = VideoFrameCache; exports.VideoLutCache = _chunkA57ZQDNNcjs.VideoLutCache; exports.VideoPreviewEngine = VideoPreviewEngine; exports.VideoPreviewPixels = VideoPreviewPixels; exports.allVideoClipIds = _chunkA57ZQDNNcjs.allVideoClipIds; exports.allVideoTracks = _chunkA57ZQDNNcjs.allVideoTracks; exports.animationEasingToVideoEase = animationEasingToVideoEase; exports.applyVideoEdits = applyVideoEdits; exports.applyVideoGrade = _chunkA57ZQDNNcjs.applyVideoGrade; exports.applyVideoLut = _chunkA57ZQDNNcjs.applyVideoLut; exports.applyVideoLutToPixels = _chunkA57ZQDNNcjs.applyVideoLutToPixels; exports.buildVideoAudioPeaks = buildVideoAudioPeaks; exports.checkVideoEffectPlace = _chunkA57ZQDNNcjs.checkVideoEffectPlace; exports.checkVideoEffectValues = _chunkA57ZQDNNcjs.checkVideoEffectValues; exports.checkVideoProject = checkVideoProject; exports.checkVideoTimeRemap = _chunkA57ZQDNNcjs.checkVideoTimeRemap; exports.createVideoDialogueToolProvider = createVideoDialogueToolProvider; exports.createVideoEditorDocument = createVideoEditorDocument; exports.createVideoEditorToolProvider = createVideoEditorToolProvider; exports.createVideoEffectsToolProvider = createVideoEffectsToolProvider; exports.createVideoElementDecoder = createVideoElementDecoder; exports.createVideoMusicToolProvider = createVideoMusicToolProvider; exports.createVideoProject = createVideoProject; exports.decodeVideoAudioPeaks = decodeVideoAudioPeaks; exports.describeVideoEditPlan = describeVideoEditPlan; exports.describeVideoProject = describeVideoProject; exports.describeVideoSequence = describeVideoSequence; exports.detectVideoDisfluencies = detectVideoDisfluencies; exports.diffVideoProjects = diffVideoProjects; exports.drawVideoFrame = _chunkA57ZQDNNcjs.drawVideoFrame; exports.ffmpegFilterValue = _chunkA57ZQDNNcjs.ffmpegFilterValue; exports.findVideoAudioBeats = findVideoAudioBeats; exports.findVideoAudioSilences = findVideoAudioSilences; exports.findVideoClip = _chunkA57ZQDNNcjs.findVideoClip; exports.findVideoFillers = findVideoFillers; exports.findVideoGaps = _chunkA57ZQDNNcjs.findVideoGaps; exports.findVideoRepetitions = findVideoRepetitions; exports.findVideoSequenceClip = _chunkA57ZQDNNcjs.findVideoSequenceClip; exports.findVideoSequenceCycle = _chunkA57ZQDNNcjs.findVideoSequenceCycle; exports.findVideoTranscriptPauses = findVideoTranscriptPauses; exports.findVideoTranscriptText = findVideoTranscriptText; exports.formatVideoSeconds = _chunkA57ZQDNNcjs.formatVideoSeconds; exports.formatVideoTimecode = _chunkA57ZQDNNcjs.formatVideoTimecode; exports.formatVideoTimecodeFrames = _chunkA57ZQDNNcjs.formatVideoTimecodeFrames; exports.isVideoDropFrameRate = _chunkA57ZQDNNcjs.isVideoDropFrameRate; exports.isVideoKeyframes = _chunkA57ZQDNNcjs.isVideoKeyframes; exports.measureVideoLoudness = measureVideoLoudness; exports.mergeVideoRanges = mergeVideoRanges; exports.mixEffectPixels = _chunkA57ZQDNNcjs.mixEffectPixels; exports.nearestVideoBeat = nearestVideoBeat; exports.nextFreeVideoSlot = _chunkA57ZQDNNcjs.nextFreeVideoSlot; exports.normalizeVideoClipMask = _chunkA57ZQDNNcjs.normalizeVideoClipMask; exports.normalizeVideoGrade = _chunkA57ZQDNNcjs.normalizeVideoGrade; exports.normalizeVideoGradeLut = _chunkA57ZQDNNcjs.normalizeVideoGradeLut; exports.normalizeVideoWord = normalizeVideoWord; exports.openVideoClipEffectAuthoring = openVideoClipEffectAuthoring; exports.overEffectPixels = _chunkA57ZQDNNcjs.overEffectPixels; exports.parseVideoAnimatable = parseVideoAnimatable; exports.parseVideoAsset = parseVideoAsset; exports.parseVideoAssetProxies = parseVideoAssetProxies; exports.parseVideoClip = parseVideoClip; exports.parseVideoClipAnimation = parseVideoClipAnimation; exports.parseVideoClipEffects = parseVideoClipEffects; exports.parseVideoClipMask = parseVideoClipMask; exports.parseVideoCubeLut = _chunkA57ZQDNNcjs.parseVideoCubeLut; exports.parseVideoEffectRef = parseVideoEffectRef; exports.parseVideoEffectValues = parseVideoEffectValues; exports.parseVideoGrade = parseVideoGrade; exports.parseVideoGradeLut = parseVideoGradeLut; exports.parseVideoKeyframes = parseVideoKeyframes; exports.parseVideoLoudnessMeasurement = _chunkA57ZQDNNcjs.parseVideoLoudnessMeasurement; exports.parseVideoMarker = parseVideoMarker; exports.parseVideoPreviewScale = parseVideoPreviewScale; exports.parseVideoProject = parseVideoProject; exports.parseVideoSequence = parseVideoSequence; exports.parseVideoTimeRef = parseVideoTimeRef; exports.parseVideoTimeRemap = parseVideoTimeRemap; exports.parseVideoTrack = parseVideoTrack; exports.parseVideoTranscript = parseVideoTranscript; exports.parseVideoTranscriptWords = parseVideoTranscriptWords; exports.parseVideoTransform = parseVideoTransform; exports.parseVideoTransition = parseVideoTransition; exports.placeVideoRect = _chunkA57ZQDNNcjs.placeVideoRect; exports.planVideoClipDrag = planVideoClipDrag; exports.planVideoEdits = planVideoEdits; exports.planVideoPrefetch = planVideoPrefetch; exports.planVideoToolPlayback = planVideoToolPlayback; exports.probeVideoMedia = probeVideoMedia; exports.readVideoScopesPanel = readVideoScopesPanel; exports.removeVideoKey = _chunkA57ZQDNNcjs.removeVideoKey; exports.renderVideoFrameExact = _chunkA57ZQDNNcjs.renderVideoFrameExact; exports.resolveVideoPreviewScale = resolveVideoPreviewScale; exports.retimeVideoAnimatable = _chunkA57ZQDNNcjs.retimeVideoAnimatable; exports.setVideoKey = _chunkA57ZQDNNcjs.setVideoKey; exports.snapToVideoFrame = _chunkA57ZQDNNcjs.snapToVideoFrame; exports.snapVideoTime = _chunkA57ZQDNNcjs.snapVideoTime; exports.sortVideoKeys = _chunkA57ZQDNNcjs.sortVideoKeys; exports.sortedVideoClips = _chunkA57ZQDNNcjs.sortedVideoClips; exports.splitVideoAnimatable = _chunkA57ZQDNNcjs.splitVideoAnimatable; exports.summarizeVideoScopes = summarizeVideoScopes; exports.toVideoEdl = _chunkA57ZQDNNcjs.toVideoEdl; exports.toVideoFfmpeg = _chunkA57ZQDNNcjs.toVideoFfmpeg; exports.toVideoLoudnessMeasure = _chunkA57ZQDNNcjs.toVideoLoudnessMeasure; exports.videoAddAdjustmentEdits = videoAddAdjustmentEdits; exports.videoAssetDropEdit = videoAssetDropEdit; exports.videoAssetHasSound = _chunkA57ZQDNNcjs.videoAssetHasSound; exports.videoAssetKindOf = videoAssetKindOf; exports.videoAssetMap = _chunkA57ZQDNNcjs.videoAssetMap; exports.videoAssetProxy = videoAssetProxy; exports.videoAudioLevels = videoAudioLevels; exports.videoAudioLoudness = videoAudioLoudness; exports.videoAudioPeakRange = videoAudioPeakRange; exports.videoAudioPeakSpans = videoAudioPeakSpans; exports.videoAudioPeaksDuration = videoAudioPeaksDuration; exports.videoAuthorableEffects = videoAuthorableEffects; exports.videoCacheEvictions = videoCacheEvictions; exports.videoChroma = videoChroma; exports.videoClipAfter = _chunkA57ZQDNNcjs.videoClipAfter; exports.videoClipAnimated = _chunkA57ZQDNNcjs.videoClipAnimated; exports.videoClipAnimationProperties = _chunkA57ZQDNNcjs.videoClipAnimationProperties; exports.videoClipAnimationSpans = _chunkA57ZQDNNcjs.videoClipAnimationSpans; exports.videoClipAppliedEffects = videoClipAppliedEffects; exports.videoClipBefore = _chunkA57ZQDNNcjs.videoClipBefore; exports.videoClipEffectDocument = videoClipEffectDocument; exports.videoClipEffectUses = _chunkA57ZQDNNcjs.videoClipEffectUses; exports.videoClipEnd = _chunkA57ZQDNNcjs.videoClipEnd; exports.videoClipHandles = _chunkA57ZQDNNcjs.videoClipHandles; exports.videoClipHeading = videoClipHeading; exports.videoClipKeyframes = videoClipKeyframes; exports.videoClipLabel = videoClipLabel; exports.videoClipOverhang = _chunkA57ZQDNNcjs.videoClipOverhang; exports.videoClipShowsWaveform = videoClipShowsWaveform; exports.videoClipSoundGain = _chunkA57ZQDNNcjs.videoClipSoundGain; exports.videoClipSourceRange = _chunkA57ZQDNNcjs.videoClipSourceRange; exports.videoClipSourceTime = _chunkA57ZQDNNcjs.videoClipSourceTime; exports.videoClipSpeed = _chunkA57ZQDNNcjs.videoClipSpeed; exports.videoClipSpeedAt = _chunkA57ZQDNNcjs.videoClipSpeedAt; exports.videoClipTint = videoClipTint; exports.videoClipTypeLabel = _chunkA57ZQDNNcjs.videoClipTypeLabel; exports.videoClipWaveform = videoClipWaveform; exports.videoClipWaveformPath = videoClipWaveformPath; exports.videoClipsAt = _chunkA57ZQDNNcjs.videoClipsAt; exports.videoContactSheetSvg = _chunkA57ZQDNNcjs.videoContactSheetSvg; exports.videoCutsWithMargin = videoCutsWithMargin; exports.videoDragLabel = videoDragLabel; exports.videoDropTracks = videoDropTracks; exports.videoDuckingKeys = videoDuckingKeys; exports.videoEaseBezier = _chunkA57ZQDNNcjs.videoEaseBezier; exports.videoEaseProgress = _chunkA57ZQDNNcjs.videoEaseProgress; exports.videoEaseToAnimationEasing = videoEaseToAnimationEasing; exports.videoEffectFrameTime = _chunkA57ZQDNNcjs.videoEffectFrameTime; exports.videoEffectLayerKey = _chunkA57ZQDNNcjs.videoEffectLayerKey; exports.videoEffectValuesAt = _chunkA57ZQDNNcjs.videoEffectValuesAt; exports.videoEffectValuesFromDocument = videoEffectValuesFromDocument; exports.videoExposureNotes = videoExposureNotes; exports.videoExposureStats = videoExposureStats; exports.videoFadeCurveGain = _chunkA57ZQDNNcjs.videoFadeCurveGain; exports.videoFfmpegUnsupportedEffects = _chunkA57ZQDNNcjs.videoFfmpegUnsupportedEffects; exports.videoFfmpegUnsupportedFeatures = _chunkA57ZQDNNcjs.videoFfmpegUnsupportedFeatures; exports.videoFrameAt = _chunkA57ZQDNNcjs.videoFrameAt; exports.videoFrameCacheKey = videoFrameCacheKey; exports.videoFrameDuration = _chunkA57ZQDNNcjs.videoFrameDuration; exports.videoFrameLeafLayers = _chunkA57ZQDNNcjs.videoFrameLeafLayers; exports.videoFrameRequestsAt = videoFrameRequestsAt; exports.videoFrameToSvg = _chunkA57ZQDNNcjs.videoFrameToSvg; exports.videoFrames = _chunkA57ZQDNNcjs.videoFrames; exports.videoFreezeFrameEdit = _chunkA57ZQDNNcjs.videoFreezeFrameEdit; exports.videoGradeCssFilter = _chunkA57ZQDNNcjs.videoGradeCssFilter; exports.videoGradeFfmpegFilters = _chunkA57ZQDNNcjs.videoGradeFfmpegFilters; exports.videoGradeGainsFilterId = _chunkA57ZQDNNcjs.videoGradeGainsFilterId; exports.videoGradeLook = _chunkA57ZQDNNcjs.videoGradeLook; exports.videoGradePreset = _chunkA57ZQDNNcjs.videoGradePreset; exports.videoGradeStepMatrix = _chunkA57ZQDNNcjs.videoGradeStepMatrix; exports.videoGradeStepSvgValues = _chunkA57ZQDNNcjs.videoGradeStepSvgValues; exports.videoGradeSteps = _chunkA57ZQDNNcjs.videoGradeSteps; exports.videoGradeSvgDefs = _chunkA57ZQDNNcjs.videoGradeSvgDefs; exports.videoGradeSvgFilter = _chunkA57ZQDNNcjs.videoGradeSvgFilter; exports.videoHistogram = videoHistogram; exports.videoHistogramImage = videoHistogramImage; exports.videoHourFrames = _chunkA57ZQDNNcjs.videoHourFrames; exports.videoIrisRadius = _chunkA57ZQDNNcjs.videoIrisRadius; exports.videoIssueKey = videoIssueKey; exports.videoKeyframeBreakpoints = _chunkA57ZQDNNcjs.videoKeyframeBreakpoints; exports.videoKeyframeFfmpegExpr = _chunkA57ZQDNNcjs.videoKeyframeFfmpegExpr; exports.videoKeyframeRows = videoKeyframeRows; exports.videoKeyframeToggleEdit = videoKeyframeToggleEdit; exports.videoKeyframeValueEdit = videoKeyframeValueEdit; exports.videoKeysOf = _chunkA57ZQDNNcjs.videoKeysOf; exports.videoLayerMask = _chunkA57ZQDNNcjs.videoLayerMask; exports.videoLayersUseEffects = _chunkA57ZQDNNcjs.videoLayersUseEffects; exports.videoLayersWithoutTransitionEffects = _chunkA57ZQDNNcjs.videoLayersWithoutTransitionEffects; exports.videoLoudnessEnergy = videoLoudnessEnergy; exports.videoLoudnessGain = videoLoudnessGain; exports.videoLoudnessOf = videoLoudnessOf; exports.videoLuma = videoLuma; exports.videoLumaWaveform = videoLumaWaveform; exports.videoLutEdits = videoLutEdits; exports.videoLutFromFunction = _chunkA57ZQDNNcjs.videoLutFromFunction; exports.videoLutSvgApproximation = _chunkA57ZQDNNcjs.videoLutSvgApproximation; exports.videoLutSvgPrimitives = _chunkA57ZQDNNcjs.videoLutSvgPrimitives; exports.videoLutToCube = _chunkA57ZQDNNcjs.videoLutToCube; exports.videoMaskContains = _chunkA57ZQDNNcjs.videoMaskContains; exports.videoMaskEdit = videoMaskEdit; exports.videoMaskPolygon = _chunkA57ZQDNNcjs.videoMaskPolygon; exports.videoMaskSvgPath = _chunkA57ZQDNNcjs.videoMaskSvgPath; exports.videoOverlap = _chunkA57ZQDNNcjs.videoOverlap; exports.videoPeakDb = videoPeakDb; exports.videoPreviewSrc = videoPreviewSrc; exports.videoProjectDuration = _chunkA57ZQDNNcjs.videoProjectDuration; exports.videoProjectEffects = _chunkA57ZQDNNcjs.videoProjectEffects; exports.videoProjectHasProxies = videoProjectHasProxies; exports.videoProjectSvg = _chunkA57ZQDNNcjs.videoProjectSvg; exports.videoProxyFfmpeg = videoProxyFfmpeg; exports.videoProxyName = videoProxyName; exports.videoProxyPlan = videoProxyPlan; exports.videoRemoveRangesEdits = videoRemoveRangesEdits; exports.videoRulerTicks = videoRulerTicks; exports.videoScopeImage = videoScopeImage; exports.videoSequenceChildren = _chunkA57ZQDNNcjs.videoSequenceChildren; exports.videoSequenceDuration = _chunkA57ZQDNNcjs.videoSequenceDuration; exports.videoSequenceMap = _chunkA57ZQDNNcjs.videoSequenceMap; exports.videoShellQuote = _chunkA57ZQDNNcjs.videoShellQuote; exports.videoSkinProtectionEdits = videoSkinProtectionEdits; exports.videoSkinToneWeight = _chunkA57ZQDNNcjs.videoSkinToneWeight; exports.videoSlowMotionRamp = _chunkA57ZQDNNcjs.videoSlowMotionRamp; exports.videoSnapPoints = _chunkA57ZQDNNcjs.videoSnapPoints; exports.videoSourceFrame = videoSourceFrame; exports.videoSourceFrameTime = videoSourceFrameTime; exports.videoSpeechRanges = videoSpeechRanges; exports.videoSpeedRampEdit = _chunkA57ZQDNNcjs.videoSpeedRampEdit; exports.videoSpeedRampKeys = _chunkA57ZQDNNcjs.videoSpeedRampKeys; exports.videoTextStyle = _chunkA57ZQDNNcjs.videoTextStyle; exports.videoTimeRef = videoTimeRef; exports.videoTimeRemapBreakpoints = _chunkA57ZQDNNcjs.videoTimeRemapBreakpoints; exports.videoTimeRemapSpan = _chunkA57ZQDNNcjs.videoTimeRemapSpan; exports.videoTimecodeFrames = _chunkA57ZQDNNcjs.videoTimecodeFrames; exports.videoTimelineTranscript = videoTimelineTranscript; exports.videoTitleFrame = _chunkA57ZQDNNcjs.videoTitleFrame; exports.videoTrackSyncLocked = _chunkA57ZQDNNcjs.videoTrackSyncLocked; exports.videoTranscriptEdit = videoTranscriptEdit; exports.videoTranscriptTrack = videoTranscriptTrack; exports.videoTransformAt = _chunkA57ZQDNNcjs.videoTransformAt; exports.videoTransitionAudioCurve = _chunkA57ZQDNNcjs.videoTransitionAudioCurve; exports.videoTransitionEase = _chunkA57ZQDNNcjs.videoTransitionEase; exports.videoTransitionHasDirection = videoTransitionHasDirection; exports.videoValueAt = _chunkA57ZQDNNcjs.videoValueAt; exports.videoVectorscope = videoVectorscope; exports.videoVectorscopeAngle = videoVectorscopeAngle; exports.videoVectorscopeImage = videoVectorscopeImage; exports.videoVectorscopePoint = videoVectorscopePoint; exports.videoWaveformImage = videoWaveformImage; exports.videoWaveformPath = videoWaveformPath; exports.videoWipeRect = _chunkA57ZQDNNcjs.videoWipeRect; exports.videoWordAt = videoWordAt; exports.videoWordsRange = videoWordsRange; exports.withVideoPlayback = withVideoPlayback;
|
|
6787
|
+
|
|
6788
|
+
|
|
6789
|
+
|
|
6790
|
+
|
|
6791
|
+
|
|
6792
|
+
|
|
6793
|
+
|
|
6794
|
+
|
|
6795
|
+
exports.TranscriptVideoController = TranscriptVideoController; exports.VIDEO_ADJUSTMENT_SCOPES = _chunk5T3H7CGGcjs.VIDEO_ADJUSTMENT_SCOPES; exports.VIDEO_ADJUSTMENT_SCOPE_LABELS = VIDEO_ADJUSTMENT_SCOPE_LABELS; exports.VIDEO_BLEND_MODES = _chunk5T3H7CGGcjs.VIDEO_BLEND_MODES; exports.VIDEO_BLEND_MODE_LABELS = VIDEO_BLEND_MODE_LABELS; exports.VIDEO_CLIP_ANIMATION_DURATION = _chunk5T3H7CGGcjs.VIDEO_CLIP_ANIMATION_DURATION; exports.VIDEO_CLIP_ANIMATION_EFFECTS = _chunk5T3H7CGGcjs.VIDEO_CLIP_ANIMATION_EFFECTS; exports.VIDEO_CLIP_ANIMATION_LABELS = VIDEO_CLIP_ANIMATION_LABELS; exports.VIDEO_CLIP_TYPES = _chunk5T3H7CGGcjs.VIDEO_CLIP_TYPES; exports.VIDEO_DEFAULT_FILLERS = VIDEO_DEFAULT_FILLERS; exports.VIDEO_DEFAULT_STILL_DURATION = VIDEO_DEFAULT_STILL_DURATION; exports.VIDEO_DEFAULT_TITLE_DURATION = VIDEO_DEFAULT_TITLE_DURATION; exports.VIDEO_DISFLUENCY_KINDS = VIDEO_DISFLUENCY_KINDS; exports.VIDEO_EASE_NAMES = _chunk5T3H7CGGcjs.VIDEO_EASE_NAMES; exports.VIDEO_EDIT_OPS = VIDEO_EDIT_OPS; exports.VIDEO_EFFECT_PLACES = _chunk5T3H7CGGcjs.VIDEO_EFFECT_PLACES; exports.VIDEO_FADE_CURVES = _chunk5T3H7CGGcjs.VIDEO_FADE_CURVES; exports.VIDEO_FADE_CURVE_LABELS = VIDEO_FADE_CURVE_LABELS; exports.VIDEO_FITS = _chunk5T3H7CGGcjs.VIDEO_FITS; exports.VIDEO_GRADE_CONTROLS = _chunk5T3H7CGGcjs.VIDEO_GRADE_CONTROLS; exports.VIDEO_GRADE_PRESETS = _chunk5T3H7CGGcjs.VIDEO_GRADE_PRESETS; exports.VIDEO_GRADE_PRESET_NAMES = _chunk5T3H7CGGcjs.VIDEO_GRADE_PRESET_NAMES; exports.VIDEO_ISSUE_CODES = VIDEO_ISSUE_CODES; exports.VIDEO_KEYFRAME_LIMITS = _chunk5T3H7CGGcjs.VIDEO_KEYFRAME_LIMITS; exports.VIDEO_KEYFRAME_PROPERTIES = _chunk5T3H7CGGcjs.VIDEO_KEYFRAME_PROPERTIES; exports.VIDEO_LOUDNESS_HOP = VIDEO_LOUDNESS_HOP; exports.VIDEO_LUT_MAX_SIZE = _chunk5T3H7CGGcjs.VIDEO_LUT_MAX_SIZE; exports.VIDEO_MASK_DEFAULTS = _chunk5T3H7CGGcjs.VIDEO_MASK_DEFAULTS; exports.VIDEO_MASK_SHAPES = _chunk5T3H7CGGcjs.VIDEO_MASK_SHAPES; exports.VIDEO_MASK_SHAPE_LABELS = VIDEO_MASK_SHAPE_LABELS; exports.VIDEO_PEAK_BLOCK = VIDEO_PEAK_BLOCK; exports.VIDEO_PLACEMENT_MODES = _chunk5T3H7CGGcjs.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 = _chunk5T3H7CGGcjs.VIDEO_TIME_EPSILON; exports.VIDEO_TRANSFORM_PROPERTIES = _chunk5T3H7CGGcjs.VIDEO_TRANSFORM_PROPERTIES; exports.VIDEO_TRANSITION_LABELS = VIDEO_TRANSITION_LABELS; exports.VIDEO_TRANSITION_TYPES = _chunk5T3H7CGGcjs.VIDEO_TRANSITION_TYPES; exports.VIDEO_VECTORSCOPE_TARGETS = VIDEO_VECTORSCOPE_TARGETS; exports.VIDEO_WIPE_DIRECTIONS = _chunk5T3H7CGGcjs.VIDEO_WIPE_DIRECTIONS; exports.VideoAudioPeaksCache = VideoAudioPeaksCache; exports.VideoEditorController = VideoEditorController; exports.VideoEffectsEngine = _chunk5T3H7CGGcjs.VideoEffectsEngine; exports.VideoFrameCache = VideoFrameCache; exports.VideoLutCache = _chunk5T3H7CGGcjs.VideoLutCache; exports.VideoPreviewEngine = VideoPreviewEngine; exports.VideoPreviewPixels = VideoPreviewPixels; exports.allVideoClipIds = _chunk5T3H7CGGcjs.allVideoClipIds; exports.allVideoTracks = _chunk5T3H7CGGcjs.allVideoTracks; exports.animationEasingToVideoEase = animationEasingToVideoEase; exports.applyVideoEdits = applyVideoEdits; exports.applyVideoGrade = _chunk5T3H7CGGcjs.applyVideoGrade; exports.applyVideoLut = _chunk5T3H7CGGcjs.applyVideoLut; exports.applyVideoLutToPixels = _chunk5T3H7CGGcjs.applyVideoLutToPixels; exports.bakeVideoClipCamera = bakeVideoClipCamera; exports.buildVideoAudioPeaks = buildVideoAudioPeaks; exports.checkVideoEffectPlace = _chunk5T3H7CGGcjs.checkVideoEffectPlace; exports.checkVideoEffectValues = _chunk5T3H7CGGcjs.checkVideoEffectValues; exports.checkVideoProject = checkVideoProject; exports.checkVideoTimeRemap = _chunk5T3H7CGGcjs.checkVideoTimeRemap; exports.createVideoDialogueToolProvider = createVideoDialogueToolProvider; exports.createVideoEditorDocument = createVideoEditorDocument; exports.createVideoEditorToolProvider = createVideoEditorToolProvider; exports.createVideoEffectsToolProvider = createVideoEffectsToolProvider; exports.createVideoElementDecoder = createVideoElementDecoder; exports.createVideoMusicToolProvider = createVideoMusicToolProvider; exports.createVideoProject = createVideoProject; exports.decodeVideoAudioPeaks = decodeVideoAudioPeaks; exports.describeVideoEditPlan = describeVideoEditPlan; exports.describeVideoProject = describeVideoProject; exports.describeVideoSequence = describeVideoSequence; exports.detectVideoDisfluencies = detectVideoDisfluencies; exports.diffVideoProjects = diffVideoProjects; exports.drawVideoFrame = _chunk5T3H7CGGcjs.drawVideoFrame; exports.ffmpegFilterValue = _chunk5T3H7CGGcjs.ffmpegFilterValue; exports.findVideoAudioBeats = findVideoAudioBeats; exports.findVideoAudioSilences = findVideoAudioSilences; exports.findVideoClip = _chunk5T3H7CGGcjs.findVideoClip; exports.findVideoFillers = findVideoFillers; exports.findVideoGaps = _chunk5T3H7CGGcjs.findVideoGaps; exports.findVideoRepetitions = findVideoRepetitions; exports.findVideoSequenceClip = _chunk5T3H7CGGcjs.findVideoSequenceClip; exports.findVideoSequenceCycle = _chunk5T3H7CGGcjs.findVideoSequenceCycle; exports.findVideoTranscriptPauses = findVideoTranscriptPauses; exports.findVideoTranscriptText = findVideoTranscriptText; exports.formatVideoSeconds = _chunk5T3H7CGGcjs.formatVideoSeconds; exports.formatVideoTimecode = _chunk5T3H7CGGcjs.formatVideoTimecode; exports.formatVideoTimecodeFrames = _chunk5T3H7CGGcjs.formatVideoTimecodeFrames; exports.isVideoDropFrameRate = _chunk5T3H7CGGcjs.isVideoDropFrameRate; exports.isVideoKeyframes = _chunk5T3H7CGGcjs.isVideoKeyframes; exports.measureVideoLoudness = measureVideoLoudness; exports.mergeVideoRanges = mergeVideoRanges; exports.mixEffectPixels = _chunk5T3H7CGGcjs.mixEffectPixels; exports.nearestVideoBeat = nearestVideoBeat; exports.nextFreeVideoSlot = _chunk5T3H7CGGcjs.nextFreeVideoSlot; exports.normalizeVideoClipMask = _chunk5T3H7CGGcjs.normalizeVideoClipMask; exports.normalizeVideoGrade = _chunk5T3H7CGGcjs.normalizeVideoGrade; exports.normalizeVideoGradeLut = _chunk5T3H7CGGcjs.normalizeVideoGradeLut; exports.normalizeVideoWord = normalizeVideoWord; exports.openVideoClipEffectAuthoring = openVideoClipEffectAuthoring; exports.overEffectPixels = _chunk5T3H7CGGcjs.overEffectPixels; exports.parseVideoAnimatable = parseVideoAnimatable; exports.parseVideoAsset = parseVideoAsset; exports.parseVideoAssetProxies = parseVideoAssetProxies; exports.parseVideoClip = parseVideoClip; exports.parseVideoClipAnimation = parseVideoClipAnimation; exports.parseVideoClipCamera = parseVideoClipCamera; exports.parseVideoClipEffects = parseVideoClipEffects; exports.parseVideoClipMask = parseVideoClipMask; exports.parseVideoCubeLut = _chunk5T3H7CGGcjs.parseVideoCubeLut; exports.parseVideoEffectRef = parseVideoEffectRef; exports.parseVideoEffectValues = parseVideoEffectValues; exports.parseVideoGrade = parseVideoGrade; exports.parseVideoGradeLut = parseVideoGradeLut; exports.parseVideoKeyframes = parseVideoKeyframes; exports.parseVideoLoudnessMeasurement = _chunk5T3H7CGGcjs.parseVideoLoudnessMeasurement; exports.parseVideoMarker = parseVideoMarker; exports.parseVideoPreviewScale = parseVideoPreviewScale; exports.parseVideoProject = parseVideoProject; exports.parseVideoSequence = parseVideoSequence; exports.parseVideoTimeRef = parseVideoTimeRef; exports.parseVideoTimeRemap = parseVideoTimeRemap; exports.parseVideoTrack = parseVideoTrack; exports.parseVideoTranscript = parseVideoTranscript; exports.parseVideoTranscriptWords = parseVideoTranscriptWords; exports.parseVideoTransform = parseVideoTransform; exports.parseVideoTransition = parseVideoTransition; exports.placeVideoRect = _chunk5T3H7CGGcjs.placeVideoRect; exports.planVideoClipDrag = planVideoClipDrag; exports.planVideoEdits = planVideoEdits; exports.planVideoPrefetch = planVideoPrefetch; exports.planVideoToolPlayback = planVideoToolPlayback; exports.probeVideoMedia = probeVideoMedia; exports.readVideoScopesPanel = readVideoScopesPanel; exports.removeVideoKey = _chunk5T3H7CGGcjs.removeVideoKey; exports.renderVideoFrameExact = _chunk5T3H7CGGcjs.renderVideoFrameExact; exports.resolveVideoPreviewScale = resolveVideoPreviewScale; exports.retimeVideoAnimatable = _chunk5T3H7CGGcjs.retimeVideoAnimatable; exports.setVideoKey = _chunk5T3H7CGGcjs.setVideoKey; exports.snapToVideoFrame = _chunk5T3H7CGGcjs.snapToVideoFrame; exports.snapVideoTime = _chunk5T3H7CGGcjs.snapVideoTime; exports.sortVideoKeys = _chunk5T3H7CGGcjs.sortVideoKeys; exports.sortedVideoClips = _chunk5T3H7CGGcjs.sortedVideoClips; exports.splitVideoAnimatable = _chunk5T3H7CGGcjs.splitVideoAnimatable; exports.summarizeVideoScopes = summarizeVideoScopes; exports.toVideoEdl = _chunk5T3H7CGGcjs.toVideoEdl; exports.toVideoFfmpeg = _chunk5T3H7CGGcjs.toVideoFfmpeg; exports.toVideoLoudnessMeasure = _chunk5T3H7CGGcjs.toVideoLoudnessMeasure; exports.videoAddAdjustmentEdits = videoAddAdjustmentEdits; exports.videoAssetDropEdit = videoAssetDropEdit; exports.videoAssetHasSound = _chunk5T3H7CGGcjs.videoAssetHasSound; exports.videoAssetKindOf = videoAssetKindOf; exports.videoAssetMap = _chunk5T3H7CGGcjs.videoAssetMap; exports.videoAssetProxy = videoAssetProxy; exports.videoAudioLevels = videoAudioLevels; exports.videoAudioLoudness = videoAudioLoudness; exports.videoAudioPeakRange = videoAudioPeakRange; exports.videoAudioPeakSpans = videoAudioPeakSpans; exports.videoAudioPeaksDuration = videoAudioPeaksDuration; exports.videoAuthorableEffects = videoAuthorableEffects; exports.videoCacheEvictions = videoCacheEvictions; exports.videoCameraBase = videoCameraBase; exports.videoCameraMoveTools = videoCameraMoveTools; exports.videoCameraView = videoCameraView; exports.videoChroma = videoChroma; exports.videoClipAfter = _chunk5T3H7CGGcjs.videoClipAfter; exports.videoClipAnimated = _chunk5T3H7CGGcjs.videoClipAnimated; exports.videoClipAnimationProperties = _chunk5T3H7CGGcjs.videoClipAnimationProperties; exports.videoClipAnimationSpans = _chunk5T3H7CGGcjs.videoClipAnimationSpans; exports.videoClipAppliedEffects = videoClipAppliedEffects; exports.videoClipBefore = _chunk5T3H7CGGcjs.videoClipBefore; exports.videoClipCameraMove = videoClipCameraMove; exports.videoClipEffectDocument = videoClipEffectDocument; exports.videoClipEffectUses = _chunk5T3H7CGGcjs.videoClipEffectUses; exports.videoClipEnd = _chunk5T3H7CGGcjs.videoClipEnd; exports.videoClipHandles = _chunk5T3H7CGGcjs.videoClipHandles; exports.videoClipHeading = videoClipHeading; exports.videoClipKeyframes = videoClipKeyframes; exports.videoClipLabel = videoClipLabel; exports.videoClipOverhang = _chunk5T3H7CGGcjs.videoClipOverhang; exports.videoClipShowsWaveform = videoClipShowsWaveform; exports.videoClipSoundGain = _chunk5T3H7CGGcjs.videoClipSoundGain; exports.videoClipSourceRange = _chunk5T3H7CGGcjs.videoClipSourceRange; exports.videoClipSourceTime = _chunk5T3H7CGGcjs.videoClipSourceTime; exports.videoClipSpeed = _chunk5T3H7CGGcjs.videoClipSpeed; exports.videoClipSpeedAt = _chunk5T3H7CGGcjs.videoClipSpeedAt; exports.videoClipTint = videoClipTint; exports.videoClipTypeLabel = _chunk5T3H7CGGcjs.videoClipTypeLabel; exports.videoClipWaveform = videoClipWaveform; exports.videoClipWaveformPath = videoClipWaveformPath; exports.videoClipsAt = _chunk5T3H7CGGcjs.videoClipsAt; exports.videoContactSheetSvg = _chunk5T3H7CGGcjs.videoContactSheetSvg; exports.videoCutsWithMargin = videoCutsWithMargin; exports.videoDragLabel = videoDragLabel; exports.videoDropTracks = videoDropTracks; exports.videoDuckingKeys = videoDuckingKeys; exports.videoEaseBezier = _chunk5T3H7CGGcjs.videoEaseBezier; exports.videoEaseProgress = _chunk5T3H7CGGcjs.videoEaseProgress; exports.videoEaseToAnimationEasing = videoEaseToAnimationEasing; exports.videoEffectFrameTime = _chunk5T3H7CGGcjs.videoEffectFrameTime; exports.videoEffectLayerKey = _chunk5T3H7CGGcjs.videoEffectLayerKey; exports.videoEffectValuesAt = _chunk5T3H7CGGcjs.videoEffectValuesAt; exports.videoEffectValuesFromDocument = videoEffectValuesFromDocument; exports.videoExposureNotes = videoExposureNotes; exports.videoExposureStats = videoExposureStats; exports.videoFadeCurveGain = _chunk5T3H7CGGcjs.videoFadeCurveGain; exports.videoFfmpegUnsupportedEffects = _chunk5T3H7CGGcjs.videoFfmpegUnsupportedEffects; exports.videoFfmpegUnsupportedFeatures = _chunk5T3H7CGGcjs.videoFfmpegUnsupportedFeatures; exports.videoFrameAt = _chunk5T3H7CGGcjs.videoFrameAt; exports.videoFrameCacheKey = videoFrameCacheKey; exports.videoFrameDuration = _chunk5T3H7CGGcjs.videoFrameDuration; exports.videoFrameLeafLayers = _chunk5T3H7CGGcjs.videoFrameLeafLayers; exports.videoFrameRequestsAt = videoFrameRequestsAt; exports.videoFrameToSvg = _chunk5T3H7CGGcjs.videoFrameToSvg; exports.videoFrames = _chunk5T3H7CGGcjs.videoFrames; exports.videoFreezeFrameEdit = _chunk5T3H7CGGcjs.videoFreezeFrameEdit; exports.videoGradeCssFilter = _chunk5T3H7CGGcjs.videoGradeCssFilter; exports.videoGradeFfmpegFilters = _chunk5T3H7CGGcjs.videoGradeFfmpegFilters; exports.videoGradeGainsFilterId = _chunk5T3H7CGGcjs.videoGradeGainsFilterId; exports.videoGradeLook = _chunk5T3H7CGGcjs.videoGradeLook; exports.videoGradePreset = _chunk5T3H7CGGcjs.videoGradePreset; exports.videoGradeStepMatrix = _chunk5T3H7CGGcjs.videoGradeStepMatrix; exports.videoGradeStepSvgValues = _chunk5T3H7CGGcjs.videoGradeStepSvgValues; exports.videoGradeSteps = _chunk5T3H7CGGcjs.videoGradeSteps; exports.videoGradeSvgDefs = _chunk5T3H7CGGcjs.videoGradeSvgDefs; exports.videoGradeSvgFilter = _chunk5T3H7CGGcjs.videoGradeSvgFilter; exports.videoHistogram = videoHistogram; exports.videoHistogramImage = videoHistogramImage; exports.videoHourFrames = _chunk5T3H7CGGcjs.videoHourFrames; exports.videoIrisRadius = _chunk5T3H7CGGcjs.videoIrisRadius; exports.videoIssueKey = videoIssueKey; exports.videoKeyTimesProblem = _chunk5T3H7CGGcjs.videoKeyTimesProblem; exports.videoKeyframeBreakpoints = _chunk5T3H7CGGcjs.videoKeyframeBreakpoints; exports.videoKeyframeFfmpegExpr = _chunk5T3H7CGGcjs.videoKeyframeFfmpegExpr; exports.videoKeyframeRows = videoKeyframeRows; exports.videoKeyframeToggleEdit = videoKeyframeToggleEdit; exports.videoKeyframeValueEdit = videoKeyframeValueEdit; exports.videoKeysOf = _chunk5T3H7CGGcjs.videoKeysOf; exports.videoLayerMask = _chunk5T3H7CGGcjs.videoLayerMask; exports.videoLayersUseEffects = _chunk5T3H7CGGcjs.videoLayersUseEffects; exports.videoLayersWithoutTransitionEffects = _chunk5T3H7CGGcjs.videoLayersWithoutTransitionEffects; exports.videoLoudnessEnergy = videoLoudnessEnergy; exports.videoLoudnessGain = videoLoudnessGain; exports.videoLoudnessOf = videoLoudnessOf; exports.videoLuma = videoLuma; exports.videoLumaWaveform = videoLumaWaveform; exports.videoLutEdits = videoLutEdits; exports.videoLutFromFunction = _chunk5T3H7CGGcjs.videoLutFromFunction; exports.videoLutSvgApproximation = _chunk5T3H7CGGcjs.videoLutSvgApproximation; exports.videoLutSvgPrimitives = _chunk5T3H7CGGcjs.videoLutSvgPrimitives; exports.videoLutToCube = _chunk5T3H7CGGcjs.videoLutToCube; exports.videoMaskContains = _chunk5T3H7CGGcjs.videoMaskContains; exports.videoMaskEdit = videoMaskEdit; exports.videoMaskPolygon = _chunk5T3H7CGGcjs.videoMaskPolygon; exports.videoMaskSvgPath = _chunk5T3H7CGGcjs.videoMaskSvgPath; exports.videoOverlap = _chunk5T3H7CGGcjs.videoOverlap; exports.videoPeakDb = videoPeakDb; exports.videoPreviewSrc = videoPreviewSrc; exports.videoProjectDuration = _chunk5T3H7CGGcjs.videoProjectDuration; exports.videoProjectEffects = _chunk5T3H7CGGcjs.videoProjectEffects; exports.videoProjectHasProxies = videoProjectHasProxies; exports.videoProjectSvg = _chunk5T3H7CGGcjs.videoProjectSvg; exports.videoProxyFfmpeg = videoProxyFfmpeg; exports.videoProxyName = videoProxyName; exports.videoProxyPlan = videoProxyPlan; exports.videoRemoveRangesEdits = videoRemoveRangesEdits; exports.videoRulerTicks = videoRulerTicks; exports.videoScopeImage = videoScopeImage; exports.videoSequenceChildren = _chunk5T3H7CGGcjs.videoSequenceChildren; exports.videoSequenceDuration = _chunk5T3H7CGGcjs.videoSequenceDuration; exports.videoSequenceMap = _chunk5T3H7CGGcjs.videoSequenceMap; exports.videoShellQuote = _chunk5T3H7CGGcjs.videoShellQuote; exports.videoSkinProtectionEdits = videoSkinProtectionEdits; exports.videoSkinToneWeight = _chunk5T3H7CGGcjs.videoSkinToneWeight; exports.videoSlowMotionRamp = _chunk5T3H7CGGcjs.videoSlowMotionRamp; exports.videoSnapPoints = _chunk5T3H7CGGcjs.videoSnapPoints; exports.videoSourceFrame = videoSourceFrame; exports.videoSourceFrameTime = videoSourceFrameTime; exports.videoSpeechRanges = videoSpeechRanges; exports.videoSpeedRampEdit = _chunk5T3H7CGGcjs.videoSpeedRampEdit; exports.videoSpeedRampKeys = _chunk5T3H7CGGcjs.videoSpeedRampKeys; exports.videoTextStyle = _chunk5T3H7CGGcjs.videoTextStyle; exports.videoTimeRef = videoTimeRef; exports.videoTimeRemapBreakpoints = _chunk5T3H7CGGcjs.videoTimeRemapBreakpoints; exports.videoTimeRemapSpan = _chunk5T3H7CGGcjs.videoTimeRemapSpan; exports.videoTimecodeFrames = _chunk5T3H7CGGcjs.videoTimecodeFrames; exports.videoTimelineTranscript = videoTimelineTranscript; exports.videoTitleFrame = _chunk5T3H7CGGcjs.videoTitleFrame; exports.videoTrackSyncLocked = _chunk5T3H7CGGcjs.videoTrackSyncLocked; exports.videoTranscriptEdit = videoTranscriptEdit; exports.videoTranscriptTrack = videoTranscriptTrack; exports.videoTransformAt = _chunk5T3H7CGGcjs.videoTransformAt; exports.videoTransformOfView = videoTransformOfView; exports.videoTransitionAudioCurve = _chunk5T3H7CGGcjs.videoTransitionAudioCurve; exports.videoTransitionEase = _chunk5T3H7CGGcjs.videoTransitionEase; exports.videoTransitionHasDirection = videoTransitionHasDirection; exports.videoValueAt = _chunk5T3H7CGGcjs.videoValueAt; exports.videoVectorscope = videoVectorscope; exports.videoVectorscopeAngle = videoVectorscopeAngle; exports.videoVectorscopeImage = videoVectorscopeImage; exports.videoVectorscopePoint = videoVectorscopePoint; exports.videoWaveformImage = videoWaveformImage; exports.videoWaveformPath = videoWaveformPath; exports.videoWipeRect = _chunk5T3H7CGGcjs.videoWipeRect; exports.videoWordAt = videoWordAt; exports.videoWordsRange = videoWordsRange; exports.withVideoPlayback = withVideoPlayback;
|