sgl-project/sglang · error · ValueError

Dots omni audio must be mono, got shape={tuple(waveform.shap

Error message

Dots omni audio must be mono, got shape={tuple(waveform.shape)}

What it means

Raised by _normalize_audio when, after squeezing, the waveform tensor is not 1-D — i.e. the audio is stereo/multi-channel rather than mono. The Dots Omni pipeline only accepts mono waveforms.

Source

Thrown at python/sglang/srt/multimodal/processors/dots_note_omni.py:245

        token_ids = processor.encode(token, add_special_tokens=False)
        if len(token_ids) != 1:
            raise ValueError(
                f"Dots omni special token {token!r} must encode to one id, got "
                f"{token_ids}"
            )
        return token_ids[0]

    @staticmethod
    def _normalize_audio(audio) -> torch.Tensor:
        if isinstance(audio, torch.Tensor):
            waveform = audio
        elif isinstance(audio, np.ndarray):
            waveform = torch.from_numpy(audio)
        else:
            waveform = torch.as_tensor(audio)
        waveform = waveform.float().squeeze()
        if waveform.ndim != 1:
            raise ValueError(
                f"Dots omni audio must be mono, got shape={tuple(waveform.shape)}"
            )
        return waveform.contiguous()

    def _render_video_content(
        self,
        input_text: str,
        question: str,
        video_index: int,
        content: list[dict],
    ) -> tuple[str, dict[str, tuple[Modality, str]]]:
        """Insert one expanded video while retaining its media ordering."""
        rendered = []
        media = {}
        for item in content:
            item_type = item.get("type")
            if item_type == "text":
                rendered.append(item.get("text", ""))

View on GitHub (pinned to 0132848349)

Solutions

  1. Downmix to mono before sending: waveform.mean(axis=channel_axis) or use torchaudio/ffmpeg to convert
  2. If passing a tensor/array, ensure final shape is (num_samples,) or (1, num_samples)
  3. Resample is fine — only channel count matters here

Example fix

# before
audio = stereo_waveform  # shape (2, N)
# after
audio = stereo_waveform.mean(axis=0)  # shape (N,) mono
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
def to_mono(w):
    a = np.asarray(w)
    if a.ndim == 1:
        return a
    if a.ndim == 2 and a.shape[0] <= 8:
        return a.mean(axis=0)
    raise ValueError(f'unsupported audio shape {a.shape}')
audio = to_mono(audio)  # send (N,) mono

Type guard

def is_mono(audio) -> bool:
    import numpy as np
    a = np.asarray(audio)
    return a.ndim == 1 or (a.ndim == 2 and 1 in a.shape)

Prevention

When it happens

Trigger: Sending audio_data (or video-attached audio converted to waveform) whose array has 2+ channels, e.g. shape (2, N); after .squeeze() it stays 2-D, tripping the ndim != 1 check.

Common situations: Users feed stereo WAV/PCM arrays or tensors with a channel dimension; many datasets and TTS outputs default to stereo. Note a shape like (1, N) squeezes to (N,) and passes — only genuinely multi-channel audio fails.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/c713e451c29ec3ba. Report an issue: GitHub.