babysor/MockingBird · error · RuntimeError

kokoro-tts failed for cue {cue.index}: {proc.stderr}

Error message

kokoro-tts failed for cue {cue.index}: {proc.stderr}

What it means

RuntimeError raised in _kokoro_tts when the kokoro-tts subprocess exits non-zero for a cue; its stderr is captured and embedded. The command is built from cue text, voice, speed, and output format, then run against a temp script file.

Source

Thrown at skills/speak/scripts/render_timeline.py:342

        tmp.write(cue.text)
        tmp_path = tmp.name

    try:
        cmd = ["kokoro-tts", tmp_path, str(out_path)]
        voice = cfg.get("voice")
        if voice:
            cmd += ["--voice", str(voice)]
        lang = cfg.get("lang")
        if lang:
            cmd += ["--lang", str(lang)]
        speed = cfg.get("speed")
        if speed is not None:
            cmd += ["--speed", str(speed)]
        cmd += ["--format", output_format]

        proc = subprocess.run(cmd, capture_output=True, text=True)
        if proc.returncode != 0:
            raise RuntimeError(
                f"kokoro-tts failed for cue {cue.index}: {proc.stderr}"
            )
    finally:
        Path(tmp_path).unlink(missing_ok=True)

    if out_path.exists():
        return probe_duration_ms(out_path) / 1000.0
    raise RuntimeError(f"kokoro-tts produced no output for cue {cue.index}")


# ── main ─────────────────────────────────────────────────────────────


def main() -> int:
    ap = argparse.ArgumentParser(
        description="Render timeline-accurate speech from SRT."
    )
    ap.add_argument("--srt", required=True, help="Input SRT file")

View on GitHub (pinned to 28dc5e14f1)

Solutions

  1. Run kokoro-tts manually with the same args to see full stderr
  2. Pre-download/verify model assets per the CLI's docs
  3. Sanitize cue text (strip emoji/control chars) before rendering
  4. Use a supported --format value (e.g. wav)

Example fix

# before
text = cue.text
# after
import re
text = re.sub(r'[\U0001F000-\U0001FAFF\u2600-\u27BF]', '', cue.text).strip()
Defensive patterns

Strategy: try-catch

Validate before calling

import re
clean = re.sub(r'[^\S\n ]+', '', cue.text).strip()
assert clean, f'cue {cue.index} has no speakable text'

Try / catch

try:
    _kokoro_tts(cue, cfg, fmt, ...)
except RuntimeError as e:
    print(f'cue {cue.index} failed: {e}')
    raise if not cfg.get('skip_failed_cues') else None

Prevention

When it happens

Trigger: Cue text containing characters that break the temp input handling, an invalid voice name or unsupported --format value, model files not downloaded, or speed out of the CLI's accepted range.

Common situations: First run before model weights are fetched, emoji/unicode in subtitle lines, or format strings like 'mp3' where the build only supports wav.

Related errors


AI-assisted analysis of babysor/MockingBird@28dc5e14f1 (2026-08-27). Data as JSON: /api/errors/94d4af51664ed857. Report an issue: GitHub.