@vosjs/studio-core 0.5.1 → 0.7.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 +15 -0
- package/dist/index.js +83 -24
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -922,6 +922,15 @@ interface EndCard {
|
|
|
922
922
|
headline?: string;
|
|
923
923
|
sub?: string;
|
|
924
924
|
wordmark?: string;
|
|
925
|
+
/**
|
|
926
|
+
* The brand's MARK as an image (a take-dir path or a URL the render page
|
|
927
|
+
* can load), with its aspect (width over height), drawn above the
|
|
928
|
+
* wordmark; a wide mark (a stylised wordmark asset) stands alone.
|
|
929
|
+
*/
|
|
930
|
+
mark?: {
|
|
931
|
+
key: string;
|
|
932
|
+
aspect: number;
|
|
933
|
+
};
|
|
925
934
|
/**
|
|
926
935
|
* The words' colour (any CSS colour). The house presets are white for
|
|
927
936
|
* footage; over a light plate the brand's ink is what reads. Absent =
|
|
@@ -1050,6 +1059,12 @@ interface TextOverlayClip extends OverlayClipBase {
|
|
|
1050
1059
|
letterSpacing?: number;
|
|
1051
1060
|
/** Line height multiplier (default OVERLAY_LINE_HEIGHT). */
|
|
1052
1061
|
lineHeight?: number;
|
|
1062
|
+
/**
|
|
1063
|
+
* Legibility shadow strength 0..1 (the preset's when absent; 0 = none).
|
|
1064
|
+
* Words on a plate ground carry none: the shadow exists for words over
|
|
1065
|
+
* footage.
|
|
1066
|
+
*/
|
|
1067
|
+
shadow?: number;
|
|
1053
1068
|
/** Text outline, drawn under the fill. */
|
|
1054
1069
|
stroke?: TextOverlayStroke;
|
|
1055
1070
|
/** Background pill behind the text block (absent = none). */
|
package/dist/index.js
CHANGED
|
@@ -1266,6 +1266,7 @@ var CARD_FOV = 30;
|
|
|
1266
1266
|
var OVERLAY_Z = -2;
|
|
1267
1267
|
var CARD_Z = -4;
|
|
1268
1268
|
var BACKGROUND_Z = -6;
|
|
1269
|
+
var CARD_OVERSCAN = 1.25;
|
|
1269
1270
|
var CAMERA_NEAR = 0.1;
|
|
1270
1271
|
var CAMERA_FAR = 100;
|
|
1271
1272
|
function planeSizeAtDepth(distance, fovDeg, aspect) {
|
|
@@ -1361,6 +1362,7 @@ function resolveOverlayStyle(clip) {
|
|
|
1361
1362
|
)
|
|
1362
1363
|
} : {},
|
|
1363
1364
|
...clip.color ? { color: clip.color } : {},
|
|
1365
|
+
...clip.shadow !== void 0 ? { shadow: Math.min(1, Math.max(0, clip.shadow)) } : {},
|
|
1364
1366
|
fontStyle: clip.italic ? "italic" : "normal",
|
|
1365
1367
|
align: clip.align ?? "center",
|
|
1366
1368
|
letterSpacing: clip.letterSpacing ?? 0,
|
|
@@ -2850,11 +2852,44 @@ function expandEndCard(doc, outputDuration) {
|
|
|
2850
2852
|
enter: "rise",
|
|
2851
2853
|
exit: "none",
|
|
2852
2854
|
align: "center",
|
|
2853
|
-
...card.ink ? { color: card.ink } : {}
|
|
2855
|
+
...card.ink ? { color: card.ink } : {},
|
|
2856
|
+
shadow: 0
|
|
2854
2857
|
});
|
|
2855
|
-
if (card.headline?.trim())
|
|
2856
|
-
|
|
2857
|
-
if (card.
|
|
2858
|
+
if (card.headline?.trim())
|
|
2859
|
+
clips.push(text("endcard-title", card.headline.trim(), "title", 0.44, 0.35));
|
|
2860
|
+
if (card.sub?.trim())
|
|
2861
|
+
clips.push(text("endcard-sub", card.sub.trim(), "caption", 0.57, 0.5));
|
|
2862
|
+
const mark = card.mark;
|
|
2863
|
+
const wide = !!mark && mark.aspect > 2.2;
|
|
2864
|
+
if (mark && mark.key) {
|
|
2865
|
+
const size = resolveExportSize(doc);
|
|
2866
|
+
const designW = 1080 * size.width / Math.max(1, size.height);
|
|
2867
|
+
const hPx = wide ? 44 : 30;
|
|
2868
|
+
const clip = {
|
|
2869
|
+
id: "endcard-markimg",
|
|
2870
|
+
kind: "image",
|
|
2871
|
+
key: mark.key,
|
|
2872
|
+
width: Math.min(0.9, hPx * Math.max(0.2, mark.aspect) / designW),
|
|
2873
|
+
radius: 0,
|
|
2874
|
+
shadow: "none",
|
|
2875
|
+
start: endStart + 0.65,
|
|
2876
|
+
duration: Math.max(0.3, seconds - 0.65),
|
|
2877
|
+
transform: { x: 0.5, y: wide ? 0.88 : 0.835, scale: 1, rotation: 0 },
|
|
2878
|
+
enter: "rise",
|
|
2879
|
+
exit: "none"
|
|
2880
|
+
};
|
|
2881
|
+
clips.push(clip);
|
|
2882
|
+
}
|
|
2883
|
+
if (card.wordmark?.trim() && !wide)
|
|
2884
|
+
clips.push(
|
|
2885
|
+
text(
|
|
2886
|
+
"endcard-mark",
|
|
2887
|
+
card.wordmark.trim(),
|
|
2888
|
+
"label",
|
|
2889
|
+
mark && mark.key ? 0.895 : 0.88,
|
|
2890
|
+
0.65
|
|
2891
|
+
)
|
|
2892
|
+
);
|
|
2858
2893
|
const overlays = [...doc.overlays ?? [], ...clips];
|
|
2859
2894
|
return { doc: { ...doc, segments, overlays }, endStart, seconds };
|
|
2860
2895
|
}
|
|
@@ -3526,24 +3561,33 @@ var ON_FRAME = `(ctx, content, dt) => {
|
|
|
3526
3561
|
// the GPU texture allocated at the original dims and re-uploads the new canvas
|
|
3527
3562
|
// against stale dims \u2192 stretch/duplicate; dispose() forces a full realloc) and
|
|
3528
3563
|
// rebuilding each frustum-filling plane at the new aspect + syncing the camera.
|
|
3529
|
-
|
|
3564
|
+
// Card OVERSCAN (stage.ts CARD_OVERSCAN): a frame whose inset bleeds the
|
|
3565
|
+
// card past an edge paints it on a canvas and a plane larger than the
|
|
3566
|
+
// frame by ck about the centre, so a tilt that turns the bled edge back
|
|
3567
|
+
// toward the viewer shows card there, not the texture's edge. Every doc
|
|
3568
|
+
// that keeps its card inside the frame (and the flat stub, which has no
|
|
3569
|
+
// card layer) stays at 1: byte- and pixel-identical.
|
|
3570
|
+
var d = ctx.data || {}
|
|
3571
|
+
var ckIns = (d.frame && d.frame.inset) || {}
|
|
3572
|
+
var ck = r.card && (ckIns.left < 0 || ckIns.right < 0 || ckIns.top < 0 || ckIns.bottom < 0) ? ${CARD_OVERSCAN} : 1
|
|
3573
|
+
var cW = Math.round(W * ck), cH = Math.round(H * ck)
|
|
3574
|
+
if (cv.width !== cW || cv.height !== cH) {
|
|
3530
3575
|
var THREE = ctx.THREE
|
|
3531
3576
|
var aspect = W / H
|
|
3532
3577
|
var cm = ctx.camera
|
|
3533
3578
|
if (cm && cm.isPerspectiveCamera) { cm.aspect = aspect; cm.updateProjectionMatrix() }
|
|
3534
|
-
var lyr = [[bg, ${BACKGROUND_Z}], [card, ${CARD_Z}], [ov, ${OVERLAY_Z}]]
|
|
3579
|
+
var lyr = [[bg, ${BACKGROUND_Z}, 1], [card, ${CARD_Z}, ck], [ov, ${OVERLAY_Z}, 1]]
|
|
3535
3580
|
for (var Li = 0; Li < lyr.length; Li++) {
|
|
3536
|
-
var Ly = lyr[Li][0], Lz = lyr[Li][1]
|
|
3537
|
-
if (Ly.canvas) { Ly.canvas.width = W; Ly.canvas.height = H }
|
|
3581
|
+
var Ly = lyr[Li][0], Lz = lyr[Li][1], Lk = lyr[Li][2]
|
|
3582
|
+
if (Ly.canvas) { Ly.canvas.width = Math.round(W * Lk); Ly.canvas.height = Math.round(H * Lk) }
|
|
3538
3583
|
if (Ly.texture && Ly.texture.dispose) Ly.texture.dispose()
|
|
3539
3584
|
if (Ly.mesh && THREE) {
|
|
3540
3585
|
if (Ly.mesh.geometry && Ly.mesh.geometry.dispose) Ly.mesh.geometry.dispose()
|
|
3541
|
-
var Lh = 2 * Math.abs(Lz) * Math.tan(${CARD_FOV} * Math.PI / 180 / 2)
|
|
3586
|
+
var Lh = 2 * Math.abs(Lz) * Math.tan(${CARD_FOV} * Math.PI / 180 / 2) * Lk
|
|
3542
3587
|
Ly.mesh.geometry = new THREE.PlaneGeometry(Lh * aspect, Lh)
|
|
3543
3588
|
}
|
|
3544
3589
|
}
|
|
3545
3590
|
}
|
|
3546
|
-
var d = ctx.data || {}
|
|
3547
3591
|
var frame = d.frame || {}
|
|
3548
3592
|
var TL = globalThis.__vosTimeline
|
|
3549
3593
|
// Output-timeline seconds (engine-fed master clock) \u2192 source seconds on screen.
|
|
@@ -3862,7 +3906,15 @@ var ON_FRAME = `(ctx, content, dt) => {
|
|
|
3862
3906
|
|
|
3863
3907
|
// The CARD layer canvas starts transparent each frame \u2014 the padding around
|
|
3864
3908
|
// the contain-fit card shows the background layer through the plane's alpha.
|
|
3865
|
-
|
|
3909
|
+
// Under overscan the canvas is larger than the frame and every frame-space
|
|
3910
|
+
// draw below rides a base translation to its centre.
|
|
3911
|
+
if (ck !== 1) c.setTransform(1, 0, 0, 1, 0, 0)
|
|
3912
|
+
c.clearRect(0, 0, cv.width, cv.height)
|
|
3913
|
+
if (ck !== 1) c.setTransform(1, 0, 0, 1, (cW - W) / 2, (cH - H) / 2)
|
|
3914
|
+
// Footage is nearly always drawn SMALLER than it was recorded (a 1920
|
|
3915
|
+
// recording in a padded 1080 card, or a 440-wide tile): the default
|
|
3916
|
+
// bilinear tap aliases and blurs a large downscale; 'high' resamples.
|
|
3917
|
+
c.imageSmoothingQuality = 'high'
|
|
3866
3918
|
|
|
3867
3919
|
// video destination rect (contain within the padded area). The optional browser-bar
|
|
3868
3920
|
// strip is part of the card: it takes barH from the available height and the video
|
|
@@ -3973,14 +4025,21 @@ var ON_FRAME = `(ctx, content, dt) => {
|
|
|
3973
4025
|
// corners, drawn by the clip alone, hid theirs inside the arc.
|
|
3974
4026
|
var shD = ceZs * (cardW + cardH) + 2 * (W + H)
|
|
3975
4027
|
var shX = cardX - shD / ceZs
|
|
3976
|
-
//
|
|
4028
|
+
// The card shadow is LAYERED: three shadows whose blur and offset grow
|
|
4029
|
+
// while each stays at a low alpha (shadow is the strength they share),
|
|
4030
|
+
// so the card reads as lifted a little off the ground. One wide layer at
|
|
4031
|
+
// the full strength was the old paint, and at the default 0.4 it read as
|
|
4032
|
+
// a dark pool under the card.
|
|
3977
4033
|
if (shadow > 0) {
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
4034
|
+
var shL = [[3, 1, 0.2], [14, 6, 0.22], [48, 22, 0.3]]
|
|
4035
|
+
for (var shI = 0; shI < shL.length; shI++) {
|
|
4036
|
+
c.save()
|
|
4037
|
+
c.shadowColor = 'rgba(' + shRgb + ',' + +(shadow * shL[shI][2]).toFixed(3) + ')'
|
|
4038
|
+
c.shadowBlur = shL[shI][0] * s2; c.shadowOffsetX = shD; c.shadowOffsetY = shL[shI][1] * s2
|
|
4039
|
+
c.fillStyle = '#000'
|
|
4040
|
+
rr(shX, cardY, cardW, cardH, radius); c.fill()
|
|
4041
|
+
c.restore()
|
|
4042
|
+
}
|
|
3984
4043
|
}
|
|
3985
4044
|
// contact shadow: tight and close, over the ambient layer
|
|
3986
4045
|
if (shC > 0) {
|
|
@@ -5884,8 +5943,8 @@ var LOOKS = {
|
|
|
5884
5943
|
cardWidth: 0.84,
|
|
5885
5944
|
headroom: 0.16,
|
|
5886
5945
|
radius: 12,
|
|
5887
|
-
shadow: 0.
|
|
5888
|
-
shadowContact: 0
|
|
5946
|
+
shadow: 0.42,
|
|
5947
|
+
shadowContact: 0,
|
|
5889
5948
|
border: 0.08,
|
|
5890
5949
|
borderColor: "#000000"
|
|
5891
5950
|
},
|
|
@@ -5895,8 +5954,8 @@ var LOOKS = {
|
|
|
5895
5954
|
cardWidth: 0.84,
|
|
5896
5955
|
headroom: 0.16,
|
|
5897
5956
|
radius: 12,
|
|
5898
|
-
shadow: 0.
|
|
5899
|
-
shadowContact: 0
|
|
5957
|
+
shadow: 0.5,
|
|
5958
|
+
shadowContact: 0,
|
|
5900
5959
|
border: 0
|
|
5901
5960
|
},
|
|
5902
5961
|
dark: {
|
|
@@ -5905,8 +5964,8 @@ var LOOKS = {
|
|
|
5905
5964
|
cardWidth: 0.86,
|
|
5906
5965
|
headroom: 0.14,
|
|
5907
5966
|
radius: 12,
|
|
5908
|
-
shadow: 0.
|
|
5909
|
-
shadowContact: 0
|
|
5967
|
+
shadow: 0.7,
|
|
5968
|
+
shadowContact: 0,
|
|
5910
5969
|
shadowColor: "#000000",
|
|
5911
5970
|
border: 0.12,
|
|
5912
5971
|
borderColor: "#ffffff"
|