Title
Gradio UI produces deterministic near-silent/noise output (repaint & text2music), while the identical generate_music() call succeeds when invoked directly outside the Gradio session
Environment
- Image:
ghcr.io/ace-step/ace-step-1.5:latest
- GPU: NVIDIA RTX 2000 Ada Laptop GPU, 8GB VRAM
- PyTorch 2.10.0+cu128, torchao 0.16.0, CUDA 12.8
- Config:
acestep-v15-turbo DiT, acestep-5Hz-lm-1.7B LM (auto-downgraded from 4B by the app's own GPU-tier detection), pt LM backend, --quantization none (also reproduced with default int8_weight_only quantization)
- 8 inference steps (turbo), DCW enabled (
double mode, default scalers)
Summary
Every generation submitted through the bundled Gradio web UI for task_type="repaint" or task_type="text2music" comes back as near-silent audio that decodes to broadband noise after loudness normalization — regardless of the caption, lyrics, seed, or batch content entered. Across 6+ distinct UI-submitted requests (different prompts, different seeds, both single and batch-size-2), the pre-normalization peak was bit-identical or near-identical every time: Peak=0.0034 (×4), Peak=0.0035, Peak=0.0036. After the app's own -1dB normalization step, this becomes audible full-volume noise.
Calling the exact same underlying generate_music() function directly in a fresh Python process — same checkpoints, same DiT/LM handlers, same parameters captured verbatim from a failing UI request (including the same caption, seed, src_audio, repaint settings) — consistently succeeds, with Peak=1.0000 before normalization and spectrally/perceptually correct musical output (verified via spectrogram: clear rhythmic structure, natural harmonic content, matching the requested instrumentation) in every one of 6+ direct-API attempts, including one that reproduced a task_type="text2music" batch and one that reproduced a task_type="repaint" request.
This strongly suggests the bug is not in generate_music(), the DiT/LM checkpoints, or GPU/precision handling, but somewhere in the Gradio server process's request handling — something that behaves differently for a long-running, previously-used server session vs. a fresh single-shot process.
What was ruled out (with evidence)
- Gradio event-wiring / positional-argument mismatch. Traced the full call chain (
generation_run_wiring.py → generate_with_batch_management → generate_with_progress → GenerationParams(...)) — all 78 positional arguments in the .click() wiring match their callee's signature 1:1, in order. The final GenerationParams(...) construction uses explicit keyword arguments throughout, not positional, eliminating ordering bugs at that layer.
- Checkpoint/weight loading. Loaded
acestep-v15-turbo's state dict directly and inspected weight statistics (mean/std/min/max across first and last layers, including detokenizer.proj_out.{weight,bias}) — all values look like genuinely trained parameters, no missing keys reported, nothing zeroed or randomly-initialized-looking.
--quantization (torchao AffineQuantizedTensor). Reproduced with quantization fully disabled (--quantization none) — identical failure (Peak=0.0034/0.0035).
guidance_scale / shift. The app already auto-corrects guidance_scale for turbo models (Turbo model detected: overriding guidance_scale 7.0 -> 1.0) regardless of what the UI sends. Explicitly testing shift=3.0 (the UI's actual default, vs. the dataclass default 1.0) via direct API still succeeded (Peak=1.0000).
- DCW correction. Active with identical settings (
mode=double, UI defaults) in both failing and succeeding runs — not differentiating.
- The LM "thinking" step. A
task_type="repaint" request with think_checkbox=False (LM skipped — confirmed via log: Skipping LM for task_type='repaint' - using DiT directly, use_lm=False) still failed identically (Peak=0.0035). Ruled out LM-state corruption in the long-lived llm_handler singleton as the sole cause.
- Stale
text2music_audio_code_string textbox. Confirmed via logs that the app's own defensive guard (if task_type != "text2music": text2music_audio_code_string = "") correctly clears this field for repaint/cover before use — the failing repaint request genuinely processed the fresh src_audio file ([generate_music] Processing source audio..., followed by a correct text_prompt reaching the DiT text encoder with the real caption).
custom_timesteps override. UI default is "" (empty), which safely no-ops in parse_and_validate_timesteps.
Diagnostic method
Patched a temporary debug block at the top of generate_with_progress (acestep/ui/gradio/events/results/generation_progress.py) logging every one of its ~55 raw incoming arguments before any processing. This let me capture, verbatim, what the live Gradio server actually received for both a succeeding (task_type="cover") and a failing (task_type="repaint") request, and confirmed the caption/lyrics/metadata text reaching the DiT's text encoder was correct in the failing case — i.e., the input to generation was fine, but the output was still degenerate.
Suspected (not confirmed) contributing factor: reference_audio
Every failing repaint/text2music request I captured or was shown had reference_audio set (in addition to src_audio). My only fully clean, successful direct-API reproduction of a repaint request never set reference_audio. When I attempted to reproduce the exact failing scenario — task_type="repaint", reference_audio and src_audio both pointing at the same real ~4.5-minute track — the direct-API call hung on _prepare_reference_and_source_audio's "Processing source audio..." step for 15+ minutes (131–151% CPU, no forward progress, no error), whereas the live Gradio server processed the identical file (both reference and source encode) in ~7 seconds. I killed the hung process rather than let it run indefinitely, so I can't confirm whether it would have eventually produced degenerate output, errored, or completed correctly.
This is offered as a lead for maintainers with more context on the reference_audio + repaint conditioning path, not a confirmed root cause — the hang itself is a distinct, second anomaly worth investigating alongside the primary near-silent-output bug.
Reproduction steps (primary bug)
- Run the container per the official
docker-compose.yml (nanobot-gateway-equivalent gateway/Gradio service).
- In the Gradio UI, submit a
text2music or repaint generation with any caption/lyrics, default settings otherwise.
- Observe: generation completes without error, but the resulting audio is broadband noise. Check server logs for
[Normalization] Audio N BEFORE: Peak= — expect a value in the 0.003–0.004 range regardless of prompt content.
- For comparison,
docker exec into the container and run the same request via acestep.inference.generate_music() directly in a fresh python3 process (see run_generate_test.py in the repo root for the pattern) — expect Peak≈1.0.
Impact
This affects the primary, documented way most users are expected to interact with the model (the bundled Gradio web UI via docker-compose.yml/docker run ... gateway). Anyone following the README's Docker instructions and using the default UI for text2music or repaint tasks will get unusable output every time, with no error surfaced — the UI reports success.
Title
Gradio UI produces deterministic near-silent/noise output (repaint & text2music), while the identical
generate_music()call succeeds when invoked directly outside the Gradio sessionEnvironment
ghcr.io/ace-step/ace-step-1.5:latestacestep-v15-turboDiT,acestep-5Hz-lm-1.7BLM (auto-downgraded from 4B by the app's own GPU-tier detection),ptLM backend,--quantization none(also reproduced with defaultint8_weight_onlyquantization)doublemode, default scalers)Summary
Every generation submitted through the bundled Gradio web UI for
task_type="repaint"ortask_type="text2music"comes back as near-silent audio that decodes to broadband noise after loudness normalization — regardless of the caption, lyrics, seed, or batch content entered. Across 6+ distinct UI-submitted requests (different prompts, different seeds, both single and batch-size-2), the pre-normalization peak was bit-identical or near-identical every time:Peak=0.0034(×4),Peak=0.0035,Peak=0.0036. After the app's own-1dBnormalization step, this becomes audible full-volume noise.Calling the exact same underlying
generate_music()function directly in a fresh Python process — same checkpoints, same DiT/LM handlers, same parameters captured verbatim from a failing UI request (including the same caption, seed,src_audio, repaint settings) — consistently succeeds, withPeak=1.0000before normalization and spectrally/perceptually correct musical output (verified via spectrogram: clear rhythmic structure, natural harmonic content, matching the requested instrumentation) in every one of 6+ direct-API attempts, including one that reproduced atask_type="text2music"batch and one that reproduced atask_type="repaint"request.This strongly suggests the bug is not in
generate_music(), the DiT/LM checkpoints, or GPU/precision handling, but somewhere in the Gradio server process's request handling — something that behaves differently for a long-running, previously-used server session vs. a fresh single-shot process.What was ruled out (with evidence)
generation_run_wiring.py→generate_with_batch_management→generate_with_progress→GenerationParams(...)) — all 78 positional arguments in the.click()wiring match their callee's signature 1:1, in order. The finalGenerationParams(...)construction uses explicit keyword arguments throughout, not positional, eliminating ordering bugs at that layer.acestep-v15-turbo's state dict directly and inspected weight statistics (mean/std/min/max across first and last layers, includingdetokenizer.proj_out.{weight,bias}) — all values look like genuinely trained parameters, no missing keys reported, nothing zeroed or randomly-initialized-looking.--quantization(torchaoAffineQuantizedTensor). Reproduced with quantization fully disabled (--quantization none) — identical failure (Peak=0.0034/0.0035).guidance_scale/shift. The app already auto-correctsguidance_scalefor turbo models (Turbo model detected: overriding guidance_scale 7.0 -> 1.0) regardless of what the UI sends. Explicitly testingshift=3.0(the UI's actual default, vs. the dataclass default1.0) via direct API still succeeded (Peak=1.0000).mode=double, UI defaults) in both failing and succeeding runs — not differentiating.task_type="repaint"request withthink_checkbox=False(LM skipped — confirmed via log:Skipping LM for task_type='repaint' - using DiT directly,use_lm=False) still failed identically (Peak=0.0035). Ruled out LM-state corruption in the long-livedllm_handlersingleton as the sole cause.text2music_audio_code_stringtextbox. Confirmed via logs that the app's own defensive guard (if task_type != "text2music": text2music_audio_code_string = "") correctly clears this field for repaint/cover before use — the failing repaint request genuinely processed the freshsrc_audiofile ([generate_music] Processing source audio..., followed by a correcttext_promptreaching the DiT text encoder with the real caption).custom_timestepsoverride. UI default is""(empty), which safely no-ops inparse_and_validate_timesteps.Diagnostic method
Patched a temporary debug block at the top of
generate_with_progress(acestep/ui/gradio/events/results/generation_progress.py) logging every one of its ~55 raw incoming arguments before any processing. This let me capture, verbatim, what the live Gradio server actually received for both a succeeding (task_type="cover") and a failing (task_type="repaint") request, and confirmed the caption/lyrics/metadata text reaching the DiT's text encoder was correct in the failing case — i.e., the input to generation was fine, but the output was still degenerate.Suspected (not confirmed) contributing factor:
reference_audioEvery failing repaint/text2music request I captured or was shown had
reference_audioset (in addition tosrc_audio). My only fully clean, successful direct-API reproduction of a repaint request never setreference_audio. When I attempted to reproduce the exact failing scenario —task_type="repaint",reference_audioandsrc_audioboth pointing at the same real ~4.5-minute track — the direct-API call hung on_prepare_reference_and_source_audio's "Processing source audio..." step for 15+ minutes (131–151% CPU, no forward progress, no error), whereas the live Gradio server processed the identical file (both reference and source encode) in ~7 seconds. I killed the hung process rather than let it run indefinitely, so I can't confirm whether it would have eventually produced degenerate output, errored, or completed correctly.This is offered as a lead for maintainers with more context on the
reference_audio+ repaint conditioning path, not a confirmed root cause — the hang itself is a distinct, second anomaly worth investigating alongside the primary near-silent-output bug.Reproduction steps (primary bug)
docker-compose.yml(nanobot-gateway-equivalentgateway/Gradio service).text2musicorrepaintgeneration with any caption/lyrics, default settings otherwise.[Normalization] Audio N BEFORE: Peak=— expect a value in the0.003–0.004range regardless of prompt content.docker execinto the container and run the same request viaacestep.inference.generate_music()directly in a freshpython3process (seerun_generate_test.pyin the repo root for the pattern) — expectPeak≈1.0.Impact
This affects the primary, documented way most users are expected to interact with the model (the bundled Gradio web UI via
docker-compose.yml/docker run ... gateway). Anyone following the README's Docker instructions and using the default UI fortext2musicorrepainttasks will get unusable output every time, with no error surfaced — the UI reports success.