Files
hyperframes/skills/media-use/audio/scripts/lib/bgm.test.mjs
T
Vance IngallsandClaude Fable 5 c992a136bf fix(skills): pipeline fixes from prompt-guide validation (BGM, caption accent, voice, PR version)
Behavior fixes surfaced by the prompt-guide validation campaign (Tier 1+2
of the upstream bug list; Tier 3 tracked in #2107). Split out from the
doc-only updates, which follow in a separate PR.

- BGM level: default bed volume under narration was 0.8 linear (~-2 dB,
  ~16 dB too hot vs voice). Now 0.12 (~-18 dB) via shared
  bgmDefaultVolume() in media-use bgm.mjs + assemble-index fallbacks in
  faceless-explainer / pr-to-video / product-launch-video. Explicit
  volume still wins; silent-film 0.9 and music-to-video unchanged.
  Adds bgm.test.mjs (3 cases); bgm.md reference updated to match.
- Caption accent: semanticColors() ranked accents purely by chroma, so a
  preserved status red (#dc2626) outranked the brand accent and captions
  highlighted in error-red. Status-keyed colors now excluded via shared
  STATUS_ROLE_KEY regex consumed by both tokens.mjs and build-frame.mjs
  (all three skill copies kept in sync).
- Voice threading: workflow SKILL.md Step 3.1 blocks now instruct
  choosing the narration voice from the user's ask and passing
  --voice <id>; previously "a male voice" was silently ignored and the
  default (Marcia/am_michael) always won.
- fetch-pr shipping version: MERGED PRs get best-effort shipped_version
  + version_source in pr.json (first release published at/after merge,
  else default-branch package.json marked unreleased); ingest surfaces
  it as a 'Shipped in:' brief line; story-design.md forbids inventing
  versions when absent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 22:12:52 -07:00

31 lines
1.2 KiB
JavaScript

import { test } from "node:test";
import assert from "node:assert/strict";
import { BGM_BED_VOLUME, BGM_SILENT_VOLUME, bgmDefaultVolume } from "./bgm.mjs";
// Regression: narrated pipelines used to ship BGM at 0.8 (≈ -2 dB), ~16 dB
// hotter than a music bed under a voice should be. The default under narration
// must be a proper bed (≈ -18 dB); a silent film keeps the louder default.
const dbfs = (linear) => 20 * Math.log10(linear);
test("BGM under narration is a bed near -18 dB", () => {
assert.equal(bgmDefaultVolume(true), BGM_BED_VOLUME);
assert.equal(BGM_BED_VOLUME, 0.12);
const db = dbfs(BGM_BED_VOLUME);
assert.ok(db < -17 && db > -19, `bed should be ≈ -18 dB, got ${db.toFixed(1)} dB`);
});
test("a silent film (no voice) keeps BGM forward", () => {
assert.equal(bgmDefaultVolume(false), BGM_SILENT_VOLUME);
assert.equal(BGM_SILENT_VOLUME, 0.9);
});
test("the narrated default is well below the voice (≈ 0 dBFS)", () => {
// Voice sits at data-volume="1" (0 dBFS); the bed must be ~16+ dB under it.
const separation = dbfs(1) - dbfs(bgmDefaultVolume(true));
assert.ok(
separation >= 16,
`bed should sit ≥16 dB under the voice, got ${separation.toFixed(1)} dB`,
);
});