reframe-video 0.6.31 → 0.6.33
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/assets/sfx/LICENSE.md +5 -4
- package/dist/bin.js +359 -42
- package/dist/browserEntry.js +8 -8
- package/dist/cli.js +327 -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 +2289 -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 +13 -2
- package/package.json +1 -1
package/assets/sfx/LICENSE.md
CHANGED
|
@@ -21,7 +21,8 @@ Verified against each asset page's license field on 2026-06-11.
|
|
|
21
21
|
(The three `bgm-{synthwave,piano,battle}.mp3` are re-encoded to mono 96 kbps to keep the package small.)
|
|
22
22
|
|
|
23
23
|
CC0 requires no attribution; this file records provenance anyway.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
Six names (`whoosh`/`rise`/`shimmer`/`thud`/`pop`/`tick`) ship a curated `.wav`
|
|
25
|
+
that sounds better than the synth, so a bare `sfx:` uses that sample by default
|
|
26
|
+
(fixed — it doesn't pitch-vary); pass `params: { synth: 1 }` to force the varying
|
|
27
|
+
synth. Every other name synthesizes. Any `.wav`/`.ogg` here is also playable
|
|
28
|
+
directly via an explicit `file:` cue.
|
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,182 @@ var init_gradient = __esm({
|
|
|
1109
1262
|
}
|
|
1110
1263
|
});
|
|
1111
1264
|
|
|
1265
|
+
// ../core/src/evaluate.ts
|
|
1266
|
+
function behaviorEnvelope(b, t) {
|
|
1267
|
+
const from = b.from ?? Number.NEGATIVE_INFINITY;
|
|
1268
|
+
const until = b.until ?? Number.POSITIVE_INFINITY;
|
|
1269
|
+
if (t < from || t > until) return 0;
|
|
1270
|
+
const ramp = b.ramp ?? 0.2;
|
|
1271
|
+
let envelope = 1;
|
|
1272
|
+
if (Number.isFinite(from) && ramp > 0) envelope = Math.min(envelope, (t - from) / ramp);
|
|
1273
|
+
if (Number.isFinite(until) && ramp > 0) envelope = Math.min(envelope, (until - t) / ramp);
|
|
1274
|
+
return Math.max(0, Math.min(1, envelope));
|
|
1275
|
+
}
|
|
1276
|
+
function sampleProp(compiled, t, target, prop, fallback) {
|
|
1277
|
+
let value = compiled.initialValues.get(`${target}.${prop}`) ?? fallback;
|
|
1278
|
+
let segStart = Number.NEGATIVE_INFINITY;
|
|
1279
|
+
const segs = compiled.segments.get(`${target}.${prop}`);
|
|
1280
|
+
if (segs) {
|
|
1281
|
+
let active;
|
|
1282
|
+
for (const seg of segs) {
|
|
1283
|
+
if (seg.t0 <= t) active = seg;
|
|
1284
|
+
else break;
|
|
1285
|
+
}
|
|
1286
|
+
if (active) {
|
|
1287
|
+
segStart = active.t0;
|
|
1288
|
+
if (t >= active.t1) {
|
|
1289
|
+
value = active.to;
|
|
1290
|
+
} else {
|
|
1291
|
+
const u = resolveEase(active.ease)((t - active.t0) / (active.t1 - active.t0));
|
|
1292
|
+
value = lerpValue(active.from, active.to, u);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
if (prop === "x" || prop === "y" || prop === "rotation") {
|
|
1297
|
+
const drivers = compiled.motionPaths.get(target);
|
|
1298
|
+
if (drivers) {
|
|
1299
|
+
let active;
|
|
1300
|
+
for (const d of drivers) {
|
|
1301
|
+
if (d.t0 <= t) active = d;
|
|
1302
|
+
else break;
|
|
1303
|
+
}
|
|
1304
|
+
if (active && active.t0 >= segStart && (prop !== "rotation" || active.autoRotate) && active.points.length > 0) {
|
|
1305
|
+
const span = active.t1 - active.t0;
|
|
1306
|
+
const u = span <= 0 ? 1 : resolveEase(active.ease)(Math.max(0, Math.min(1, (t - active.t0) / span)));
|
|
1307
|
+
if (prop === "x") value = pathPoint(active.points, active.closed, u, active.curviness)[0];
|
|
1308
|
+
else if (prop === "y") value = pathPoint(active.points, active.closed, u, active.curviness)[1];
|
|
1309
|
+
else value = pathTangentAngle(active.points, active.closed, u, active.curviness) + active.rotateOffset;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
for (const b of compiled.ir.behaviors ?? []) {
|
|
1314
|
+
if (b.target === target && b.prop === prop && typeof value === "number") {
|
|
1315
|
+
const envelope = behaviorEnvelope(b, t);
|
|
1316
|
+
if (envelope > 0) value = value + envelope * sampleBehavior(b.behavior, t);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
return value;
|
|
1320
|
+
}
|
|
1321
|
+
var DEG;
|
|
1322
|
+
var init_evaluate = __esm({
|
|
1323
|
+
"../core/src/evaluate.ts"() {
|
|
1324
|
+
"use strict";
|
|
1325
|
+
init_behaviors();
|
|
1326
|
+
init_camera();
|
|
1327
|
+
init_gradient();
|
|
1328
|
+
init_interpolate();
|
|
1329
|
+
init_path();
|
|
1330
|
+
DEG = Math.PI / 180;
|
|
1331
|
+
}
|
|
1332
|
+
});
|
|
1333
|
+
|
|
1334
|
+
// ../core/src/autoFoley.ts
|
|
1335
|
+
function nodeSize(node) {
|
|
1336
|
+
const p = node.props;
|
|
1337
|
+
return Math.max(p.width ?? 0, p.height ?? 0, (p.radius ?? 0) * 2, p.fontSize ?? 0, 0);
|
|
1338
|
+
}
|
|
1339
|
+
function autoFoley(compiled, opts = {}) {
|
|
1340
|
+
const master = opts.gain ?? 0.5;
|
|
1341
|
+
const sens = opts.sensitivity ?? 1;
|
|
1342
|
+
const wantWhoosh = opts.whoosh !== false;
|
|
1343
|
+
const wantImpact = opts.impact !== false;
|
|
1344
|
+
const wantPop = opts.pop !== false;
|
|
1345
|
+
const wantPan = opts.pan !== false;
|
|
1346
|
+
const vMin = V_MIN / sens, vStop = V_STOP, vDecel = V_DECEL / sens;
|
|
1347
|
+
const fps = compiled.ir.fps ?? 30;
|
|
1348
|
+
const N = Math.max(1, Math.ceil(compiled.duration * fps));
|
|
1349
|
+
const W = compiled.ir.size.width || 1920;
|
|
1350
|
+
const ids = opts.nodes ?? [...compiled.nodeById.keys()];
|
|
1351
|
+
const cands = [];
|
|
1352
|
+
const panOf = (x) => wantPan ? Math.max(-1, Math.min(1, x / W * 2 - 1)) : 0;
|
|
1353
|
+
const loud = (v) => Math.max(0.2, Math.min(1, (v - vMin) / (V_MAX - vMin)));
|
|
1354
|
+
for (const id of ids) {
|
|
1355
|
+
const node = compiled.nodeById.get(id);
|
|
1356
|
+
if (!node || node.type === "line") continue;
|
|
1357
|
+
const size = nodeSize(node);
|
|
1358
|
+
const xs = [], ys = [], ss = [], os = [];
|
|
1359
|
+
for (let i2 = 0; i2 <= N; i2++) {
|
|
1360
|
+
const t = i2 / fps;
|
|
1361
|
+
xs.push(num(compiled, t, id, "x", node.props.x ?? 0));
|
|
1362
|
+
ys.push(num(compiled, t, id, "y", node.props.y ?? 0));
|
|
1363
|
+
ss.push(num(compiled, t, id, "scale", node.props.scale ?? 1));
|
|
1364
|
+
os.push(num(compiled, t, id, "opacity", node.props.opacity ?? 1));
|
|
1365
|
+
}
|
|
1366
|
+
const speed = (i2) => i2 <= 0 ? 0 : Math.hypot(xs[i2] - xs[i2 - 1], ys[i2] - ys[i2 - 1]) * fps;
|
|
1367
|
+
let i = 1;
|
|
1368
|
+
while (i <= N) {
|
|
1369
|
+
if (speed(i) <= vMin) {
|
|
1370
|
+
i++;
|
|
1371
|
+
continue;
|
|
1372
|
+
}
|
|
1373
|
+
const a = i;
|
|
1374
|
+
let peak = i, peakV = speed(i);
|
|
1375
|
+
while (i <= N && speed(i) > vStop) {
|
|
1376
|
+
const s = speed(i);
|
|
1377
|
+
if (s > peakV) {
|
|
1378
|
+
peakV = s;
|
|
1379
|
+
peak = i;
|
|
1380
|
+
}
|
|
1381
|
+
i++;
|
|
1382
|
+
}
|
|
1383
|
+
const b = i - 1;
|
|
1384
|
+
const durS = (b - a + 1) / fps;
|
|
1385
|
+
const visible = os[peak] > 0.1;
|
|
1386
|
+
if (peakV > vMin && durS >= MIN_DUR && visible) {
|
|
1387
|
+
if (wantWhoosh) {
|
|
1388
|
+
const quickFlick = durS < 0.25;
|
|
1389
|
+
cands.push({ t: peak / fps, sfx: quickFlick ? "swish" : "whoosh", gain: master * loud(peakV), pan: panOf(xs[peak]), rank: peakV });
|
|
1390
|
+
}
|
|
1391
|
+
const stopped = b >= N || speed(b + 1) < vStop && speed(Math.min(N, b + 2)) < vStop;
|
|
1392
|
+
const landsOnScreen = xs[b] >= 0 && xs[b] <= W && os[b] > 0.1;
|
|
1393
|
+
if (wantImpact && peakV > vDecel && stopped && landsOnScreen && b < N) {
|
|
1394
|
+
cands.push({ t: (b + 1) / fps, sfx: size > 220 ? "thud" : "knock", gain: master * loud(peakV), pan: panOf(xs[b]), rank: peakV * 1.1 });
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
if (wantPop && ss[0] < 0.25) {
|
|
1399
|
+
for (let k = 1; k <= N; k++) {
|
|
1400
|
+
if (ss[k - 1] < 0.5 && ss[k] >= 0.5 && os[k] > 0.05) {
|
|
1401
|
+
cands.push({ t: k / fps, sfx: "pop", gain: master * 0.7, pan: panOf(xs[k]), rank: 600 });
|
|
1402
|
+
break;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
cands.sort((p, q) => q.rank - p.rank);
|
|
1408
|
+
const kept = [];
|
|
1409
|
+
for (const c of cands) {
|
|
1410
|
+
const fam = FAMILY[c.sfx] ?? c.sfx;
|
|
1411
|
+
if (kept.some((k) => (FAMILY[k.sfx] ?? k.sfx) === fam && Math.abs(k.t - c.t) < DEDUP_DT)) continue;
|
|
1412
|
+
kept.push(c);
|
|
1413
|
+
}
|
|
1414
|
+
const max = opts.maxCues ?? 32;
|
|
1415
|
+
return kept.slice(0, max).map((c) => ({
|
|
1416
|
+
at: Number(c.t.toFixed(3)),
|
|
1417
|
+
sfx: c.sfx,
|
|
1418
|
+
gain: Number(c.gain.toFixed(3)),
|
|
1419
|
+
...c.pan !== 0 ? { pan: Number(c.pan.toFixed(3)) } : {}
|
|
1420
|
+
}));
|
|
1421
|
+
}
|
|
1422
|
+
var V_MIN, V_STOP, V_DECEL, V_MAX, MIN_DUR, num, FAMILY, DEDUP_DT;
|
|
1423
|
+
var init_autoFoley = __esm({
|
|
1424
|
+
"../core/src/autoFoley.ts"() {
|
|
1425
|
+
"use strict";
|
|
1426
|
+
init_evaluate();
|
|
1427
|
+
V_MIN = 360;
|
|
1428
|
+
V_STOP = 60;
|
|
1429
|
+
V_DECEL = 520;
|
|
1430
|
+
V_MAX = 2600;
|
|
1431
|
+
MIN_DUR = 0.1;
|
|
1432
|
+
num = (c, t, id, prop, fb) => {
|
|
1433
|
+
const v = sampleProp(c, t, id, prop, fb);
|
|
1434
|
+
return typeof v === "number" ? v : fb;
|
|
1435
|
+
};
|
|
1436
|
+
FAMILY = { whoosh: "move", swish: "move", thud: "hit", knock: "hit", pop: "pop" };
|
|
1437
|
+
DEDUP_DT = 0.09;
|
|
1438
|
+
}
|
|
1439
|
+
});
|
|
1440
|
+
|
|
1112
1441
|
// ../core/src/effects.ts
|
|
1113
1442
|
var init_effects = __esm({
|
|
1114
1443
|
"../core/src/effects.ts"() {
|
|
@@ -1403,11 +1732,13 @@ function resolveAudioPlan(compiled) {
|
|
|
1403
1732
|
const warnings = [];
|
|
1404
1733
|
const duration = compiled.duration;
|
|
1405
1734
|
const clipAudio = collectClipAudio(compiled.ir, duration, warnings);
|
|
1406
|
-
|
|
1735
|
+
const autoCues = audio?.autoFoley ? autoFoley(compiled, audio.autoFoley === true ? {} : audio.autoFoley) : [];
|
|
1736
|
+
const manualCues = [...audio?.cues ?? [], ...autoCues];
|
|
1737
|
+
if (!audio || !audio.bgm && manualCues.length === 0) {
|
|
1407
1738
|
return clipAudio.length === 0 ? null : { duration, bgm: null, cues: [], duckWindows: [], clipAudio, warnings };
|
|
1408
1739
|
}
|
|
1409
1740
|
const cues = [];
|
|
1410
|
-
for (const [index, cue] of
|
|
1741
|
+
for (const [index, cue] of manualCues.entries()) {
|
|
1411
1742
|
let anchor;
|
|
1412
1743
|
if (typeof cue.at === "number") {
|
|
1413
1744
|
anchor = cue.at;
|
|
@@ -1481,6 +1812,7 @@ var SFX_DURATION, FILE_CUE_DURATION;
|
|
|
1481
1812
|
var init_audio = __esm({
|
|
1482
1813
|
"../core/src/audio.ts"() {
|
|
1483
1814
|
"use strict";
|
|
1815
|
+
init_autoFoley();
|
|
1484
1816
|
SFX_DURATION = {
|
|
1485
1817
|
// transition
|
|
1486
1818
|
whoosh: 0.35,
|
|
@@ -1527,27 +1859,6 @@ var init_audio = __esm({
|
|
|
1527
1859
|
}
|
|
1528
1860
|
});
|
|
1529
1861
|
|
|
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
1862
|
// ../core/src/assets.ts
|
|
1552
1863
|
function collectSrcs(ir, type) {
|
|
1553
1864
|
const srcs = /* @__PURE__ */ new Set();
|
|
@@ -1611,6 +1922,7 @@ var init_src = __esm({
|
|
|
1611
1922
|
init_compile();
|
|
1612
1923
|
init_path();
|
|
1613
1924
|
init_camera();
|
|
1925
|
+
init_autoFoley();
|
|
1614
1926
|
init_gradient();
|
|
1615
1927
|
init_effects();
|
|
1616
1928
|
init_layout();
|
|
@@ -1810,7 +2122,7 @@ var init_wav = __esm({
|
|
|
1810
2122
|
});
|
|
1811
2123
|
|
|
1812
2124
|
// ../render-cli/src/audio/synth.ts
|
|
1813
|
-
function
|
|
2125
|
+
function hash012(n, seed) {
|
|
1814
2126
|
let h = n * 374761393 + seed * 668265263 | 0;
|
|
1815
2127
|
h = h ^ h >>> 13 | 0;
|
|
1816
2128
|
h = Math.imul(h, 1274126177);
|
|
@@ -2056,7 +2368,7 @@ function sparkle(seed, pitch) {
|
|
|
2056
2368
|
const on = u * steps.length - g;
|
|
2057
2369
|
if (on > 0 && on < 3) {
|
|
2058
2370
|
const ge = Math.exp(-on * 1.8);
|
|
2059
|
-
s += Math.sin(TAU * base * steps[g] * t +
|
|
2371
|
+
s += Math.sin(TAU * base * steps[g] * t + hash012(g, seed) * TAU) * ge;
|
|
2060
2372
|
}
|
|
2061
2373
|
}
|
|
2062
2374
|
out[i] = s / 2.4 * Math.sin(Math.PI * u) ** 0.5 * 0.5;
|
|
@@ -2083,9 +2395,9 @@ function shimmer(seed, pitch) {
|
|
|
2083
2395
|
const dur2 = 0.9;
|
|
2084
2396
|
const { out, n } = buffer(dur2);
|
|
2085
2397
|
const partials = Array.from({ length: 5 }, (_, p) => ({
|
|
2086
|
-
freq: (2e3 +
|
|
2087
|
-
am: 0.5 +
|
|
2088
|
-
phase:
|
|
2398
|
+
freq: (2e3 + hash012(p, seed + 7) * 2e3) * pitch,
|
|
2399
|
+
am: 0.5 + hash012(p, seed + 8) * 1.5,
|
|
2400
|
+
phase: hash012(p, seed + 9) * TAU
|
|
2089
2401
|
}));
|
|
2090
2402
|
for (let i = 0; i < n; i++) {
|
|
2091
2403
|
const t = i / SAMPLE_RATE, u = t / dur2;
|
|
@@ -2146,8 +2458,8 @@ function glitch(seed, pitch) {
|
|
|
2146
2458
|
for (let i = 0; i < n; i++) {
|
|
2147
2459
|
const t = i / SAMPLE_RATE, u = t / dur2;
|
|
2148
2460
|
const c = Math.floor(i / cell);
|
|
2149
|
-
const on =
|
|
2150
|
-
const freq = 400 * pitch * (1 + Math.floor(
|
|
2461
|
+
const on = hash012(c, seed) > 0.4 ? 1 : 0;
|
|
2462
|
+
const freq = 400 * pitch * (1 + Math.floor(hash012(c, seed + 1) * 6));
|
|
2151
2463
|
phase += TAU * freq / SAMPLE_RATE;
|
|
2152
2464
|
const crush = Math.round(square(phase) * 4) / 4;
|
|
2153
2465
|
out[i] = (crush * 0.7 + noise(i, seed + c) * 0.3) * on * (1 - u * 0.3) * 0.55;
|
|
@@ -2306,8 +2618,8 @@ function synthSfx(name, params = {}) {
|
|
|
2306
2618
|
function pad(freqs, duration, seed, opts) {
|
|
2307
2619
|
const { out, n } = buffer(duration);
|
|
2308
2620
|
const voices = freqs.flatMap((f, v) => [
|
|
2309
|
-
{ freq: f * (1 + (
|
|
2310
|
-
{ freq: f * (1 - (
|
|
2621
|
+
{ 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 },
|
|
2622
|
+
{ 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
2623
|
]);
|
|
2312
2624
|
for (let i = 0; i < n; i++) {
|
|
2313
2625
|
const t = i / SAMPLE_RATE;
|
|
@@ -2346,8 +2658,8 @@ function synthTension(duration, seed = 0) {
|
|
|
2346
2658
|
const drift = 1 + 0.03 * (t / Math.max(1e-3, duration));
|
|
2347
2659
|
let s = 0;
|
|
2348
2660
|
for (let v = 0; v < base.length; v++) {
|
|
2349
|
-
const f = base[v] * drift * (1 + (
|
|
2350
|
-
s += Math.sin(TAU * f * t +
|
|
2661
|
+
const f = base[v] * drift * (1 + (hash012(v, seed) - 0.5) * 6e-3);
|
|
2662
|
+
s += Math.sin(TAU * f * t + hash012(v, seed + 1) * TAU);
|
|
2351
2663
|
}
|
|
2352
2664
|
const swell = 0.6 + 0.4 * Math.sin(TAU * 0.08 * t);
|
|
2353
2665
|
out[i] = s / base.length * swell * 0.6;
|
|
@@ -2365,7 +2677,7 @@ var init_synth = __esm({
|
|
|
2365
2677
|
"../render-cli/src/audio/synth.ts"() {
|
|
2366
2678
|
"use strict";
|
|
2367
2679
|
init_wav();
|
|
2368
|
-
noise = (n, seed) =>
|
|
2680
|
+
noise = (n, seed) => hash012(n, seed) * 2 - 1;
|
|
2369
2681
|
TAU = Math.PI * 2;
|
|
2370
2682
|
expDecay = (t, dur2, k = 5) => Math.exp(-k * t / dur2);
|
|
2371
2683
|
square = (ph) => (Math.sin(ph) + 0.33 * Math.sin(3 * ph) + 0.2 * Math.sin(5 * ph)) / 1.4;
|
|
@@ -2453,6 +2765,10 @@ async function resolveCueFile(cue, sceneDir) {
|
|
|
2453
2765
|
);
|
|
2454
2766
|
}
|
|
2455
2767
|
const { name, params } = cue.source;
|
|
2768
|
+
if (SAMPLE_DEFAULT.has(name) && !params.synth) {
|
|
2769
|
+
const vendored = join(VENDORED, `${name}.wav`);
|
|
2770
|
+
if (existsSync2(vendored)) return vendored;
|
|
2771
|
+
}
|
|
2456
2772
|
return writeCached(`${name}-${fnv1a(JSON.stringify(params))}`, () => synthSfx(name, params));
|
|
2457
2773
|
}
|
|
2458
2774
|
async function resolveBgmFile(source, duration, sceneDir) {
|
|
@@ -2465,7 +2781,7 @@ async function resolveBgmFile(source, duration, sceneDir) {
|
|
|
2465
2781
|
}
|
|
2466
2782
|
return writeCached(`${source.name}-${duration.toFixed(2)}`, () => synthBgm(source.name, duration));
|
|
2467
2783
|
}
|
|
2468
|
-
var ROOT, VENDORED, CACHE;
|
|
2784
|
+
var ROOT, VENDORED, CACHE, SAMPLE_DEFAULT;
|
|
2469
2785
|
var init_sfx = __esm({
|
|
2470
2786
|
"../render-cli/src/audio/sfx.ts"() {
|
|
2471
2787
|
"use strict";
|
|
@@ -2474,6 +2790,7 @@ var init_sfx = __esm({
|
|
|
2474
2790
|
ROOT = true ? resolve(dirname(fileURLToPath(import.meta.url)), "..") : resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "..");
|
|
2475
2791
|
VENDORED = join(ROOT, "assets", "sfx");
|
|
2476
2792
|
CACHE = join(tmpdir(), "reframe-sfx-cache");
|
|
2793
|
+
SAMPLE_DEFAULT = /* @__PURE__ */ new Set(["whoosh", "rise", "shimmer", "thud", "pop", "tick"]);
|
|
2477
2794
|
}
|
|
2478
2795
|
});
|
|
2479
2796
|
|
|
@@ -3611,15 +3928,15 @@ ${USAGE}`);
|
|
|
3611
3928
|
preflightFfmpeg();
|
|
3612
3929
|
const { tmpdir: tmpdir6 } = await import("node:os");
|
|
3613
3930
|
const { resolveLogo: resolveLogo2, buildLogoSting: buildLogoSting2 } = await Promise.resolve().then(() => (init_logoSting(), logoSting_exports));
|
|
3614
|
-
const
|
|
3931
|
+
const num2 = (k) => flags[k] !== void 0 ? Number(flags[k]) : void 0;
|
|
3615
3932
|
console.log(`loading logo: ${arg} \u2026`);
|
|
3616
3933
|
const { data, slug } = await resolveLogo2(arg, positional[1], {
|
|
3617
3934
|
motion: flags.motion,
|
|
3618
|
-
energy:
|
|
3619
|
-
speed:
|
|
3620
|
-
intensity:
|
|
3935
|
+
energy: num2("energy"),
|
|
3936
|
+
speed: num2("speed"),
|
|
3937
|
+
intensity: num2("intensity"),
|
|
3621
3938
|
from: flags.from,
|
|
3622
|
-
seed:
|
|
3939
|
+
seed: num2("seed")
|
|
3623
3940
|
});
|
|
3624
3941
|
const sceneIR = buildLogoSting2(data);
|
|
3625
3942
|
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;
|