Comfy-Org/ComfyUI · error · ValueError
Expected waveform tensor shape (1, channels, samples)
Error message
Expected waveform tensor shape (1, channels, samples)
What it means
audio_tensor_to_contiguous_ndarray requires the Comfy AUDIO waveform tensor to be exactly 3-D with a batch dimension of 1, i.e. shape (1, channels, samples). It raises ValueError when waveform.ndim != 3 or waveform.shape[0] != 1 because the PyAV encoding path squeezes dimension 0 and cannot handle a batched or rank-mismatched tensor.
Source
Thrown at comfy_api_nodes/util/conversions.py:275
audio_bytes_io.seek(0)
return audio_bytes_io
def audio_tensor_to_contiguous_ndarray(waveform: torch.Tensor) -> np.ndarray:
"""
Prepares audio waveform for av library by converting to a contiguous numpy array.
Args:
waveform: a tensor of shape (1, channels, samples) derived from a Comfy `AUDIO` type.
Returns:
Contiguous numpy array of the audio waveform.
Raises:
ValueError: If the waveform is not shaped (1, channels, samples).
"""
if waveform.ndim != 3 or waveform.shape[0] != 1:
raise ValueError("Expected waveform tensor shape (1, channels, samples)")
# Prepare for av: remove batch dim, move to CPU, make contiguous, convert to numpy array
audio_data_np = waveform.squeeze(0).cpu().contiguous().numpy()
if audio_data_np.dtype != np.float32:
audio_data_np = audio_data_np.astype(np.float32)
return audio_data_np
def audio_input_to_mp3(audio: Input.Audio) -> BytesIO:
audio_data_np = audio_tensor_to_contiguous_ndarray(audio["waveform"])
sample_rate = int(audio["sample_rate"])
output_buffer = BytesIO()
output_container = av.open(output_buffer, mode="w", format="mp3")
out_stream = output_container.add_stream("libmp3lame", rate=sample_rate)
out_stream.bit_rate = 320000View on GitHub (pinned to 1c6d8d45b3)
Solutions
- Inspect waveform.shape before the call and fix the upstream node producing the AUDIO dict.
- If the tensor is (C, T), add a batch dimension: waveform.unsqueeze(0).
- If you have a batch (N, C, T), select one item with waveform[i:i+1] or loop over items.
- Prefer sourcing AUDIO from Comfy's standard audio nodes so the (1, C, T) contract holds.
Example fix
// before
mp3 = audio_input_to_mp3(audio) # audio['waveform'] is (C, T)
// after
waveform = audio['waveform']
if waveform.ndim == 2:
waveform = waveform.unsqueeze(0)
audio = {**audio, 'waveform': waveform}
mp3 = audio_input_to_mp3(audio) Defensive patterns
Strategy: validation
Validate before calling
def is_valid_audio_waveform(waveform: torch.Tensor) -> bool:
return waveform.ndim == 3 and waveform.shape[0] == 1 Type guard
from typing import TypeGuard
def is_comfy_audio(audio: dict) -> TypeGuard[dict]:
wf = audio.get('waveform')
return (
isinstance(wf, torch.Tensor)
and wf.ndim == 3
and wf.shape[0] == 1
and isinstance(audio.get('sample_rate'), int)
) Prevention
- Always produce AUDIO via Comfy's standard audio nodes, preserving the (1, C, T) contract.
- After any tensor surgery on waveforms, assert wf.ndim == 3 and wf.shape[0] == 1 in debug builds.
- Document the (1, channels, samples) shape in custom node signatures.
When it happens
Trigger: Passing an AUDIO dict whose waveform is (channels, samples) (2-D), (N, channels, samples) with N>1 (a batch), or a raw unbatched tensor into audio_input_to_mp3 or the av-based video/audio conversion helpers in comfy_api_nodes/util/conversions.py.
Common situations: Manually constructing the AUDIO dict instead of using a Load Audio / audio preview node; batching audio through a node that assumes a single clip; feeding a latent-shaped or preprocessed tensor by mistake.
Related errors
- No audio stream found in response.
- Decoded zero audio frames.
- Minimum cutoff must be larger than zero.
- A cutoff above 0.5 does not make sense.
- Minimum cutoff must be larger than zero.
AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14).
Data as JSON: /api/errors/3912047ac2f86456.
Report an issue: GitHub.