@bitmagic/cli 0.1.61-dev.0 → 0.1.61-dev.2
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/README.md +47 -8
- package/assets/fonts/NotoSans-Bold.ttf +0 -0
- package/assets/fonts/OFL.txt +94 -0
- package/dist/chrome-launch.d.ts +18 -0
- package/dist/chrome-launch.js +24 -0
- package/dist/chrome-launch.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/generate.d.ts +44 -0
- package/dist/commands/generate.js +143 -0
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/trailer-publish.d.ts +15 -0
- package/dist/commands/trailer-publish.js +45 -0
- package/dist/commands/trailer-publish.js.map +1 -0
- package/dist/commands/trailer.d.ts +3 -0
- package/dist/commands/trailer.js +396 -0
- package/dist/commands/trailer.js.map +1 -0
- package/dist/editor/hud-replay-page.d.ts +7 -0
- package/dist/editor/hud-replay-page.js +219 -0
- package/dist/editor/hud-replay-page.js.map +1 -0
- package/dist/editor/recording-panel.d.ts +3 -1
- package/dist/editor/recording-panel.js +6 -2
- package/dist/editor/recording-panel.js.map +1 -1
- package/dist/editor/recording-sink.d.ts +3 -20
- package/dist/editor/recording-sink.js +14 -35
- package/dist/editor/recording-sink.js.map +1 -1
- package/dist/editor/server.js +15 -18
- package/dist/editor/server.js.map +1 -1
- package/dist/editor/shell-page.d.ts +0 -8
- package/dist/editor/shell-page.js +23 -19
- package/dist/editor/shell-page.js.map +1 -1
- package/dist/generate/music.d.ts +51 -0
- package/dist/generate/music.js +93 -0
- package/dist/generate/music.js.map +1 -0
- package/dist/generate/stream.d.ts +13 -0
- package/dist/generate/stream.js +17 -1
- package/dist/generate/stream.js.map +1 -1
- package/dist/project/jobs.d.ts +1 -1
- package/dist/scaffold/project-files.d.ts +0 -1
- package/dist/scaffold/project-files.js +6 -33
- package/dist/scaffold/project-files.js.map +1 -1
- package/dist/scaffold/project.js +3 -1
- package/dist/scaffold/project.js.map +1 -1
- package/dist/scaffold/skill-files.d.ts +22 -0
- package/dist/scaffold/skill-files.js +198 -0
- package/dist/scaffold/skill-files.js.map +1 -0
- package/dist/trailer/analyze.d.ts +23 -0
- package/dist/trailer/analyze.js +186 -0
- package/dist/trailer/analyze.js.map +1 -0
- package/dist/trailer/auto-edl.d.ts +46 -0
- package/dist/trailer/auto-edl.js +148 -0
- package/dist/trailer/auto-edl.js.map +1 -0
- package/dist/trailer/beat-cut.d.ts +57 -0
- package/dist/trailer/beat-cut.js +232 -0
- package/dist/trailer/beat-cut.js.map +1 -0
- package/dist/trailer/client.d.ts +52 -0
- package/dist/trailer/client.js +133 -0
- package/dist/trailer/client.js.map +1 -0
- package/dist/trailer/edl-time.d.ts +61 -0
- package/dist/trailer/edl-time.js +105 -0
- package/dist/trailer/edl-time.js.map +1 -0
- package/dist/trailer/ffmpeg.d.ts +8 -0
- package/dist/trailer/ffmpeg.js +55 -0
- package/dist/trailer/ffmpeg.js.map +1 -0
- package/dist/trailer/hud-raster.d.ts +28 -0
- package/dist/trailer/hud-raster.js +114 -0
- package/dist/trailer/hud-raster.js.map +1 -0
- package/dist/trailer/hud-state.d.ts +110 -0
- package/dist/trailer/hud-state.js +410 -0
- package/dist/trailer/hud-state.js.map +1 -0
- package/dist/trailer/io.d.ts +20 -0
- package/dist/trailer/io.js +15 -0
- package/dist/trailer/io.js.map +1 -0
- package/dist/trailer/make.d.ts +54 -0
- package/dist/trailer/make.js +205 -0
- package/dist/trailer/make.js.map +1 -0
- package/dist/trailer/merge.d.ts +7 -0
- package/dist/trailer/merge.js +144 -0
- package/dist/trailer/merge.js.map +1 -0
- package/dist/trailer/music-beats.d.ts +123 -0
- package/dist/trailer/music-beats.js +707 -0
- package/dist/trailer/music-beats.js.map +1 -0
- package/dist/trailer/paths.d.ts +28 -0
- package/dist/trailer/paths.js +101 -0
- package/dist/trailer/paths.js.map +1 -0
- package/dist/trailer/publish-record.d.ts +17 -0
- package/dist/trailer/publish-record.js +59 -0
- package/dist/trailer/publish-record.js.map +1 -0
- package/dist/trailer/publish.d.ts +45 -0
- package/dist/trailer/publish.js +149 -0
- package/dist/trailer/publish.js.map +1 -0
- package/dist/trailer/record-session.d.ts +72 -0
- package/dist/trailer/record-session.js +331 -0
- package/dist/trailer/record-session.js.map +1 -0
- package/dist/trailer/render.d.ts +57 -0
- package/dist/trailer/render.js +475 -0
- package/dist/trailer/render.js.map +1 -0
- package/dist/trailer/revision.d.ts +8 -0
- package/dist/trailer/revision.js +31 -0
- package/dist/trailer/revision.js.map +1 -0
- package/dist/trailer/synth.d.ts +9 -0
- package/dist/trailer/synth.js +120 -0
- package/dist/trailer/synth.js.map +1 -0
- package/dist/trailer/timeline-types.d.ts +176 -0
- package/dist/trailer/timeline-types.js +379 -0
- package/dist/trailer/timeline-types.js.map +1 -0
- package/dist/trailer/title-raster.d.ts +6 -0
- package/dist/trailer/title-raster.js +47 -0
- package/dist/trailer/title-raster.js.map +1 -0
- package/dist/trailer/titles.d.ts +44 -0
- package/dist/trailer/titles.js +119 -0
- package/dist/trailer/titles.js.map +1 -0
- package/dist/trailer/video-chain.d.ts +41 -0
- package/dist/trailer/video-chain.js +78 -0
- package/dist/trailer/video-chain.js.map +1 -0
- package/dist/verify/browser.js +12 -19
- package/dist/verify/browser.js.map +1 -1
- package/package.json +5 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/trailer/analyze.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The first cut nobody had to author.
|
|
3
|
+
*
|
|
4
|
+
* `bitmagic trailer make` on a fresh recording has an analysis (scored highlight windows with
|
|
5
|
+
* contact sheets) and a target length, and must produce a watchable trailer with no shots file —
|
|
6
|
+
* so the agent has something to react to and tune, rather than a blank page. This module turns
|
|
7
|
+
* the analysis into a `ShotsFile` that follows the craft rules the make-trailer skill paid for:
|
|
8
|
+
*
|
|
9
|
+
* - shots run 1.5–3 s and VARY in length (a fixed pattern, so no two neighbours match);
|
|
10
|
+
* - the body is chronological — a first cut should tell the session's story, not shuffle it;
|
|
11
|
+
* - a forced window (`score`, `lap`, `goal`, `match-end`) is always in, and a match-end is
|
|
12
|
+
* pinned last so the end card dims over the finish;
|
|
13
|
+
* - every shot starts a little BEFORE its peak event, so the action lands inside the shot
|
|
14
|
+
* instead of on its first frame;
|
|
15
|
+
* - speed is 1.0 everywhere — slow motion reads as a low framerate on gameplay footage;
|
|
16
|
+
* - text is an end card only.
|
|
17
|
+
*
|
|
18
|
+
* When the analysis is thin (few events logged) the remaining slots are filled with evenly spaced
|
|
19
|
+
* shots across the recording, so every recording yields a trailer — a boring cut beats no cut, and
|
|
20
|
+
* the sheets let the agent replace shots in the next turn.
|
|
21
|
+
*/
|
|
22
|
+
import type { Analysis } from './timeline-types.js';
|
|
23
|
+
import type { BeatAnalysis } from './music-beats.js';
|
|
24
|
+
import type { ShotsFile } from './beat-cut.js';
|
|
25
|
+
/** Seconds per body shot, cycled. All inside the craft doc's 1.5–3 s band, never two alike in a row. */
|
|
26
|
+
export declare const SHOT_LENGTH_PATTERN_SEC: readonly number[];
|
|
27
|
+
export declare const END_CARD_SEC = 2.5;
|
|
28
|
+
/** How far before the peak event a shot begins, as a fraction of its length. */
|
|
29
|
+
export declare const LEAD_IN_FRACTION = 0.6;
|
|
30
|
+
/** Nothing in the first second: the game is still fading in from its menu. */
|
|
31
|
+
export declare const SKIP_LEADING_SEC = 1;
|
|
32
|
+
export declare const MIN_BEATS_PER_SHOT = 2;
|
|
33
|
+
export declare const MAX_BEATS_PER_SHOT = 8;
|
|
34
|
+
export interface AutoShotsInput {
|
|
35
|
+
analysis: Analysis;
|
|
36
|
+
recordingName: string;
|
|
37
|
+
/** Whole trailer including the end card, in seconds. */
|
|
38
|
+
targetSeconds: number;
|
|
39
|
+
/** When present, shot lengths become whole beats and the end card too. */
|
|
40
|
+
beats: BeatAnalysis | null;
|
|
41
|
+
title: string;
|
|
42
|
+
sub?: string;
|
|
43
|
+
/** Draw the HUD replay over every shot (the render's --ui). */
|
|
44
|
+
ui?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export declare function buildAutoShots(input: AutoShotsInput): ShotsFile;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { FORCED_EVENT_TYPES, eventWeight } from './analyze.js';
|
|
2
|
+
/** Seconds per body shot, cycled. All inside the craft doc's 1.5–3 s band, never two alike in a row. */
|
|
3
|
+
export const SHOT_LENGTH_PATTERN_SEC = [2, 1.5, 3, 2, 2.5, 1.5, 3];
|
|
4
|
+
export const END_CARD_SEC = 2.5;
|
|
5
|
+
/** How far before the peak event a shot begins, as a fraction of its length. */
|
|
6
|
+
export const LEAD_IN_FRACTION = 0.6;
|
|
7
|
+
/** Nothing in the first second: the game is still fading in from its menu. */
|
|
8
|
+
export const SKIP_LEADING_SEC = 1;
|
|
9
|
+
export const MIN_BEATS_PER_SHOT = 2;
|
|
10
|
+
export const MAX_BEATS_PER_SHOT = 8;
|
|
11
|
+
/** `"f3121 explosion i0.9"` -> the event's frame, type and weighted intensity. */
|
|
12
|
+
function parseDigest(line) {
|
|
13
|
+
const match = /^f(\d+)\s+(\S+)\s+i([\d.]+)$/.exec(line.trim());
|
|
14
|
+
if (match === null)
|
|
15
|
+
return null;
|
|
16
|
+
const intensity = Number(match[3]);
|
|
17
|
+
return {
|
|
18
|
+
frame: Number(match[1]),
|
|
19
|
+
type: match[2],
|
|
20
|
+
weighted: eventWeight(match[2]) * (Number.isFinite(intensity) ? intensity : 1),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function toCandidate(window) {
|
|
24
|
+
let best = null;
|
|
25
|
+
let forced = false;
|
|
26
|
+
for (const line of window.events) {
|
|
27
|
+
const event = parseDigest(line);
|
|
28
|
+
if (event === null)
|
|
29
|
+
continue;
|
|
30
|
+
if (FORCED_EVENT_TYPES.includes(event.type))
|
|
31
|
+
forced = true;
|
|
32
|
+
if (best === null || event.weighted > best.weighted)
|
|
33
|
+
best = event;
|
|
34
|
+
}
|
|
35
|
+
const mid = Math.round((window.startFrame + window.endFrame) / 2);
|
|
36
|
+
return {
|
|
37
|
+
window,
|
|
38
|
+
peakFrame: best?.frame ?? mid,
|
|
39
|
+
peakType: best?.type ?? 'none',
|
|
40
|
+
forced,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/** A shot's length in whole beats when there is a grid — rounding the seconds, clamped to the band. */
|
|
44
|
+
function beatsFor(seconds, beats) {
|
|
45
|
+
const beatSec = 60 / beats.bpm;
|
|
46
|
+
return Math.min(MAX_BEATS_PER_SHOT, Math.max(MIN_BEATS_PER_SHOT, Math.round(seconds / beatSec)));
|
|
47
|
+
}
|
|
48
|
+
/** Frame count a shot of `seconds` will occupy, including the slack a beat-snapped cut can add. */
|
|
49
|
+
function framesFor(seconds, fps, beats) {
|
|
50
|
+
const slack = beats !== null ? 60 / beats.bpm : 0;
|
|
51
|
+
return Math.ceil((seconds + slack) * fps);
|
|
52
|
+
}
|
|
53
|
+
function describe(candidate, fps) {
|
|
54
|
+
const sec = candidate.peakFrame / fps;
|
|
55
|
+
const mm = Math.floor(sec / 60);
|
|
56
|
+
const ss = Math.floor(sec % 60).toString().padStart(2, '0');
|
|
57
|
+
const types = new Set();
|
|
58
|
+
for (const line of candidate.window.events) {
|
|
59
|
+
const event = parseDigest(line);
|
|
60
|
+
if (event !== null && event.weighted > 0)
|
|
61
|
+
types.add(event.type);
|
|
62
|
+
}
|
|
63
|
+
const what = types.size > 0 ? [...types].slice(0, 3).join(' + ') : 'gameplay';
|
|
64
|
+
return `${what} @${mm}:${ss}`;
|
|
65
|
+
}
|
|
66
|
+
export function buildAutoShots(input) {
|
|
67
|
+
const { analysis, beats } = input;
|
|
68
|
+
const fps = analysis.fps;
|
|
69
|
+
const frameCount = analysis.frameCount;
|
|
70
|
+
const skipFrames = Math.round(SKIP_LEADING_SEC * fps);
|
|
71
|
+
const bodyBudget = Math.max(SHOT_LENGTH_PATTERN_SEC[0], input.targetSeconds - END_CARD_SEC);
|
|
72
|
+
const meanLen = SHOT_LENGTH_PATTERN_SEC.reduce((a, b) => a + b, 0) / SHOT_LENGTH_PATTERN_SEC.length;
|
|
73
|
+
const slots = Math.max(1, Math.floor(bodyBudget / meanLen));
|
|
74
|
+
// Candidates: every analysed window with its peak inside the usable range; forced ones first,
|
|
75
|
+
// then by score, so the k best are taken but a forced window is never dropped for a louder one.
|
|
76
|
+
const candidates = analysis.windows
|
|
77
|
+
.map(toCandidate)
|
|
78
|
+
.filter((c) => c.peakFrame >= skipFrames && c.peakFrame < frameCount)
|
|
79
|
+
.filter((c) => c.peakType !== 'state');
|
|
80
|
+
const ranked = [...candidates].sort((a, b) => {
|
|
81
|
+
if (a.forced !== b.forced)
|
|
82
|
+
return a.forced ? -1 : 1;
|
|
83
|
+
return b.window.score - a.window.score;
|
|
84
|
+
});
|
|
85
|
+
const chosen = ranked.slice(0, Math.min(slots, ranked.length));
|
|
86
|
+
// Fill: evenly spaced across the recording, skipping spots an ANALYSED window already covers.
|
|
87
|
+
// Only the analysed picks count as cover — a filler must never shadow the next filler, or a
|
|
88
|
+
// short recording (fillers closer together than the radius) loses every second slot.
|
|
89
|
+
const missing = slots - chosen.length;
|
|
90
|
+
if (missing > 0) {
|
|
91
|
+
const analysed = [...chosen];
|
|
92
|
+
const usable = frameCount - skipFrames;
|
|
93
|
+
const spacing = usable / missing;
|
|
94
|
+
const radius = Math.min(3 * fps, spacing / 2);
|
|
95
|
+
for (let i = 0; i < missing; i++) {
|
|
96
|
+
const frame = skipFrames + Math.round((i + 0.5) * spacing);
|
|
97
|
+
const covered = analysed.some((c) => Math.abs(c.peakFrame - frame) < radius);
|
|
98
|
+
const filler = {
|
|
99
|
+
window: { startFrame: frame, endFrame: frame, score: 0, events: [], sheet: '' },
|
|
100
|
+
peakFrame: frame,
|
|
101
|
+
peakType: 'none',
|
|
102
|
+
forced: false,
|
|
103
|
+
};
|
|
104
|
+
if (!covered)
|
|
105
|
+
chosen.push(filler);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Chronological, with a match-end pinned last.
|
|
109
|
+
chosen.sort((a, b) => a.peakFrame - b.peakFrame);
|
|
110
|
+
const endIndex = chosen.findIndex((c) => c.window.events.some((e) => parseDigest(e)?.type === 'match-end'));
|
|
111
|
+
if (endIndex >= 0 && endIndex !== chosen.length - 1) {
|
|
112
|
+
const [end] = chosen.splice(endIndex, 1);
|
|
113
|
+
chosen.push(end);
|
|
114
|
+
}
|
|
115
|
+
const shots = chosen.map((candidate, i) => {
|
|
116
|
+
const seconds = SHOT_LENGTH_PATTERN_SEC[i % SHOT_LENGTH_PATTERN_SEC.length];
|
|
117
|
+
const lenFrames = framesFor(seconds, fps, beats);
|
|
118
|
+
const ideal = candidate.peakFrame - Math.round(LEAD_IN_FRACTION * seconds * fps);
|
|
119
|
+
const start = Math.max(0, Math.min(ideal, frameCount - lenFrames));
|
|
120
|
+
const shot = { in: start, label: describe(candidate, fps) };
|
|
121
|
+
if (beats !== null)
|
|
122
|
+
shot.beats = beatsFor(seconds, beats);
|
|
123
|
+
else
|
|
124
|
+
shot.seconds = seconds;
|
|
125
|
+
if (input.ui === true)
|
|
126
|
+
shot.ui = true;
|
|
127
|
+
return shot;
|
|
128
|
+
});
|
|
129
|
+
// The end card sits over the last shot, so that shot must be long enough to carry it.
|
|
130
|
+
const last = shots[shots.length - 1];
|
|
131
|
+
if (beats !== null)
|
|
132
|
+
last.beats = Math.max(last.beats ?? 0, beatsFor(END_CARD_SEC, beats));
|
|
133
|
+
else
|
|
134
|
+
last.seconds = Math.max(last.seconds ?? 0, END_CARD_SEC);
|
|
135
|
+
last.in = Math.max(0, Math.min(last.in, frameCount - framesFor(last.seconds ?? END_CARD_SEC, fps, beats)));
|
|
136
|
+
const title = { at: 'last-clip', text: input.title.toUpperCase(), style: 'card' };
|
|
137
|
+
if (input.sub !== undefined)
|
|
138
|
+
title.sub = input.sub;
|
|
139
|
+
return {
|
|
140
|
+
version: 1,
|
|
141
|
+
recording: input.recordingName,
|
|
142
|
+
notes: 'First cut written by `bitmagic trailer make`. Edit freely: reorder, swap "in" frames for ' +
|
|
143
|
+
'better moments from analysis.json, change beats/seconds, add titles. Re-run make to render.',
|
|
144
|
+
shots,
|
|
145
|
+
titles: [title],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=auto-edl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-edl.js","sourceRoot":"","sources":["../../src/trailer/auto-edl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { BeatAnalysis } from './music-beats.js';
|
|
2
|
+
import type { TitleCue } from './titles.js';
|
|
3
|
+
import type { Edl } from './timeline-types.js';
|
|
4
|
+
export interface Shot {
|
|
5
|
+
/** Source frame the shot starts on. */
|
|
6
|
+
in: number;
|
|
7
|
+
/** Hold for this many beats (needs a beat grid). */
|
|
8
|
+
beats?: number;
|
|
9
|
+
/** Hold for this many seconds (used when there is no beat grid, or the shot has no `beats`). */
|
|
10
|
+
seconds?: number;
|
|
11
|
+
label: string;
|
|
12
|
+
/** Playback speed; the craft rule is 1.0 — slow-mo reads as a low framerate. */
|
|
13
|
+
speed?: number;
|
|
14
|
+
/** Draw (or suppress) the HUD replay over this shot; menus want `false`. */
|
|
15
|
+
ui?: boolean;
|
|
16
|
+
transition?: 'cut' | 'crossfade';
|
|
17
|
+
transitionDuration?: number;
|
|
18
|
+
}
|
|
19
|
+
/** A title whose `at` may be the literal `"last-clip"`; `dur` is then the last clip's length. */
|
|
20
|
+
export type ShotTitle = Omit<TitleCue, 'at' | 'dur'> & {
|
|
21
|
+
at: number | 'last-clip';
|
|
22
|
+
dur?: number;
|
|
23
|
+
};
|
|
24
|
+
export interface ShotsFile {
|
|
25
|
+
version: 1;
|
|
26
|
+
/** Name of the recording these frame indices were chosen from. */
|
|
27
|
+
recording?: string;
|
|
28
|
+
/** Free-form notes the author keeps with the cut (never read by the tool). */
|
|
29
|
+
notes?: string;
|
|
30
|
+
shots: Shot[];
|
|
31
|
+
titles?: ShotTitle[];
|
|
32
|
+
}
|
|
33
|
+
export interface CutOptions {
|
|
34
|
+
/** Frames in the recording; a shot that would run past the end is shifted earlier and reported. */
|
|
35
|
+
frameCount?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface CutResult {
|
|
38
|
+
edl: Edl;
|
|
39
|
+
/** Beats consumed from the downbeat (0 without a grid). */
|
|
40
|
+
beatsUsed: number;
|
|
41
|
+
totalSec: number;
|
|
42
|
+
/** Largest distance between a cut and its beat target, in ms (0 without a grid). */
|
|
43
|
+
worstCutErrorMs: number;
|
|
44
|
+
/** The first shot that did not fit in the track, when the grid ran out. */
|
|
45
|
+
truncatedAt?: string;
|
|
46
|
+
}
|
|
47
|
+
/** Parse a shots document: either a bare array of shots or `{ version, shots, titles? }`. */
|
|
48
|
+
export declare function parseShots(raw: unknown, source: string): ShotsFile;
|
|
49
|
+
export declare function loadShots(filePath: string): ShotsFile;
|
|
50
|
+
/**
|
|
51
|
+
* Turn shots into frame-exact clips. With `beats` every cut lands on the grid counted from the
|
|
52
|
+
* downbeat; without, each shot's `seconds` decides its length. Returns the EDL plus the numbers
|
|
53
|
+
* the command prints so the author can judge the fit.
|
|
54
|
+
*/
|
|
55
|
+
export declare function cutShots(shots: ShotsFile, beats: BeatAnalysis | null, fps: number, options?: CutOptions): CutResult;
|
|
56
|
+
/** The one-line summary `bitmagic trailer cut` prints, mirroring the Python script's. */
|
|
57
|
+
export declare function describeCut(result: CutResult, beats: BeatAnalysis | null): string;
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snap a shot list onto a beat grid (or plain seconds) and emit an EDL.
|
|
3
|
+
*
|
|
4
|
+
* A shot says WHICH source frame to start on and HOW LONG to hold, in beats when there is music
|
|
5
|
+
* and in seconds when there is not; this turns that into the frame-exact `edl.json` the renderer
|
|
6
|
+
* consumes. It is the TypeScript port of the make-trailer skill's `beat-edl.py`, so creators need
|
|
7
|
+
* no Python.
|
|
8
|
+
*
|
|
9
|
+
* Each cut's target time comes straight from the beat grid, and the frame count is the difference
|
|
10
|
+
* against the frames ACTUALLY emitted so far — not against the previous target. That matters for
|
|
11
|
+
* speed-ramped clips: at 0.5x the output length is forced to an even number of frames, so a clip
|
|
12
|
+
* whose beat-target is odd lands one frame long. Measuring from actual output makes the next clip
|
|
13
|
+
* absorb that frame instead of every later cut inheriting it.
|
|
14
|
+
*
|
|
15
|
+
* A title cue with `"at": "last-clip"` is resolved to cover the final clip (the end card), so it
|
|
16
|
+
* survives regeneration without hand-editing output times.
|
|
17
|
+
*/
|
|
18
|
+
import * as fs from 'fs';
|
|
19
|
+
import { CliError } from '../errors.js';
|
|
20
|
+
import { warn } from './io.js';
|
|
21
|
+
function isRecord(value) {
|
|
22
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
23
|
+
}
|
|
24
|
+
function finiteNumber(value, ctx) {
|
|
25
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
26
|
+
throw new CliError(`${ctx}: expected a number, got ${JSON.stringify(value)}`);
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
function parseShot(raw, index) {
|
|
31
|
+
const ctx = `shots[${index}]`;
|
|
32
|
+
if (!isRecord(raw))
|
|
33
|
+
throw new CliError(`${ctx}: expected an object`);
|
|
34
|
+
const shot = {
|
|
35
|
+
in: finiteNumber(raw.in, `${ctx}.in`),
|
|
36
|
+
label: typeof raw.label === 'string' && raw.label.length > 0 ? raw.label : `shot ${index + 1}`,
|
|
37
|
+
};
|
|
38
|
+
if (shot.in < 0 || !Number.isInteger(shot.in))
|
|
39
|
+
throw new CliError(`${ctx}.in: expected a frame index >= 0`);
|
|
40
|
+
if (raw.beats !== undefined) {
|
|
41
|
+
shot.beats = finiteNumber(raw.beats, `${ctx}.beats`);
|
|
42
|
+
if (shot.beats <= 0)
|
|
43
|
+
throw new CliError(`${ctx}.beats: must be > 0`);
|
|
44
|
+
}
|
|
45
|
+
if (raw.seconds !== undefined) {
|
|
46
|
+
shot.seconds = finiteNumber(raw.seconds, `${ctx}.seconds`);
|
|
47
|
+
if (shot.seconds <= 0)
|
|
48
|
+
throw new CliError(`${ctx}.seconds: must be > 0`);
|
|
49
|
+
}
|
|
50
|
+
if (shot.beats === undefined && shot.seconds === undefined) {
|
|
51
|
+
throw new CliError(`${ctx} ("${shot.label}"): needs "beats" (with music) or "seconds"`);
|
|
52
|
+
}
|
|
53
|
+
if (raw.speed !== undefined)
|
|
54
|
+
shot.speed = finiteNumber(raw.speed, `${ctx}.speed`);
|
|
55
|
+
if (raw.ui !== undefined) {
|
|
56
|
+
if (typeof raw.ui !== 'boolean')
|
|
57
|
+
throw new CliError(`${ctx}.ui: expected true or false`);
|
|
58
|
+
shot.ui = raw.ui;
|
|
59
|
+
}
|
|
60
|
+
if (raw.transition !== undefined) {
|
|
61
|
+
if (raw.transition !== 'cut' && raw.transition !== 'crossfade') {
|
|
62
|
+
throw new CliError(`${ctx}.transition: expected "cut" or "crossfade"`);
|
|
63
|
+
}
|
|
64
|
+
shot.transition = raw.transition;
|
|
65
|
+
}
|
|
66
|
+
if (raw.transitionDuration !== undefined) {
|
|
67
|
+
shot.transitionDuration = finiteNumber(raw.transitionDuration, `${ctx}.transitionDuration`);
|
|
68
|
+
}
|
|
69
|
+
return shot;
|
|
70
|
+
}
|
|
71
|
+
function parseTitle(raw, index) {
|
|
72
|
+
const ctx = `titles[${index}]`;
|
|
73
|
+
if (!isRecord(raw))
|
|
74
|
+
throw new CliError(`${ctx}: expected an object`);
|
|
75
|
+
if (typeof raw.text !== 'string')
|
|
76
|
+
throw new CliError(`${ctx}.text: expected a string`);
|
|
77
|
+
const title = { text: raw.text, at: 0 };
|
|
78
|
+
if (raw.at === 'last-clip')
|
|
79
|
+
title.at = 'last-clip';
|
|
80
|
+
else
|
|
81
|
+
title.at = finiteNumber(raw.at, `${ctx}.at`);
|
|
82
|
+
if (raw.dur !== undefined)
|
|
83
|
+
title.dur = finiteNumber(raw.dur, `${ctx}.dur`);
|
|
84
|
+
if (typeof raw.sub === 'string')
|
|
85
|
+
title.sub = raw.sub;
|
|
86
|
+
if (typeof raw.note === 'string')
|
|
87
|
+
title.note = raw.note;
|
|
88
|
+
if (raw.style === 'title' || raw.style === 'line' || raw.style === 'card')
|
|
89
|
+
title.style = raw.style;
|
|
90
|
+
return title;
|
|
91
|
+
}
|
|
92
|
+
/** Parse a shots document: either a bare array of shots or `{ version, shots, titles? }`. */
|
|
93
|
+
export function parseShots(raw, source) {
|
|
94
|
+
const shotsRaw = Array.isArray(raw) ? raw : isRecord(raw) ? raw.shots : undefined;
|
|
95
|
+
if (!Array.isArray(shotsRaw))
|
|
96
|
+
throw new CliError(`${source}: expected a "shots" array`);
|
|
97
|
+
if (shotsRaw.length === 0)
|
|
98
|
+
throw new CliError(`${source}: "shots" is empty — nothing to cut`);
|
|
99
|
+
const file = { version: 1, shots: shotsRaw.map(parseShot) };
|
|
100
|
+
if (isRecord(raw)) {
|
|
101
|
+
if (raw.version !== undefined && raw.version !== 1) {
|
|
102
|
+
throw new CliError(`${source}: unsupported version ${JSON.stringify(raw.version)} (this CLI writes version 1)`);
|
|
103
|
+
}
|
|
104
|
+
if (typeof raw.recording === 'string')
|
|
105
|
+
file.recording = raw.recording;
|
|
106
|
+
if (typeof raw.notes === 'string')
|
|
107
|
+
file.notes = raw.notes;
|
|
108
|
+
if (raw.titles !== undefined) {
|
|
109
|
+
if (!Array.isArray(raw.titles))
|
|
110
|
+
throw new CliError(`${source}: "titles" must be an array`);
|
|
111
|
+
file.titles = raw.titles.map(parseTitle);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return file;
|
|
115
|
+
}
|
|
116
|
+
export function loadShots(filePath) {
|
|
117
|
+
if (!fs.existsSync(filePath))
|
|
118
|
+
throw new CliError(`Shots file not found: ${filePath}`);
|
|
119
|
+
let raw;
|
|
120
|
+
try {
|
|
121
|
+
raw = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
throw new CliError(`Invalid JSON in ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
125
|
+
}
|
|
126
|
+
return parseShots(raw, filePath);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Turn shots into frame-exact clips. With `beats` every cut lands on the grid counted from the
|
|
130
|
+
* downbeat; without, each shot's `seconds` decides its length. Returns the EDL plus the numbers
|
|
131
|
+
* the command prints so the author can judge the fit.
|
|
132
|
+
*/
|
|
133
|
+
export function cutShots(shots, beats, fps, options = {}) {
|
|
134
|
+
if (!Number.isFinite(fps) || fps <= 0)
|
|
135
|
+
throw new CliError(`invalid fps: ${fps}`);
|
|
136
|
+
const grid = beats?.beatTimes ?? null;
|
|
137
|
+
const start = beats?.downbeatIndex ?? 0;
|
|
138
|
+
const t0 = grid !== null ? grid[start] : 0;
|
|
139
|
+
if (grid !== null && (t0 === undefined || grid.length < 2)) {
|
|
140
|
+
throw new CliError('The beat grid has too few beats to cut on — check the music file or pass --bpm.');
|
|
141
|
+
}
|
|
142
|
+
const clips = [];
|
|
143
|
+
let cum = start;
|
|
144
|
+
let emitted = 0;
|
|
145
|
+
let worst = 0;
|
|
146
|
+
let truncatedAt;
|
|
147
|
+
for (const shot of shots.shots) {
|
|
148
|
+
const speed = shot.speed ?? 1.0;
|
|
149
|
+
let need;
|
|
150
|
+
let suffix;
|
|
151
|
+
if (grid !== null && shot.beats !== undefined) {
|
|
152
|
+
const next = cum + shot.beats;
|
|
153
|
+
if (next >= grid.length) {
|
|
154
|
+
truncatedAt = shot.label;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
const target = Math.round((grid[next] - t0) * fps);
|
|
158
|
+
need = target - emitted;
|
|
159
|
+
cum = next;
|
|
160
|
+
suffix = `[${shot.beats}b]`;
|
|
161
|
+
}
|
|
162
|
+
else if (shot.seconds !== undefined) {
|
|
163
|
+
need = Math.round(shot.seconds * fps);
|
|
164
|
+
suffix = `[${shot.seconds}s]`;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
throw new CliError(`Shot "${shot.label}" is timed in beats but there is no beat grid — pass --music (or --beats), or give it "seconds".`);
|
|
168
|
+
}
|
|
169
|
+
const src = Math.max(1, Math.round(need * speed));
|
|
170
|
+
const actual = Math.round(src / speed);
|
|
171
|
+
emitted += actual;
|
|
172
|
+
if (grid !== null && shot.beats !== undefined) {
|
|
173
|
+
const target = Math.round((grid[cum] - t0) * fps);
|
|
174
|
+
worst = Math.max(worst, (Math.abs(emitted - target) / fps) * 1000);
|
|
175
|
+
}
|
|
176
|
+
let inFrame = shot.in;
|
|
177
|
+
if (options.frameCount !== undefined && inFrame + src > options.frameCount) {
|
|
178
|
+
const shifted = Math.max(0, options.frameCount - src);
|
|
179
|
+
warn(`shot "${shot.label}" runs past the recording's last frame — starting it at ${shifted} instead of ${inFrame}`);
|
|
180
|
+
inFrame = shifted;
|
|
181
|
+
}
|
|
182
|
+
const clip = {
|
|
183
|
+
in: inFrame,
|
|
184
|
+
out: inFrame + src,
|
|
185
|
+
speed,
|
|
186
|
+
transition: shot.transition ?? 'cut',
|
|
187
|
+
label: `${shot.label} ${suffix}`,
|
|
188
|
+
};
|
|
189
|
+
if (shot.transitionDuration !== undefined)
|
|
190
|
+
clip.transitionDuration = shot.transitionDuration;
|
|
191
|
+
if (shot.ui !== undefined)
|
|
192
|
+
clip.ui = shot.ui;
|
|
193
|
+
clips.push(clip);
|
|
194
|
+
}
|
|
195
|
+
if (clips.length === 0) {
|
|
196
|
+
throw new CliError(`Not a single shot fits the music: "${truncatedAt ?? shots.shots[0].label}" already runs past the end of the track.`);
|
|
197
|
+
}
|
|
198
|
+
const totalSec = emitted / fps;
|
|
199
|
+
const edl = { version: 1, targetDuration: Math.round(totalSec * 100) / 100, clips };
|
|
200
|
+
if (shots.titles !== undefined && shots.titles.length > 0) {
|
|
201
|
+
const last = clips[clips.length - 1];
|
|
202
|
+
const lastDur = Math.round(last.out - last.in) / ((last.speed ?? 1) * fps);
|
|
203
|
+
edl.titles = shots.titles.map((title) => {
|
|
204
|
+
const { at, dur, ...rest } = title;
|
|
205
|
+
if (at === 'last-clip') {
|
|
206
|
+
return { ...rest, at: Math.round((totalSec - lastDur) * 1000) / 1000, dur: Math.round(lastDur * 1000) / 1000 };
|
|
207
|
+
}
|
|
208
|
+
return { ...rest, at, dur: dur ?? 2.5 };
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
const result = {
|
|
212
|
+
edl,
|
|
213
|
+
beatsUsed: grid !== null ? cum - start : 0,
|
|
214
|
+
totalSec,
|
|
215
|
+
worstCutErrorMs: worst,
|
|
216
|
+
};
|
|
217
|
+
if (truncatedAt !== undefined)
|
|
218
|
+
result.truncatedAt = truncatedAt;
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
/** The one-line summary `bitmagic trailer cut` prints, mirroring the Python script's. */
|
|
222
|
+
export function describeCut(result, beats) {
|
|
223
|
+
const parts = [
|
|
224
|
+
beats !== null ? `bpm=${beats.bpm.toFixed(2)}` : 'no beat grid',
|
|
225
|
+
`clips=${result.edl.clips.length}`,
|
|
226
|
+
beats !== null ? `beats=${result.beatsUsed}` : null,
|
|
227
|
+
`total=${result.totalSec.toFixed(3)}s`,
|
|
228
|
+
beats !== null ? `worst cut error=${result.worstCutErrorMs.toFixed(1)} ms` : null,
|
|
229
|
+
].filter((p) => p !== null);
|
|
230
|
+
return parts.join(' ');
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=beat-cut.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"beat-cut.js","sourceRoot":"","sources":["../../src/trailer/beat-cut.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Environment } from '../config/environments.js';
|
|
2
|
+
import { type ApiDeps } from '../http/client.js';
|
|
3
|
+
export declare const TRAILER_UPLOAD_URL_PATH = "/api/cli/v1/trailer/upload-url";
|
|
4
|
+
export declare const TRAILER_ATTACH_PATH = "/api/cli/v1/trailer/attach";
|
|
5
|
+
/** The gallery cap api-server enforces (`MAX_MEDIA_ITEMS` in game-page-edit-rules.ts). */
|
|
6
|
+
export declare const MAX_GALLERY_ITEMS = 12;
|
|
7
|
+
export interface TrailerUploadRequest {
|
|
8
|
+
gameId: string;
|
|
9
|
+
/** `video/mp4` or `video/webm` — api-server refuses anything else before minting. */
|
|
10
|
+
contentType: string;
|
|
11
|
+
bytes: number;
|
|
12
|
+
}
|
|
13
|
+
/** `cli-trailer.ts`'s upload-url response. */
|
|
14
|
+
export interface TrailerUploadTicket {
|
|
15
|
+
uploadUrl: string;
|
|
16
|
+
/** Where the video is served from once the PUT lands — what `attach` is given. */
|
|
17
|
+
publicUrl: string;
|
|
18
|
+
path: string;
|
|
19
|
+
maxBytes: number;
|
|
20
|
+
/** Echoed by the server: the exact value the PUT's Content-Type must carry. */
|
|
21
|
+
contentType: string;
|
|
22
|
+
}
|
|
23
|
+
export interface TrailerAttachRequest {
|
|
24
|
+
gameId: string;
|
|
25
|
+
url: string;
|
|
26
|
+
/** The previous trailer's URL, dropped from the gallery so a re-run replaces instead of adding. */
|
|
27
|
+
replaceUrl?: string;
|
|
28
|
+
}
|
|
29
|
+
/** `cli-trailer.ts`'s attach response. */
|
|
30
|
+
export interface TrailerAttachResult {
|
|
31
|
+
media: unknown[];
|
|
32
|
+
pageUrl: string;
|
|
33
|
+
isPublic: boolean;
|
|
34
|
+
/** False until the game's first `bitmagic publish` — the page exists but is not live yet. */
|
|
35
|
+
published: boolean;
|
|
36
|
+
}
|
|
37
|
+
/** Context the 409 message can use: where the creator goes to make room. */
|
|
38
|
+
export interface TrailerAttachHints {
|
|
39
|
+
/** The My games page, from the publish record when there has been a publish. */
|
|
40
|
+
manageUrl?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Ask api-server for a signed PUT under `game-media/<gameId>/`. Ownership and the video-only rule
|
|
44
|
+
* are checked there before anything is minted, so a refusal here has cost nothing.
|
|
45
|
+
*/
|
|
46
|
+
export declare function mintTrailerUploadUrl(environment: Environment, accessToken: string, body: TrailerUploadRequest, deps: ApiDeps): Promise<TrailerUploadTicket>;
|
|
47
|
+
/**
|
|
48
|
+
* Put the uploaded video at the front of the game page's gallery. api-server drops any item already
|
|
49
|
+
* pointing at `url` or at `replaceUrl`, so re-running replaces the previous trailer rather than
|
|
50
|
+
* stacking a new one beside it.
|
|
51
|
+
*/
|
|
52
|
+
export declare function attachTrailer(environment: Environment, accessToken: string, body: TrailerAttachRequest, deps: ApiDeps, hints?: TrailerAttachHints): Promise<TrailerAttachResult>;
|