@vosjs/studio-core 0.42.5 → 0.44.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/README.md +18 -16
- package/dist/index.d.ts +368 -6
- package/dist/index.js +396 -62
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -3531,16 +3531,17 @@ function planAutoZoom(track, options) {
|
|
|
3531
3531
|
const withoutDrags = (list) => list.map((cl) => cl.filter((c) => !dragPress.has(round2(c.t)))).filter((cl) => cl.length > 0);
|
|
3532
3532
|
const clusters = withoutDrags(grouped.clusters);
|
|
3533
3533
|
const surfaces = withoutDrags(grouped.surfaces);
|
|
3534
|
-
const
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
cy: round2(d.ny),
|
|
3541
|
-
focusMode: "auto",
|
|
3542
|
-
source: "auto"
|
|
3534
|
+
const dragWork = drags.map((d) => ({
|
|
3535
|
+
in: Math.max(0, d.t0 - lead),
|
|
3536
|
+
out: d.t1 + hold,
|
|
3537
|
+
cx: d.nx,
|
|
3538
|
+
cy: d.ny,
|
|
3539
|
+
level: Math.min(Math.max(dragLevel, 1.1), maxLevel)
|
|
3543
3540
|
}));
|
|
3541
|
+
for (let i = 0; i + 1 < dragWork.length; i++) {
|
|
3542
|
+
if (dragWork[i].out > dragWork[i + 1].in)
|
|
3543
|
+
dragWork[i].out = dragWork[i + 1].in;
|
|
3544
|
+
}
|
|
3544
3545
|
const eligible = clusters.filter((c) => c.length >= minClusterClicks);
|
|
3545
3546
|
const clickSpans = [];
|
|
3546
3547
|
const dragReserved = surfaces.map((cluster, i) => {
|
|
@@ -3612,6 +3613,19 @@ function planAutoZoom(track, options) {
|
|
|
3612
3613
|
if (typing[i].out > typing[i + 1].in) typing[i].out = typing[i + 1].in;
|
|
3613
3614
|
}
|
|
3614
3615
|
typing = typing.filter((t) => t.out - t.in >= 0.3);
|
|
3616
|
+
for (const w of [...clickSpans, ...typing]) cedeTo(w, dragWork);
|
|
3617
|
+
typing = typing.filter((t) => !t.dead && t.out - t.in >= 0.3);
|
|
3618
|
+
for (const z of clickSpans) if (z.out - z.in < 0.3) z.dead = true;
|
|
3619
|
+
const dragSpans = dragWork.filter((d) => d.out - d.in >= 0.3).map((d, i) => ({
|
|
3620
|
+
id: `g${i}`,
|
|
3621
|
+
in: round2(d.in),
|
|
3622
|
+
out: round2(d.out),
|
|
3623
|
+
level: clampZoomLevel(d.level),
|
|
3624
|
+
cx: round2(d.cx),
|
|
3625
|
+
cy: round2(d.cy),
|
|
3626
|
+
focusMode: "auto",
|
|
3627
|
+
source: "auto"
|
|
3628
|
+
}));
|
|
3615
3629
|
const zSpans = clickSpans.filter((s) => !s.dead).sort((a, b) => a.in - b.in).map((s, i) => ({
|
|
3616
3630
|
id: `z${i}`,
|
|
3617
3631
|
in: round2(s.in),
|
|
@@ -3645,6 +3659,17 @@ function planAutoZoom(track, options) {
|
|
|
3645
3659
|
]).filter((d) => firstStep === void 0 || d.out > firstStep);
|
|
3646
3660
|
return within([...spans, ...dwells]).sort((a, b) => a.in - b.in);
|
|
3647
3661
|
}
|
|
3662
|
+
function cedeTo(w, keep) {
|
|
3663
|
+
for (const k of keep) {
|
|
3664
|
+
if (w.dead || w.in >= k.out || w.out <= k.in) continue;
|
|
3665
|
+
if (k.in <= w.in && k.out >= w.out) w.dead = true;
|
|
3666
|
+
else if (k.in > w.in && k.out < w.out) {
|
|
3667
|
+
if (k.in - w.in >= w.out - k.out) w.out = k.in;
|
|
3668
|
+
else w.in = k.out;
|
|
3669
|
+
} else if (k.in > w.in) w.out = k.in;
|
|
3670
|
+
else w.in = k.out;
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3648
3673
|
function typingSessions(track, width, height, typingGap) {
|
|
3649
3674
|
const pings = track.filter((e) => e.type === "key").map((e) => ({ t: e.t / 1e3, rect: e.rect, x: e.x, y: e.y }));
|
|
3650
3675
|
const all = [];
|
|
@@ -3791,7 +3816,7 @@ import {
|
|
|
3791
3816
|
EASINGS,
|
|
3792
3817
|
lerpArray as lerpArray2,
|
|
3793
3818
|
sample as sample2,
|
|
3794
|
-
segmentRate as
|
|
3819
|
+
segmentRate as segmentRate3,
|
|
3795
3820
|
sortKeyframes as sortKeyframes2,
|
|
3796
3821
|
sourceToTimeline,
|
|
3797
3822
|
splitBySpeed as splitBySpeed3,
|
|
@@ -4245,6 +4270,51 @@ function sourceAt(rated, t) {
|
|
|
4245
4270
|
return null;
|
|
4246
4271
|
}
|
|
4247
4272
|
|
|
4273
|
+
// src/lower/loudness.ts
|
|
4274
|
+
var NORMALIZE_MIN_LUFS = -30;
|
|
4275
|
+
var NORMALIZE_MAX_LUFS = -6;
|
|
4276
|
+
var NORMALIZE_PEAK_CEILING_DB = -1;
|
|
4277
|
+
var NORMALIZE_MAX_LIFT_DB = 24;
|
|
4278
|
+
var finite = (v) => typeof v === "number" && Number.isFinite(v);
|
|
4279
|
+
var clamp014 = (v) => Math.max(0, Math.min(1, v));
|
|
4280
|
+
function loudnessMatches(clip) {
|
|
4281
|
+
const l = clip.loudness;
|
|
4282
|
+
return !!l && typeof l === "object" && finite(l.lufs) && typeof l.src === "string" && l.src === clip.key;
|
|
4283
|
+
}
|
|
4284
|
+
function clipGain(clip) {
|
|
4285
|
+
const trim = finite(clip.gain) ? Math.max(0, clip.gain) : 1;
|
|
4286
|
+
if (!finite(clip.normalize)) return { gain: clamp014(trim), basis: "gain" };
|
|
4287
|
+
if (!clip.loudness || typeof clip.loudness !== "object")
|
|
4288
|
+
return { gain: clamp014(trim), basis: "unmeasured" };
|
|
4289
|
+
if (!loudnessMatches(clip)) return { gain: clamp014(trim), basis: "stale" };
|
|
4290
|
+
const l = clip.loudness;
|
|
4291
|
+
const target = Math.max(
|
|
4292
|
+
NORMALIZE_MIN_LUFS,
|
|
4293
|
+
Math.min(NORMALIZE_MAX_LUFS, clip.normalize)
|
|
4294
|
+
);
|
|
4295
|
+
const asked = Math.pow(10, (target - l.lufs) / 20) * trim;
|
|
4296
|
+
let gain = asked;
|
|
4297
|
+
let capped;
|
|
4298
|
+
const lift = Math.pow(10, NORMALIZE_MAX_LIFT_DB / 20);
|
|
4299
|
+
if (gain > lift) {
|
|
4300
|
+
gain = lift;
|
|
4301
|
+
capped = "lift";
|
|
4302
|
+
}
|
|
4303
|
+
if (finite(l.peakDb)) {
|
|
4304
|
+
const peak = Math.pow(10, (NORMALIZE_PEAK_CEILING_DB - l.peakDb) / 20);
|
|
4305
|
+
if (gain > peak) {
|
|
4306
|
+
gain = peak;
|
|
4307
|
+
capped = "peak";
|
|
4308
|
+
}
|
|
4309
|
+
}
|
|
4310
|
+
return {
|
|
4311
|
+
gain: Math.max(0, gain),
|
|
4312
|
+
basis: "normalize",
|
|
4313
|
+
asked,
|
|
4314
|
+
...capped ? { capped } : {}
|
|
4315
|
+
};
|
|
4316
|
+
}
|
|
4317
|
+
|
|
4248
4318
|
// src/lower/audioEnvelope.ts
|
|
4249
4319
|
function clipEnvelope(clip) {
|
|
4250
4320
|
const span = clipLength(clip);
|
|
@@ -4256,7 +4326,7 @@ function clipEnvelope(clip) {
|
|
|
4256
4326
|
fi *= scale;
|
|
4257
4327
|
fo *= scale;
|
|
4258
4328
|
}
|
|
4259
|
-
const g =
|
|
4329
|
+
const g = clipGain(clip).gain;
|
|
4260
4330
|
const pts = [];
|
|
4261
4331
|
pts.push({ t: clip.start, g: fi > 0 ? 0 : g });
|
|
4262
4332
|
if (fi > 0) pts.push({ t: clip.start + fi, g });
|
|
@@ -4293,8 +4363,8 @@ function followFocusEvents(span, cursor, space, layout, options = {}) {
|
|
|
4293
4363
|
}
|
|
4294
4364
|
const pts = cursor.filter((e) => e.type === "move" || e.type === "down" || e.type === "up").map((e) => ({
|
|
4295
4365
|
t: e.t / 1e3,
|
|
4296
|
-
nx:
|
|
4297
|
-
ny:
|
|
4366
|
+
nx: clamp015(e.x / space.w),
|
|
4367
|
+
ny: clamp015(e.y / space.h)
|
|
4298
4368
|
}));
|
|
4299
4369
|
if (!pts.length) return { entry: null, events: [] };
|
|
4300
4370
|
const entry = clampFocus(span.cx, span.cy, level, layout, camera);
|
|
@@ -4372,7 +4442,7 @@ function sampleAt2(pts, t) {
|
|
|
4372
4442
|
}
|
|
4373
4443
|
return pts[pts.length - 1];
|
|
4374
4444
|
}
|
|
4375
|
-
function
|
|
4445
|
+
function clamp015(v) {
|
|
4376
4446
|
return Math.max(0, Math.min(1, v));
|
|
4377
4447
|
}
|
|
4378
4448
|
function round4(v) {
|
|
@@ -4709,6 +4779,114 @@ function round42(v) {
|
|
|
4709
4779
|
return Math.round(v * 1e5) / 1e5;
|
|
4710
4780
|
}
|
|
4711
4781
|
|
|
4782
|
+
// src/lower/anchor.ts
|
|
4783
|
+
import { segmentRate } from "@vosjs/timeline";
|
|
4784
|
+
var ELAPSED_PLACEHOLDER = "{elapsed}";
|
|
4785
|
+
var EPS = 1e-9;
|
|
4786
|
+
function sourceMomentToOutput(rated, t, media) {
|
|
4787
|
+
if (!Number.isFinite(t)) return null;
|
|
4788
|
+
let acc = 0;
|
|
4789
|
+
let edge = null;
|
|
4790
|
+
for (const p of rated) {
|
|
4791
|
+
const rate = segmentRate(p);
|
|
4792
|
+
const len = Math.max(0, p.out - p.in) / rate;
|
|
4793
|
+
if (sameMedia(p.media, media)) {
|
|
4794
|
+
if (t >= p.in - EPS && t < p.out - EPS)
|
|
4795
|
+
return acc + Math.max(0, t - p.in) / rate;
|
|
4796
|
+
if (edge === null && Math.abs(t - p.out) <= 1e-6) edge = acc + len;
|
|
4797
|
+
}
|
|
4798
|
+
acc += len;
|
|
4799
|
+
}
|
|
4800
|
+
return edge;
|
|
4801
|
+
}
|
|
4802
|
+
var isNum = (v) => typeof v === "number" && Number.isFinite(v);
|
|
4803
|
+
function stepElapsedMs(meta, step) {
|
|
4804
|
+
const skips = Array.isArray(meta.skips) ? meta.skips : [];
|
|
4805
|
+
for (const raw of skips) {
|
|
4806
|
+
if (!raw || typeof raw !== "object") continue;
|
|
4807
|
+
const s = raw;
|
|
4808
|
+
if (!isNum(s.ms) || s.ms < 0) continue;
|
|
4809
|
+
const named = step.id !== void 0 && (s.id === step.id || s.step === step.id) || s.step === step.step;
|
|
4810
|
+
if (named) return s.ms;
|
|
4811
|
+
}
|
|
4812
|
+
const own = step.offCameraMs;
|
|
4813
|
+
return isNum(own) && own >= 0 ? own : null;
|
|
4814
|
+
}
|
|
4815
|
+
function elapsedFor(meta, step) {
|
|
4816
|
+
const own = stepElapsedMs(meta, step);
|
|
4817
|
+
if (own !== null) return { ms: own };
|
|
4818
|
+
const earlier = (meta.steps ?? []).filter((s) => s !== step && s.step < step.step).sort((a, b) => b.step - a.step);
|
|
4819
|
+
for (const s of earlier) {
|
|
4820
|
+
const ms = stepElapsedMs(meta, s);
|
|
4821
|
+
if (ms !== null) return { ms, from: s };
|
|
4822
|
+
}
|
|
4823
|
+
return null;
|
|
4824
|
+
}
|
|
4825
|
+
function resolveAnchor(doc, anchor, rated) {
|
|
4826
|
+
const source = mediaSource(doc, anchor.media);
|
|
4827
|
+
if (!source) return { start: null, miss: "media" };
|
|
4828
|
+
const meta = source.meta;
|
|
4829
|
+
const step = findStep(meta.steps ?? [], anchor.step);
|
|
4830
|
+
if (!step) return { start: null, miss: "step" };
|
|
4831
|
+
const elapsed = elapsedFor(meta, step);
|
|
4832
|
+
const extra = elapsed ? {
|
|
4833
|
+
elapsedMs: elapsed.ms,
|
|
4834
|
+
...elapsed.from ? { elapsedFrom: elapsed.from } : {}
|
|
4835
|
+
} : {};
|
|
4836
|
+
if (step.skipped) return { start: null, step, miss: "skipped", ...extra };
|
|
4837
|
+
const moment = anchor.at === "end" ? step.tEnd : step.tStart;
|
|
4838
|
+
const out = sourceMomentToOutput(rated, moment, anchor.media);
|
|
4839
|
+
if (out === null) return { start: null, step, miss: "cut", ...extra };
|
|
4840
|
+
const offset = isNum(anchor.offset) ? anchor.offset : 0;
|
|
4841
|
+
return { start: round33(Math.max(0, out + offset)), step, ...extra };
|
|
4842
|
+
}
|
|
4843
|
+
var round33 = (v) => Math.round(v * 1e3) / 1e3;
|
|
4844
|
+
function formatElapsed(ms) {
|
|
4845
|
+
const s = Math.max(0, ms) / 1e3;
|
|
4846
|
+
const plural = (n, unit) => `${n} ${unit}${n === 1 ? "" : "s"}`;
|
|
4847
|
+
if (s < 9.5) return plural(Math.max(1, Math.round(s)), "second");
|
|
4848
|
+
if (s < 57.5) return plural(Math.round(s / 5) * 5, "second");
|
|
4849
|
+
const m = s / 60;
|
|
4850
|
+
if (m < 59.5) return plural(Math.max(1, Math.round(m)), "minute");
|
|
4851
|
+
const h = m / 60;
|
|
4852
|
+
if (h < 47.5) return plural(Math.max(1, Math.round(h)), "hour");
|
|
4853
|
+
return plural(Math.round(h / 24), "day");
|
|
4854
|
+
}
|
|
4855
|
+
function hasElapsed(text) {
|
|
4856
|
+
if (typeof text === "string") return text.includes(ELAPSED_PLACEHOLDER);
|
|
4857
|
+
return Array.isArray(text) && text.some(
|
|
4858
|
+
(r) => typeof r?.text === "string" && r.text.includes(ELAPSED_PLACEHOLDER)
|
|
4859
|
+
);
|
|
4860
|
+
}
|
|
4861
|
+
function fillElapsed(text, words) {
|
|
4862
|
+
const fill = (s) => s.split(ELAPSED_PLACEHOLDER).join(words);
|
|
4863
|
+
if (typeof text === "string") return fill(text);
|
|
4864
|
+
return text.map(
|
|
4865
|
+
(r) => typeof r.text === "string" && r.text.includes(ELAPSED_PLACEHOLDER) ? { ...r, text: fill(r.text) } : r
|
|
4866
|
+
);
|
|
4867
|
+
}
|
|
4868
|
+
function anchoredClip(clip, doc, rated) {
|
|
4869
|
+
if (!clip.anchor || typeof clip.anchor !== "object") return clip;
|
|
4870
|
+
const r = resolveAnchor(doc, clip.anchor, rated);
|
|
4871
|
+
let next = clip;
|
|
4872
|
+
if (r.start !== null && r.start !== clip.start)
|
|
4873
|
+
next = { ...next, start: r.start };
|
|
4874
|
+
if (next.kind === "text" && r.elapsedMs !== void 0 && hasElapsed(next.text)) {
|
|
4875
|
+
next = { ...next, text: fillElapsed(next.text, formatElapsed(r.elapsedMs)) };
|
|
4876
|
+
}
|
|
4877
|
+
return next;
|
|
4878
|
+
}
|
|
4879
|
+
function resolveOverlayAnchors(doc, rated) {
|
|
4880
|
+
const overlays = Array.isArray(doc.overlays) ? doc.overlays : [];
|
|
4881
|
+
if (!overlays.some((o) => o && o.anchor)) return doc;
|
|
4882
|
+
return {
|
|
4883
|
+
...doc,
|
|
4884
|
+
overlays: overlays.map(
|
|
4885
|
+
(o) => o && o.anchor ? anchoredClip(o, doc, rated) : o
|
|
4886
|
+
)
|
|
4887
|
+
};
|
|
4888
|
+
}
|
|
4889
|
+
|
|
4712
4890
|
// src/lower/cursorIdle.ts
|
|
4713
4891
|
var CURSOR_IDLE_HOLD = 1;
|
|
4714
4892
|
var CURSOR_IDLE_FADE_OUT = 0.35;
|
|
@@ -6264,7 +6442,7 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
|
|
|
6264
6442
|
}`;
|
|
6265
6443
|
|
|
6266
6444
|
// src/lower/extractClicks.ts
|
|
6267
|
-
import { segmentRate } from "@vosjs/timeline";
|
|
6445
|
+
import { segmentRate as segmentRate2 } from "@vosjs/timeline";
|
|
6268
6446
|
var CLICK_FX_PRE = 0.06;
|
|
6269
6447
|
var CLICK_RIPPLE_DUR = 0.45;
|
|
6270
6448
|
var CLICK_PULSE_DUR = 0.35;
|
|
@@ -6277,7 +6455,7 @@ function outputAt(segments, sourceT, media) {
|
|
|
6277
6455
|
if (!segments.length) return sourceT;
|
|
6278
6456
|
let acc = 0;
|
|
6279
6457
|
for (const s of segments) {
|
|
6280
|
-
const rate =
|
|
6458
|
+
const rate = segmentRate2(s);
|
|
6281
6459
|
if (sameMedia(s.media, media) && sourceT >= s.in && sourceT <= s.out)
|
|
6282
6460
|
return acc + (sourceT - s.in) / rate;
|
|
6283
6461
|
acc += Math.max(0, s.out - s.in) / rate;
|
|
@@ -6288,7 +6466,7 @@ function keptOutputEnd(segments, sIn, sOut, media) {
|
|
|
6288
6466
|
let acc = 0;
|
|
6289
6467
|
let end = null;
|
|
6290
6468
|
for (const p of segments) {
|
|
6291
|
-
const rate =
|
|
6469
|
+
const rate = segmentRate2(p);
|
|
6292
6470
|
if (sameMedia(p.media, media)) {
|
|
6293
6471
|
const ovIn = Math.max(sIn, p.in);
|
|
6294
6472
|
const ovOut = Math.min(sOut, p.out);
|
|
@@ -6401,7 +6579,7 @@ function spanOutputExtent(segments, sIn, sOut, media) {
|
|
|
6401
6579
|
let start = null;
|
|
6402
6580
|
let end = null;
|
|
6403
6581
|
for (const p of segments) {
|
|
6404
|
-
const rate =
|
|
6582
|
+
const rate = segmentRate3(p);
|
|
6405
6583
|
const len = Math.max(0, p.out - p.in) / rate;
|
|
6406
6584
|
if (!sameMedia(p.media, media)) {
|
|
6407
6585
|
acc += len;
|
|
@@ -8623,17 +8801,22 @@ function studioLayerData(input, duration, pins) {
|
|
|
8623
8801
|
// preview scheduler and the export's offline mix). `duckEnv` (the mic-derived
|
|
8624
8802
|
// duck multiplier curve) is merged in asynchronously by useComposition — it
|
|
8625
8803
|
// needs a decoded recording, which a sync lowering can't produce.
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8804
|
+
// A measured `normalize` sets the gain (it may exceed 1); a clip with
|
|
8805
|
+
// no target keeps its own, byte for byte.
|
|
8806
|
+
audio: (layers.audio ?? []).map((c) => {
|
|
8807
|
+
const g = clipGain(c);
|
|
8808
|
+
return {
|
|
8809
|
+
key: c.key,
|
|
8810
|
+
start: round8(c.start),
|
|
8811
|
+
in: round8(c.in),
|
|
8812
|
+
out: round8(c.out),
|
|
8813
|
+
gain: round8(g.basis === "normalize" ? g.gain : c.gain),
|
|
8814
|
+
loop: !!c.loop,
|
|
8815
|
+
len: round8(clipLength(c)),
|
|
8816
|
+
duck: !!c.duck,
|
|
8817
|
+
env: clipEnvelope(c).map((p) => ({ t: round8(p.t), g: round8(p.g) }))
|
|
8818
|
+
};
|
|
8819
|
+
}),
|
|
8637
8820
|
// Object clips: numbers resolved HERE; shapes are the drafted engine spec.
|
|
8638
8821
|
...layers.objects && layers.objects.length ? {
|
|
8639
8822
|
objects: layers.objects.map((o) => ({
|
|
@@ -8851,8 +9034,9 @@ function studioLayerData(input, duration, pins) {
|
|
|
8851
9034
|
};
|
|
8852
9035
|
}
|
|
8853
9036
|
function lowerToComposition(input) {
|
|
8854
|
-
const
|
|
8855
|
-
const rated = ratedSegments(
|
|
9037
|
+
const read = migrateText(migrateMotion(input));
|
|
9038
|
+
const rated = ratedSegments(read);
|
|
9039
|
+
const doc = resolveOverlayAnchors(read, rated);
|
|
8856
9040
|
const transitions = docTransitions(doc);
|
|
8857
9041
|
const footageEnd = durationSec(doc, rated);
|
|
8858
9042
|
const duration = outputEnd(doc, footageEnd);
|
|
@@ -9066,8 +9250,9 @@ function loweredZoomSpans(doc, rated, transitions, layout, camera, zoomStyle) {
|
|
|
9066
9250
|
});
|
|
9067
9251
|
}
|
|
9068
9252
|
function docZoomTrack(input) {
|
|
9069
|
-
const
|
|
9070
|
-
const rated = ratedSegments(
|
|
9253
|
+
const read = migrateText(migrateMotion(input));
|
|
9254
|
+
const rated = ratedSegments(read);
|
|
9255
|
+
const doc = resolveOverlayAnchors(read, rated);
|
|
9071
9256
|
const transitions = docTransitions(doc);
|
|
9072
9257
|
const layout = docCardLayout(doc);
|
|
9073
9258
|
const camera = cameraModel(doc.frame);
|
|
@@ -9795,14 +9980,16 @@ import { totalDuration as totalDuration5 } from "@vosjs/timeline";
|
|
|
9795
9980
|
|
|
9796
9981
|
// src/audioBeds.ts
|
|
9797
9982
|
import { totalDuration as totalDuration4 } from "@vosjs/timeline";
|
|
9798
|
-
var
|
|
9983
|
+
var round34 = (v) => Math.round(v * 1e3) / 1e3;
|
|
9799
9984
|
function docOutputDuration(doc) {
|
|
9800
|
-
const
|
|
9801
|
-
|
|
9985
|
+
const rated = ratedSegments(doc);
|
|
9986
|
+
const footage = totalDuration4(rated);
|
|
9987
|
+
if (!isRecordingDoc(doc)) return footage;
|
|
9988
|
+
return outputEnd(resolveOverlayAnchors(migrateMotion(doc), rated), footage);
|
|
9802
9989
|
}
|
|
9803
9990
|
function musicBedClip(input) {
|
|
9804
|
-
const track =
|
|
9805
|
-
const output =
|
|
9991
|
+
const track = round34(input.trackDuration);
|
|
9992
|
+
const output = round34(input.outputDuration);
|
|
9806
9993
|
const clip = {
|
|
9807
9994
|
id: input.id,
|
|
9808
9995
|
key: input.key,
|
|
@@ -9817,7 +10004,7 @@ function musicBedClip(input) {
|
|
|
9817
10004
|
fadeIn: 0,
|
|
9818
10005
|
// A bed that just stops reads as a glitch; clamp so a very short cut
|
|
9819
10006
|
// still spends most of its time at full level.
|
|
9820
|
-
fadeOut: output > 0 ? Math.min(1.5,
|
|
10007
|
+
fadeOut: output > 0 ? Math.min(1.5, round34(output / 4)) : 1.5,
|
|
9821
10008
|
duck: input.hasMic || void 0
|
|
9822
10009
|
};
|
|
9823
10010
|
if (output <= 0) return clip;
|
|
@@ -9836,28 +10023,28 @@ function isMusicBed(clip, outputDuration) {
|
|
|
9836
10023
|
return Math.abs(placed - outputDuration) <= 1;
|
|
9837
10024
|
}
|
|
9838
10025
|
function refillAudioBeds(doc, prevDuration, nextDuration) {
|
|
9839
|
-
const
|
|
9840
|
-
if (Math.abs(nextDuration - prevDuration) <=
|
|
10026
|
+
const EPS3 = 0.05;
|
|
10027
|
+
if (Math.abs(nextDuration - prevDuration) <= EPS3 || nextDuration <= 0) {
|
|
9841
10028
|
return false;
|
|
9842
10029
|
}
|
|
9843
10030
|
let changed = false;
|
|
9844
10031
|
for (const clip of doc.audio) {
|
|
9845
10032
|
if (clip.start >= nextDuration) continue;
|
|
9846
10033
|
const placed = clip.loop ? Math.max(clip.out - clip.in, clip.loopLen ?? clip.out - clip.in) : clip.out - clip.in;
|
|
9847
|
-
if (Math.abs(clip.start + placed - prevDuration) >
|
|
10034
|
+
if (Math.abs(clip.start + placed - prevDuration) > EPS3) continue;
|
|
9848
10035
|
const span = clip.out - clip.in;
|
|
9849
|
-
const nextLen =
|
|
10036
|
+
const nextLen = round34(nextDuration - clip.start);
|
|
9850
10037
|
if (clip.loop) {
|
|
9851
10038
|
if (nextLen >= span) {
|
|
9852
10039
|
clip.loopLen = nextLen;
|
|
9853
10040
|
} else {
|
|
9854
10041
|
clip.loop = void 0;
|
|
9855
10042
|
clip.loopLen = void 0;
|
|
9856
|
-
clip.out =
|
|
10043
|
+
clip.out = round34(clip.in + nextLen);
|
|
9857
10044
|
}
|
|
9858
10045
|
} else {
|
|
9859
10046
|
if (clip.in + nextLen <= clip.duration) {
|
|
9860
|
-
clip.out =
|
|
10047
|
+
clip.out = round34(clip.in + nextLen);
|
|
9861
10048
|
} else {
|
|
9862
10049
|
clip.out = clip.duration;
|
|
9863
10050
|
clip.loop = true;
|
|
@@ -10102,7 +10289,7 @@ function applyTemplate(template, take, opts) {
|
|
|
10102
10289
|
const skipped = [];
|
|
10103
10290
|
for (const clip of template.overlays ?? []) {
|
|
10104
10291
|
const next = structuredClone(clip);
|
|
10105
|
-
next.start = Math.max(0,
|
|
10292
|
+
next.start = Math.max(0, round35(clip.start + shift));
|
|
10106
10293
|
next.from = from;
|
|
10107
10294
|
const mine = own.get(clip.id);
|
|
10108
10295
|
if (next.kind === "text") {
|
|
@@ -10131,7 +10318,7 @@ function applyTemplate(template, take, opts) {
|
|
|
10131
10318
|
for (const clip of template.objects ?? []) {
|
|
10132
10319
|
const next = structuredClone(clip);
|
|
10133
10320
|
if (next.span)
|
|
10134
|
-
next.span.start = Math.max(0,
|
|
10321
|
+
next.span.start = Math.max(0, round35(next.span.start + shift));
|
|
10135
10322
|
next.from = from;
|
|
10136
10323
|
objects.push(next);
|
|
10137
10324
|
}
|
|
@@ -10141,7 +10328,7 @@ function applyTemplate(template, take, opts) {
|
|
|
10141
10328
|
);
|
|
10142
10329
|
for (const clip of template.audio ?? []) {
|
|
10143
10330
|
const next = structuredClone(clip);
|
|
10144
|
-
next.start = Math.max(0,
|
|
10331
|
+
next.start = Math.max(0, round35(clip.start + shift));
|
|
10145
10332
|
next.from = from;
|
|
10146
10333
|
audio.push(next);
|
|
10147
10334
|
}
|
|
@@ -10162,7 +10349,7 @@ function applyTemplate(template, take, opts) {
|
|
|
10162
10349
|
}
|
|
10163
10350
|
return { doc, notes };
|
|
10164
10351
|
}
|
|
10165
|
-
var
|
|
10352
|
+
var round35 = (v) => Math.round(v * 1e3) / 1e3;
|
|
10166
10353
|
|
|
10167
10354
|
// src/digest/geometry.ts
|
|
10168
10355
|
var CROP_MIN_FRAC = 0.25;
|
|
@@ -10345,15 +10532,15 @@ function outputRangeToSource(doc, t0, t1) {
|
|
|
10345
10532
|
srcOut: mapTime2(rated, Math.max(0, t1))
|
|
10346
10533
|
};
|
|
10347
10534
|
}
|
|
10348
|
-
var
|
|
10535
|
+
var EPS2 = 1e-6;
|
|
10349
10536
|
var MIN_REMAINDER = 0.25;
|
|
10350
10537
|
var MIN_SEGMENT = 0.05;
|
|
10351
10538
|
function setSpeedInRange(spans, srcIn, srcOut, rate) {
|
|
10352
|
-
if (srcOut - srcIn <
|
|
10539
|
+
if (srcOut - srcIn < EPS2) return [...spans];
|
|
10353
10540
|
const kept = [];
|
|
10354
10541
|
const used = new Set(spans.map((s) => s.id));
|
|
10355
10542
|
for (const s of spans) {
|
|
10356
|
-
if (s.out <= srcIn +
|
|
10543
|
+
if (s.out <= srcIn + EPS2 || s.in >= srcOut - EPS2) {
|
|
10357
10544
|
kept.push(s);
|
|
10358
10545
|
continue;
|
|
10359
10546
|
}
|
|
@@ -10378,12 +10565,12 @@ function setSpeedInRange(spans, srcIn, srcOut, rate) {
|
|
|
10378
10565
|
return kept.sort((a, b) => a.in - b.in);
|
|
10379
10566
|
}
|
|
10380
10567
|
function removeSpeedInRange(spans, srcIn, srcOut) {
|
|
10381
|
-
return spans.filter((s) => s.out <= srcIn +
|
|
10568
|
+
return spans.filter((s) => s.out <= srcIn + EPS2 || s.in >= srcOut - EPS2);
|
|
10382
10569
|
}
|
|
10383
10570
|
function removeSourceRange(segments, srcIn, srcOut) {
|
|
10384
10571
|
const next = [];
|
|
10385
10572
|
for (const seg of segments) {
|
|
10386
|
-
if (seg.out <= srcIn +
|
|
10573
|
+
if (seg.out <= srcIn + EPS2 || seg.in >= srcOut - EPS2) {
|
|
10387
10574
|
next.push(seg);
|
|
10388
10575
|
continue;
|
|
10389
10576
|
}
|
|
@@ -10395,11 +10582,11 @@ function removeSourceRange(segments, srcIn, srcOut) {
|
|
|
10395
10582
|
}
|
|
10396
10583
|
function zoomSpanForRange(zoom, srcIn, srcOut) {
|
|
10397
10584
|
let start = srcIn;
|
|
10398
|
-
const covering = zoom.find((z) => z.in <= start +
|
|
10585
|
+
const covering = zoom.find((z) => z.in <= start + EPS2 && z.out > start + EPS2);
|
|
10399
10586
|
if (covering) start = covering.out;
|
|
10400
10587
|
let end = srcOut;
|
|
10401
10588
|
for (const z of zoom) {
|
|
10402
|
-
if (z.in >= start -
|
|
10589
|
+
if (z.in >= start - EPS2 && z.in < end) end = z.in;
|
|
10403
10590
|
}
|
|
10404
10591
|
if (end - start < ZOOM_SPAN_MIN) return null;
|
|
10405
10592
|
const used = new Set(zoom.map((z) => z.id));
|
|
@@ -10808,7 +10995,7 @@ function applyLook(frame, look, size, video, placement) {
|
|
|
10808
10995
|
import {
|
|
10809
10996
|
mapTime as mapTime3,
|
|
10810
10997
|
removeSegment,
|
|
10811
|
-
segmentRate as
|
|
10998
|
+
segmentRate as segmentRate4,
|
|
10812
10999
|
sourceToTimeline as sourceToTimeline2,
|
|
10813
11000
|
splitBySpeed as splitBySpeed4,
|
|
10814
11001
|
totalDuration as totalDuration7,
|
|
@@ -11214,10 +11401,10 @@ function cursorFocusAt(doc, srcT) {
|
|
|
11214
11401
|
let best = track[0];
|
|
11215
11402
|
for (const e of track)
|
|
11216
11403
|
if (Math.abs(e.t - ms) < Math.abs(best.t - ms)) best = e;
|
|
11217
|
-
const
|
|
11404
|
+
const clamp016 = (v) => Math.max(0, Math.min(1, v));
|
|
11218
11405
|
return {
|
|
11219
|
-
cx: round13(
|
|
11220
|
-
cy: round13(
|
|
11406
|
+
cx: round13(clamp016(best.x / width)),
|
|
11407
|
+
cy: round13(clamp016(best.y / height))
|
|
11221
11408
|
};
|
|
11222
11409
|
}
|
|
11223
11410
|
var tiltLane = {
|
|
@@ -11549,7 +11736,7 @@ var micLane = {
|
|
|
11549
11736
|
var spanDefaultLen = (sourceDuration) => Math.max(1, sourceDuration * 0.05);
|
|
11550
11737
|
function rateAt(rated, srcT) {
|
|
11551
11738
|
for (const p of rated)
|
|
11552
|
-
if (srcT >= p.in - 1e-9 && srcT < p.out + 1e-9) return
|
|
11739
|
+
if (srcT >= p.in - 1e-9 && srcT < p.out + 1e-9) return segmentRate4(p);
|
|
11553
11740
|
return 1;
|
|
11554
11741
|
}
|
|
11555
11742
|
function clampToKept(kept, newIn, len) {
|
|
@@ -11579,7 +11766,7 @@ var speedLane = {
|
|
|
11579
11766
|
let start = null;
|
|
11580
11767
|
let end = 0;
|
|
11581
11768
|
for (const p of rated) {
|
|
11582
|
-
const len = Math.max(0, p.out - p.in) /
|
|
11769
|
+
const len = Math.max(0, p.out - p.in) / segmentRate4(p);
|
|
11583
11770
|
if (p.rate === sp.rate && p.in >= sp.in - 1e-9 && p.out <= sp.out + 1e-9) {
|
|
11584
11771
|
if (start === null) start = acc;
|
|
11585
11772
|
end = acc + len;
|
|
@@ -12085,6 +12272,133 @@ function duckCurve(rms, segments, durationSec2, opts = DEFAULT_DUCK) {
|
|
|
12085
12272
|
return points;
|
|
12086
12273
|
}
|
|
12087
12274
|
|
|
12275
|
+
// src/docFeatures.ts
|
|
12276
|
+
var overlaysOf = (doc) => Array.isArray(doc.overlays) ? doc.overlays : [];
|
|
12277
|
+
var audioOf = (doc) => Array.isArray(doc.audio) ? doc.audio : [];
|
|
12278
|
+
var anchored = (o) => !!o && !!o.anchor && typeof o.anchor === "object";
|
|
12279
|
+
function bakeAnchors(doc) {
|
|
12280
|
+
const layers = overlaysOf(doc);
|
|
12281
|
+
if (!layers.some(anchored)) return { doc, notes: [] };
|
|
12282
|
+
const notes = [];
|
|
12283
|
+
let resolved = doc;
|
|
12284
|
+
if (isRecordingDoc(doc)) {
|
|
12285
|
+
const rated = ratedSegments(migrateMotion(doc));
|
|
12286
|
+
resolved = resolveOverlayAnchors(doc, rated);
|
|
12287
|
+
for (const o of layers) {
|
|
12288
|
+
if (!anchored(o) || !o.anchor) continue;
|
|
12289
|
+
const r = resolveAnchor(doc, o.anchor, rated);
|
|
12290
|
+
if (r.start === null)
|
|
12291
|
+
notes.push(
|
|
12292
|
+
`overlay ${o.id}: its step ${r.miss === "cut" ? "is cut out of the film" : r.miss === "skipped" ? "was skipped by the recorder" : "is not in the take"}, so it plays at its fallback start (${o.start.toFixed(2)}s)`
|
|
12293
|
+
);
|
|
12294
|
+
}
|
|
12295
|
+
}
|
|
12296
|
+
const overlays = overlaysOf(resolved).map((o) => {
|
|
12297
|
+
if (!anchored(o)) return o;
|
|
12298
|
+
const { anchor: _anchor, ...rest } = o;
|
|
12299
|
+
return rest;
|
|
12300
|
+
});
|
|
12301
|
+
return { doc: { ...resolved, overlays }, notes };
|
|
12302
|
+
}
|
|
12303
|
+
var DOC_FEATURES = [
|
|
12304
|
+
{
|
|
12305
|
+
id: "text-runs",
|
|
12306
|
+
since: "0.38.0",
|
|
12307
|
+
name: "styled text runs",
|
|
12308
|
+
before: "would draw those layers without their words",
|
|
12309
|
+
uses: (doc) => overlaysOf(doc).filter((o) => o?.kind === "text" && Array.isArray(o.text)).length
|
|
12310
|
+
},
|
|
12311
|
+
{
|
|
12312
|
+
id: "overlay-anchor",
|
|
12313
|
+
since: "0.43.0",
|
|
12314
|
+
name: "caption anchors",
|
|
12315
|
+
before: "would show them at their fallback start",
|
|
12316
|
+
uses: (doc) => overlaysOf(doc).filter(anchored).length,
|
|
12317
|
+
bake: bakeAnchors
|
|
12318
|
+
},
|
|
12319
|
+
{
|
|
12320
|
+
id: "text-elapsed",
|
|
12321
|
+
since: "0.43.0",
|
|
12322
|
+
name: "{elapsed} in text",
|
|
12323
|
+
before: "would show the placeholder as it is written",
|
|
12324
|
+
// Filled only on an anchored layer: anywhere else every release shows
|
|
12325
|
+
// the placeholder as written.
|
|
12326
|
+
uses: (doc) => overlaysOf(doc).filter(
|
|
12327
|
+
(o) => anchored(o) && o.kind === "text" && hasElapsed(o.text)
|
|
12328
|
+
).length,
|
|
12329
|
+
// The anchors' bake fills it.
|
|
12330
|
+
bake: bakeAnchors
|
|
12331
|
+
},
|
|
12332
|
+
{
|
|
12333
|
+
id: "audio-normalize",
|
|
12334
|
+
since: "0.44.0",
|
|
12335
|
+
name: "loudness targets on sound",
|
|
12336
|
+
before: "would play those clips at their gain alone",
|
|
12337
|
+
// Only a target that applies: one with no measurement for its key is
|
|
12338
|
+
// ignored by every release alike.
|
|
12339
|
+
uses: (doc) => audioOf(doc).filter((a) => a && clipGain(a).basis === "normalize").length,
|
|
12340
|
+
bake: (doc) => {
|
|
12341
|
+
const notes = [];
|
|
12342
|
+
const audio = audioOf(doc).map((a) => {
|
|
12343
|
+
if (!a || a.normalize === void 0) return a;
|
|
12344
|
+
const { normalize: _normalize, ...rest } = a;
|
|
12345
|
+
const g = clipGain(a);
|
|
12346
|
+
if (g.basis !== "normalize") return rest;
|
|
12347
|
+
const gain = Math.round(Math.min(1, g.gain) * 1e3) / 1e3;
|
|
12348
|
+
if (g.gain > 1)
|
|
12349
|
+
notes.push(
|
|
12350
|
+
`audio ${a.id}: its target asks for gain ${g.gain.toFixed(2)}, which an older renderer cannot play; baked at 1, so it plays ${(20 * Math.log10(g.gain)).toFixed(1)} dB quieter than asked`
|
|
12351
|
+
);
|
|
12352
|
+
return { ...rest, gain };
|
|
12353
|
+
});
|
|
12354
|
+
return { doc: { ...doc, audio }, notes };
|
|
12355
|
+
}
|
|
12356
|
+
}
|
|
12357
|
+
];
|
|
12358
|
+
function compareVersions(a, b) {
|
|
12359
|
+
const parts = (v) => v.trim().replace(/^v/, "").split(/[-+]/)[0].split(".").map((n) => parseInt(n, 10) || 0);
|
|
12360
|
+
const x = parts(a);
|
|
12361
|
+
const y = parts(b);
|
|
12362
|
+
for (let i = 0; i < Math.max(x.length, y.length, 3); i++) {
|
|
12363
|
+
const d = (x[i] ?? 0) - (y[i] ?? 0);
|
|
12364
|
+
if (d) return d < 0 ? -1 : 1;
|
|
12365
|
+
}
|
|
12366
|
+
return 0;
|
|
12367
|
+
}
|
|
12368
|
+
function docFeatures(doc) {
|
|
12369
|
+
const out = [];
|
|
12370
|
+
for (const feature of DOC_FEATURES) {
|
|
12371
|
+
const count = feature.uses(doc);
|
|
12372
|
+
if (count > 0) out.push({ feature, count });
|
|
12373
|
+
}
|
|
12374
|
+
return out;
|
|
12375
|
+
}
|
|
12376
|
+
function featuresNewerThan(doc, version) {
|
|
12377
|
+
return docFeatures(doc).filter(
|
|
12378
|
+
(u) => compareVersions(u.feature.since, version) > 0
|
|
12379
|
+
);
|
|
12380
|
+
}
|
|
12381
|
+
function bakeDocFeatures(doc, version) {
|
|
12382
|
+
let next = structuredClone(doc);
|
|
12383
|
+
const baked = [];
|
|
12384
|
+
const unbakeable = [];
|
|
12385
|
+
const notes = [];
|
|
12386
|
+
const done = /* @__PURE__ */ new Set();
|
|
12387
|
+
for (const { feature } of featuresNewerThan(doc, version)) {
|
|
12388
|
+
if (!feature.bake) {
|
|
12389
|
+
unbakeable.push(feature);
|
|
12390
|
+
continue;
|
|
12391
|
+
}
|
|
12392
|
+
baked.push(feature);
|
|
12393
|
+
if (done.has(feature.bake)) continue;
|
|
12394
|
+
done.add(feature.bake);
|
|
12395
|
+
const r = feature.bake(next);
|
|
12396
|
+
next = r.doc;
|
|
12397
|
+
notes.push(...r.notes);
|
|
12398
|
+
}
|
|
12399
|
+
return { doc: next, baked, unbakeable, notes };
|
|
12400
|
+
}
|
|
12401
|
+
|
|
12088
12402
|
// src/backdrop.ts
|
|
12089
12403
|
function backdropMedia(backdrop) {
|
|
12090
12404
|
return {
|
|
@@ -12205,10 +12519,12 @@ export {
|
|
|
12205
12519
|
DIGEST_CROP_MAX,
|
|
12206
12520
|
DIGEST_FULL_MAX,
|
|
12207
12521
|
DIGEST_VERSION,
|
|
12522
|
+
DOC_FEATURES,
|
|
12208
12523
|
DOC_SCHEMA_VERSION,
|
|
12209
12524
|
DRAG_FIT_LEVEL,
|
|
12210
12525
|
DRAG_MIN_S,
|
|
12211
12526
|
DRAG_MIN_TRAVEL_FRAC,
|
|
12527
|
+
ELAPSED_PLACEHOLDER,
|
|
12212
12528
|
END_CARD_FROM,
|
|
12213
12529
|
END_CARD_RECEDE,
|
|
12214
12530
|
END_CARD_SECONDS,
|
|
@@ -12245,6 +12561,10 @@ export {
|
|
|
12245
12561
|
MIXED,
|
|
12246
12562
|
MOTION_DELTA,
|
|
12247
12563
|
MOTION_EASE,
|
|
12564
|
+
NORMALIZE_MAX_LIFT_DB,
|
|
12565
|
+
NORMALIZE_MAX_LUFS,
|
|
12566
|
+
NORMALIZE_MIN_LUFS,
|
|
12567
|
+
NORMALIZE_PEAK_CEILING_DB,
|
|
12248
12568
|
OBJECT_DEFAULT_SCALE,
|
|
12249
12569
|
OVERLAY_FONT_FACES,
|
|
12250
12570
|
OVERLAY_LINE_HEIGHT,
|
|
@@ -12319,12 +12639,14 @@ export {
|
|
|
12319
12639
|
ambientDrift,
|
|
12320
12640
|
anchorKindOf,
|
|
12321
12641
|
anchorSourceDuration,
|
|
12642
|
+
anchoredClip,
|
|
12322
12643
|
animStep,
|
|
12323
12644
|
applyLook,
|
|
12324
12645
|
applyTemplate,
|
|
12325
12646
|
aspectRatioValue,
|
|
12326
12647
|
audioLane,
|
|
12327
12648
|
backdropMedia,
|
|
12649
|
+
bakeDocFeatures,
|
|
12328
12650
|
boldWeightFor,
|
|
12329
12651
|
buildDigest,
|
|
12330
12652
|
calloutBox,
|
|
@@ -12359,9 +12681,11 @@ export {
|
|
|
12359
12681
|
clampZoomLevel,
|
|
12360
12682
|
clearStyle,
|
|
12361
12683
|
clipEnvelope,
|
|
12684
|
+
clipGain,
|
|
12362
12685
|
clipLength,
|
|
12363
12686
|
clipsFrom,
|
|
12364
12687
|
commonStyle,
|
|
12688
|
+
compareVersions,
|
|
12365
12689
|
computeCardLayout,
|
|
12366
12690
|
computeMicRms,
|
|
12367
12691
|
computePeaks,
|
|
@@ -12382,6 +12706,7 @@ export {
|
|
|
12382
12706
|
destinationsForChannel,
|
|
12383
12707
|
diffInput,
|
|
12384
12708
|
docCardLayout,
|
|
12709
|
+
docFeatures,
|
|
12385
12710
|
docFreezes,
|
|
12386
12711
|
docMediaList,
|
|
12387
12712
|
docOutputDuration,
|
|
@@ -12395,6 +12720,7 @@ export {
|
|
|
12395
12720
|
dropTemplate,
|
|
12396
12721
|
duckCurve,
|
|
12397
12722
|
effectiveSegments,
|
|
12723
|
+
elapsedFor,
|
|
12398
12724
|
endCardClips,
|
|
12399
12725
|
enterKey,
|
|
12400
12726
|
enterOf,
|
|
@@ -12410,13 +12736,16 @@ export {
|
|
|
12410
12736
|
expectedFrameSize,
|
|
12411
12737
|
exportSizeFor,
|
|
12412
12738
|
extractClicks,
|
|
12739
|
+
featuresNewerThan,
|
|
12413
12740
|
findStep,
|
|
12414
12741
|
focusBounds,
|
|
12415
12742
|
focusForViewportCentre,
|
|
12416
12743
|
followFocusEvents,
|
|
12744
|
+
formatElapsed,
|
|
12417
12745
|
frameGeometry,
|
|
12418
12746
|
freezeLane,
|
|
12419
12747
|
freezeOutputExtents,
|
|
12748
|
+
hasElapsed,
|
|
12420
12749
|
hexToRgb,
|
|
12421
12750
|
hexToRgbTriplet,
|
|
12422
12751
|
houseLook,
|
|
@@ -12455,6 +12784,7 @@ export {
|
|
|
12455
12784
|
liveZoomStyleName,
|
|
12456
12785
|
lookFromBrand,
|
|
12457
12786
|
lookKindForGround,
|
|
12787
|
+
loudnessMatches,
|
|
12458
12788
|
lowerProgramDoc,
|
|
12459
12789
|
lowerStudioDoc,
|
|
12460
12790
|
lowerToComposition,
|
|
@@ -12532,7 +12862,9 @@ export {
|
|
|
12532
12862
|
removeSourceRange,
|
|
12533
12863
|
removeSpeedInRange,
|
|
12534
12864
|
replaceRange,
|
|
12865
|
+
resolveAnchor,
|
|
12535
12866
|
resolveExportSize,
|
|
12867
|
+
resolveOverlayAnchors,
|
|
12536
12868
|
resolveOverlayBox,
|
|
12537
12869
|
resolveOverlayStyle,
|
|
12538
12870
|
resolvePins,
|
|
@@ -12556,8 +12888,10 @@ export {
|
|
|
12556
12888
|
smoothCursor,
|
|
12557
12889
|
snapOffset,
|
|
12558
12890
|
snapRunWeight,
|
|
12891
|
+
sourceMomentToOutput,
|
|
12559
12892
|
spanOutputExtent,
|
|
12560
12893
|
speedLane,
|
|
12894
|
+
stepElapsedMs,
|
|
12561
12895
|
studioAudioPlan,
|
|
12562
12896
|
studioEntry,
|
|
12563
12897
|
studioLayerData,
|