Stable Audio 3: default seconds_total uses wrong latent rate (10.7666 vs 21.5332), conditioning every clip as 2x its real duration
- Dominant language
- Python
- Stars
- 133k
- Forks
- 15.7k
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 158
Description
### Summary
`StableAudio3.extra_conds` in `comfy/model_base.py` computes the default `seconds_total` conditioning with the wrong latent temporal rate, so every Stable Audio 3 generation that does not explicitly set `seconds_total` (including the official workflow templates, which don't use `ConditioningStableAudio`) is conditioned as if the clip were **twice its real duration**.
```python
seconds_total = kwargs.get("seconds_total", int(noise.shape[-1] / 10.7666))
```
- `EmptyLatentAudio` builds audio latents at `44100 / 2048 ≈ 21.5332` frames/s (`length = round((seconds * 44100 / 2048) / 2) * 2`, `downscale_ratio_temporal: 2048`).
- VAE decode confirms 2048 samples per latent frame: a 4.0 s request (86 frames) decodes to 3.99 s of audio.
- But the default above divides by `10.7666` (= 44100/4096), so an 86-frame latent yields `seconds_total = 8` for a 4-second clip.
Introduced in f9c84c94 ("Support Stable Audio 3 model." #14010) — present since day 0.
### Observable symptom
The model believes the canvas is 2× longer than it is: audible content occupies only the first ~50–60 % of every clip (regardless of requested duration — 1 s, 4 s, 11 s all show the same proportional cutoff on a spectrogram), and the remainder collapses into noise. Overall output sounds garbled/degraded. This may explain the reports remaining in #14131 after the Sage Attention fix (degraded output with Sage disabled).
### Reproduction (A/B, same seed)
Minimal graph: `CheckpointLoaderSimple (stable_audio_3_medium_base)` + `CLIPLoader (t5gemma_b_b_ul2, stable_audio)` + `CLIPTextEncode` + `EmptyLatentAudio (4.0 s)` + `KSampler (seed 42, lcm/simple/50/cfg 7 — template defaults)` + `VAEDecodeAudio`.
1. **Default path** (no `ConditioningStableAudio`): content dies at ~60 % of the clip, tail is noise. RMS 0.034.
2. **Same graph + `ConditioningStableAudio(seconds_start=0, seconds_total=4)`**: content fills the entire clip, RMS 0.072. Night-and-day difference on the spectrogram.
3. Patching the divisor to `21.5332` fixes the default path identically (verified with `stable_audio_3_medium_base` and `stable_audio_3_small_sfx_base` from Comfy-Org/stable-audio-3).
### Suggested fix
Use the actual latent rate (or read `downscale_ratio_temporal` from the latent instead of hard-coding):
```python
seconds_total = kwargs.get("seconds_total", int(noise.shape[-1] / 21.5332))
```
### Environment
- ComfyUI 0.27.0 (master `ffbecfff`), frontend 1.45.20, templates 0.11.2
- Windows 11, Python 3.12.2, torch 2.12.1+cu130, RTX 3080 10 GB
- Checkpoints: Comfy-Org/stable-audio-3 (`stable_audio_3_medium_base.safetensors`, `stable_audio_3_small_sfx_base.safetensors`), text encoder `t5gemma_b_b_ul2.safetensors`
- No Sage Attention (default SDPA), no other custom nodes involved in the repro
Contributor guide
Research direction
Start in comfy/model_base.py at StableAudio3.extra_conds and compare its default seconds_total calculation with EmptyLatentAudio's temporal rate. Reproduce the reported Stable Audio 3 workflow with and without explicit ConditioningStableAudio values, then verify that the default conditioning matches the explicit-duration result and that generated audio content fills the requested clip.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, pytorch
- Domain
- machine-learning
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100