perf(align): render previews on worker threads in parallel chunks, send Opus

The MIDI preview render (~2 s for a 5 min song) and auto-align ran synchronously on the
server's event loop, and each preview was a 12.4 MB WAV. Renders now run as 4 parallel time
chunks (2 s pre-roll, 10 ms cross-fade) on worker threads, auto-align on its own worker, and
previews are mono Ogg Opus 48 kb/s via ffmpeg (1.5 MB, same timing as the WAV in Chrome).
?format=wav keeps the PCM output. Swimming: render 2.0 s -> 0.65 s + 0.6 s encode; event loop
blocked 2.0 s -> <0.1 s per render.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas Winther
2026-10-30 22:04:46 +01:00
co-authored by Claude Opus 5.5
parent 7b7a1cc6c9
commit 3ce58e1e05
7 changed files with 319 additions and 30 deletions
+15 -2
View File
@@ -151,10 +151,23 @@ describe("API", () => {
expect(String.fromCharCode(...b.subarray(0, 4))).toBe("OggS");
expect(await Bun.file(join(root, "fix", "audio.ogg")).exists()).toBe(true);
}, BIG);
test("render: RIFF WAV, mono 22.05 kHz, cached by anchors", async () => {
test("render: Ogg Opus by default (small), cached by anchors", async () => {
const body = json({ anchors: first.anchors });
const r = await api("/api/song/fix/render", body);
expect(r.status).toBe(200);
expect(r.headers.get("content-type")).toBe("audio/ogg");
const b = new Uint8Array(await r.arrayBuffer());
expect(String.fromCharCode(...b.subarray(0, 4))).toBe("OggS");
expect(new TextDecoder().decode(b.subarray(28, 36))).toBe("OpusHead");
expect(b.length).toBeLessThan(first.audioDur * 22050 * 2 / 4); // far below 16-bit PCM
const again = await api("/api/song/fix/render", body);
expect(again.headers.get("x-cache")).toBe("hit");
expect(again.headers.get("x-anchors-hash")).toBe(r.headers.get("x-anchors-hash"));
}, BIG);
test("render ?format=wav: RIFF WAV, mono 22.05 kHz, cached by anchors", async () => {
const body = json({ anchors: first.anchors });
const r = await api("/api/song/fix/render?format=wav", body);
expect(r.status).toBe(200);
expect(r.headers.get("content-type")).toBe("audio/wav");
const b = new Uint8Array(await r.arrayBuffer());
const dv = new DataView(b.buffer);
@@ -162,7 +175,7 @@ describe("API", () => {
expect(dv.getUint16(22, true)).toBe(1);
expect(dv.getUint32(24, true)).toBe(22050);
expect(b.length).toBeGreaterThan(first.audioDur * 22050 * 2);
const again = await api("/api/song/fix/render", body);
const again = await api("/api/song/fix/render?format=wav", body);
expect(again.headers.get("x-cache")).toBe("hit");
expect(again.headers.get("x-anchors-hash")).toBe(r.headers.get("x-anchors-hash"));
}, BIG);