Comfy-Org/ComfyUI · error · ValueError

No audio stream found in response.

Error message

No audio stream found in response.

What it means

audio_bytes_to_audio_input opens the downloaded bytes with PyAV and requires at least one audio stream. If af.streams.audio is empty it raises ValueError('No audio stream found in response.') because there is nothing to decode into a Comfy AUDIO dict.

Source

Thrown at comfy_api_nodes/util/conversions.py:578

def _f32_pcm(wav: torch.Tensor) -> torch.Tensor:
    """Convert audio to float 32 bits PCM format. Copy-paste from nodes_audio.py file."""
    if wav.dtype.is_floating_point:
        return wav
    elif wav.dtype == torch.int16:
        return wav.float() / (2**15)
    elif wav.dtype == torch.int32:
        return wav.float() / (2**31)
    raise ValueError(f"Unsupported wav dtype: {wav.dtype}")


def audio_bytes_to_audio_input(audio_bytes: bytes) -> dict:
    """
    Decode any common audio container from bytes using PyAV and return
    a Comfy AUDIO dict: {"waveform": [1, C, T] float32, "sample_rate": int}.
    """
    with av.open(BytesIO(audio_bytes)) as af:
        if not af.streams.audio:
            raise ValueError("No audio stream found in response.")
        stream = af.streams.audio[0]

        in_sr = int(stream.codec_context.sample_rate)
        out_sr = in_sr

        frames: list[torch.Tensor] = []
        n_channels = stream.channels or 1

        for frame in af.decode(streams=stream.index):
            arr = frame.to_ndarray()  # shape can be [C, T] or [T, C] or [T]
            buf = torch.from_numpy(arr)
            if buf.ndim == 1:
                buf = buf.unsqueeze(0)  # [T] -> [1, T]
            elif buf.shape[0] != n_channels and buf.shape[-1] == n_channels:
                buf = buf.transpose(0, 1).contiguous()  # [T, C] -> [C, T]
            elif buf.shape[0] != n_channels:
                buf = buf.reshape(-1, n_channels).t().contiguous()  # fallback to [C, T]
            frames.append(buf)

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Dump the first bytes of the response to a file and inspect with ffprobe or a text editor — if it is JSON/HTML, the upstream call failed, not the audio parsing.
  2. Check the API node's status/job polling: confirm the job actually completed before the download step.
  3. Re-run the request and inspect the logged response body in request logs.
  4. If the file is real audio in an exotic container, re-export it as WAV/MP3 and feed it via Load Audio instead.
Defensive patterns

Strategy: validation

Validate before calling

import av
from io import BytesIO

with av.open(BytesIO(audio_bytes)) as c:
    if not c.streams.audio:
        # inspect bytes: probably a JSON/HTML error, not audio
        preview = audio_bytes[:64]
        raise ValueError(f'No audio stream; body starts with: {preview!r}')

Try / catch

try:
    audio = audio_bytes_to_audio_input(data)
except ValueError as e:
    if 'No audio stream' in str(e):
        # upstream returned a non-audio body; do not retry blindly
        log.error('Non-audio response: %r', data[:200])
        raise
    raise

Prevention

When it happens

Trigger: A text-to-music/speech API node downloads the response body and the bytes are not audio-with-a-stream: a video-only MP4, a JSON error object, an HTML error page, or an empty body that still parses as a container.

Common situations: The API returned an error payload with HTTP 200 (async job failed server-side but body is JSON); the endpoint changed to return a zip/manifest instead of raw audio; a CDN intercepting the request; wrong endpoint URL used in a custom node.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/e61ea1b5dfa1ceb5. Report an issue: GitHub.