diff --git a/packages/engine/src/config.test.ts b/packages/engine/src/config.test.ts index ce26ae847..69465d67c 100644 --- a/packages/engine/src/config.test.ts +++ b/packages/engine/src/config.test.ts @@ -29,6 +29,7 @@ describe("resolveConfig", () => { expect(config.quality).toBe("standard"); expect(config.format).toBe("jpeg"); expect(config.jpegQuality).toBe(80); + expect(config.audioGain).toBe(1); expect(config.debug).toBe(false); }); diff --git a/packages/engine/src/config.ts b/packages/engine/src/config.ts index b1c1f01ff..b0ea98d96 100644 --- a/packages/engine/src/config.ts +++ b/packages/engine/src/config.ts @@ -105,7 +105,7 @@ export const DEFAULT_CONFIG: EngineConfig = { hdr: false, hdrAutoDetect: true, - audioGain: 1.35, + audioGain: 1, frameDataUriCacheLimit: 256, playerReadyTimeout: 45_000, diff --git a/packages/engine/src/services/audioMixer.test.ts b/packages/engine/src/services/audioMixer.test.ts new file mode 100644 index 000000000..bdccb005e --- /dev/null +++ b/packages/engine/src/services/audioMixer.test.ts @@ -0,0 +1,67 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { join } from "node:path"; +import { tmpdir } from "node:os"; + +const { runFfmpegMock } = vi.hoisted(() => ({ + runFfmpegMock: vi.fn(async () => ({ + success: true, + durationMs: 1, + stderr: "", + exitCode: 0, + })), +})); + +vi.mock("../utils/runFfmpeg.js", () => ({ + runFfmpeg: runFfmpegMock, +})); + +import { processCompositionAudio } from "./audioMixer.js"; + +describe("processCompositionAudio", () => { + const tempDirs: string[] = []; + + afterEach(() => { + runFfmpegMock.mockClear(); + for (const dir of tempDirs.splice(0)) { + rmSync(dir, { recursive: true, force: true }); + } + }); + + it("preserves muted tracks and uses unity master gain by default", async () => { + const baseDir = mkdtempSync(join(tmpdir(), "hf-audio-base-")); + const workDir = mkdtempSync(join(tmpdir(), "hf-audio-work-")); + tempDirs.push(baseDir, workDir); + + writeFileSync(join(baseDir, "voice.wav"), "stub"); + + const result = await processCompositionAudio( + [ + { + id: "voice", + src: "voice.wav", + start: 0, + end: 2, + mediaStart: 0, + layer: 0, + volume: 0, + type: "audio", + }, + ], + baseDir, + workDir, + join(baseDir, "out.m4a"), + 2, + ); + + expect(result.success).toBe(true); + expect(runFfmpegMock).toHaveBeenCalledTimes(2); + + const mixArgs = runFfmpegMock.mock.calls[1]?.[0]; + const filterIndex = mixArgs.indexOf("-filter_complex"); + const filter = mixArgs[filterIndex + 1]; + + expect(filter).toContain("volume=0"); + expect(filter).toContain("[mixed]volume=1[out]"); + }); +}); diff --git a/packages/engine/src/services/audioMixer.ts b/packages/engine/src/services/audioMixer.ts index 2a928776f..6875bb567 100644 --- a/packages/engine/src/services/audioMixer.ts +++ b/packages/engine/src/services/audioMixer.ts @@ -396,7 +396,7 @@ export async function processCompositionAudio( end: element.end, mediaStart: element.mediaStart, duration: element.end - element.start, - volume: element.volume || 1.0, + volume: element.volume ?? 1.0, }); } catch (err: unknown) { errors.push(`Error: ${element.id} — ${err instanceof Error ? err.message : String(err)}`); diff --git a/packages/producer/src/regression-harness.ts b/packages/producer/src/regression-harness.ts index c559918e2..96662df72 100644 --- a/packages/producer/src/regression-harness.ts +++ b/packages/producer/src/regression-harness.ts @@ -18,6 +18,7 @@ import { createRenderJob, executeRenderJob } from "./services/renderOrchestrator import { compileForRender } from "./services/htmlCompiler.js"; import { validateCompilation } from "./services/compilationTester.js"; import { extractVideoMetadata } from "./utils/ffprobe.js"; +import { buildRmsEnvelope, compareAudioEnvelopes } from "./utils/audioRegression.js"; // ── Types ──────────────────────────────────────────────────────────────────── @@ -348,66 +349,6 @@ function extractMonoPcm16(videoPath: string): Int16Array { } } -function buildRmsEnvelope(samples: Int16Array, windowSize = 2048, hopSize = 1024): number[] { - if (samples.length < windowSize) return []; - const envelope: number[] = []; - for (let start = 0; start + windowSize <= samples.length; start += hopSize) { - let energy = 0; - for (let i = 0; i < windowSize; i += 1) { - const normalized = (samples[start + i] ?? 0) / 32768; - energy += normalized * normalized; - } - envelope.push(Math.sqrt(energy / windowSize)); - } - return envelope; -} - -function correlationAtLag(a: number[], b: number[], lag: number): number { - const startA = Math.max(0, lag); - const startB = Math.max(0, -lag); - const length = Math.min(a.length - startA, b.length - startB); - if (length <= 32) return -1; - - let meanA = 0; - let meanB = 0; - for (let i = 0; i < length; i += 1) { - meanA += a[startA + i] ?? 0; - meanB += b[startB + i] ?? 0; - } - meanA /= length; - meanB /= length; - - let numerator = 0; - let denA = 0; - let denB = 0; - for (let i = 0; i < length; i += 1) { - const da = (a[startA + i] ?? 0) - meanA; - const db = (b[startB + i] ?? 0) - meanB; - numerator += da * db; - denA += da * da; - denB += db * db; - } - if (denA <= 1e-12 || denB <= 1e-12) return -1; - return numerator / Math.sqrt(denA * denB); -} - -function bestEnvelopeCorrelation( - rendered: number[], - snapshot: number[], - maxLagWindows: number, -): { correlation: number; lagWindows: number } { - let best = -1; - let bestLag = 0; - for (let lag = -maxLagWindows; lag <= maxLagWindows; lag += 1) { - const corr = correlationAtLag(rendered, snapshot, lag); - if (corr > best) { - best = corr; - bestLag = lag; - } - } - return { correlation: best, lagWindows: bestLag }; -} - // ── Failure Reporting ──────────────────────────────────────────────────────── function saveFailureDetails( @@ -751,7 +692,7 @@ async function runTestSuite( if (renderedAudio.length > 0 && snapshotAudio.length > 0) { const renderedEnvelope = buildRmsEnvelope(renderedAudio); const snapshotEnvelope = buildRmsEnvelope(snapshotAudio); - const audio = bestEnvelopeCorrelation( + const audio = compareAudioEnvelopes( renderedEnvelope, snapshotEnvelope, suite.meta.maxAudioLagWindows, diff --git a/packages/producer/src/services/renderOrchestrator.test.ts b/packages/producer/src/services/renderOrchestrator.test.ts index 6ec80f584..c805fd026 100644 --- a/packages/producer/src/services/renderOrchestrator.test.ts +++ b/packages/producer/src/services/renderOrchestrator.test.ts @@ -203,7 +203,7 @@ describe("applyRenderModeHints", () => { ffmpegEncodeTimeout: 600000, ffmpegProcessTimeout: 300000, ffmpegStreamingTimeout: 600000, - audioGain: 1.35, + audioGain: 1, frameDataUriCacheLimit: 256, playerReadyTimeout: 45000, renderReadyTimeout: 15000, diff --git a/packages/producer/src/utils/audioRegression.test.ts b/packages/producer/src/utils/audioRegression.test.ts new file mode 100644 index 000000000..ba7c6521e --- /dev/null +++ b/packages/producer/src/utils/audioRegression.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, it } from "vitest"; +import { buildRmsEnvelope, compareAudioEnvelopes } from "./audioRegression.js"; + +describe("compareAudioEnvelopes", () => { + it("treats silent-vs-silent audio as a perfect match", () => { + const silentSamples = new Int16Array(4096); + + const rendered = buildRmsEnvelope(silentSamples); + const snapshot = buildRmsEnvelope(silentSamples); + + expect(compareAudioEnvelopes(rendered, snapshot, 120)).toEqual({ + correlation: 1, + lagWindows: 0, + }); + }); +}); diff --git a/packages/producer/src/utils/audioRegression.ts b/packages/producer/src/utils/audioRegression.ts new file mode 100644 index 000000000..5acc06af8 --- /dev/null +++ b/packages/producer/src/utils/audioRegression.ts @@ -0,0 +1,79 @@ +export function buildRmsEnvelope(samples: Int16Array, windowSize = 2048, hopSize = 1024): number[] { + if (samples.length < windowSize) return []; + const envelope: number[] = []; + for (let start = 0; start + windowSize <= samples.length; start += hopSize) { + let energy = 0; + for (let i = 0; i < windowSize; i += 1) { + const normalized = (samples[start + i] ?? 0) / 32768; + energy += normalized * normalized; + } + envelope.push(Math.sqrt(energy / windowSize)); + } + return envelope; +} + +function correlationAtLag(a: number[], b: number[], lag: number): number { + const startA = Math.max(0, lag); + const startB = Math.max(0, -lag); + const length = Math.min(a.length - startA, b.length - startB); + if (length <= 32) return -1; + + let meanA = 0; + let meanB = 0; + for (let i = 0; i < length; i += 1) { + meanA += a[startA + i] ?? 0; + meanB += b[startB + i] ?? 0; + } + meanA /= length; + meanB /= length; + + let numerator = 0; + let denA = 0; + let denB = 0; + for (let i = 0; i < length; i += 1) { + const da = (a[startA + i] ?? 0) - meanA; + const db = (b[startB + i] ?? 0) - meanB; + numerator += da * db; + denA += da * da; + denB += db * db; + } + if (denA <= 1e-12 || denB <= 1e-12) return -1; + return numerator / Math.sqrt(denA * denB); +} + +function bestEnvelopeCorrelation( + rendered: number[], + snapshot: number[], + maxLagWindows: number, +): { correlation: number; lagWindows: number } { + let best = -1; + let bestLag = 0; + for (let lag = -maxLagWindows; lag <= maxLagWindows; lag += 1) { + const corr = correlationAtLag(rendered, snapshot, lag); + if (corr > best) { + best = corr; + bestLag = lag; + } + } + return { correlation: best, lagWindows: bestLag }; +} + +function isSilentEnvelope(envelope: number[]): boolean { + return envelope.length > 0 && envelope.every((sample) => Math.abs(sample) <= 1e-9); +} + +export function compareAudioEnvelopes( + rendered: number[], + snapshot: number[], + maxLagWindows: number, +): { correlation: number; lagWindows: number } { + if (rendered.length === 0 || snapshot.length === 0) { + return { correlation: 1, lagWindows: 0 }; + } + + if (isSilentEnvelope(rendered) && isSilentEnvelope(snapshot)) { + return { correlation: 1, lagWindows: 0 }; + } + + return bestEnvelopeCorrelation(rendered, snapshot, maxLagWindows); +} diff --git a/packages/producer/tests/font-variant-numeric/output/compiled.html b/packages/producer/tests/font-variant-numeric/output/compiled.html index 3cd931758..c74692232 100644 --- a/packages/producer/tests/font-variant-numeric/output/compiled.html +++ b/packages/producer/tests/font-variant-numeric/output/compiled.html @@ -1,30 +1,40 @@ - + -
- - - +@font-face { + font-family: "Space Mono"; + src: url("data:font/woff2;base64,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") format("woff2"); + font-style: normal; + font-weight: 700; + font-display: block; +} + +