{"record":{"id":"3912047ac2f86456","repo":"Comfy-Org/ComfyUI","slug":"expected-waveform-tensor-shape-1-channels-sampl","errorCode":null,"errorMessage":"Expected waveform tensor shape (1, channels, samples)","messagePattern":"Expected waveform tensor shape \\(1, channels, samples\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy_api_nodes/util/conversions.py","lineNumber":275,"sourceCode":"    audio_bytes_io.seek(0)\n    return audio_bytes_io\n\n\ndef audio_tensor_to_contiguous_ndarray(waveform: torch.Tensor) -> np.ndarray:\n    \"\"\"\n    Prepares audio waveform for av library by converting to a contiguous numpy array.\n\n    Args:\n        waveform: a tensor of shape (1, channels, samples) derived from a Comfy `AUDIO` type.\n\n    Returns:\n        Contiguous numpy array of the audio waveform.\n\n    Raises:\n        ValueError: If the waveform is not shaped (1, channels, samples).\n    \"\"\"\n    if waveform.ndim != 3 or waveform.shape[0] != 1:\n        raise ValueError(\"Expected waveform tensor shape (1, channels, samples)\")\n\n    # Prepare for av: remove batch dim, move to CPU, make contiguous, convert to numpy array\n    audio_data_np = waveform.squeeze(0).cpu().contiguous().numpy()\n    if audio_data_np.dtype != np.float32:\n        audio_data_np = audio_data_np.astype(np.float32)\n\n    return audio_data_np\n\n\ndef audio_input_to_mp3(audio: Input.Audio) -> BytesIO:\n    audio_data_np = audio_tensor_to_contiguous_ndarray(audio[\"waveform\"])\n    sample_rate = int(audio[\"sample_rate\"])\n\n    output_buffer = BytesIO()\n    output_container = av.open(output_buffer, mode=\"w\", format=\"mp3\")\n\n    out_stream = output_container.add_stream(\"libmp3lame\", rate=sample_rate)\n    out_stream.bit_rate = 320000","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_api_nodes/util/conversions.py#L257-L293","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmp3 = audio_input_to_mp3(audio)  # audio['waveform'] is (C, T)\n\n// after\nwaveform = audio['waveform']\nif waveform.ndim == 2:\n    waveform = waveform.unsqueeze(0)\naudio = {**audio, 'waveform': waveform}\nmp3 = audio_input_to_mp3(audio)","handlingStrategy":"validation","validationCode":"def is_valid_audio_waveform(waveform: torch.Tensor) -> bool:\n    return waveform.ndim == 3 and waveform.shape[0] == 1","typeGuard":"from typing import TypeGuard\n\ndef is_comfy_audio(audio: dict) -> TypeGuard[dict]:\n    wf = audio.get('waveform')\n    return (\n        isinstance(wf, torch.Tensor)\n        and wf.ndim == 3\n        and wf.shape[0] == 1\n        and isinstance(audio.get('sample_rate'), int)\n    )","tryCatchPattern":null,"preventionTips":["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."],"tags":["audio","tensor-shape","pyav","validation"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}