demobites 1.29.0 → 1.30.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/package.json +1 -1
- package/scripts/calibrate.mjs +4 -2
- package/scripts/trim.mjs +28 -5
package/package.json
CHANGED
package/scripts/calibrate.mjs
CHANGED
|
@@ -45,8 +45,10 @@ const tb = man.timebase;
|
|
|
45
45
|
// of it compounded two shifts (-0.71 then -1.67 on one take) and produced a
|
|
46
46
|
// clock that matched nothing. Re-base first, then anchor once.
|
|
47
47
|
if (tb && typeof man.record_from === "number") {
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
// The base keeps the take's speed (trim.mjs 1.30.0: one uniform compression to fit the plan): video = (wall - record_from) / speed.
|
|
49
|
+
const speed = typeof man.speed === "number" && man.speed > 0 ? man.speed : 1;
|
|
50
|
+
tb.a = 1 / speed; tb.k = 1; tb.speed = speed; tb.b = -man.record_from / speed; tb.videoRecordFrom = man.record_from;
|
|
51
|
+
tb.method = speed === 1 ? "identity (raw is wall-rate; see 2026-08-09 four-lane verification)" : `identity, then one uniform ${speed}x compression to fit the plan`;
|
|
50
52
|
}
|
|
51
53
|
if (!tb || typeof tb.a !== "number" || typeof tb.b !== "number") {
|
|
52
54
|
console.error("manifest.json has no timebase stamp. Run trim.mjs first.");
|
package/scripts/trim.mjs
CHANGED
|
@@ -129,21 +129,44 @@ if (lastStepEnd > r0) {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
if (cutAt !== r0 - beaconDelta) console.log("beacon: corrected cut clamped at 0 — head shorter than the anchor error");
|
|
132
|
+
|
|
133
|
+
// THE TAKE FITS ITS PLAN (founder 2026-10-18: "it's no shame to run it via ffmpeg and make it 1.4 times faster… planned
|
|
134
|
+
// 30, took 46 — make it 33 or 34"). When the filmed story runs past the storyboard's own clock, the whole take is
|
|
135
|
+
// sped up by ONE factor (1.5 at most) so it lands near the plan, and the timebase carries that factor: every stamped
|
|
136
|
+
// moment (steps, cursor, shots) maps through video = (wall - record_from) / speed, so nothing drifts. Not a rate
|
|
137
|
+
// fit (the identity law stands): a known, deliberate, uniform compression, recorded in the manifest.
|
|
138
|
+
let speed = 1;
|
|
139
|
+
try {
|
|
140
|
+
const { estimateTake } = await import("../skill/scripts/clock.mjs");
|
|
141
|
+
const sb = JSON.parse(fs.readFileSync(path.join(dir, "storyboard.json"), "utf8"));
|
|
142
|
+
const planned = estimateTake(sb.steps);
|
|
143
|
+
const filmed = lastStepEnd > r0 ? lastStepEnd - r0 + TAIL_BEAT_S : 0;
|
|
144
|
+
const target = planned * 1.1;
|
|
145
|
+
if (planned > 5 && filmed > target * 1.03) {
|
|
146
|
+
speed = Math.min(1.5, Math.round((filmed / target) * 100) / 100);
|
|
147
|
+
console.log(`speed: planned ${planned.toFixed(1)}s, filmed ${filmed.toFixed(1)}s — the take is sped up ${speed}x to ${(filmed / speed).toFixed(1)}s`);
|
|
148
|
+
void postEvent("finishing", { text: `Fitting the take to its plan (${speed}x)…` });
|
|
149
|
+
} else console.log(`speed: planned ${planned.toFixed(1)}s, filmed ${filmed.toFixed(1)}s — as filmed`);
|
|
150
|
+
} catch (e) {
|
|
151
|
+
console.log("speed: as filmed (" + String(e?.message ?? e).split("\n")[0] + ")");
|
|
152
|
+
}
|
|
153
|
+
man.speed = speed;
|
|
132
154
|
man.timebase = {
|
|
133
|
-
a: 1,
|
|
134
|
-
b: -r0,
|
|
135
|
-
method: "identity (raw is wall-rate; see 2026-08-09 four-lane verification)" + beaconMethod,
|
|
155
|
+
a: 1 / speed,
|
|
156
|
+
b: -r0 / speed,
|
|
157
|
+
method: (speed === 1 ? "identity (raw is wall-rate; see 2026-08-09 four-lane verification)" : `identity, then one uniform ${speed}x compression to fit the plan`) + beaconMethod,
|
|
136
158
|
k: 1,
|
|
159
|
+
speed,
|
|
137
160
|
videoRecordFrom: r0,
|
|
138
161
|
...(beaconMethod ? { beaconDelta } : {}),
|
|
139
162
|
};
|
|
140
163
|
fs.writeFileSync(manPath, JSON.stringify(man, null, 2));
|
|
141
|
-
console.log(`timebase:
|
|
164
|
+
console.log(`timebase: video = (wall - ${r0.toFixed(3)})${speed === 1 ? "" : ` / ${speed}`}${beaconMethod ? ` (cut at raw ${cutAt.toFixed(3)}s)` : ""}`);
|
|
142
165
|
|
|
143
166
|
execFileSync(FFMPEG(), [
|
|
144
167
|
"-y", "-loglevel", "error",
|
|
145
168
|
"-i", raw,
|
|
146
|
-
"-filter_complex", `[0:v]trim=${tailCut ? `start=${cutAt}:end=${tailCut}` : `start=${cutAt}`},setpts=PTS-STARTPTS,fps=30,format=yuv420p[out]`,
|
|
169
|
+
"-filter_complex", `[0:v]trim=${tailCut ? `start=${cutAt}:end=${tailCut}` : `start=${cutAt}`},setpts=(PTS-STARTPTS)/${speed},fps=30,format=yuv420p[out]`,
|
|
147
170
|
"-map", "[out]",
|
|
148
171
|
"-c:v", "libx264", "-preset", "medium", "-crf", "19",
|
|
149
172
|
"-movflags", "+faststart",
|