harry0703/MoneyPrinterTurbo · error · ValueError

MiniMax TTS returned audio with an invalid duration

Error message

MiniMax TTS returned audio with an invalid duration

What it means

After MiniMax TTS audio bytes are written to a temp file, the code opens it with moviepy AudioFileClip and reads duration. If duration is not finite or is <= 0 (empty/corrupt audio, zero-byte decode), it raises ValueError; the finally block removes the temp file so no partial output lands at voice_file.

Source

Thrown at app/services/voice.py:1477

    output_dir = os.path.dirname(os.path.abspath(voice_file))
    output_suffix = os.path.splitext(voice_file)[1] or ".mp3"
    temp_fd, temp_path = tempfile.mkstemp(
        prefix=".minimax-tts-", suffix=output_suffix, dir=output_dir
    )
    os.close(temp_fd)

    try:
        with open(temp_path, "wb") as output:
            output.write(audio_bytes)

        audio_clip = AudioFileClip(temp_path)
        try:
            audio_duration = float(audio_clip.duration)
        finally:
            audio_clip.close()

        if not math.isfinite(audio_duration) or audio_duration <= 0:
            raise ValueError("MiniMax TTS returned audio with an invalid duration")

        os.replace(temp_path, voice_file)
        return audio_duration
    finally:
        if os.path.exists(temp_path):
            os.remove(temp_path)


def minimax_tts(text: str, voice_id: str, voice_rate: float, voice_file: str, voice_volume: float = 1.0) -> Union[SubMaker, None]:
    """Generate speech with the synchronous MiniMax T2A HTTP API."""
    text, voice_id = (text or "").strip(), (voice_id or "").strip()
    if not text or not voice_id:
        logger.error("MiniMax TTS requires text and a voice ID")
        return None
    settings = config.minimax_tts
    api_key = get_minimax_tts_api_key()
    if not api_key:
        logger.error("MiniMax TTS API key is not set")

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Retry the synthesis once — truncated audio from upstream is usually transient.
  2. Check the input text is non-empty after stripping; avoid feeding only punctuation/whitespace.
  3. If persistent, save and inspect the raw audio bytes returned by MiniMax (decode with ffprobe) to see whether corruption is upstream or local.
  4. Update moviepy/ffmpeg — decoding of some MiniMax encodings depends on the local ffmpeg build.
Defensive patterns

Strategy: retry

Validate before calling

text = (text or "").strip()
if not text:
    raise ValueError("refusing to synthesize empty text")

Try / catch

try:
    duration = minimax_tts_to_file(...)
except ValueError as exc:
    if "invalid duration" in str(exc):
        return minimax_tts_to_file(...)  # one retry for truncated upstream audio
    raise

Prevention

When it happens

Trigger: MiniMax returns a 200 response whose audio payload decodes to a zero-length or corrupt WAV/MP3; the container header is valid but frames are missing so moviepy reports duration 0 or NaN.

Common situations: Upstream serving a stub audio on overload; encoding change in MiniMax output that the local decoder mishandles; extremely short/whitespace-only input text producing empty audio.

Related errors


AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14). Data as JSON: /api/errors/66d9dca99452d293. Report an issue: GitHub.