@vosjs/studio-core 0.12.0 → 0.13.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/index.d.ts +6 -4
- package/dist/index.js +221 -174
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -571,7 +571,7 @@ function entranceSeconds(e) {
|
|
|
571
571
|
function exitSeconds(e) {
|
|
572
572
|
if (!e || e.kind === "none") return 0;
|
|
573
573
|
const house = e.kind === "fade" ? CARD_FADE_SECONDS : END_CARD_RECEDE;
|
|
574
|
-
return Math.max(0.1, Math.min(
|
|
574
|
+
return Math.max(0.1, Math.min(8, e.seconds ?? house));
|
|
575
575
|
}
|
|
576
576
|
function placeFreezes(rated, freezes) {
|
|
577
577
|
const marks = /* @__PURE__ */ new Map();
|
|
@@ -663,8 +663,9 @@ function prependEntrance(track, head) {
|
|
|
663
663
|
return { keyframes: sortKeyframes([...head, ...rest]) };
|
|
664
664
|
}
|
|
665
665
|
function exitPose(e) {
|
|
666
|
-
return e?.kind === "fade" ? [1, 0, 0] : [0.9, -0.02, 0
|
|
666
|
+
return e?.kind === "fade" ? [1, 0, 0] : [0.9, -0.02, 0];
|
|
667
667
|
}
|
|
668
|
+
var RECEDE_MID = [0.91, -0.018, 0.8];
|
|
668
669
|
function cardPoseTrack(enter, exit, footageEnd, outputEnd2 = footageEnd) {
|
|
669
670
|
const keyframes = [];
|
|
670
671
|
const s = entranceSeconds(enter);
|
|
@@ -674,16 +675,36 @@ function cardPoseTrack(enter, exit, footageEnd, outputEnd2 = footageEnd) {
|
|
|
674
675
|
keyframes.push({ t: s, value: [1, 0, 1], ease: "power3.out" });
|
|
675
676
|
}
|
|
676
677
|
const x = exitSeconds(exit);
|
|
678
|
+
let last = [1, 0, 1];
|
|
677
679
|
if (x > 0 && footageEnd > 0) {
|
|
678
|
-
const
|
|
679
|
-
const
|
|
680
|
-
|
|
680
|
+
const t0 = round3(Math.max(s, footageEnd - x));
|
|
681
|
+
const t1 = round3(Math.max(t0 + 0.05, footageEnd));
|
|
682
|
+
last = exitPose(exit);
|
|
681
683
|
keyframes.push({ t: t0, value: [1, 0, 1], ease: "none" });
|
|
682
|
-
|
|
684
|
+
if (exit?.kind !== "fade") {
|
|
685
|
+
keyframes.push({
|
|
686
|
+
t: round3(t0 + (t1 - t0) * 0.45),
|
|
687
|
+
value: [...RECEDE_MID],
|
|
688
|
+
ease: "power2.out"
|
|
689
|
+
});
|
|
690
|
+
keyframes.push({ t: t1, value: last, ease: "power1.in" });
|
|
691
|
+
} else {
|
|
692
|
+
keyframes.push({ t: t1, value: last, ease: "power2.out" });
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
if (outputEnd2 > footageEnd + 1e-6 && footageEnd > 0) {
|
|
696
|
+
if (!keyframes.some((k) => Math.abs(k.t - footageEnd) < 1e-9))
|
|
697
|
+
keyframes.push({ t: footageEnd, value: [...last], ease: "none" });
|
|
698
|
+
keyframes.push({
|
|
699
|
+
t: round3(footageEnd + 1e-3),
|
|
700
|
+
value: [last[0], last[1], 0],
|
|
701
|
+
ease: "none"
|
|
702
|
+
});
|
|
683
703
|
}
|
|
684
704
|
if (!keyframes.length) return void 0;
|
|
685
705
|
return { keyframes: sortKeyframes(keyframes) };
|
|
686
706
|
}
|
|
707
|
+
var round3 = (v) => Math.round(v * 1e3) / 1e3;
|
|
687
708
|
function endCardClips(card, doc, endStart) {
|
|
688
709
|
const seconds = Math.max(1, Math.min(8, card.seconds ?? END_CARD_SECONDS));
|
|
689
710
|
const anim = { enter: "rise", exit: "none" };
|
|
@@ -822,18 +843,25 @@ function migrateMotion(doc) {
|
|
|
822
843
|
const card = doc.endCard;
|
|
823
844
|
if (card && segments.length) {
|
|
824
845
|
const seconds = Math.max(1, Math.min(8, card.seconds ?? END_CARD_SECONDS));
|
|
846
|
+
const segsNow = out.segments ?? segments;
|
|
847
|
+
const lastSeg = segsNow.at(-1);
|
|
848
|
+
const freezesNow = docFreezes({ segments: segsNow, freeze: out.freeze });
|
|
825
849
|
const rated = withFreezes(
|
|
826
|
-
splitBySpeed(
|
|
827
|
-
|
|
850
|
+
splitBySpeed(segsNow, doc.speed ?? []),
|
|
851
|
+
freezesNow
|
|
828
852
|
);
|
|
829
853
|
const endStart = totalDuration(rated);
|
|
854
|
+
const taken = new Set(freezesNow.map((f) => f.id));
|
|
855
|
+
let n = 0;
|
|
856
|
+
while (taken.has(`f${n}`)) n++;
|
|
857
|
+
out.freeze = [
|
|
858
|
+
...freezesNow,
|
|
859
|
+
{ id: `f${n}`, at: lastSeg.out, seconds, from: END_CARD_FROM }
|
|
860
|
+
].sort((a, b) => a.at - b.at);
|
|
830
861
|
nextOverlays = [...nextOverlays, ...endCardClips(card, doc, endStart)];
|
|
831
862
|
nextFrame.anim = {
|
|
832
863
|
...nextFrame.anim ?? {},
|
|
833
|
-
exit: {
|
|
834
|
-
kind: "recede",
|
|
835
|
-
seconds: Math.min(END_CARD_RECEDE, seconds * 0.4)
|
|
836
|
-
}
|
|
864
|
+
exit: { kind: "recede", seconds }
|
|
837
865
|
};
|
|
838
866
|
}
|
|
839
867
|
delete out.endCard;
|
|
@@ -1910,14 +1938,14 @@ function resolveOverlayFx(clip, clipDuration) {
|
|
|
1910
1938
|
const maxTotal = Math.max(dur, clipDuration * 0.9);
|
|
1911
1939
|
st = Math.min(st, Math.max(0, (maxTotal - dur) / (upperN - 1)));
|
|
1912
1940
|
}
|
|
1913
|
-
const
|
|
1941
|
+
const round12 = (v) => Math.round(v * 1e4) / 1e4;
|
|
1914
1942
|
return {
|
|
1915
1943
|
k: spec.fx,
|
|
1916
1944
|
u: unit,
|
|
1917
1945
|
d: FX_DIR[spec.direction ?? "forward"] ?? 0,
|
|
1918
|
-
st:
|
|
1919
|
-
dur:
|
|
1920
|
-
tt:
|
|
1946
|
+
st: round12(st),
|
|
1947
|
+
dur: round12(dur),
|
|
1948
|
+
tt: round12(st * (upperN - 1) + dur),
|
|
1921
1949
|
units,
|
|
1922
1950
|
n
|
|
1923
1951
|
};
|
|
@@ -2132,7 +2160,7 @@ var CURSOR_IDLE_HOLD = 1;
|
|
|
2132
2160
|
var CURSOR_IDLE_FADE_OUT = 0.35;
|
|
2133
2161
|
var CURSOR_IDLE_FADE_IN = 0.18;
|
|
2134
2162
|
var CURSOR_IDLE_EPS_FRAC = 25e-4;
|
|
2135
|
-
var
|
|
2163
|
+
var round4 = (n) => Math.round(n * 1e3) / 1e3;
|
|
2136
2164
|
function cursorIdleFade(track, o) {
|
|
2137
2165
|
const moves = track.filter((e) => e.type === "move" || e.type === "down" || e.type === "up").map((e) => ({ t: e.t / 1e3, x: e.x, y: e.y }));
|
|
2138
2166
|
if (moves.length === 0) return [];
|
|
@@ -2184,7 +2212,7 @@ function emit(keys, s, e) {
|
|
|
2184
2212
|
push(keys, e + CURSOR_IDLE_FADE_IN, 1);
|
|
2185
2213
|
}
|
|
2186
2214
|
function push(keys, t, a) {
|
|
2187
|
-
const rt =
|
|
2215
|
+
const rt = round4(t);
|
|
2188
2216
|
if (keys.length > 0 && rt <= keys[keys.length - 1].t) {
|
|
2189
2217
|
keys[keys.length - 1].a = a;
|
|
2190
2218
|
return;
|
|
@@ -3242,7 +3270,7 @@ function gatedRect(rect, x, y, space) {
|
|
|
3242
3270
|
return null;
|
|
3243
3271
|
const m = RECT_CONTAIN_MARGIN;
|
|
3244
3272
|
const inside = x >= rect.x - m && x <= rect.x + rect.w + m && y >= rect.y - m && y <= rect.y + rect.h + m;
|
|
3245
|
-
return inside ? [
|
|
3273
|
+
return inside ? [round5(rect.x), round5(rect.y), round5(rect.w), round5(rect.h)] : null;
|
|
3246
3274
|
}
|
|
3247
3275
|
function extractClicks(track, segments, opts) {
|
|
3248
3276
|
const out = [];
|
|
@@ -3267,11 +3295,11 @@ function extractClicks(track, segments, opts) {
|
|
|
3267
3295
|
const upSrc = st + Math.max(pressLen, 0.02);
|
|
3268
3296
|
const up = keptOutputEnd(segments, st, upSrc) ?? ot + CLICK_SYNTH_RELEASE;
|
|
3269
3297
|
const click = {
|
|
3270
|
-
ot:
|
|
3271
|
-
up:
|
|
3272
|
-
st:
|
|
3273
|
-
x:
|
|
3274
|
-
y:
|
|
3298
|
+
ot: round5(ot),
|
|
3299
|
+
up: round5(Math.max(up, ot + 0.02)),
|
|
3300
|
+
st: round5(st),
|
|
3301
|
+
x: round5(e.x),
|
|
3302
|
+
y: round5(e.y),
|
|
3275
3303
|
b: button
|
|
3276
3304
|
};
|
|
3277
3305
|
if (opts.rects && e.rect) {
|
|
@@ -3290,7 +3318,7 @@ function hexToRgbTriplet(hex) {
|
|
|
3290
3318
|
const n = parseInt(h, 16);
|
|
3291
3319
|
return [n >> 16, n >> 8 & 255, n & 255];
|
|
3292
3320
|
}
|
|
3293
|
-
function
|
|
3321
|
+
function round5(v) {
|
|
3294
3322
|
return Math.round(v * 1e3) / 1e3;
|
|
3295
3323
|
}
|
|
3296
3324
|
|
|
@@ -3353,7 +3381,7 @@ function trackEmitter() {
|
|
|
3353
3381
|
if (tt <= prev.t + 1e-6 && sameVec(prev.value, value)) return prev.t;
|
|
3354
3382
|
if (tt <= prev.t + 1e-6) tt = prev.t + 1e-3;
|
|
3355
3383
|
}
|
|
3356
|
-
keyframes.push({ t:
|
|
3384
|
+
keyframes.push({ t: round6(tt), value: value.map(round6), ease });
|
|
3357
3385
|
return tt;
|
|
3358
3386
|
};
|
|
3359
3387
|
return { keyframes, push: push2 };
|
|
@@ -4849,10 +4877,13 @@ var ON_FRAME = `(ctx, content, dt) => {
|
|
|
4849
4877
|
card.mesh.scale.x = cpv[0]; card.mesh.scale.y = cpv[0]
|
|
4850
4878
|
card.mesh.position.y = cpv[1] * cpH
|
|
4851
4879
|
if (card.mesh.material) card.mesh.material.opacity = cpv[2]
|
|
4852
|
-
|
|
4880
|
+
// Gone past its clip: the mesh leaves the scene, not just its paint.
|
|
4881
|
+
card.mesh.visible = cpv[2] > 0.001
|
|
4882
|
+
} else if (card.mesh.scale && card.mesh.position && ((card.mesh.scale.x !== undefined && card.mesh.scale.x !== 1) || (card.mesh.position.y !== undefined && card.mesh.position.y !== 0) || card.mesh.visible === false)) {
|
|
4853
4883
|
card.mesh.scale.x = 1; card.mesh.scale.y = 1
|
|
4854
4884
|
card.mesh.position.y = 0
|
|
4855
4885
|
if (card.mesh.material) card.mesh.material.opacity = 1
|
|
4886
|
+
card.mesh.visible = true
|
|
4856
4887
|
}
|
|
4857
4888
|
var tilted = rx * rx + ry * ry > 1e-6
|
|
4858
4889
|
if (card.texture && card.texture.generateMipmaps !== tilted) {
|
|
@@ -4884,14 +4915,14 @@ function studioLayerData(layers, duration) {
|
|
|
4884
4915
|
// needs a decoded recording, which a sync lowering can't produce.
|
|
4885
4916
|
audio: (layers.audio ?? []).map((c) => ({
|
|
4886
4917
|
key: c.key,
|
|
4887
|
-
start:
|
|
4888
|
-
in:
|
|
4889
|
-
out:
|
|
4890
|
-
gain:
|
|
4918
|
+
start: round6(c.start),
|
|
4919
|
+
in: round6(c.in),
|
|
4920
|
+
out: round6(c.out),
|
|
4921
|
+
gain: round6(c.gain),
|
|
4891
4922
|
loop: !!c.loop,
|
|
4892
|
-
len:
|
|
4923
|
+
len: round6(clipLength(c)),
|
|
4893
4924
|
duck: !!c.duck,
|
|
4894
|
-
env: clipEnvelope(c).map((p) => ({ t:
|
|
4925
|
+
env: clipEnvelope(c).map((p) => ({ t: round6(p.t), g: round6(p.g) }))
|
|
4895
4926
|
})),
|
|
4896
4927
|
// Object clips: numbers resolved HERE; shapes are the drafted engine spec.
|
|
4897
4928
|
...layers.objects && layers.objects.length ? {
|
|
@@ -4904,17 +4935,17 @@ function studioLayerData(layers, duration) {
|
|
|
4904
4935
|
} : o.asset.kind === "text3d" ? resolveText3dAsset(o.asset) : { kind: "gltf", key: o.asset.key },
|
|
4905
4936
|
...o.span ? {
|
|
4906
4937
|
span: {
|
|
4907
|
-
start:
|
|
4908
|
-
duration:
|
|
4938
|
+
start: round6(o.span.start),
|
|
4939
|
+
duration: round6(o.span.duration)
|
|
4909
4940
|
}
|
|
4910
4941
|
} : {},
|
|
4911
|
-
x:
|
|
4912
|
-
y:
|
|
4913
|
-
z:
|
|
4914
|
-
rx:
|
|
4915
|
-
ry:
|
|
4916
|
-
rz:
|
|
4917
|
-
scale:
|
|
4942
|
+
x: round6(o.transform3d.x),
|
|
4943
|
+
y: round6(o.transform3d.y),
|
|
4944
|
+
z: round6(o.transform3d.z),
|
|
4945
|
+
rx: round6(o.transform3d.rx),
|
|
4946
|
+
ry: round6(o.transform3d.ry),
|
|
4947
|
+
rz: round6(o.transform3d.rz),
|
|
4948
|
+
scale: round6(o.transform3d.scale || OBJECT_DEFAULT_SCALE),
|
|
4918
4949
|
anim: idleKey(o),
|
|
4919
4950
|
// Pose keyframes: clip-local [x,y,z,rx,ry,rz,scale] track,
|
|
4920
4951
|
// sampled at t − span.start. Omitted when absent — parity.
|
|
@@ -4941,12 +4972,12 @@ function studioLayerData(layers, duration) {
|
|
|
4941
4972
|
const base = {
|
|
4942
4973
|
id: o.id,
|
|
4943
4974
|
kind: o.kind,
|
|
4944
|
-
start:
|
|
4945
|
-
dur:
|
|
4946
|
-
x:
|
|
4947
|
-
y:
|
|
4948
|
-
scale:
|
|
4949
|
-
rot:
|
|
4975
|
+
start: round6(o.start),
|
|
4976
|
+
dur: round6(Math.max(OVERLAY_MIN_DURATION, o.duration)),
|
|
4977
|
+
x: round6(o.transform.x),
|
|
4978
|
+
y: round6(o.transform.y),
|
|
4979
|
+
scale: round6(o.transform.scale || 1),
|
|
4980
|
+
rot: round6(o.transform.rotation || 0),
|
|
4950
4981
|
enter: enterKey(o),
|
|
4951
4982
|
exit: exitKey(o),
|
|
4952
4983
|
// Pose keyframes: a CLIP-LOCAL [x, y, scale, rot, opacity]
|
|
@@ -4967,7 +4998,7 @@ function studioLayerData(layers, duration) {
|
|
|
4967
4998
|
return {
|
|
4968
4999
|
...base,
|
|
4969
5000
|
key: o.key,
|
|
4970
|
-
w:
|
|
5001
|
+
w: round6(o.width ?? OVERLAY_MEDIA_DEFAULT_WIDTH),
|
|
4971
5002
|
radius: o.radius ?? OVERLAY_MEDIA_DEFAULT_RADIUS,
|
|
4972
5003
|
opacity: o.opacity ?? 1,
|
|
4973
5004
|
loop: !!o.loop,
|
|
@@ -4977,7 +5008,7 @@ function studioLayerData(layers, duration) {
|
|
|
4977
5008
|
...o.shadow ? { shadow: o.shadow } : {},
|
|
4978
5009
|
...o.border && o.border.width > 0 ? {
|
|
4979
5010
|
border: {
|
|
4980
|
-
width:
|
|
5011
|
+
width: round6(o.border.width),
|
|
4981
5012
|
color: o.border.color
|
|
4982
5013
|
}
|
|
4983
5014
|
} : {}
|
|
@@ -4997,11 +5028,11 @@ function studioLayerData(layers, duration) {
|
|
|
4997
5028
|
// Style-v2 fields bake only when non-default (byte parity for
|
|
4998
5029
|
// older docs); ON_FRAME reads them unconditionally.
|
|
4999
5030
|
...st.fontStyle === "italic" ? { sty: "italic" } : {},
|
|
5000
|
-
...o.maxWidth ? { mw:
|
|
5001
|
-
...st.letterSpacing ? { ls:
|
|
5002
|
-
...st.lineHeight !== OVERLAY_LINE_HEIGHT ? { lh:
|
|
5031
|
+
...o.maxWidth ? { mw: round6(o.maxWidth) } : {},
|
|
5032
|
+
...st.letterSpacing ? { ls: round6(st.letterSpacing) } : {},
|
|
5033
|
+
...st.lineHeight !== OVERLAY_LINE_HEIGHT ? { lh: round6(st.lineHeight) } : {},
|
|
5003
5034
|
...st.align !== "center" ? { align: st.align } : {},
|
|
5004
|
-
...st.stroke ? { stroke: { c: st.stroke.color, w:
|
|
5035
|
+
...st.stroke ? { stroke: { c: st.stroke.color, w: round6(st.stroke.width) } } : {},
|
|
5005
5036
|
// Hosted face behind an override: ON_FRAME lazy-loads it so a
|
|
5006
5037
|
// live family/weight edit paints without a LOAD (SETUP only
|
|
5007
5038
|
// runs on cold load).
|
|
@@ -5014,10 +5045,10 @@ function studioLayerData(layers, duration) {
|
|
|
5014
5045
|
...bx ? {
|
|
5015
5046
|
box: {
|
|
5016
5047
|
c: bx.color,
|
|
5017
|
-
o:
|
|
5018
|
-
px:
|
|
5019
|
-
py:
|
|
5020
|
-
r:
|
|
5048
|
+
o: round6(bx.opacity),
|
|
5049
|
+
px: round6(bx.padX),
|
|
5050
|
+
py: round6(bx.padY),
|
|
5051
|
+
r: round6(bx.radius)
|
|
5021
5052
|
}
|
|
5022
5053
|
} : {},
|
|
5023
5054
|
// Entrance animation: segmentation + timing normalized
|
|
@@ -5092,16 +5123,16 @@ function lowerToComposition(input) {
|
|
|
5092
5123
|
// Rated segments (speed spans pre-intersected): ON_FRAME's mapTime and the
|
|
5093
5124
|
// export's audio splice read the rate straight off each segment.
|
|
5094
5125
|
segments: rated.map((seg) => ({
|
|
5095
|
-
in:
|
|
5096
|
-
out:
|
|
5097
|
-
...seg.rate !== void 0 && seg.rate !== 1 ? { rate:
|
|
5126
|
+
in: round6(seg.in),
|
|
5127
|
+
out: round6(seg.out),
|
|
5128
|
+
...seg.rate !== void 0 && seg.rate !== 1 ? { rate: round6(seg.rate) } : {}
|
|
5098
5129
|
})),
|
|
5099
5130
|
frame: doc.frame,
|
|
5100
5131
|
micGain: doc.micGain ?? 1,
|
|
5101
5132
|
cursor: smoothed.map((p) => ({
|
|
5102
|
-
t:
|
|
5103
|
-
x:
|
|
5104
|
-
y:
|
|
5133
|
+
t: round6(p.t),
|
|
5134
|
+
x: round6(p.x),
|
|
5135
|
+
y: round6(p.y)
|
|
5105
5136
|
})),
|
|
5106
5137
|
cursorStyle: doc.cursor,
|
|
5107
5138
|
cursorSpace: { w: doc.source.meta.width, h: doc.source.meta.height },
|
|
@@ -5186,7 +5217,7 @@ function clickFxData(doc, rated) {
|
|
|
5186
5217
|
}
|
|
5187
5218
|
};
|
|
5188
5219
|
}
|
|
5189
|
-
function
|
|
5220
|
+
function round6(v) {
|
|
5190
5221
|
return Math.round(v * 1e3) / 1e3;
|
|
5191
5222
|
}
|
|
5192
5223
|
|
|
@@ -5276,8 +5307,8 @@ function planAutoSpeed(track, opts) {
|
|
|
5276
5307
|
accepted.sort((a, b) => a.in - b.in);
|
|
5277
5308
|
return accepted.map((c, i) => ({
|
|
5278
5309
|
id: `s${i}`,
|
|
5279
|
-
in:
|
|
5280
|
-
out:
|
|
5310
|
+
in: round7(c.in),
|
|
5311
|
+
out: round7(c.out),
|
|
5281
5312
|
rate: clampSpeedRate(c.rate),
|
|
5282
5313
|
source: "auto"
|
|
5283
5314
|
}));
|
|
@@ -5330,7 +5361,7 @@ function collectRuns(evs, gap, minLen, emit2) {
|
|
|
5330
5361
|
}
|
|
5331
5362
|
flush();
|
|
5332
5363
|
}
|
|
5333
|
-
function
|
|
5364
|
+
function round7(v) {
|
|
5334
5365
|
return Math.round(v * 1e3) / 1e3;
|
|
5335
5366
|
}
|
|
5336
5367
|
|
|
@@ -5507,16 +5538,16 @@ function momentsFromDoc(doc, plan, opts = {}) {
|
|
|
5507
5538
|
return {
|
|
5508
5539
|
id: `m${String(i + 1).padStart(2, "0")}`,
|
|
5509
5540
|
kind: d.kind,
|
|
5510
|
-
source: { in:
|
|
5511
|
-
output: output ? { in:
|
|
5512
|
-
at: d.at === null ? null :
|
|
5513
|
-
outputAt: outAt ?
|
|
5514
|
-
focus: d.focus ? { cx:
|
|
5541
|
+
source: { in: round8(d.in), out: round8(d.out) },
|
|
5542
|
+
output: output ? { in: round8(output.start), out: round8(output.end) } : null,
|
|
5543
|
+
at: d.at === null ? null : round8(d.at),
|
|
5544
|
+
outputAt: outAt ? round8(outAt.start) : null,
|
|
5545
|
+
focus: d.focus ? { cx: round8(d.focus.cx), cy: round8(d.focus.cy) } : null,
|
|
5515
5546
|
rect: d.rect ? {
|
|
5516
|
-
x:
|
|
5517
|
-
y:
|
|
5518
|
-
w:
|
|
5519
|
-
h:
|
|
5547
|
+
x: round8(d.rect.x),
|
|
5548
|
+
y: round8(d.rect.y),
|
|
5549
|
+
w: round8(d.rect.w),
|
|
5550
|
+
h: round8(d.rect.h)
|
|
5520
5551
|
} : null,
|
|
5521
5552
|
...d.clicks !== void 0 ? { clicks: d.clicks } : {},
|
|
5522
5553
|
...d.pings !== void 0 ? { pings: d.pings } : {},
|
|
@@ -5536,7 +5567,7 @@ function activityOf(bins, d) {
|
|
|
5536
5567
|
sum += bins[i];
|
|
5537
5568
|
n++;
|
|
5538
5569
|
}
|
|
5539
|
-
return n ?
|
|
5570
|
+
return n ? round8(sum / n) : null;
|
|
5540
5571
|
}
|
|
5541
5572
|
function saidOver(transcript, d) {
|
|
5542
5573
|
if (!transcript?.length) return null;
|
|
@@ -5545,7 +5576,7 @@ function saidOver(transcript, d) {
|
|
|
5545
5576
|
const text = transcript.filter((s) => s.start < hi && s.end > lo).map((s) => s.text.trim()).filter(Boolean).join(" ");
|
|
5546
5577
|
return text || null;
|
|
5547
5578
|
}
|
|
5548
|
-
function
|
|
5579
|
+
function round8(v) {
|
|
5549
5580
|
return Math.round(v * 1e3) / 1e3;
|
|
5550
5581
|
}
|
|
5551
5582
|
|
|
@@ -5833,12 +5864,14 @@ function clipsFrom(doc, from) {
|
|
|
5833
5864
|
}
|
|
5834
5865
|
function dropTemplate(doc, from) {
|
|
5835
5866
|
const has = clipsFrom(doc, from);
|
|
5836
|
-
|
|
5867
|
+
const freezes = (doc.freeze ?? []).some((f) => f.from === from);
|
|
5868
|
+
if (!has.overlays.length && !has.objects.length && !has.audio.length && !freezes)
|
|
5837
5869
|
return doc;
|
|
5838
5870
|
const out = { ...doc };
|
|
5839
5871
|
if (doc.overlays) out.overlays = doc.overlays.filter((o) => o.from !== from);
|
|
5840
5872
|
if (doc.objects) out.objects = doc.objects.filter((o) => o.from !== from);
|
|
5841
5873
|
out.audio = doc.audio.filter((a) => a.from !== from);
|
|
5874
|
+
if (doc.freeze) out.freeze = doc.freeze.filter((f) => f.from !== from);
|
|
5842
5875
|
return out;
|
|
5843
5876
|
}
|
|
5844
5877
|
function applyTemplate(template, take, opts) {
|
|
@@ -5846,8 +5879,22 @@ function applyTemplate(template, take, opts) {
|
|
|
5846
5879
|
const notes = [];
|
|
5847
5880
|
const base = dropTemplate(take, from);
|
|
5848
5881
|
const doc = structuredClone(base);
|
|
5882
|
+
const tail = trailingFreeze(template);
|
|
5883
|
+
const lastSeg = doc.segments.at(-1);
|
|
5884
|
+
if (tail && opts.at === "end" && lastSeg) {
|
|
5885
|
+
const own2 = (doc.freeze ?? []).filter(
|
|
5886
|
+
(f) => Math.abs(f.at - lastSeg.out) > 1e-9
|
|
5887
|
+
);
|
|
5888
|
+
const taken = new Set(own2.map((f) => f.id));
|
|
5889
|
+
let n = 0;
|
|
5890
|
+
while (taken.has(`f${n}`)) n++;
|
|
5891
|
+
doc.freeze = [
|
|
5892
|
+
...own2,
|
|
5893
|
+
{ id: `f${n}`, at: lastSeg.out, seconds: tail.seconds, from }
|
|
5894
|
+
].sort((a, b) => a.at - b.at);
|
|
5895
|
+
}
|
|
5849
5896
|
const templateEnd = totalDuration4(ratedSegments(template));
|
|
5850
|
-
const takeEnd = totalDuration4(ratedSegments(
|
|
5897
|
+
const takeEnd = totalDuration4(ratedSegments(doc));
|
|
5851
5898
|
const shift = shiftBy(opts.at, templateEnd, takeEnd);
|
|
5852
5899
|
const own = new Map((take.overlays ?? []).map((o) => [o.id, o]));
|
|
5853
5900
|
const overlays = (doc.overlays ?? []).filter(
|
|
@@ -6011,8 +6058,8 @@ function buildDigest(input) {
|
|
|
6011
6058
|
return {
|
|
6012
6059
|
digestVersion: DIGEST_VERSION,
|
|
6013
6060
|
take: {
|
|
6014
|
-
sourceDuration:
|
|
6015
|
-
outputDuration:
|
|
6061
|
+
sourceDuration: round9(meta.durationMs / 1e3),
|
|
6062
|
+
outputDuration: round9(input.outputDuration),
|
|
6016
6063
|
width: meta.width,
|
|
6017
6064
|
height: meta.height,
|
|
6018
6065
|
captureWidth: meta.captureWidth ?? null,
|
|
@@ -6061,7 +6108,7 @@ function buildDigest(input) {
|
|
|
6061
6108
|
function outputDurationOf(doc) {
|
|
6062
6109
|
return docOutputDuration(doc);
|
|
6063
6110
|
}
|
|
6064
|
-
function
|
|
6111
|
+
function round9(v) {
|
|
6065
6112
|
return Math.round(v * 1e3) / 1e3;
|
|
6066
6113
|
}
|
|
6067
6114
|
|
|
@@ -6087,20 +6134,20 @@ function setSpeedInRange(spans, srcIn, srcOut, rate) {
|
|
|
6087
6134
|
continue;
|
|
6088
6135
|
}
|
|
6089
6136
|
if (srcIn - s.in >= MIN_REMAINDER)
|
|
6090
|
-
kept.push({ ...s, out:
|
|
6137
|
+
kept.push({ ...s, out: round10(srcIn), source: "manual" });
|
|
6091
6138
|
if (s.out - srcOut >= MIN_REMAINDER)
|
|
6092
6139
|
kept.push({
|
|
6093
6140
|
...s,
|
|
6094
6141
|
id: mintId(used),
|
|
6095
|
-
in:
|
|
6142
|
+
in: round10(srcOut),
|
|
6096
6143
|
source: "manual"
|
|
6097
6144
|
});
|
|
6098
6145
|
}
|
|
6099
6146
|
if (rate != null)
|
|
6100
6147
|
kept.push({
|
|
6101
6148
|
id: mintId(used),
|
|
6102
|
-
in:
|
|
6103
|
-
out:
|
|
6149
|
+
in: round10(srcIn),
|
|
6150
|
+
out: round10(srcOut),
|
|
6104
6151
|
rate: clampSpeedRate(rate),
|
|
6105
6152
|
source: "manual"
|
|
6106
6153
|
});
|
|
@@ -6116,9 +6163,9 @@ function removeSourceRange(segments, srcIn, srcOut) {
|
|
|
6116
6163
|
next.push(seg);
|
|
6117
6164
|
continue;
|
|
6118
6165
|
}
|
|
6119
|
-
if (srcIn - seg.in >= MIN_SEGMENT) next.push({ ...seg, out:
|
|
6166
|
+
if (srcIn - seg.in >= MIN_SEGMENT) next.push({ ...seg, out: round10(srcIn) });
|
|
6120
6167
|
if (seg.out - srcOut >= MIN_SEGMENT)
|
|
6121
|
-
next.push({ ...seg, in:
|
|
6168
|
+
next.push({ ...seg, in: round10(srcOut) });
|
|
6122
6169
|
}
|
|
6123
6170
|
return next.length ? next : [...segments];
|
|
6124
6171
|
}
|
|
@@ -6136,8 +6183,8 @@ function zoomSpanForRange(zoom, srcIn, srcOut) {
|
|
|
6136
6183
|
while (used.has(`u${n}`)) n++;
|
|
6137
6184
|
return {
|
|
6138
6185
|
id: `u${n}`,
|
|
6139
|
-
in:
|
|
6140
|
-
out:
|
|
6186
|
+
in: round10(start),
|
|
6187
|
+
out: round10(end),
|
|
6141
6188
|
level: DEFAULT_ZOOM_LEVEL,
|
|
6142
6189
|
cx: 0.5,
|
|
6143
6190
|
cy: 0.5,
|
|
@@ -6151,7 +6198,7 @@ function mintId(used) {
|
|
|
6151
6198
|
used.add(id);
|
|
6152
6199
|
return id;
|
|
6153
6200
|
}
|
|
6154
|
-
function
|
|
6201
|
+
function round10(v) {
|
|
6155
6202
|
return Math.round(v * 1e3) / 1e3;
|
|
6156
6203
|
}
|
|
6157
6204
|
|
|
@@ -6822,8 +6869,8 @@ var videoLane = {
|
|
|
6822
6869
|
return segments.map((s, i) => ({
|
|
6823
6870
|
id: `seg-${i}`,
|
|
6824
6871
|
kind: "clip",
|
|
6825
|
-
t:
|
|
6826
|
-
duration:
|
|
6872
|
+
t: round11(starts[i]),
|
|
6873
|
+
duration: round11(
|
|
6827
6874
|
outputLen(s, speeds, freezes, i === 0 || !contiguous(segments, i))
|
|
6828
6875
|
)
|
|
6829
6876
|
}));
|
|
@@ -6906,7 +6953,7 @@ var videoLane = {
|
|
|
6906
6953
|
if (local >= m.t - 1e-9 && local <= m.t + m.duration + 1e-9)
|
|
6907
6954
|
return null;
|
|
6908
6955
|
}
|
|
6909
|
-
const sourceT =
|
|
6956
|
+
const sourceT = round11(
|
|
6910
6957
|
mapTime2(segmentPieces(s, speeds, freezes, leading), local)
|
|
6911
6958
|
);
|
|
6912
6959
|
if (sourceT - s.in < 0.05 || s.out - sourceT < 0.05) return null;
|
|
@@ -6947,7 +6994,7 @@ var videoLane = {
|
|
|
6947
6994
|
n === 1 || !contiguous(segments, n - 1)
|
|
6948
6995
|
)
|
|
6949
6996
|
] : []
|
|
6950
|
-
].map(
|
|
6997
|
+
].map(round11);
|
|
6951
6998
|
}
|
|
6952
6999
|
};
|
|
6953
7000
|
function nextFreezeId(doc) {
|
|
@@ -6974,8 +7021,8 @@ var freezeLane = {
|
|
|
6974
7021
|
{
|
|
6975
7022
|
id: f.id,
|
|
6976
7023
|
kind: "clip",
|
|
6977
|
-
t:
|
|
6978
|
-
duration:
|
|
7024
|
+
t: round11(m.t),
|
|
7025
|
+
duration: round11(m.duration),
|
|
6979
7026
|
label: `${trimZeros(f.seconds)}s`
|
|
6980
7027
|
}
|
|
6981
7028
|
] : [];
|
|
@@ -6997,7 +7044,7 @@ var freezeLane = {
|
|
|
6997
7044
|
if (g.t >= m.t - 1e-9 && g.t <= m.t + m.duration + 1e-9) return null;
|
|
6998
7045
|
}
|
|
6999
7046
|
if (g.t > totalDuration6(rated) + 1e-9) return null;
|
|
7000
|
-
const srcT =
|
|
7047
|
+
const srcT = round11(mapTime2(rated, Math.max(0, g.t)));
|
|
7001
7048
|
if (!kept(srcT) || !clear(srcT)) return null;
|
|
7002
7049
|
const id = nextFreezeId(doc);
|
|
7003
7050
|
return (d) => {
|
|
@@ -7033,7 +7080,7 @@ var freezeLane = {
|
|
|
7033
7080
|
const marks = freezeOutputExtents(splitBySpeed3(segs, speeds), freezes);
|
|
7034
7081
|
const mine = marks.get(f.id);
|
|
7035
7082
|
const endOut = mine ? mine.t + mine.duration : null;
|
|
7036
|
-
const srcT =
|
|
7083
|
+
const srcT = round11(
|
|
7037
7084
|
Math.min(sourceDuration, mapTime2(base, Math.max(0, g.t)))
|
|
7038
7085
|
);
|
|
7039
7086
|
if (!kept(srcT) || !clear(srcT, f.id)) return null;
|
|
@@ -7093,8 +7140,8 @@ var zoomLane = {
|
|
|
7093
7140
|
{
|
|
7094
7141
|
id: z.id,
|
|
7095
7142
|
kind: "clip",
|
|
7096
|
-
t:
|
|
7097
|
-
duration:
|
|
7143
|
+
t: round11(ext.start),
|
|
7144
|
+
duration: round11(ext.end - ext.start),
|
|
7098
7145
|
label: `${z.level.toFixed(2)}\xD7`
|
|
7099
7146
|
}
|
|
7100
7147
|
];
|
|
@@ -7118,8 +7165,8 @@ var zoomLane = {
|
|
|
7118
7165
|
...d.zoom,
|
|
7119
7166
|
{
|
|
7120
7167
|
id,
|
|
7121
|
-
in:
|
|
7122
|
-
out:
|
|
7168
|
+
in: round11(srcT),
|
|
7169
|
+
out: round11(srcT + len),
|
|
7123
7170
|
level: DEFAULT_ZOOM_LEVEL,
|
|
7124
7171
|
cx,
|
|
7125
7172
|
cy,
|
|
@@ -7150,8 +7197,8 @@ var zoomLane = {
|
|
|
7150
7197
|
return (d) => {
|
|
7151
7198
|
const z = d.zoom.find((x) => x.id === g.id);
|
|
7152
7199
|
if (!z) return;
|
|
7153
|
-
z.in =
|
|
7154
|
-
z.out =
|
|
7200
|
+
z.in = round11(newIn);
|
|
7201
|
+
z.out = round11(newIn + len);
|
|
7155
7202
|
z.source = "manual";
|
|
7156
7203
|
d.zoom.sort((a, b) => a.in - b.in);
|
|
7157
7204
|
};
|
|
@@ -7180,8 +7227,8 @@ var zoomLane = {
|
|
|
7180
7227
|
return (d) => {
|
|
7181
7228
|
const z = d.zoom.find((x) => x.id === g.id);
|
|
7182
7229
|
if (!z) return;
|
|
7183
|
-
z.in =
|
|
7184
|
-
z.out =
|
|
7230
|
+
z.in = round11(next.in);
|
|
7231
|
+
z.out = round11(next.out);
|
|
7185
7232
|
z.source = "manual";
|
|
7186
7233
|
};
|
|
7187
7234
|
}
|
|
@@ -7203,8 +7250,8 @@ function cursorFocusAt(doc, srcT) {
|
|
|
7203
7250
|
if (Math.abs(e.t - ms) < Math.abs(best.t - ms)) best = e;
|
|
7204
7251
|
const clamp015 = (v) => Math.max(0, Math.min(1, v));
|
|
7205
7252
|
return {
|
|
7206
|
-
cx:
|
|
7207
|
-
cy:
|
|
7253
|
+
cx: round11(clamp015(best.x / width)),
|
|
7254
|
+
cy: round11(clamp015(best.y / height))
|
|
7208
7255
|
};
|
|
7209
7256
|
}
|
|
7210
7257
|
var tiltLane = {
|
|
@@ -7218,8 +7265,8 @@ var tiltLane = {
|
|
|
7218
7265
|
{
|
|
7219
7266
|
id: z.id,
|
|
7220
7267
|
kind: "clip",
|
|
7221
|
-
t:
|
|
7222
|
-
duration:
|
|
7268
|
+
t: round11(ext.start),
|
|
7269
|
+
duration: round11(ext.end - ext.start),
|
|
7223
7270
|
label: `${formatDeg(z.rx)}\xB0/${formatDeg(z.ry)}\xB0`
|
|
7224
7271
|
}
|
|
7225
7272
|
];
|
|
@@ -7242,8 +7289,8 @@ var tiltLane = {
|
|
|
7242
7289
|
...d.tilt ?? [],
|
|
7243
7290
|
{
|
|
7244
7291
|
id,
|
|
7245
|
-
in:
|
|
7246
|
-
out:
|
|
7292
|
+
in: round11(srcT),
|
|
7293
|
+
out: round11(srcT + len),
|
|
7247
7294
|
rx: DEFAULT_TILT_POSE.rx,
|
|
7248
7295
|
ry: DEFAULT_TILT_POSE.ry,
|
|
7249
7296
|
source: "manual"
|
|
@@ -7273,8 +7320,8 @@ var tiltLane = {
|
|
|
7273
7320
|
return (d) => {
|
|
7274
7321
|
const z = (d.tilt ?? []).find((x) => x.id === g.id);
|
|
7275
7322
|
if (!z || !d.tilt) return;
|
|
7276
|
-
z.in =
|
|
7277
|
-
z.out =
|
|
7323
|
+
z.in = round11(newIn);
|
|
7324
|
+
z.out = round11(newIn + len);
|
|
7278
7325
|
z.source = "manual";
|
|
7279
7326
|
d.tilt.sort((a, b) => a.in - b.in);
|
|
7280
7327
|
};
|
|
@@ -7303,8 +7350,8 @@ var tiltLane = {
|
|
|
7303
7350
|
return (d) => {
|
|
7304
7351
|
const z = (d.tilt ?? []).find((x) => x.id === g.id);
|
|
7305
7352
|
if (!z) return;
|
|
7306
|
-
z.in =
|
|
7307
|
-
z.out =
|
|
7353
|
+
z.in = round11(next.in);
|
|
7354
|
+
z.out = round11(next.out);
|
|
7308
7355
|
z.source = "manual";
|
|
7309
7356
|
};
|
|
7310
7357
|
}
|
|
@@ -7331,8 +7378,8 @@ var camMoveLane = {
|
|
|
7331
7378
|
{
|
|
7332
7379
|
id: z.id,
|
|
7333
7380
|
kind: "clip",
|
|
7334
|
-
t:
|
|
7335
|
-
duration:
|
|
7381
|
+
t: round11(ext.start),
|
|
7382
|
+
duration: round11(ext.end - ext.start),
|
|
7336
7383
|
label: z.size != null ? `${Math.round(z.size * 100)}%` : "Move"
|
|
7337
7384
|
}
|
|
7338
7385
|
];
|
|
@@ -7356,8 +7403,8 @@ var camMoveLane = {
|
|
|
7356
7403
|
...d.camMotion ?? [],
|
|
7357
7404
|
{
|
|
7358
7405
|
id,
|
|
7359
|
-
in:
|
|
7360
|
-
out:
|
|
7406
|
+
in: round11(srcT),
|
|
7407
|
+
out: round11(srcT + len),
|
|
7361
7408
|
...DEFAULT_CAM_POSE,
|
|
7362
7409
|
source: "manual"
|
|
7363
7410
|
}
|
|
@@ -7386,8 +7433,8 @@ var camMoveLane = {
|
|
|
7386
7433
|
return (d) => {
|
|
7387
7434
|
const z = (d.camMotion ?? []).find((x) => x.id === g.id);
|
|
7388
7435
|
if (!z || !d.camMotion) return;
|
|
7389
|
-
z.in =
|
|
7390
|
-
z.out =
|
|
7436
|
+
z.in = round11(newIn);
|
|
7437
|
+
z.out = round11(newIn + len);
|
|
7391
7438
|
z.source = "manual";
|
|
7392
7439
|
d.camMotion.sort((a, b) => a.in - b.in);
|
|
7393
7440
|
};
|
|
@@ -7416,8 +7463,8 @@ var camMoveLane = {
|
|
|
7416
7463
|
return (d) => {
|
|
7417
7464
|
const z = (d.camMotion ?? []).find((x) => x.id === g.id);
|
|
7418
7465
|
if (!z) return;
|
|
7419
|
-
z.in =
|
|
7420
|
-
z.out =
|
|
7466
|
+
z.in = round11(next.in);
|
|
7467
|
+
z.out = round11(next.out);
|
|
7421
7468
|
z.source = "manual";
|
|
7422
7469
|
};
|
|
7423
7470
|
}
|
|
@@ -7450,10 +7497,10 @@ var camLane = {
|
|
|
7450
7497
|
items.push({
|
|
7451
7498
|
id: `cam-${i}`,
|
|
7452
7499
|
kind: "clip",
|
|
7453
|
-
t:
|
|
7500
|
+
t: round11(
|
|
7454
7501
|
starts[i] + outputLen({ in: s.in, out: a }, speeds, freezes, leading)
|
|
7455
7502
|
),
|
|
7456
|
-
duration:
|
|
7503
|
+
duration: round11(
|
|
7457
7504
|
outputLen({ in: a, out: b }, speeds, freezes, a === s.in && leading)
|
|
7458
7505
|
)
|
|
7459
7506
|
});
|
|
@@ -7482,7 +7529,7 @@ var camLane = {
|
|
|
7482
7529
|
Math.max(first.in, last.out - span)
|
|
7483
7530
|
);
|
|
7484
7531
|
return (d) => {
|
|
7485
|
-
d.cam.window = { in:
|
|
7532
|
+
d.cam.window = { in: round11(newIn), out: round11(newIn + span) };
|
|
7486
7533
|
};
|
|
7487
7534
|
}
|
|
7488
7535
|
const overlapping = eff.map((s, i) => ({
|
|
@@ -7495,8 +7542,8 @@ var camLane = {
|
|
|
7495
7542
|
const next = g.edge === "start" ? { in: Math.min(sourceT, current.out - 0.05), out: current.out } : { in: current.in, out: Math.max(sourceT, current.in + 0.05) };
|
|
7496
7543
|
return (d) => {
|
|
7497
7544
|
d.cam.window = {
|
|
7498
|
-
in:
|
|
7499
|
-
out:
|
|
7545
|
+
in: round11(Math.max(0, next.in)),
|
|
7546
|
+
out: round11(Math.min(sourceDuration, next.out))
|
|
7500
7547
|
};
|
|
7501
7548
|
};
|
|
7502
7549
|
},
|
|
@@ -7516,8 +7563,8 @@ var micLane = {
|
|
|
7516
7563
|
return segments.map((s, i) => ({
|
|
7517
7564
|
id: `mic-${i}`,
|
|
7518
7565
|
kind: "clip",
|
|
7519
|
-
t:
|
|
7520
|
-
duration:
|
|
7566
|
+
t: round11(starts[i]),
|
|
7567
|
+
duration: round11(
|
|
7521
7568
|
outputLen(s, speeds, freezes, i === 0 || !contiguous(segments, i))
|
|
7522
7569
|
)
|
|
7523
7570
|
}));
|
|
@@ -7573,8 +7620,8 @@ var speedLane = {
|
|
|
7573
7620
|
{
|
|
7574
7621
|
id: sp.id,
|
|
7575
7622
|
kind: "clip",
|
|
7576
|
-
t:
|
|
7577
|
-
duration:
|
|
7623
|
+
t: round11(start),
|
|
7624
|
+
duration: round11(end - start),
|
|
7578
7625
|
label: `${sp.rate}\xD7`
|
|
7579
7626
|
}
|
|
7580
7627
|
];
|
|
@@ -7597,8 +7644,8 @@ var speedLane = {
|
|
|
7597
7644
|
...d.speed ?? [],
|
|
7598
7645
|
{
|
|
7599
7646
|
id,
|
|
7600
|
-
in:
|
|
7601
|
-
out:
|
|
7647
|
+
in: round11(srcT),
|
|
7648
|
+
out: round11(srcT + len),
|
|
7602
7649
|
rate: DEFAULT_SPEED_RATE,
|
|
7603
7650
|
source: "manual"
|
|
7604
7651
|
}
|
|
@@ -7628,8 +7675,8 @@ var speedLane = {
|
|
|
7628
7675
|
return (d) => {
|
|
7629
7676
|
const s = d.speed?.find((x) => x.id === g.id);
|
|
7630
7677
|
if (!s) return;
|
|
7631
|
-
s.in =
|
|
7632
|
-
s.out =
|
|
7678
|
+
s.in = round11(newIn);
|
|
7679
|
+
s.out = round11(newIn + len);
|
|
7633
7680
|
s.source = "manual";
|
|
7634
7681
|
d.speed.sort((a, b) => a.in - b.in);
|
|
7635
7682
|
};
|
|
@@ -7658,8 +7705,8 @@ var speedLane = {
|
|
|
7658
7705
|
return (d) => {
|
|
7659
7706
|
const s = d.speed?.find((x) => x.id === g.id);
|
|
7660
7707
|
if (!s) return;
|
|
7661
|
-
s.in =
|
|
7662
|
-
s.out =
|
|
7708
|
+
s.in = round11(next.in);
|
|
7709
|
+
s.out = round11(next.out);
|
|
7663
7710
|
s.source = "manual";
|
|
7664
7711
|
};
|
|
7665
7712
|
}
|
|
@@ -7678,8 +7725,8 @@ var audioLane = {
|
|
|
7678
7725
|
return doc.audio.map((c) => ({
|
|
7679
7726
|
id: c.id,
|
|
7680
7727
|
kind: "clip",
|
|
7681
|
-
t:
|
|
7682
|
-
duration:
|
|
7728
|
+
t: round11(c.start),
|
|
7729
|
+
duration: round11(clipLength(c)),
|
|
7683
7730
|
label: c.name
|
|
7684
7731
|
}));
|
|
7685
7732
|
},
|
|
@@ -7690,7 +7737,7 @@ var audioLane = {
|
|
|
7690
7737
|
const start = Math.max(0, g.t);
|
|
7691
7738
|
return (d) => {
|
|
7692
7739
|
const c = d.audio.find((x) => x.id === g.id);
|
|
7693
|
-
if (c) c.start =
|
|
7740
|
+
if (c) c.start = round11(start);
|
|
7694
7741
|
};
|
|
7695
7742
|
}
|
|
7696
7743
|
if (g.type === "resize") {
|
|
@@ -7703,8 +7750,8 @@ var audioLane = {
|
|
|
7703
7750
|
return (d) => {
|
|
7704
7751
|
const c = d.audio.find((x) => x.id === g.id);
|
|
7705
7752
|
if (!c) return;
|
|
7706
|
-
c.start =
|
|
7707
|
-
c.loopLen =
|
|
7753
|
+
c.start = round11(newStart2);
|
|
7754
|
+
c.loopLen = round11(end - newStart2);
|
|
7708
7755
|
};
|
|
7709
7756
|
}
|
|
7710
7757
|
const delta = g.t - clip.start;
|
|
@@ -7713,22 +7760,22 @@ var audioLane = {
|
|
|
7713
7760
|
return (d) => {
|
|
7714
7761
|
const c = d.audio.find((x) => x.id === g.id);
|
|
7715
7762
|
if (!c) return;
|
|
7716
|
-
c.in =
|
|
7717
|
-
c.start =
|
|
7763
|
+
c.in = round11(newIn);
|
|
7764
|
+
c.start = round11(newStart);
|
|
7718
7765
|
};
|
|
7719
7766
|
}
|
|
7720
7767
|
if (clip.loop) {
|
|
7721
7768
|
const newLen = Math.max(0.1, g.t - clip.start);
|
|
7722
7769
|
return (d) => {
|
|
7723
7770
|
const c = d.audio.find((x) => x.id === g.id);
|
|
7724
|
-
if (c) c.loopLen =
|
|
7771
|
+
if (c) c.loopLen = round11(newLen);
|
|
7725
7772
|
};
|
|
7726
7773
|
}
|
|
7727
7774
|
const span = Math.max(0.05, g.t - clip.start);
|
|
7728
7775
|
const newOut = Math.min(clip.in + span, clip.duration);
|
|
7729
7776
|
return (d) => {
|
|
7730
7777
|
const c = d.audio.find((x) => x.id === g.id);
|
|
7731
|
-
if (c) c.out =
|
|
7778
|
+
if (c) c.out = round11(Math.max(c.in + 0.05, newOut));
|
|
7732
7779
|
};
|
|
7733
7780
|
}
|
|
7734
7781
|
if (g.type === "remove") {
|
|
@@ -7741,8 +7788,8 @@ var audioLane = {
|
|
|
7741
7788
|
},
|
|
7742
7789
|
magnets(doc) {
|
|
7743
7790
|
return doc.audio.flatMap((c) => [
|
|
7744
|
-
|
|
7745
|
-
|
|
7791
|
+
round11(c.start),
|
|
7792
|
+
round11(c.start + clipLength(c))
|
|
7746
7793
|
]);
|
|
7747
7794
|
}
|
|
7748
7795
|
};
|
|
@@ -7760,7 +7807,7 @@ function poseItems(clipId, start, duration, motion) {
|
|
|
7760
7807
|
return (motion ?? []).map((p, i) => ({
|
|
7761
7808
|
id: `${clipId}::k${i}`,
|
|
7762
7809
|
kind: "keyframe",
|
|
7763
|
-
t:
|
|
7810
|
+
t: round11(start + Math.min(Math.max(0, p.at), duration))
|
|
7764
7811
|
}));
|
|
7765
7812
|
}
|
|
7766
7813
|
var overlaysLane = {
|
|
@@ -7771,8 +7818,8 @@ var overlaysLane = {
|
|
|
7771
7818
|
{
|
|
7772
7819
|
id: o.id,
|
|
7773
7820
|
kind: "clip",
|
|
7774
|
-
t:
|
|
7775
|
-
duration:
|
|
7821
|
+
t: round11(o.start),
|
|
7822
|
+
duration: round11(o.duration),
|
|
7776
7823
|
label: o.kind === "text" ? o.text.split("\n")[0].slice(0, 24) || "Text" : o.kind === "image" ? "Image" : "Video"
|
|
7777
7824
|
},
|
|
7778
7825
|
// Pose diamonds render after the clips, so they sit on top.
|
|
@@ -7792,7 +7839,7 @@ var overlaysLane = {
|
|
|
7792
7839
|
return (d) => {
|
|
7793
7840
|
const o = (d.overlays ?? []).find((x) => x.id === kf.clipId);
|
|
7794
7841
|
const p = o?.motion?.[kf.index];
|
|
7795
|
-
if (p) p.at =
|
|
7842
|
+
if (p) p.at = round11(at);
|
|
7796
7843
|
};
|
|
7797
7844
|
}
|
|
7798
7845
|
if (g.type === "remove") {
|
|
@@ -7821,8 +7868,8 @@ var overlaysLane = {
|
|
|
7821
7868
|
{
|
|
7822
7869
|
id,
|
|
7823
7870
|
kind: "text",
|
|
7824
|
-
start:
|
|
7825
|
-
duration:
|
|
7871
|
+
start: round11(start),
|
|
7872
|
+
duration: round11(len),
|
|
7826
7873
|
text: "Title",
|
|
7827
7874
|
preset: "title",
|
|
7828
7875
|
// Frame fractions: centered, lower-third — at any aspect ratio.
|
|
@@ -7837,7 +7884,7 @@ var overlaysLane = {
|
|
|
7837
7884
|
const start = Math.max(0, g.t);
|
|
7838
7885
|
return (d) => {
|
|
7839
7886
|
const o = (d.overlays ?? []).find((x) => x.id === g.id);
|
|
7840
|
-
if (o) o.start =
|
|
7887
|
+
if (o) o.start = round11(start);
|
|
7841
7888
|
};
|
|
7842
7889
|
}
|
|
7843
7890
|
if (g.type === "resize") {
|
|
@@ -7847,14 +7894,14 @@ var overlaysLane = {
|
|
|
7847
7894
|
return (d) => {
|
|
7848
7895
|
const o = (d.overlays ?? []).find((x) => x.id === g.id);
|
|
7849
7896
|
if (!o) return;
|
|
7850
|
-
o.start =
|
|
7851
|
-
o.duration =
|
|
7897
|
+
o.start = round11(newStart);
|
|
7898
|
+
o.duration = round11(end - newStart);
|
|
7852
7899
|
};
|
|
7853
7900
|
}
|
|
7854
7901
|
const newLen = Math.max(OVERLAY_MIN_DURATION, g.t - clip.start);
|
|
7855
7902
|
return (d) => {
|
|
7856
7903
|
const o = (d.overlays ?? []).find((x) => x.id === g.id);
|
|
7857
|
-
if (o) o.duration =
|
|
7904
|
+
if (o) o.duration = round11(newLen);
|
|
7858
7905
|
};
|
|
7859
7906
|
}
|
|
7860
7907
|
return (d) => {
|
|
@@ -7863,8 +7910,8 @@ var overlaysLane = {
|
|
|
7863
7910
|
},
|
|
7864
7911
|
magnets(doc) {
|
|
7865
7912
|
return (doc.overlays ?? []).flatMap((o) => [
|
|
7866
|
-
|
|
7867
|
-
|
|
7913
|
+
round11(o.start),
|
|
7914
|
+
round11(o.start + o.duration)
|
|
7868
7915
|
]);
|
|
7869
7916
|
}
|
|
7870
7917
|
};
|
|
@@ -7877,8 +7924,8 @@ var objectsLane = {
|
|
|
7877
7924
|
{
|
|
7878
7925
|
id: o.id,
|
|
7879
7926
|
kind: "clip",
|
|
7880
|
-
t:
|
|
7881
|
-
duration:
|
|
7927
|
+
t: round11(o.span?.start ?? 0),
|
|
7928
|
+
duration: round11(o.span?.duration ?? outDur),
|
|
7882
7929
|
label: o.asset.kind === "primitive" ? o.asset.shape : o.asset.kind === "text3d" ? o.asset.text : "model"
|
|
7883
7930
|
},
|
|
7884
7931
|
// Pose diamonds: clip-local `at` from the span start (0 span-less).
|
|
@@ -7906,7 +7953,7 @@ var objectsLane = {
|
|
|
7906
7953
|
return (d) => {
|
|
7907
7954
|
const o = (d.objects ?? []).find((x) => x.id === kf.clipId);
|
|
7908
7955
|
const p = o?.motion?.[kf.index];
|
|
7909
|
-
if (p) p.at =
|
|
7956
|
+
if (p) p.at = round11(at);
|
|
7910
7957
|
};
|
|
7911
7958
|
}
|
|
7912
7959
|
if (g.type === "remove") {
|
|
@@ -7927,7 +7974,7 @@ var objectsLane = {
|
|
|
7927
7974
|
const start = Math.max(0, g.t);
|
|
7928
7975
|
return (d) => {
|
|
7929
7976
|
const o = (d.objects ?? []).find((x) => x.id === g.id);
|
|
7930
|
-
if (o?.span) o.span.start =
|
|
7977
|
+
if (o?.span) o.span.start = round11(start);
|
|
7931
7978
|
};
|
|
7932
7979
|
}
|
|
7933
7980
|
if (g.type === "resize") {
|
|
@@ -7938,14 +7985,14 @@ var objectsLane = {
|
|
|
7938
7985
|
return (d) => {
|
|
7939
7986
|
const o = (d.objects ?? []).find((x) => x.id === g.id);
|
|
7940
7987
|
if (!o?.span) return;
|
|
7941
|
-
o.span.start =
|
|
7942
|
-
o.span.duration =
|
|
7988
|
+
o.span.start = round11(newStart);
|
|
7989
|
+
o.span.duration = round11(end - newStart);
|
|
7943
7990
|
};
|
|
7944
7991
|
}
|
|
7945
7992
|
const newLen = Math.max(OVERLAY_MIN_DURATION, g.t - clip.span.start);
|
|
7946
7993
|
return (d) => {
|
|
7947
7994
|
const o = (d.objects ?? []).find((x) => x.id === g.id);
|
|
7948
|
-
if (o?.span) o.span.duration =
|
|
7995
|
+
if (o?.span) o.span.duration = round11(newLen);
|
|
7949
7996
|
};
|
|
7950
7997
|
}
|
|
7951
7998
|
return (d) => {
|
|
@@ -7954,7 +8001,7 @@ var objectsLane = {
|
|
|
7954
8001
|
},
|
|
7955
8002
|
magnets(doc) {
|
|
7956
8003
|
return (doc.objects ?? []).flatMap(
|
|
7957
|
-
(o) => o.span ? [
|
|
8004
|
+
(o) => o.span ? [round11(o.span.start), round11(o.span.start + o.span.duration)] : []
|
|
7958
8005
|
);
|
|
7959
8006
|
}
|
|
7960
8007
|
};
|
|
@@ -7981,7 +8028,7 @@ function nextSpeedId(doc) {
|
|
|
7981
8028
|
function segIndex(id) {
|
|
7982
8029
|
return Number(id.replace("seg-", ""));
|
|
7983
8030
|
}
|
|
7984
|
-
function
|
|
8031
|
+
function round11(v) {
|
|
7985
8032
|
return Math.round(v * 1e3) / 1e3;
|
|
7986
8033
|
}
|
|
7987
8034
|
|