@vosjs/studio-core 0.42.4 → 0.43.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 +15 -15
- package/dist/index.d.ts +158 -3
- package/dist/index.js +176 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3791,7 +3791,7 @@ import {
|
|
|
3791
3791
|
EASINGS,
|
|
3792
3792
|
lerpArray as lerpArray2,
|
|
3793
3793
|
sample as sample2,
|
|
3794
|
-
segmentRate as
|
|
3794
|
+
segmentRate as segmentRate3,
|
|
3795
3795
|
sortKeyframes as sortKeyframes2,
|
|
3796
3796
|
sourceToTimeline,
|
|
3797
3797
|
splitBySpeed as splitBySpeed3,
|
|
@@ -4709,6 +4709,114 @@ function round42(v) {
|
|
|
4709
4709
|
return Math.round(v * 1e5) / 1e5;
|
|
4710
4710
|
}
|
|
4711
4711
|
|
|
4712
|
+
// src/lower/anchor.ts
|
|
4713
|
+
import { segmentRate } from "@vosjs/timeline";
|
|
4714
|
+
var ELAPSED_PLACEHOLDER = "{elapsed}";
|
|
4715
|
+
var EPS = 1e-9;
|
|
4716
|
+
function sourceMomentToOutput(rated, t, media) {
|
|
4717
|
+
if (!Number.isFinite(t)) return null;
|
|
4718
|
+
let acc = 0;
|
|
4719
|
+
let edge = null;
|
|
4720
|
+
for (const p of rated) {
|
|
4721
|
+
const rate = segmentRate(p);
|
|
4722
|
+
const len = Math.max(0, p.out - p.in) / rate;
|
|
4723
|
+
if (sameMedia(p.media, media)) {
|
|
4724
|
+
if (t >= p.in - EPS && t < p.out - EPS)
|
|
4725
|
+
return acc + Math.max(0, t - p.in) / rate;
|
|
4726
|
+
if (edge === null && Math.abs(t - p.out) <= 1e-6) edge = acc + len;
|
|
4727
|
+
}
|
|
4728
|
+
acc += len;
|
|
4729
|
+
}
|
|
4730
|
+
return edge;
|
|
4731
|
+
}
|
|
4732
|
+
var isNum = (v) => typeof v === "number" && Number.isFinite(v);
|
|
4733
|
+
function stepElapsedMs(meta, step) {
|
|
4734
|
+
const skips = Array.isArray(meta.skips) ? meta.skips : [];
|
|
4735
|
+
for (const raw of skips) {
|
|
4736
|
+
if (!raw || typeof raw !== "object") continue;
|
|
4737
|
+
const s = raw;
|
|
4738
|
+
if (!isNum(s.ms) || s.ms < 0) continue;
|
|
4739
|
+
const named = step.id !== void 0 && (s.id === step.id || s.step === step.id) || s.step === step.step;
|
|
4740
|
+
if (named) return s.ms;
|
|
4741
|
+
}
|
|
4742
|
+
const own = step.offCameraMs;
|
|
4743
|
+
return isNum(own) && own >= 0 ? own : null;
|
|
4744
|
+
}
|
|
4745
|
+
function elapsedFor(meta, step) {
|
|
4746
|
+
const own = stepElapsedMs(meta, step);
|
|
4747
|
+
if (own !== null) return { ms: own };
|
|
4748
|
+
const earlier = (meta.steps ?? []).filter((s) => s !== step && s.step < step.step).sort((a, b) => b.step - a.step);
|
|
4749
|
+
for (const s of earlier) {
|
|
4750
|
+
const ms = stepElapsedMs(meta, s);
|
|
4751
|
+
if (ms !== null) return { ms, from: s };
|
|
4752
|
+
}
|
|
4753
|
+
return null;
|
|
4754
|
+
}
|
|
4755
|
+
function resolveAnchor(doc, anchor, rated) {
|
|
4756
|
+
const source = mediaSource(doc, anchor.media);
|
|
4757
|
+
if (!source) return { start: null, miss: "media" };
|
|
4758
|
+
const meta = source.meta;
|
|
4759
|
+
const step = findStep(meta.steps ?? [], anchor.step);
|
|
4760
|
+
if (!step) return { start: null, miss: "step" };
|
|
4761
|
+
const elapsed = elapsedFor(meta, step);
|
|
4762
|
+
const extra = elapsed ? {
|
|
4763
|
+
elapsedMs: elapsed.ms,
|
|
4764
|
+
...elapsed.from ? { elapsedFrom: elapsed.from } : {}
|
|
4765
|
+
} : {};
|
|
4766
|
+
if (step.skipped) return { start: null, step, miss: "skipped", ...extra };
|
|
4767
|
+
const moment = anchor.at === "end" ? step.tEnd : step.tStart;
|
|
4768
|
+
const out = sourceMomentToOutput(rated, moment, anchor.media);
|
|
4769
|
+
if (out === null) return { start: null, step, miss: "cut", ...extra };
|
|
4770
|
+
const offset = isNum(anchor.offset) ? anchor.offset : 0;
|
|
4771
|
+
return { start: round33(Math.max(0, out + offset)), step, ...extra };
|
|
4772
|
+
}
|
|
4773
|
+
var round33 = (v) => Math.round(v * 1e3) / 1e3;
|
|
4774
|
+
function formatElapsed(ms) {
|
|
4775
|
+
const s = Math.max(0, ms) / 1e3;
|
|
4776
|
+
const plural = (n, unit) => `${n} ${unit}${n === 1 ? "" : "s"}`;
|
|
4777
|
+
if (s < 9.5) return plural(Math.max(1, Math.round(s)), "second");
|
|
4778
|
+
if (s < 57.5) return plural(Math.round(s / 5) * 5, "second");
|
|
4779
|
+
const m = s / 60;
|
|
4780
|
+
if (m < 59.5) return plural(Math.max(1, Math.round(m)), "minute");
|
|
4781
|
+
const h = m / 60;
|
|
4782
|
+
if (h < 47.5) return plural(Math.max(1, Math.round(h)), "hour");
|
|
4783
|
+
return plural(Math.round(h / 24), "day");
|
|
4784
|
+
}
|
|
4785
|
+
function hasElapsed(text) {
|
|
4786
|
+
if (typeof text === "string") return text.includes(ELAPSED_PLACEHOLDER);
|
|
4787
|
+
return Array.isArray(text) && text.some(
|
|
4788
|
+
(r) => typeof r?.text === "string" && r.text.includes(ELAPSED_PLACEHOLDER)
|
|
4789
|
+
);
|
|
4790
|
+
}
|
|
4791
|
+
function fillElapsed(text, words) {
|
|
4792
|
+
const fill = (s) => s.split(ELAPSED_PLACEHOLDER).join(words);
|
|
4793
|
+
if (typeof text === "string") return fill(text);
|
|
4794
|
+
return text.map(
|
|
4795
|
+
(r) => typeof r.text === "string" && r.text.includes(ELAPSED_PLACEHOLDER) ? { ...r, text: fill(r.text) } : r
|
|
4796
|
+
);
|
|
4797
|
+
}
|
|
4798
|
+
function anchoredClip(clip, doc, rated) {
|
|
4799
|
+
if (!clip.anchor || typeof clip.anchor !== "object") return clip;
|
|
4800
|
+
const r = resolveAnchor(doc, clip.anchor, rated);
|
|
4801
|
+
let next = clip;
|
|
4802
|
+
if (r.start !== null && r.start !== clip.start)
|
|
4803
|
+
next = { ...next, start: r.start };
|
|
4804
|
+
if (next.kind === "text" && r.elapsedMs !== void 0 && hasElapsed(next.text)) {
|
|
4805
|
+
next = { ...next, text: fillElapsed(next.text, formatElapsed(r.elapsedMs)) };
|
|
4806
|
+
}
|
|
4807
|
+
return next;
|
|
4808
|
+
}
|
|
4809
|
+
function resolveOverlayAnchors(doc, rated) {
|
|
4810
|
+
const overlays = Array.isArray(doc.overlays) ? doc.overlays : [];
|
|
4811
|
+
if (!overlays.some((o) => o && o.anchor)) return doc;
|
|
4812
|
+
return {
|
|
4813
|
+
...doc,
|
|
4814
|
+
overlays: overlays.map(
|
|
4815
|
+
(o) => o && o.anchor ? anchoredClip(o, doc, rated) : o
|
|
4816
|
+
)
|
|
4817
|
+
};
|
|
4818
|
+
}
|
|
4819
|
+
|
|
4712
4820
|
// src/lower/cursorIdle.ts
|
|
4713
4821
|
var CURSOR_IDLE_HOLD = 1;
|
|
4714
4822
|
var CURSOR_IDLE_FADE_OUT = 0.35;
|
|
@@ -6264,7 +6372,7 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
|
|
|
6264
6372
|
}`;
|
|
6265
6373
|
|
|
6266
6374
|
// src/lower/extractClicks.ts
|
|
6267
|
-
import { segmentRate } from "@vosjs/timeline";
|
|
6375
|
+
import { segmentRate as segmentRate2 } from "@vosjs/timeline";
|
|
6268
6376
|
var CLICK_FX_PRE = 0.06;
|
|
6269
6377
|
var CLICK_RIPPLE_DUR = 0.45;
|
|
6270
6378
|
var CLICK_PULSE_DUR = 0.35;
|
|
@@ -6277,7 +6385,7 @@ function outputAt(segments, sourceT, media) {
|
|
|
6277
6385
|
if (!segments.length) return sourceT;
|
|
6278
6386
|
let acc = 0;
|
|
6279
6387
|
for (const s of segments) {
|
|
6280
|
-
const rate =
|
|
6388
|
+
const rate = segmentRate2(s);
|
|
6281
6389
|
if (sameMedia(s.media, media) && sourceT >= s.in && sourceT <= s.out)
|
|
6282
6390
|
return acc + (sourceT - s.in) / rate;
|
|
6283
6391
|
acc += Math.max(0, s.out - s.in) / rate;
|
|
@@ -6288,7 +6396,7 @@ function keptOutputEnd(segments, sIn, sOut, media) {
|
|
|
6288
6396
|
let acc = 0;
|
|
6289
6397
|
let end = null;
|
|
6290
6398
|
for (const p of segments) {
|
|
6291
|
-
const rate =
|
|
6399
|
+
const rate = segmentRate2(p);
|
|
6292
6400
|
if (sameMedia(p.media, media)) {
|
|
6293
6401
|
const ovIn = Math.max(sIn, p.in);
|
|
6294
6402
|
const ovOut = Math.min(sOut, p.out);
|
|
@@ -6401,7 +6509,7 @@ function spanOutputExtent(segments, sIn, sOut, media) {
|
|
|
6401
6509
|
let start = null;
|
|
6402
6510
|
let end = null;
|
|
6403
6511
|
for (const p of segments) {
|
|
6404
|
-
const rate =
|
|
6512
|
+
const rate = segmentRate3(p);
|
|
6405
6513
|
const len = Math.max(0, p.out - p.in) / rate;
|
|
6406
6514
|
if (!sameMedia(p.media, media)) {
|
|
6407
6515
|
acc += len;
|
|
@@ -6911,9 +7019,24 @@ var SETUP = `async (ctx) => {
|
|
|
6911
7019
|
;(ns.videoBlobs || (ns.videoBlobs = new Map())).set(src, fetched)
|
|
6912
7020
|
return URL.createObjectURL(fetched)
|
|
6913
7021
|
}
|
|
7022
|
+
// Every element handed out by this SETUP, so two players never share one.
|
|
7023
|
+
// A take may name one file as two media (the same shot as a teaser and in
|
|
7024
|
+
// full), or as a media and the footage; the by-src cache would hand both
|
|
7025
|
+
// ONE element, and ON_FRAME's concat rule, which pauses every media that
|
|
7026
|
+
// is not under the playhead, then paused the playing clip every frame under
|
|
7027
|
+
// the other name: play/pause churn, the element falling behind the clock,
|
|
7028
|
+
// and a drift-guard seek every ~0.3 s that read as a stuck picture jumping
|
|
7029
|
+
// forward. A second claim on the same bytes gets its OWN element, kept in
|
|
7030
|
+
// the cache under a slot of its own so a warm LOAD reuses it like the first.
|
|
7031
|
+
const claimed = new Set()
|
|
6914
7032
|
const load = async (src, muted) => {
|
|
6915
|
-
let
|
|
6916
|
-
|
|
7033
|
+
let key = src
|
|
7034
|
+
let v = cache.get(key)
|
|
7035
|
+
for (let n = 2; v && claimed.has(v); n++) {
|
|
7036
|
+
key = src + '#' + n
|
|
7037
|
+
v = cache.get(key)
|
|
7038
|
+
}
|
|
7039
|
+
if (v) { claimed.add(v); return v }
|
|
6917
7040
|
let url = src
|
|
6918
7041
|
if (ctx.data.videoFetchMode === 'blob') {
|
|
6919
7042
|
try { url = await toBlobUrl(src) }
|
|
@@ -6933,7 +7056,8 @@ var SETUP = `async (ctx) => {
|
|
|
6933
7056
|
v.onerror = () => rej(new Error('[studio] video failed to load' + (v.error ? ' (' + v.error.code + (v.error.message ? ': ' + v.error.message : '') + ')' : '')))
|
|
6934
7057
|
v.load()
|
|
6935
7058
|
})
|
|
6936
|
-
cache.set(
|
|
7059
|
+
cache.set(key, v)
|
|
7060
|
+
claimed.add(v)
|
|
6937
7061
|
return v
|
|
6938
7062
|
}
|
|
6939
7063
|
// Shots: the "video" is a still image \u2014 drawImage accepts it directly and the
|
|
@@ -7377,7 +7501,7 @@ var ON_FRAME = `(ctx, content, dt) => {
|
|
|
7377
7501
|
// The card under the playhead: another media's own card fields over the
|
|
7378
7502
|
// take's frame (resolved at lowering), the take's frame for the primary.
|
|
7379
7503
|
var cfr = amId && actM && actM.frame ? actM.frame : frame
|
|
7380
|
-
if (r.media) for (var amK in r.media) { var amE = r.media[amK]; if (amK !== amId && amE && amE.pause && amE.paused === false) amE.pause() }
|
|
7504
|
+
if (r.media) for (var amK in r.media) { var amE = r.media[amK]; if (amK !== amId && amE && amE !== video && amE.pause && amE.paused === false) amE.pause() }
|
|
7381
7505
|
if (amId) {
|
|
7382
7506
|
if (r.video && r.video.pause && r.video.paused === false) r.video.pause()
|
|
7383
7507
|
if (r.cam && r.cam.pause && r.cam.paused === false) r.cam.pause()
|
|
@@ -8835,8 +8959,9 @@ function studioLayerData(input, duration, pins) {
|
|
|
8835
8959
|
};
|
|
8836
8960
|
}
|
|
8837
8961
|
function lowerToComposition(input) {
|
|
8838
|
-
const
|
|
8839
|
-
const rated = ratedSegments(
|
|
8962
|
+
const read = migrateText(migrateMotion(input));
|
|
8963
|
+
const rated = ratedSegments(read);
|
|
8964
|
+
const doc = resolveOverlayAnchors(read, rated);
|
|
8840
8965
|
const transitions = docTransitions(doc);
|
|
8841
8966
|
const footageEnd = durationSec(doc, rated);
|
|
8842
8967
|
const duration = outputEnd(doc, footageEnd);
|
|
@@ -9050,8 +9175,9 @@ function loweredZoomSpans(doc, rated, transitions, layout, camera, zoomStyle) {
|
|
|
9050
9175
|
});
|
|
9051
9176
|
}
|
|
9052
9177
|
function docZoomTrack(input) {
|
|
9053
|
-
const
|
|
9054
|
-
const rated = ratedSegments(
|
|
9178
|
+
const read = migrateText(migrateMotion(input));
|
|
9179
|
+
const rated = ratedSegments(read);
|
|
9180
|
+
const doc = resolveOverlayAnchors(read, rated);
|
|
9055
9181
|
const transitions = docTransitions(doc);
|
|
9056
9182
|
const layout = docCardLayout(doc);
|
|
9057
9183
|
const camera = cameraModel(doc.frame);
|
|
@@ -9779,14 +9905,16 @@ import { totalDuration as totalDuration5 } from "@vosjs/timeline";
|
|
|
9779
9905
|
|
|
9780
9906
|
// src/audioBeds.ts
|
|
9781
9907
|
import { totalDuration as totalDuration4 } from "@vosjs/timeline";
|
|
9782
|
-
var
|
|
9908
|
+
var round34 = (v) => Math.round(v * 1e3) / 1e3;
|
|
9783
9909
|
function docOutputDuration(doc) {
|
|
9784
|
-
const
|
|
9785
|
-
|
|
9910
|
+
const rated = ratedSegments(doc);
|
|
9911
|
+
const footage = totalDuration4(rated);
|
|
9912
|
+
if (!isRecordingDoc(doc)) return footage;
|
|
9913
|
+
return outputEnd(resolveOverlayAnchors(migrateMotion(doc), rated), footage);
|
|
9786
9914
|
}
|
|
9787
9915
|
function musicBedClip(input) {
|
|
9788
|
-
const track =
|
|
9789
|
-
const output =
|
|
9916
|
+
const track = round34(input.trackDuration);
|
|
9917
|
+
const output = round34(input.outputDuration);
|
|
9790
9918
|
const clip = {
|
|
9791
9919
|
id: input.id,
|
|
9792
9920
|
key: input.key,
|
|
@@ -9801,7 +9929,7 @@ function musicBedClip(input) {
|
|
|
9801
9929
|
fadeIn: 0,
|
|
9802
9930
|
// A bed that just stops reads as a glitch; clamp so a very short cut
|
|
9803
9931
|
// still spends most of its time at full level.
|
|
9804
|
-
fadeOut: output > 0 ? Math.min(1.5,
|
|
9932
|
+
fadeOut: output > 0 ? Math.min(1.5, round34(output / 4)) : 1.5,
|
|
9805
9933
|
duck: input.hasMic || void 0
|
|
9806
9934
|
};
|
|
9807
9935
|
if (output <= 0) return clip;
|
|
@@ -9820,28 +9948,28 @@ function isMusicBed(clip, outputDuration) {
|
|
|
9820
9948
|
return Math.abs(placed - outputDuration) <= 1;
|
|
9821
9949
|
}
|
|
9822
9950
|
function refillAudioBeds(doc, prevDuration, nextDuration) {
|
|
9823
|
-
const
|
|
9824
|
-
if (Math.abs(nextDuration - prevDuration) <=
|
|
9951
|
+
const EPS3 = 0.05;
|
|
9952
|
+
if (Math.abs(nextDuration - prevDuration) <= EPS3 || nextDuration <= 0) {
|
|
9825
9953
|
return false;
|
|
9826
9954
|
}
|
|
9827
9955
|
let changed = false;
|
|
9828
9956
|
for (const clip of doc.audio) {
|
|
9829
9957
|
if (clip.start >= nextDuration) continue;
|
|
9830
9958
|
const placed = clip.loop ? Math.max(clip.out - clip.in, clip.loopLen ?? clip.out - clip.in) : clip.out - clip.in;
|
|
9831
|
-
if (Math.abs(clip.start + placed - prevDuration) >
|
|
9959
|
+
if (Math.abs(clip.start + placed - prevDuration) > EPS3) continue;
|
|
9832
9960
|
const span = clip.out - clip.in;
|
|
9833
|
-
const nextLen =
|
|
9961
|
+
const nextLen = round34(nextDuration - clip.start);
|
|
9834
9962
|
if (clip.loop) {
|
|
9835
9963
|
if (nextLen >= span) {
|
|
9836
9964
|
clip.loopLen = nextLen;
|
|
9837
9965
|
} else {
|
|
9838
9966
|
clip.loop = void 0;
|
|
9839
9967
|
clip.loopLen = void 0;
|
|
9840
|
-
clip.out =
|
|
9968
|
+
clip.out = round34(clip.in + nextLen);
|
|
9841
9969
|
}
|
|
9842
9970
|
} else {
|
|
9843
9971
|
if (clip.in + nextLen <= clip.duration) {
|
|
9844
|
-
clip.out =
|
|
9972
|
+
clip.out = round34(clip.in + nextLen);
|
|
9845
9973
|
} else {
|
|
9846
9974
|
clip.out = clip.duration;
|
|
9847
9975
|
clip.loop = true;
|
|
@@ -10086,7 +10214,7 @@ function applyTemplate(template, take, opts) {
|
|
|
10086
10214
|
const skipped = [];
|
|
10087
10215
|
for (const clip of template.overlays ?? []) {
|
|
10088
10216
|
const next = structuredClone(clip);
|
|
10089
|
-
next.start = Math.max(0,
|
|
10217
|
+
next.start = Math.max(0, round35(clip.start + shift));
|
|
10090
10218
|
next.from = from;
|
|
10091
10219
|
const mine = own.get(clip.id);
|
|
10092
10220
|
if (next.kind === "text") {
|
|
@@ -10115,7 +10243,7 @@ function applyTemplate(template, take, opts) {
|
|
|
10115
10243
|
for (const clip of template.objects ?? []) {
|
|
10116
10244
|
const next = structuredClone(clip);
|
|
10117
10245
|
if (next.span)
|
|
10118
|
-
next.span.start = Math.max(0,
|
|
10246
|
+
next.span.start = Math.max(0, round35(next.span.start + shift));
|
|
10119
10247
|
next.from = from;
|
|
10120
10248
|
objects.push(next);
|
|
10121
10249
|
}
|
|
@@ -10125,7 +10253,7 @@ function applyTemplate(template, take, opts) {
|
|
|
10125
10253
|
);
|
|
10126
10254
|
for (const clip of template.audio ?? []) {
|
|
10127
10255
|
const next = structuredClone(clip);
|
|
10128
|
-
next.start = Math.max(0,
|
|
10256
|
+
next.start = Math.max(0, round35(clip.start + shift));
|
|
10129
10257
|
next.from = from;
|
|
10130
10258
|
audio.push(next);
|
|
10131
10259
|
}
|
|
@@ -10146,7 +10274,7 @@ function applyTemplate(template, take, opts) {
|
|
|
10146
10274
|
}
|
|
10147
10275
|
return { doc, notes };
|
|
10148
10276
|
}
|
|
10149
|
-
var
|
|
10277
|
+
var round35 = (v) => Math.round(v * 1e3) / 1e3;
|
|
10150
10278
|
|
|
10151
10279
|
// src/digest/geometry.ts
|
|
10152
10280
|
var CROP_MIN_FRAC = 0.25;
|
|
@@ -10329,15 +10457,15 @@ function outputRangeToSource(doc, t0, t1) {
|
|
|
10329
10457
|
srcOut: mapTime2(rated, Math.max(0, t1))
|
|
10330
10458
|
};
|
|
10331
10459
|
}
|
|
10332
|
-
var
|
|
10460
|
+
var EPS2 = 1e-6;
|
|
10333
10461
|
var MIN_REMAINDER = 0.25;
|
|
10334
10462
|
var MIN_SEGMENT = 0.05;
|
|
10335
10463
|
function setSpeedInRange(spans, srcIn, srcOut, rate) {
|
|
10336
|
-
if (srcOut - srcIn <
|
|
10464
|
+
if (srcOut - srcIn < EPS2) return [...spans];
|
|
10337
10465
|
const kept = [];
|
|
10338
10466
|
const used = new Set(spans.map((s) => s.id));
|
|
10339
10467
|
for (const s of spans) {
|
|
10340
|
-
if (s.out <= srcIn +
|
|
10468
|
+
if (s.out <= srcIn + EPS2 || s.in >= srcOut - EPS2) {
|
|
10341
10469
|
kept.push(s);
|
|
10342
10470
|
continue;
|
|
10343
10471
|
}
|
|
@@ -10362,12 +10490,12 @@ function setSpeedInRange(spans, srcIn, srcOut, rate) {
|
|
|
10362
10490
|
return kept.sort((a, b) => a.in - b.in);
|
|
10363
10491
|
}
|
|
10364
10492
|
function removeSpeedInRange(spans, srcIn, srcOut) {
|
|
10365
|
-
return spans.filter((s) => s.out <= srcIn +
|
|
10493
|
+
return spans.filter((s) => s.out <= srcIn + EPS2 || s.in >= srcOut - EPS2);
|
|
10366
10494
|
}
|
|
10367
10495
|
function removeSourceRange(segments, srcIn, srcOut) {
|
|
10368
10496
|
const next = [];
|
|
10369
10497
|
for (const seg of segments) {
|
|
10370
|
-
if (seg.out <= srcIn +
|
|
10498
|
+
if (seg.out <= srcIn + EPS2 || seg.in >= srcOut - EPS2) {
|
|
10371
10499
|
next.push(seg);
|
|
10372
10500
|
continue;
|
|
10373
10501
|
}
|
|
@@ -10379,11 +10507,11 @@ function removeSourceRange(segments, srcIn, srcOut) {
|
|
|
10379
10507
|
}
|
|
10380
10508
|
function zoomSpanForRange(zoom, srcIn, srcOut) {
|
|
10381
10509
|
let start = srcIn;
|
|
10382
|
-
const covering = zoom.find((z) => z.in <= start +
|
|
10510
|
+
const covering = zoom.find((z) => z.in <= start + EPS2 && z.out > start + EPS2);
|
|
10383
10511
|
if (covering) start = covering.out;
|
|
10384
10512
|
let end = srcOut;
|
|
10385
10513
|
for (const z of zoom) {
|
|
10386
|
-
if (z.in >= start -
|
|
10514
|
+
if (z.in >= start - EPS2 && z.in < end) end = z.in;
|
|
10387
10515
|
}
|
|
10388
10516
|
if (end - start < ZOOM_SPAN_MIN) return null;
|
|
10389
10517
|
const used = new Set(zoom.map((z) => z.id));
|
|
@@ -10792,7 +10920,7 @@ function applyLook(frame, look, size, video, placement) {
|
|
|
10792
10920
|
import {
|
|
10793
10921
|
mapTime as mapTime3,
|
|
10794
10922
|
removeSegment,
|
|
10795
|
-
segmentRate as
|
|
10923
|
+
segmentRate as segmentRate4,
|
|
10796
10924
|
sourceToTimeline as sourceToTimeline2,
|
|
10797
10925
|
splitBySpeed as splitBySpeed4,
|
|
10798
10926
|
totalDuration as totalDuration7,
|
|
@@ -11533,7 +11661,7 @@ var micLane = {
|
|
|
11533
11661
|
var spanDefaultLen = (sourceDuration) => Math.max(1, sourceDuration * 0.05);
|
|
11534
11662
|
function rateAt(rated, srcT) {
|
|
11535
11663
|
for (const p of rated)
|
|
11536
|
-
if (srcT >= p.in - 1e-9 && srcT < p.out + 1e-9) return
|
|
11664
|
+
if (srcT >= p.in - 1e-9 && srcT < p.out + 1e-9) return segmentRate4(p);
|
|
11537
11665
|
return 1;
|
|
11538
11666
|
}
|
|
11539
11667
|
function clampToKept(kept, newIn, len) {
|
|
@@ -11563,7 +11691,7 @@ var speedLane = {
|
|
|
11563
11691
|
let start = null;
|
|
11564
11692
|
let end = 0;
|
|
11565
11693
|
for (const p of rated) {
|
|
11566
|
-
const len = Math.max(0, p.out - p.in) /
|
|
11694
|
+
const len = Math.max(0, p.out - p.in) / segmentRate4(p);
|
|
11567
11695
|
if (p.rate === sp.rate && p.in >= sp.in - 1e-9 && p.out <= sp.out + 1e-9) {
|
|
11568
11696
|
if (start === null) start = acc;
|
|
11569
11697
|
end = acc + len;
|
|
@@ -12193,6 +12321,7 @@ export {
|
|
|
12193
12321
|
DRAG_FIT_LEVEL,
|
|
12194
12322
|
DRAG_MIN_S,
|
|
12195
12323
|
DRAG_MIN_TRAVEL_FRAC,
|
|
12324
|
+
ELAPSED_PLACEHOLDER,
|
|
12196
12325
|
END_CARD_FROM,
|
|
12197
12326
|
END_CARD_RECEDE,
|
|
12198
12327
|
END_CARD_SECONDS,
|
|
@@ -12303,6 +12432,7 @@ export {
|
|
|
12303
12432
|
ambientDrift,
|
|
12304
12433
|
anchorKindOf,
|
|
12305
12434
|
anchorSourceDuration,
|
|
12435
|
+
anchoredClip,
|
|
12306
12436
|
animStep,
|
|
12307
12437
|
applyLook,
|
|
12308
12438
|
applyTemplate,
|
|
@@ -12379,6 +12509,7 @@ export {
|
|
|
12379
12509
|
dropTemplate,
|
|
12380
12510
|
duckCurve,
|
|
12381
12511
|
effectiveSegments,
|
|
12512
|
+
elapsedFor,
|
|
12382
12513
|
endCardClips,
|
|
12383
12514
|
enterKey,
|
|
12384
12515
|
enterOf,
|
|
@@ -12398,9 +12529,11 @@ export {
|
|
|
12398
12529
|
focusBounds,
|
|
12399
12530
|
focusForViewportCentre,
|
|
12400
12531
|
followFocusEvents,
|
|
12532
|
+
formatElapsed,
|
|
12401
12533
|
frameGeometry,
|
|
12402
12534
|
freezeLane,
|
|
12403
12535
|
freezeOutputExtents,
|
|
12536
|
+
hasElapsed,
|
|
12404
12537
|
hexToRgb,
|
|
12405
12538
|
hexToRgbTriplet,
|
|
12406
12539
|
houseLook,
|
|
@@ -12516,7 +12649,9 @@ export {
|
|
|
12516
12649
|
removeSourceRange,
|
|
12517
12650
|
removeSpeedInRange,
|
|
12518
12651
|
replaceRange,
|
|
12652
|
+
resolveAnchor,
|
|
12519
12653
|
resolveExportSize,
|
|
12654
|
+
resolveOverlayAnchors,
|
|
12520
12655
|
resolveOverlayBox,
|
|
12521
12656
|
resolveOverlayStyle,
|
|
12522
12657
|
resolvePins,
|
|
@@ -12540,8 +12675,10 @@ export {
|
|
|
12540
12675
|
smoothCursor,
|
|
12541
12676
|
snapOffset,
|
|
12542
12677
|
snapRunWeight,
|
|
12678
|
+
sourceMomentToOutput,
|
|
12543
12679
|
spanOutputExtent,
|
|
12544
12680
|
speedLane,
|
|
12681
|
+
stepElapsedMs,
|
|
12545
12682
|
studioAudioPlan,
|
|
12546
12683
|
studioEntry,
|
|
12547
12684
|
studioLayerData,
|