reframe-video 0.6.32 → 0.6.34
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/bin.js +418 -41
- package/dist/browserEntry.js +8 -8
- package/dist/cli.js +387 -17
- package/dist/compile-api.js +3 -3
- package/dist/compile.js +3 -3
- package/dist/diff.js +3 -3
- package/dist/frame.js +3 -3
- package/dist/index.js +2294 -2186
- package/dist/labels.js +3 -3
- package/dist/trace-cli.js +3 -3
- package/dist/types/autoFoley.d.ts +18 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/ir.d.ts +25 -0
- package/guides/edsl-guide.md +10 -0
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -409,7 +409,119 @@ function easeOutBounce(u) {
|
|
|
409
409
|
if (u < 2.5 / d1) return n1 * (u -= 2.25 / d1) * u + 0.9375;
|
|
410
410
|
return n1 * (u -= 2.625 / d1) * u + 0.984375;
|
|
411
411
|
}
|
|
412
|
-
|
|
412
|
+
function resolveEase(ease) {
|
|
413
|
+
if (ease === void 0) return EASE_TABLE.linear;
|
|
414
|
+
if (typeof ease === "string") {
|
|
415
|
+
const fn = EASE_TABLE[ease];
|
|
416
|
+
if (!fn) throw new Error(`unknown ease "${ease}" \u2014 valid: ${Object.keys(EASE_TABLE).join(", ")}`);
|
|
417
|
+
return fn;
|
|
418
|
+
}
|
|
419
|
+
if ("spring" in ease) {
|
|
420
|
+
const { stiffness = 100, damping = 10, velocity = 0 } = ease.spring;
|
|
421
|
+
return springEase(stiffness, damping, velocity);
|
|
422
|
+
}
|
|
423
|
+
return cubicBezierEase(...ease.cubicBezier);
|
|
424
|
+
}
|
|
425
|
+
function cubicBezierEase(x1, y1, x2, y2) {
|
|
426
|
+
const bez = (a, b) => (t) => 3 * a * t * (1 - t) ** 2 + 3 * b * t * t * (1 - t) + t ** 3;
|
|
427
|
+
const bx = bez(x1, x2);
|
|
428
|
+
const by = bez(y1, y2);
|
|
429
|
+
const dbx = (t) => 3 * x1 * (1 - t) * (1 - 3 * t) + 3 * x2 * t * (2 - 3 * t) + 3 * t * t;
|
|
430
|
+
return (u) => {
|
|
431
|
+
if (u <= 0) return 0;
|
|
432
|
+
if (u >= 1) return 1;
|
|
433
|
+
let t = u;
|
|
434
|
+
for (let i = 0; i < 8; i++) {
|
|
435
|
+
const err = bx(t) - u;
|
|
436
|
+
if (Math.abs(err) < 1e-6) return by(t);
|
|
437
|
+
const d = dbx(t);
|
|
438
|
+
if (Math.abs(d) < 1e-6) break;
|
|
439
|
+
t -= err / d;
|
|
440
|
+
}
|
|
441
|
+
let lo = 0;
|
|
442
|
+
let hi = 1;
|
|
443
|
+
t = u;
|
|
444
|
+
while (hi - lo > 1e-6) {
|
|
445
|
+
if (bx(t) < u) lo = t;
|
|
446
|
+
else hi = t;
|
|
447
|
+
t = (lo + hi) / 2;
|
|
448
|
+
}
|
|
449
|
+
return by(t);
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
function isColor(v) {
|
|
453
|
+
return typeof v === "string" && HEX_COLOR.test(v);
|
|
454
|
+
}
|
|
455
|
+
function parseColor(hex) {
|
|
456
|
+
let h = hex.slice(1);
|
|
457
|
+
if (h.length <= 4) h = [...h].map((c) => c + c).join("");
|
|
458
|
+
const n = parseInt(h.padEnd(8, "f"), 16);
|
|
459
|
+
return [n >>> 24 & 255, n >>> 16 & 255, n >>> 8 & 255, n & 255];
|
|
460
|
+
}
|
|
461
|
+
function formatColor([r, g, b, a]) {
|
|
462
|
+
const hex = (v) => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, "0");
|
|
463
|
+
return a >= 255 ? `#${hex(r)}${hex(g)}${hex(b)}` : `#${hex(r)}${hex(g)}${hex(b)}${hex(a)}`;
|
|
464
|
+
}
|
|
465
|
+
function lerpValue(from, to, u) {
|
|
466
|
+
if (typeof from === "number" && typeof to === "number") {
|
|
467
|
+
return from + (to - from) * u;
|
|
468
|
+
}
|
|
469
|
+
if (isColor(from) && isColor(to)) {
|
|
470
|
+
const a = parseColor(from);
|
|
471
|
+
const b = parseColor(to);
|
|
472
|
+
return formatColor([
|
|
473
|
+
a[0] + (b[0] - a[0]) * u,
|
|
474
|
+
a[1] + (b[1] - a[1]) * u,
|
|
475
|
+
a[2] + (b[2] - a[2]) * u,
|
|
476
|
+
a[3] + (b[3] - a[3]) * u
|
|
477
|
+
]);
|
|
478
|
+
}
|
|
479
|
+
if (looksLikePath(from) && looksLikePath(to)) {
|
|
480
|
+
const a = tokenizePath(from);
|
|
481
|
+
const b = tokenizePath(to);
|
|
482
|
+
if (a && b && morphCompatible(a, b)) return morphPath(a, b, u);
|
|
483
|
+
return u < 0.5 ? from : to;
|
|
484
|
+
}
|
|
485
|
+
return to;
|
|
486
|
+
}
|
|
487
|
+
function looksLikePath(v) {
|
|
488
|
+
return typeof v === "string" && /^\s*[Mm]/.test(v) && PATH_BODY.test(v);
|
|
489
|
+
}
|
|
490
|
+
function tokenizePath(d) {
|
|
491
|
+
const out = [];
|
|
492
|
+
let cur = null;
|
|
493
|
+
let m;
|
|
494
|
+
PATH_TOKEN.lastIndex = 0;
|
|
495
|
+
while (m = PATH_TOKEN.exec(d)) {
|
|
496
|
+
if (m[1]) out.push(cur = { cmd: m[1], nums: [] });
|
|
497
|
+
else if (m[2]) {
|
|
498
|
+
if (!cur) return null;
|
|
499
|
+
cur.nums.push(parseFloat(m[2]));
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return out.length ? out : null;
|
|
503
|
+
}
|
|
504
|
+
function morphCompatible(a, b) {
|
|
505
|
+
if (a.length !== b.length) return false;
|
|
506
|
+
for (let i = 0; i < a.length; i++) {
|
|
507
|
+
const ca = a[i];
|
|
508
|
+
const cb = b[i];
|
|
509
|
+
if (ca.cmd !== cb.cmd || ca.nums.length !== cb.nums.length) return false;
|
|
510
|
+
if (ca.cmd === "A" || ca.cmd === "a") return false;
|
|
511
|
+
}
|
|
512
|
+
return true;
|
|
513
|
+
}
|
|
514
|
+
function morphPath(a, b, u) {
|
|
515
|
+
let s = "";
|
|
516
|
+
for (let i = 0; i < a.length; i++) {
|
|
517
|
+
const an = a[i].nums;
|
|
518
|
+
const bn = b[i].nums;
|
|
519
|
+
s += (i ? " " : "") + a[i].cmd;
|
|
520
|
+
for (let j = 0; j < an.length; j++) s += " " + fmtNum(an[j] + (bn[j] - an[j]) * u);
|
|
521
|
+
}
|
|
522
|
+
return s;
|
|
523
|
+
}
|
|
524
|
+
var BACK_C1, BACK_C2, BACK_C3, ELASTIC_C4, ELASTIC_C5, EASE_TABLE, EASE_NAMES, HEX_COLOR, PATH_BODY, PATH_TOKEN, fmtNum;
|
|
413
525
|
var init_interpolate = __esm({
|
|
414
526
|
"../core/src/interpolate.ts"() {
|
|
415
527
|
"use strict";
|
|
@@ -451,6 +563,13 @@ var init_interpolate = __esm({
|
|
|
451
563
|
springStiff: springEase(210, 26, 0)
|
|
452
564
|
};
|
|
453
565
|
EASE_NAMES = Object.keys(EASE_TABLE);
|
|
566
|
+
HEX_COLOR = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
|
|
567
|
+
PATH_BODY = /^[\sMmLlHhVvCcSsQqTtAaZz0-9.,eE+-]+$/;
|
|
568
|
+
PATH_TOKEN = /([MmLlHhVvCcSsQqTtAaZz])|(-?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?)/g;
|
|
569
|
+
fmtNum = (v) => {
|
|
570
|
+
const r = Number(v.toFixed(3));
|
|
571
|
+
return Object.is(r, -0) ? "0" : String(r);
|
|
572
|
+
};
|
|
454
573
|
}
|
|
455
574
|
});
|
|
456
575
|
|
|
@@ -1102,6 +1221,40 @@ var init_camera = __esm({
|
|
|
1102
1221
|
}
|
|
1103
1222
|
});
|
|
1104
1223
|
|
|
1224
|
+
// ../core/src/behaviors.ts
|
|
1225
|
+
function sampleBehavior(b, t) {
|
|
1226
|
+
switch (b.name) {
|
|
1227
|
+
case "oscillate": {
|
|
1228
|
+
const { amplitude, frequency, phase = 0 } = b.params;
|
|
1229
|
+
return amplitude * Math.sin(2 * Math.PI * frequency * t + phase);
|
|
1230
|
+
}
|
|
1231
|
+
case "wiggle": {
|
|
1232
|
+
const { amplitude, frequency, seed } = b.params;
|
|
1233
|
+
return amplitude * valueNoise(t * frequency, seed);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
function valueNoise(x, seed) {
|
|
1238
|
+
const i = Math.floor(x);
|
|
1239
|
+
const f = x - i;
|
|
1240
|
+
const u = f * f * (3 - 2 * f);
|
|
1241
|
+
const a = hash01(i, seed) * 2 - 1;
|
|
1242
|
+
const b = hash01(i + 1, seed) * 2 - 1;
|
|
1243
|
+
return a + (b - a) * u;
|
|
1244
|
+
}
|
|
1245
|
+
function hash01(n, seed) {
|
|
1246
|
+
let h = n * 374761393 + seed * 668265263 | 0;
|
|
1247
|
+
h = h ^ h >>> 13 | 0;
|
|
1248
|
+
h = Math.imul(h, 1274126177);
|
|
1249
|
+
h = (h ^ h >>> 16) >>> 0;
|
|
1250
|
+
return h / 4294967295;
|
|
1251
|
+
}
|
|
1252
|
+
var init_behaviors = __esm({
|
|
1253
|
+
"../core/src/behaviors.ts"() {
|
|
1254
|
+
"use strict";
|
|
1255
|
+
}
|
|
1256
|
+
});
|
|
1257
|
+
|
|
1105
1258
|
// ../core/src/gradient.ts
|
|
1106
1259
|
var init_gradient = __esm({
|
|
1107
1260
|
"../core/src/gradient.ts"() {
|
|
@@ -1109,6 +1262,247 @@ var init_gradient = __esm({
|
|
|
1109
1262
|
}
|
|
1110
1263
|
});
|
|
1111
1264
|
|
|
1265
|
+
// ../core/src/evaluate.ts
|
|
1266
|
+
function multiply(m, n) {
|
|
1267
|
+
return [
|
|
1268
|
+
m[0] * n[0] + m[2] * n[1],
|
|
1269
|
+
m[1] * n[0] + m[3] * n[1],
|
|
1270
|
+
m[0] * n[2] + m[2] * n[3],
|
|
1271
|
+
m[1] * n[2] + m[3] * n[3],
|
|
1272
|
+
m[0] * n[4] + m[2] * n[5] + m[4],
|
|
1273
|
+
m[1] * n[4] + m[3] * n[5] + m[5]
|
|
1274
|
+
];
|
|
1275
|
+
}
|
|
1276
|
+
function localMatrix(x, y, rotationDeg, scale, scaleX = 1, scaleY = 1, skewXDeg = 0, skewYDeg = 0) {
|
|
1277
|
+
const r = rotationDeg * Math.PI / 180;
|
|
1278
|
+
if (scaleX === 1 && scaleY === 1 && skewXDeg === 0 && skewYDeg === 0) {
|
|
1279
|
+
const cos = Math.cos(r) * scale;
|
|
1280
|
+
const sin = Math.sin(r) * scale;
|
|
1281
|
+
return [cos, sin, -sin, cos, x, y];
|
|
1282
|
+
}
|
|
1283
|
+
const c = Math.cos(r);
|
|
1284
|
+
const s = Math.sin(r);
|
|
1285
|
+
const tx = Math.tan(skewXDeg * Math.PI / 180);
|
|
1286
|
+
const ty = Math.tan(skewYDeg * Math.PI / 180);
|
|
1287
|
+
const R = [c, s, -s, c, 0, 0];
|
|
1288
|
+
const K = [1, ty, tx, 1, 0, 0];
|
|
1289
|
+
const S = [scale * scaleX, 0, 0, scale * scaleY, 0, 0];
|
|
1290
|
+
const m = multiply(R, multiply(K, S));
|
|
1291
|
+
return [m[0], m[1], m[2], m[3], x, y];
|
|
1292
|
+
}
|
|
1293
|
+
function behaviorEnvelope(b, t) {
|
|
1294
|
+
const from = b.from ?? Number.NEGATIVE_INFINITY;
|
|
1295
|
+
const until = b.until ?? Number.POSITIVE_INFINITY;
|
|
1296
|
+
if (t < from || t > until) return 0;
|
|
1297
|
+
const ramp = b.ramp ?? 0.2;
|
|
1298
|
+
let envelope = 1;
|
|
1299
|
+
if (Number.isFinite(from) && ramp > 0) envelope = Math.min(envelope, (t - from) / ramp);
|
|
1300
|
+
if (Number.isFinite(until) && ramp > 0) envelope = Math.min(envelope, (until - t) / ramp);
|
|
1301
|
+
return Math.max(0, Math.min(1, envelope));
|
|
1302
|
+
}
|
|
1303
|
+
function sampleProp(compiled, t, target, prop, fallback) {
|
|
1304
|
+
let value = compiled.initialValues.get(`${target}.${prop}`) ?? fallback;
|
|
1305
|
+
let segStart = Number.NEGATIVE_INFINITY;
|
|
1306
|
+
const segs = compiled.segments.get(`${target}.${prop}`);
|
|
1307
|
+
if (segs) {
|
|
1308
|
+
let active;
|
|
1309
|
+
for (const seg of segs) {
|
|
1310
|
+
if (seg.t0 <= t) active = seg;
|
|
1311
|
+
else break;
|
|
1312
|
+
}
|
|
1313
|
+
if (active) {
|
|
1314
|
+
segStart = active.t0;
|
|
1315
|
+
if (t >= active.t1) {
|
|
1316
|
+
value = active.to;
|
|
1317
|
+
} else {
|
|
1318
|
+
const u = resolveEase(active.ease)((t - active.t0) / (active.t1 - active.t0));
|
|
1319
|
+
value = lerpValue(active.from, active.to, u);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
if (prop === "x" || prop === "y" || prop === "rotation") {
|
|
1324
|
+
const drivers = compiled.motionPaths.get(target);
|
|
1325
|
+
if (drivers) {
|
|
1326
|
+
let active;
|
|
1327
|
+
for (const d of drivers) {
|
|
1328
|
+
if (d.t0 <= t) active = d;
|
|
1329
|
+
else break;
|
|
1330
|
+
}
|
|
1331
|
+
if (active && active.t0 >= segStart && (prop !== "rotation" || active.autoRotate) && active.points.length > 0) {
|
|
1332
|
+
const span = active.t1 - active.t0;
|
|
1333
|
+
const u = span <= 0 ? 1 : resolveEase(active.ease)(Math.max(0, Math.min(1, (t - active.t0) / span)));
|
|
1334
|
+
if (prop === "x") value = pathPoint(active.points, active.closed, u, active.curviness)[0];
|
|
1335
|
+
else if (prop === "y") value = pathPoint(active.points, active.closed, u, active.curviness)[1];
|
|
1336
|
+
else value = pathTangentAngle(active.points, active.closed, u, active.curviness) + active.rotateOffset;
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
for (const b of compiled.ir.behaviors ?? []) {
|
|
1341
|
+
if (b.target === target && b.prop === prop && typeof value === "number") {
|
|
1342
|
+
const envelope = behaviorEnvelope(b, t);
|
|
1343
|
+
if (envelope > 0) value = value + envelope * sampleBehavior(b.behavior, t);
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
return value;
|
|
1347
|
+
}
|
|
1348
|
+
function nodeParentMatrix(compiled, id, t) {
|
|
1349
|
+
const num2 = (target, prop, fallback) => {
|
|
1350
|
+
const v = sampleProp(compiled, t, target, prop, fallback);
|
|
1351
|
+
return typeof v === "number" ? v : fallback;
|
|
1352
|
+
};
|
|
1353
|
+
let result = null;
|
|
1354
|
+
const walk = (node, parent) => {
|
|
1355
|
+
if (node.id === id) {
|
|
1356
|
+
result = parent;
|
|
1357
|
+
return true;
|
|
1358
|
+
}
|
|
1359
|
+
if (node.type === "group") {
|
|
1360
|
+
const m = multiply(
|
|
1361
|
+
parent,
|
|
1362
|
+
localMatrix(
|
|
1363
|
+
num2(node.id, "x", node.props.x),
|
|
1364
|
+
num2(node.id, "y", node.props.y),
|
|
1365
|
+
num2(node.id, "rotation", node.props.rotation ?? 0),
|
|
1366
|
+
num2(node.id, "scale", node.props.scale ?? 1),
|
|
1367
|
+
num2(node.id, "scaleX", node.props.scaleX ?? 1),
|
|
1368
|
+
num2(node.id, "scaleY", node.props.scaleY ?? 1),
|
|
1369
|
+
num2(node.id, "skewX", node.props.skewX ?? 0),
|
|
1370
|
+
num2(node.id, "skewY", node.props.skewY ?? 0)
|
|
1371
|
+
)
|
|
1372
|
+
);
|
|
1373
|
+
for (const child of node.children) if (walk(child, m)) return true;
|
|
1374
|
+
}
|
|
1375
|
+
return false;
|
|
1376
|
+
};
|
|
1377
|
+
for (const node of compiled.ir.nodes) if (walk(node, IDENTITY)) break;
|
|
1378
|
+
return result;
|
|
1379
|
+
}
|
|
1380
|
+
var IDENTITY, DEG;
|
|
1381
|
+
var init_evaluate = __esm({
|
|
1382
|
+
"../core/src/evaluate.ts"() {
|
|
1383
|
+
"use strict";
|
|
1384
|
+
init_behaviors();
|
|
1385
|
+
init_camera();
|
|
1386
|
+
init_gradient();
|
|
1387
|
+
init_interpolate();
|
|
1388
|
+
init_path();
|
|
1389
|
+
IDENTITY = [1, 0, 0, 1, 0, 0];
|
|
1390
|
+
DEG = Math.PI / 180;
|
|
1391
|
+
}
|
|
1392
|
+
});
|
|
1393
|
+
|
|
1394
|
+
// ../core/src/autoFoley.ts
|
|
1395
|
+
function nodeSize(node) {
|
|
1396
|
+
const p = node.props;
|
|
1397
|
+
return Math.max(p.width ?? 0, p.height ?? 0, (p.radius ?? 0) * 2, p.fontSize ?? 0, 0);
|
|
1398
|
+
}
|
|
1399
|
+
function autoFoley(compiled, opts = {}) {
|
|
1400
|
+
const master = opts.gain ?? 0.5;
|
|
1401
|
+
const sens = opts.sensitivity ?? 1;
|
|
1402
|
+
const wantWhoosh = opts.whoosh !== false;
|
|
1403
|
+
const wantImpact = opts.impact !== false;
|
|
1404
|
+
const wantPop = opts.pop !== false;
|
|
1405
|
+
const wantPan = opts.pan !== false;
|
|
1406
|
+
const vMin = V_MIN / sens, vStop = V_STOP, vDecel = V_DECEL / sens;
|
|
1407
|
+
const fps = compiled.ir.fps ?? 30;
|
|
1408
|
+
const N = Math.max(1, Math.ceil(compiled.duration * fps));
|
|
1409
|
+
const W = compiled.ir.size.width || 1920;
|
|
1410
|
+
const ids = opts.nodes ?? [...compiled.nodeById.keys()];
|
|
1411
|
+
const cands = [];
|
|
1412
|
+
const panOf = (x) => wantPan ? Math.max(-1, Math.min(1, x / W * 2 - 1)) : 0;
|
|
1413
|
+
const loud = (v) => Math.max(0.2, Math.min(1, (v - vMin) / (V_MAX - vMin)));
|
|
1414
|
+
for (const id of ids) {
|
|
1415
|
+
const node = compiled.nodeById.get(id);
|
|
1416
|
+
if (!node || node.type === "line") continue;
|
|
1417
|
+
const size = nodeSize(node);
|
|
1418
|
+
const xs = [], ys = [], ss = [], os = [];
|
|
1419
|
+
for (let i2 = 0; i2 <= N; i2++) {
|
|
1420
|
+
const t = i2 / fps;
|
|
1421
|
+
xs.push(num(compiled, t, id, "x", node.props.x ?? 0));
|
|
1422
|
+
ys.push(num(compiled, t, id, "y", node.props.y ?? 0));
|
|
1423
|
+
ss.push(num(compiled, t, id, "scale", node.props.scale ?? 1));
|
|
1424
|
+
os.push(num(compiled, t, id, "opacity", node.props.opacity ?? 1));
|
|
1425
|
+
}
|
|
1426
|
+
const speed = (i2) => i2 <= 0 ? 0 : Math.hypot(xs[i2] - xs[i2 - 1], ys[i2] - ys[i2 - 1]) * fps;
|
|
1427
|
+
const worldX = (frame) => {
|
|
1428
|
+
const m = nodeParentMatrix(compiled, id, frame / fps);
|
|
1429
|
+
return m ? m[0] * xs[frame] + m[2] * ys[frame] + m[4] : xs[frame];
|
|
1430
|
+
};
|
|
1431
|
+
let i = 1;
|
|
1432
|
+
while (i <= N) {
|
|
1433
|
+
if (speed(i) <= vMin) {
|
|
1434
|
+
i++;
|
|
1435
|
+
continue;
|
|
1436
|
+
}
|
|
1437
|
+
const a = i;
|
|
1438
|
+
let peak = i, peakV = speed(i);
|
|
1439
|
+
while (i <= N && speed(i) > vStop) {
|
|
1440
|
+
const s = speed(i);
|
|
1441
|
+
if (s > peakV) {
|
|
1442
|
+
peakV = s;
|
|
1443
|
+
peak = i;
|
|
1444
|
+
}
|
|
1445
|
+
i++;
|
|
1446
|
+
}
|
|
1447
|
+
const b = i - 1;
|
|
1448
|
+
const durS = (b - a + 1) / fps;
|
|
1449
|
+
const visible = os[peak] > 0.1;
|
|
1450
|
+
if (peakV > vMin && durS >= MIN_DUR && visible) {
|
|
1451
|
+
if (wantWhoosh) {
|
|
1452
|
+
const quickFlick = durS < 0.25;
|
|
1453
|
+
cands.push({ t: peak / fps, sfx: quickFlick ? "swish" : "whoosh", gain: master * loud(peakV), pan: panOf(worldX(peak)), rank: peakV });
|
|
1454
|
+
}
|
|
1455
|
+
const stopped = b >= N || speed(b + 1) < vStop && speed(Math.min(N, b + 2)) < vStop;
|
|
1456
|
+
const wxb = worldX(b);
|
|
1457
|
+
const landsOnScreen = wxb >= 0 && wxb <= W && os[b] > 0.1;
|
|
1458
|
+
if (wantImpact && peakV > vDecel && stopped && landsOnScreen && b < N) {
|
|
1459
|
+
cands.push({ t: (b + 1) / fps, sfx: size > 220 ? "thud" : "knock", gain: master * loud(peakV), pan: panOf(worldX(b)), rank: peakV * 1.1 });
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
if (wantPop && ss[0] < 0.25) {
|
|
1464
|
+
for (let k = 1; k <= N; k++) {
|
|
1465
|
+
if (ss[k - 1] < 0.5 && ss[k] >= 0.5 && os[k] > 0.05) {
|
|
1466
|
+
cands.push({ t: k / fps, sfx: "pop", gain: master * 0.7, pan: panOf(worldX(k)), rank: 600 });
|
|
1467
|
+
break;
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
cands.sort((p, q) => q.rank - p.rank);
|
|
1473
|
+
const kept = [];
|
|
1474
|
+
for (const c of cands) {
|
|
1475
|
+
const fam = FAMILY[c.sfx] ?? c.sfx;
|
|
1476
|
+
if (kept.some((k) => (FAMILY[k.sfx] ?? k.sfx) === fam && Math.abs(k.t - c.t) < DEDUP_DT)) continue;
|
|
1477
|
+
kept.push(c);
|
|
1478
|
+
}
|
|
1479
|
+
const max = opts.maxCues ?? 32;
|
|
1480
|
+
return kept.slice(0, max).map((c) => ({
|
|
1481
|
+
at: Number(c.t.toFixed(3)),
|
|
1482
|
+
sfx: c.sfx,
|
|
1483
|
+
gain: Number(c.gain.toFixed(3)),
|
|
1484
|
+
...c.pan !== 0 ? { pan: Number(c.pan.toFixed(3)) } : {}
|
|
1485
|
+
}));
|
|
1486
|
+
}
|
|
1487
|
+
var V_MIN, V_STOP, V_DECEL, V_MAX, MIN_DUR, num, FAMILY, DEDUP_DT;
|
|
1488
|
+
var init_autoFoley = __esm({
|
|
1489
|
+
"../core/src/autoFoley.ts"() {
|
|
1490
|
+
"use strict";
|
|
1491
|
+
init_evaluate();
|
|
1492
|
+
V_MIN = 360;
|
|
1493
|
+
V_STOP = 60;
|
|
1494
|
+
V_DECEL = 520;
|
|
1495
|
+
V_MAX = 2600;
|
|
1496
|
+
MIN_DUR = 0.1;
|
|
1497
|
+
num = (c, t, id, prop, fb) => {
|
|
1498
|
+
const v = sampleProp(c, t, id, prop, fb);
|
|
1499
|
+
return typeof v === "number" ? v : fb;
|
|
1500
|
+
};
|
|
1501
|
+
FAMILY = { whoosh: "move", swish: "move", thud: "hit", knock: "hit", pop: "pop" };
|
|
1502
|
+
DEDUP_DT = 0.09;
|
|
1503
|
+
}
|
|
1504
|
+
});
|
|
1505
|
+
|
|
1112
1506
|
// ../core/src/effects.ts
|
|
1113
1507
|
var init_effects = __esm({
|
|
1114
1508
|
"../core/src/effects.ts"() {
|
|
@@ -1403,11 +1797,13 @@ function resolveAudioPlan(compiled) {
|
|
|
1403
1797
|
const warnings = [];
|
|
1404
1798
|
const duration = compiled.duration;
|
|
1405
1799
|
const clipAudio = collectClipAudio(compiled.ir, duration, warnings);
|
|
1406
|
-
|
|
1800
|
+
const autoCues = audio?.autoFoley ? autoFoley(compiled, audio.autoFoley === true ? {} : audio.autoFoley) : [];
|
|
1801
|
+
const manualCues = [...audio?.cues ?? [], ...autoCues];
|
|
1802
|
+
if (!audio || !audio.bgm && manualCues.length === 0) {
|
|
1407
1803
|
return clipAudio.length === 0 ? null : { duration, bgm: null, cues: [], duckWindows: [], clipAudio, warnings };
|
|
1408
1804
|
}
|
|
1409
1805
|
const cues = [];
|
|
1410
|
-
for (const [index, cue] of
|
|
1806
|
+
for (const [index, cue] of manualCues.entries()) {
|
|
1411
1807
|
let anchor;
|
|
1412
1808
|
if (typeof cue.at === "number") {
|
|
1413
1809
|
anchor = cue.at;
|
|
@@ -1481,6 +1877,7 @@ var SFX_DURATION, FILE_CUE_DURATION;
|
|
|
1481
1877
|
var init_audio = __esm({
|
|
1482
1878
|
"../core/src/audio.ts"() {
|
|
1483
1879
|
"use strict";
|
|
1880
|
+
init_autoFoley();
|
|
1484
1881
|
SFX_DURATION = {
|
|
1485
1882
|
// transition
|
|
1486
1883
|
whoosh: 0.35,
|
|
@@ -1527,27 +1924,6 @@ var init_audio = __esm({
|
|
|
1527
1924
|
}
|
|
1528
1925
|
});
|
|
1529
1926
|
|
|
1530
|
-
// ../core/src/behaviors.ts
|
|
1531
|
-
var init_behaviors = __esm({
|
|
1532
|
-
"../core/src/behaviors.ts"() {
|
|
1533
|
-
"use strict";
|
|
1534
|
-
}
|
|
1535
|
-
});
|
|
1536
|
-
|
|
1537
|
-
// ../core/src/evaluate.ts
|
|
1538
|
-
var DEG;
|
|
1539
|
-
var init_evaluate = __esm({
|
|
1540
|
-
"../core/src/evaluate.ts"() {
|
|
1541
|
-
"use strict";
|
|
1542
|
-
init_behaviors();
|
|
1543
|
-
init_camera();
|
|
1544
|
-
init_gradient();
|
|
1545
|
-
init_interpolate();
|
|
1546
|
-
init_path();
|
|
1547
|
-
DEG = Math.PI / 180;
|
|
1548
|
-
}
|
|
1549
|
-
});
|
|
1550
|
-
|
|
1551
1927
|
// ../core/src/assets.ts
|
|
1552
1928
|
function collectSrcs(ir, type) {
|
|
1553
1929
|
const srcs = /* @__PURE__ */ new Set();
|
|
@@ -1611,6 +1987,7 @@ var init_src = __esm({
|
|
|
1611
1987
|
init_compile();
|
|
1612
1988
|
init_path();
|
|
1613
1989
|
init_camera();
|
|
1990
|
+
init_autoFoley();
|
|
1614
1991
|
init_gradient();
|
|
1615
1992
|
init_effects();
|
|
1616
1993
|
init_layout();
|
|
@@ -1810,7 +2187,7 @@ var init_wav = __esm({
|
|
|
1810
2187
|
});
|
|
1811
2188
|
|
|
1812
2189
|
// ../render-cli/src/audio/synth.ts
|
|
1813
|
-
function
|
|
2190
|
+
function hash012(n, seed) {
|
|
1814
2191
|
let h = n * 374761393 + seed * 668265263 | 0;
|
|
1815
2192
|
h = h ^ h >>> 13 | 0;
|
|
1816
2193
|
h = Math.imul(h, 1274126177);
|
|
@@ -2056,7 +2433,7 @@ function sparkle(seed, pitch) {
|
|
|
2056
2433
|
const on = u * steps.length - g;
|
|
2057
2434
|
if (on > 0 && on < 3) {
|
|
2058
2435
|
const ge = Math.exp(-on * 1.8);
|
|
2059
|
-
s += Math.sin(TAU * base * steps[g] * t +
|
|
2436
|
+
s += Math.sin(TAU * base * steps[g] * t + hash012(g, seed) * TAU) * ge;
|
|
2060
2437
|
}
|
|
2061
2438
|
}
|
|
2062
2439
|
out[i] = s / 2.4 * Math.sin(Math.PI * u) ** 0.5 * 0.5;
|
|
@@ -2083,9 +2460,9 @@ function shimmer(seed, pitch) {
|
|
|
2083
2460
|
const dur2 = 0.9;
|
|
2084
2461
|
const { out, n } = buffer(dur2);
|
|
2085
2462
|
const partials = Array.from({ length: 5 }, (_, p) => ({
|
|
2086
|
-
freq: (2e3 +
|
|
2087
|
-
am: 0.5 +
|
|
2088
|
-
phase:
|
|
2463
|
+
freq: (2e3 + hash012(p, seed + 7) * 2e3) * pitch,
|
|
2464
|
+
am: 0.5 + hash012(p, seed + 8) * 1.5,
|
|
2465
|
+
phase: hash012(p, seed + 9) * TAU
|
|
2089
2466
|
}));
|
|
2090
2467
|
for (let i = 0; i < n; i++) {
|
|
2091
2468
|
const t = i / SAMPLE_RATE, u = t / dur2;
|
|
@@ -2146,8 +2523,8 @@ function glitch(seed, pitch) {
|
|
|
2146
2523
|
for (let i = 0; i < n; i++) {
|
|
2147
2524
|
const t = i / SAMPLE_RATE, u = t / dur2;
|
|
2148
2525
|
const c = Math.floor(i / cell);
|
|
2149
|
-
const on =
|
|
2150
|
-
const freq = 400 * pitch * (1 + Math.floor(
|
|
2526
|
+
const on = hash012(c, seed) > 0.4 ? 1 : 0;
|
|
2527
|
+
const freq = 400 * pitch * (1 + Math.floor(hash012(c, seed + 1) * 6));
|
|
2151
2528
|
phase += TAU * freq / SAMPLE_RATE;
|
|
2152
2529
|
const crush = Math.round(square(phase) * 4) / 4;
|
|
2153
2530
|
out[i] = (crush * 0.7 + noise(i, seed + c) * 0.3) * on * (1 - u * 0.3) * 0.55;
|
|
@@ -2306,8 +2683,8 @@ function synthSfx(name, params = {}) {
|
|
|
2306
2683
|
function pad(freqs, duration, seed, opts) {
|
|
2307
2684
|
const { out, n } = buffer(duration);
|
|
2308
2685
|
const voices = freqs.flatMap((f, v) => [
|
|
2309
|
-
{ freq: f * (1 + (
|
|
2310
|
-
{ freq: f * (1 - (
|
|
2686
|
+
{ freq: f * (1 + (hash012(v, seed + 3) - 0.5) * 4e-3), am: opts.amBase + hash012(v, seed + 4) * 0.08, phase: hash012(v, seed + 5) * TAU },
|
|
2687
|
+
{ freq: f * (1 - (hash012(v, seed + 6) - 0.5) * 4e-3), am: opts.amBase + hash012(v, seed + 7) * 0.08, phase: hash012(v, seed + 8) * TAU }
|
|
2311
2688
|
]);
|
|
2312
2689
|
for (let i = 0; i < n; i++) {
|
|
2313
2690
|
const t = i / SAMPLE_RATE;
|
|
@@ -2346,8 +2723,8 @@ function synthTension(duration, seed = 0) {
|
|
|
2346
2723
|
const drift = 1 + 0.03 * (t / Math.max(1e-3, duration));
|
|
2347
2724
|
let s = 0;
|
|
2348
2725
|
for (let v = 0; v < base.length; v++) {
|
|
2349
|
-
const f = base[v] * drift * (1 + (
|
|
2350
|
-
s += Math.sin(TAU * f * t +
|
|
2726
|
+
const f = base[v] * drift * (1 + (hash012(v, seed) - 0.5) * 6e-3);
|
|
2727
|
+
s += Math.sin(TAU * f * t + hash012(v, seed + 1) * TAU);
|
|
2351
2728
|
}
|
|
2352
2729
|
const swell = 0.6 + 0.4 * Math.sin(TAU * 0.08 * t);
|
|
2353
2730
|
out[i] = s / base.length * swell * 0.6;
|
|
@@ -2365,7 +2742,7 @@ var init_synth = __esm({
|
|
|
2365
2742
|
"../render-cli/src/audio/synth.ts"() {
|
|
2366
2743
|
"use strict";
|
|
2367
2744
|
init_wav();
|
|
2368
|
-
noise = (n, seed) =>
|
|
2745
|
+
noise = (n, seed) => hash012(n, seed) * 2 - 1;
|
|
2369
2746
|
TAU = Math.PI * 2;
|
|
2370
2747
|
expDecay = (t, dur2, k = 5) => Math.exp(-k * t / dur2);
|
|
2371
2748
|
square = (ph) => (Math.sin(ph) + 0.33 * Math.sin(3 * ph) + 0.2 * Math.sin(5 * ph)) / 1.4;
|
|
@@ -3616,15 +3993,15 @@ ${USAGE}`);
|
|
|
3616
3993
|
preflightFfmpeg();
|
|
3617
3994
|
const { tmpdir: tmpdir6 } = await import("node:os");
|
|
3618
3995
|
const { resolveLogo: resolveLogo2, buildLogoSting: buildLogoSting2 } = await Promise.resolve().then(() => (init_logoSting(), logoSting_exports));
|
|
3619
|
-
const
|
|
3996
|
+
const num2 = (k) => flags[k] !== void 0 ? Number(flags[k]) : void 0;
|
|
3620
3997
|
console.log(`loading logo: ${arg} \u2026`);
|
|
3621
3998
|
const { data, slug } = await resolveLogo2(arg, positional[1], {
|
|
3622
3999
|
motion: flags.motion,
|
|
3623
|
-
energy:
|
|
3624
|
-
speed:
|
|
3625
|
-
intensity:
|
|
4000
|
+
energy: num2("energy"),
|
|
4001
|
+
speed: num2("speed"),
|
|
4002
|
+
intensity: num2("intensity"),
|
|
3626
4003
|
from: flags.from,
|
|
3627
|
-
seed:
|
|
4004
|
+
seed: num2("seed")
|
|
3628
4005
|
});
|
|
3629
4006
|
const sceneIR = buildLogoSting2(data);
|
|
3630
4007
|
const tmp = join9(tmpdir6(), `reframe-logo-${slug}-${process.pid}.json`);
|
package/dist/browserEntry.js
CHANGED
|
@@ -549,14 +549,6 @@
|
|
|
549
549
|
return [a, b, c, d, W / 2 - a * x - c * y, H / 2 - b * x - d * y];
|
|
550
550
|
}
|
|
551
551
|
|
|
552
|
-
// ../core/src/gradient.ts
|
|
553
|
-
function isGradient(p) {
|
|
554
|
-
return typeof p === "object" && p !== null && (p.kind === "linear" || p.kind === "radial" || p.kind === "conic");
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
// ../core/src/presets.ts
|
|
558
|
-
var SET = 1 / 120;
|
|
559
|
-
|
|
560
552
|
// ../core/src/behaviors.ts
|
|
561
553
|
function sampleBehavior(b, t) {
|
|
562
554
|
switch (b.name) {
|
|
@@ -586,6 +578,11 @@
|
|
|
586
578
|
return h / 4294967295;
|
|
587
579
|
}
|
|
588
580
|
|
|
581
|
+
// ../core/src/gradient.ts
|
|
582
|
+
function isGradient(p) {
|
|
583
|
+
return typeof p === "object" && p !== null && (p.kind === "linear" || p.kind === "radial" || p.kind === "conic");
|
|
584
|
+
}
|
|
585
|
+
|
|
589
586
|
// ../core/src/evaluate.ts
|
|
590
587
|
var IDENTITY = [1, 0, 0, 1, 0, 0];
|
|
591
588
|
function multiply(m, n) {
|
|
@@ -986,6 +983,9 @@
|
|
|
986
983
|
return ops;
|
|
987
984
|
}
|
|
988
985
|
|
|
986
|
+
// ../core/src/presets.ts
|
|
987
|
+
var SET = 1 / 120;
|
|
988
|
+
|
|
989
989
|
// ../renderer-canvas/src/index.ts
|
|
990
990
|
function resolvePaint(ctx2, paint, box) {
|
|
991
991
|
if (typeof paint === "string") return paint;
|