{"record":{"id":"2c1a14ddab6d4f04","repo":"microsoft/VibeVoice","slug":"audio-duration-duration-sec-1f-s-exceeds-the-c","errorCode":null,"errorMessage":"Audio duration ({duration_sec:.1f}s) exceeds the configured limit ({_MAX_AUDIO_DURATION:.0f}s). Set the VIBEVOICE_MAX_AUDIO_DURATION environment variable to adjust this limit, or use shorter audio.","messagePattern":"Audio duration \\((.+?)s\\) exceeds the configured limit \\((.+?)s\\)\\. Set the VIBEVOICE_MAX_AUDIO_DURATION environment variable to adjust this limit, or use shorter audio\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"vllm_plugin/inputs.py","lineNumber":87,"sourceCode":"        # Load from file path\n        audio_waveform = load_audio(data)\n        \n    elif isinstance(data, bytes):\n        # Decode bytes directly via ffmpeg stdin pipe to avoid temp-file IO\n        audio_waveform, _sr = load_audio_bytes_use_ffmpeg(data, resample=True, target_sr=24000)\n        normalizer = AudioNormalizer()\n        audio_waveform = normalizer(audio_waveform)\n                \n    elif isinstance(data, np.ndarray):\n        # Already loaded numpy array\n        audio_waveform = data\n    else:\n        raise ValueError(f\"Unsupported audio data type: {type(data)}\")\n\n    # Validate audio duration before tensor conversion to catch OOM early\n    duration_sec = len(audio_waveform) / 24000\n    if duration_sec > _MAX_AUDIO_DURATION:\n        raise ValueError(\n            f\"Audio duration ({duration_sec:.1f}s) exceeds the configured \"\n            f\"limit ({_MAX_AUDIO_DURATION:.0f}s). Set the \"\n            f\"VIBEVOICE_MAX_AUDIO_DURATION environment variable to adjust \"\n            f\"this limit, or use shorter audio.\"\n        )\n\n    # Convert to tensor\n    audio_tensor = torch.from_numpy(audio_waveform).float()\n    audio_length = audio_tensor.shape[0]\n    \n    return MultiModalInputs({\n        \"audio\": audio_tensor,\n        \"audio_length\": audio_length\n    })\n","sourceCodeStart":69,"sourceCodeEnd":102,"githubUrl":"https://github.com/microsoft/VibeVoice/blob/94da20d98b2fa7688e9cbfaf7692ddb4954f7600/vllm_plugin/inputs.py#L69-L102","documentation":"A pre-tensorization guard that rejects audio longer than the configured cap. Duration is computed as len(audio_waveform) / 24000 against _MAX_AUDIO_DURATION (overridable via the VIBEVOICE_MAX_AUDIO_DURATION environment variable). The check exists to fail fast before encoder forward passes allocate memory and OOM the GPU on very long clips.","triggerScenarios":"Submitting any clip whose sample count exceeds _MAX_AUDIO_DURATION * 24000; an ndarray supplied at a sample rate other than 24 kHz (e.g. 48 kHz audio makes len()/24000 overestimate duration 2x and can trip the limit spuriously); whole-file ingestion of podcasts/lectures/meetings that exceed the default cap.","commonSituations":"Long-form transcription use cases; users feeding 44.1/48 kHz arrays because the ndarray branch skips resampling (unlike the bytes branch); environments where the operator did not know the limit is env-tunable.","solutions":["Chunk the audio client-side into segments under the limit and transcribe each.","Resample the array to 24 kHz before submission so the duration math is correct (the ndarray path does NOT resample for you).","Raise the cap when memory allows: start the vLLM process with VIBEVOICE_MAX_AUDIO_DURATION=<seconds> set.","Trim silence at the head/tail with ffmpeg/librosa to bring clips under the limit."],"exampleFix":"# before\naudio = librosa.load(\"meeting.wav\", sr=48000)[0]  # 48k array, duration double-counted\ninputs = {\"audio\": audio}\n\n# after\naudio = librosa.load(\"meeting.wav\", sr=24000)[0]  # match the 24 kHz assumption\nsegs = [audio[i:i + 24000*120] for i in range(0, len(audio), 24000*120)]\ninputs = [{\"audio\": seg} for seg in segs]  # <=120 s chunks","handlingStrategy":"validation","validationCode":"import numpy as np\nimport os\n\nMAX_DUR = float(os.environ.get(\"VIBEVOICE_MAX_AUDIO_DURATION\", 120))  # match deployment\nSR = 24000\n\ndef check_duration(wave: np.ndarray):\n    assert wave.ndim == 1, \"expected 1-D waveform\"\n    dur = len(wave) / SR\n    if dur > MAX_DUR:\n        step = int(MAX_DUR * SR * 0.95)\n        return [wave[i:i+step] for i in range(0, len(wave), step)]\n    return [wave]","typeGuard":"def is_within_duration(wave: np.ndarray, max_dur: float) -> bool:\n    return len(wave) / 24000 <= max_dur","tryCatchPattern":"try:\n    out = llm.generate(prompt, multi_modal_data={\"audio\": wave})\nexcept ValueError as e:\n    if \"exceeds the configured limit\" in str(e):\n        results = [llm.generate(prompt, {\"audio\": seg}) for seg in chunk(wave)]\n    else:\n        raise","preventionTips":["Always resample to 24 kHz before submission — the ndarray path assumes it.","Chunk long recordings at the ingestion layer instead of relying on the server error.","Record the deployment's VIBEVOICE_MAX_AUDIO_DURATION in your client config so both sides agree."],"tags":["audio","duration-limit","oom-prevention","configuration","vllm"],"backgroundTag":null,"analyzedSha":"94da20d98b2fa7688e9cbfaf7692ddb4954f7600","analyzedAt":"2026-08-15T04:12:07.418Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}