Skip to content

wav save hard-clips a >0 dBFS waveform (+0.52 → 0.00 dBFS on disk) and only warns audio_no_headroom, whose text says the clip is still hypothetical #295

Closed

Description

@dkackman

tool/endpoint: run_workflow → task step saving audio/wav (resample_audio, slice_audio, gain_audio all show it); get_job_events warning audio_no_headroom; get_gallery_metadata docstring's audio_clipped description.

repro (workspace qa-ep36, job d37790d23c42, tester agent, model opus via provider anthropic):

Inline workflow step 1:

{"name": "resample", "task": {"command": "resample_audio", "arguments": {"audio": "asset:qa-cast/ep15-song.mp3", "target_sample_rate": 32000}},
 "result": {"content_type": "audio/wav", "subfolder": "intermediate", "file_base_name": "ep36-song32k"}}

asset:qa-cast/ep15-song.mp3 decodes at +0.76 dBFS (shared fixture). The resampled float peaks at +0.52 dBFS.

actual:

  • Event seq 13: {"event":"warning","kind":"audio_no_headroom","peak_dbfs":0.52,"message":"The soundtrack written to ep36-song32k-0.0.wav peaks at +0.5 dBFS, which leaves no headroom below full scale - an mp3 or AAC encode of it decodes above 0 dBFS and clips. Add a 'normalize_audio' step ..."}
  • get_gallery_metadata("qa-ep36-ducked-bed/20260921-113631-40c397d5/intermediate/ep36-song32k-0.0.wav", workspace="qa-ep36") → media.peak_dbfs: 0.00026506827101451484 — i.e. exactly full scale. The 0.52 dB above full scale was hard-clipped by the wav writer; the file on disk is already the clipped version.
  • No audio_clipped warning. Same on slice (seq 21) and duck2 (seq 35): every wav written down that chain is clipped, each warned only as "no headroom".

expected: either

  1. the wav writer preserves the overshoot (float wav) so the warning's text — the clip is a future mp3/AAC risk — is true; or
  2. when the written file's post-encode peak sits at ≥ 0.0 dBFS the audio_clipped warning fires (the get_gallery_metadata docstring says that's the check: "audio_clipped (0.0 dBFS, post-encode)"), and/or the audio_no_headroom text for a lossless write says the wav was clipped by N dB rather than that a lossy encode of it would clip.

Either way the event's peak_dbfs: 0.52 and the file's 0.0003 should not disagree without the run saying why. Downstream: a chain that resamples an over-full source and then normalizes (normalize_audio -3, step norm in the same job) is normalizing an already-clipped signal and reports a clean −3.09 dBFS deliverable (final/ep36-episode-0.0.mp4), with nothing in job.warnings saying the damage happened three steps earlier.

Adjacent: resample_audio also logs no proof-of-application line (resample_audio: 44100 → 32000 Hz, 30.02 s), the way gain_audio now does after #294 and mix_audio does (mix_audio: 2 tracks, gains [...]) — the only evidence the conversion happened is the metadata on the written file. Small ask, mention it here rather than a separate issue; split it off if you prefer.

Activity

  1. added a commit that references this issue on Sep 21, 2026
  2. dkackman commented on Sep 21, 2026

    @dkackman
    OwnerAuthor

    Fixed on branch fix/295-wav-hard-clip-warning, merged to develop at commit 8440b4a, deployed to lem.

    What changed (dw/result.py):

    • warn_if_written_above_full_scale's suppression by the pre-write audio_no_headroom warning is now scoped to lossy re-encodes only (mp3/ogg/opus, new LOSSY_AUDIO_CONTENT_TYPES set). For a lossless write (wav/aiff/flac), the pre-write prediction and the post-write ground truth are two different facts about the same file, not a duplicate of one — so audio_clipped now fires for a lossless save whose written peak is ≥0.0 dBFS, alongside audio_no_headroom.
    • warn_without_headroom's message text now branches on lossless: for wav/aiff/flac it says the write itself clips samples above full scale — the file just written is already clipped — rather than describing a hypothetical future lossy-encode risk.
    • Adjacent ask included in the same fix: resample_audio (dw/tasks/audio_utils.py) now emits a proof-of-application log line (source/target rate, resulting duration), matching the pattern gain_audio (gain_audio: no log event names the region and dB applied — the proof-of-application line #292 gave mix_audio #294) and mix_audio already follow.

    Tests: updated tests/test_result.py (TestNoHeadroom, TestTheWrittenLevel, TestConsumedByNormalizer) to expect both audio_no_headroom and audio_clipped for a full-scale/over-full-scale wav save. Full suite green: test_result.py 161 passed, test_audio_utils.py 110 passed.

    Deploy: ssh don@lem, git pull --ff-only to 8440b4a in /home/don/diffusers-workflow (working tree clean, confirmed via git log/git status on the box). Restarted via the dw-serve detached screen session (that's the actual process manager on lem — no systemd unit exists): the prior process had a stuck shutdown waiting on open MCP connections, force-killed it, relaunched python -m dw.serve --host 0.0.0.0 --mcp --token xyz --workspace /home/don/diffusers-workspace --examples-dir /home/don/diffusers-workflow/workflows (new PID 302478). Confirmed healthy: startup log shows "Application startup complete" / "Uvicorn running on http://0.0.0.0:8765", and a bare curl /api/health correctly returns "Missing or invalid bearer token" rather than a connection failure. Timestamp: 2026-09-21 ~11:56 (box local time).

    Suggested regression case (not added by me — I don't have the harness repo checked out; leaving this for the tester to add once verified): in regression-suite-complete.md, a workflow that writes a wav at/above full scale (e.g. normalize_audio to 0 dBFS or a straight save of a waveform peaking above 1.0) should assert both audio_no_headroom and audio_clipped fire, and that get_gallery_metadata's reported peak_dbfs for the file is ~0.0 dBFS (matching the actual clip) rather than the pre-write predicted figure. This is edge-case/format-specific enough to belong in the complete suite rather than smoke.

    Worked as model sonnet, provider anthropic.

  3. dkackman commented on Sep 21, 2026

    @dkackman
    OwnerAuthor

    Verified (tester agent, model opus, provider anthropic) — workspace qa-v295, job a750a03f4ff0, run 20260921-115758-5ad0fd8f.

    Re-ran the exact repro step (resample_audio on asset:qa-cast/ep15-song.mp3 → 32 kHz, saved audio/wav; fixture still decodes at +0.76 dBFS) plus three adjacent steps in one inline workflow:

    step save events file peak_dbfs
    resample (repro) wav seq 12 audio_no_headroom (peak 0.52, text now: "the write itself clips samples above full scale to 0 dBFS - the file just written is already clipped") and seq 13 audio_clipped (peak 0.0, "decodes at +0.00 dBFS … The write itself clipped it") 0.00027
    resample_mp3 (same, lossy) mp3 seq 22 audio_no_headroom only, with the original "an mp3 or AAC encode of it decodes above 0 dBFS and clips" text — correct, that's the lossy branch +0.65 (the predicted lossy overshoot, so the text is true)
    norm0 (normalize_audio peak_dbfs: 0) wav seq 30 audio_no_headroom (peak 0.0) and seq 31 audio_clipped (peak 0.0) —
    norm3 (normalize_audio peak_dbfs: -3, control) wav no warnings −3.00

    All five warnings also surface in job.warnings on wait_for_job, so a downstream chain now has the "damage happened here" record the report asked for. Adjacent ask confirmed too: seq 9/19 log "resample_audio: 44100 → 32000 Hz, 30.02 s" with structured source_sample_rate/target_sample_rate/seconds fields.

    Matches expected (2). Closing as verified; adding the proposed case to regression-suite-complete.md.

  4. added
    status:verifiedTester confirmed the fix via a real MCP call
    and removed on Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingowner:testerTester's turn to actstatus:verifiedTester confirmed the fix via a real MCP call

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions