Skip to content

feat: put text-to-speech providers on one contract and open narration to all of them - #356

Merged
kiyeonjeon21 merged 1 commit into
mainfrom
feat/speech-provider-contract
Oct 5, 2026
Merged

kiyeonjeon21 merged 1 commit into
mainfrom
feat/speech-provider-contract

Conversation

@kiyeonjeon21

Copy link
Copy Markdown
Contributor

Speech counterpart of the video (#349-#353) and image (#355) provider work.

What changes

  • SpeechGenerator (ai-providers/src/speech):
    • synthesize(request) returns audio bytes with their container (ElevenLabs and OpenAI MP3, Kokoro WAV), or throws ProviderError.
    • createSpeechGenerator(provider, key) opens a provider by name.
  • Providers on the contract:
    • ElevenLabs and OpenAI TTS go through providerRequest instead of their own 429 loops.
    • Models resolve through the catalog, which now lists ElevenLabs Multilingual v2 and Flash v2.5, OpenAI tts-1/tts-1-hd (shutting down 2027-01-06), and Kokoro.
  • Checks before any request:
    • ElevenLabs refuses text over a model's character limit (v3 5,000, Multilingual 10,000, Flash 40,000).
    • OpenAI refuses voices that tts-1 does not have.
  • tts-resolve on the registry, so scenes and builds get provider error kinds and the model that spoke.
  • Narration opened up: vibe generate narration and the generate_narration tool were ElevenLabs-only, even though the MCP server's own instructions tell agents to offer Kokoro, OpenAI, or ElevenLabs. They now take --provider auto|elevenlabs|openai|kokoro, --model, and --speed.
  • writeAudioFile converts with ffmpeg when the output extension doesn't match the audio, for example Kokoro WAV to narration.mp3.
  • Auth error: a missing key is now an auth error (exit 4) instead of a generic failure.

Verification

  • Tests:
    • Speech contract suite over the fake network for ElevenLabs and OpenAI: bytes and default model, unknown model and voice refused before sending, bad key as auth.
    • Specifics: the ElevenLabs character limit and Flash fallback, ElevenLabs "0 credits remaining" read as quota, tts-1 voices, Kokoro's empty-text refusal.
    • The tts-resolve tests now run against the registry.
  • Checks: pnpm build, lint, typecheck, tests (providers 239, CLI 1343 including integration, MCP 73), providers:check with 0 warnings, pre-push gate.
  • Live: vibe generate narration with
    • -p openai: 3.77 s MP3.
    • -p kokoro -o kokoro.mp3: WAV converted to a real MP3, 3.13 s.
    • -p elevenlabs -m flash: Flash v2.5, 2.83 s.
    • No key: AUTH_ERROR, exit 4.

https://claude.ai/code/session_011S1BLTaFctZNQzGERpkCuA

… to all of them

- `SpeechGenerator` (ai-providers/src/speech): `synthesize(request)` returns
  audio bytes with their container (ElevenLabs and OpenAI MP3, Kokoro WAV)
  or throws `ProviderError`. `createSpeechGenerator(provider, key)` opens
  one by name.
- ElevenLabs and OpenAI TTS go through `providerRequest` instead of their
  own 429 loops; models resolve through the catalog, which now lists
  ElevenLabs Multilingual v2 and Flash v2.5, OpenAI tts-1/tts-1-hd, and
  Kokoro. ElevenLabs refuses text over a model's character limit, and
  OpenAI refuses voices tts-1 does not have, before any request.
- `tts-resolve` builds on the registry, so scenes and builds get provider
  error kinds and the model that spoke.
- `vibe generate narration` and the `generate_narration` tool were
  ElevenLabs-only; they now take `--provider auto|elevenlabs|openai|kokoro`
  plus `--model` and `--speed`. `writeAudioFile` converts when the output
  extension does not match the audio (Kokoro WAV to `narration.mp3`).
- A missing key is an auth error (exit 4) rather than a generic failure.
- runway.md no longer lists the removed Runway image model.

Claude-Session: https://claude.ai/code/session_011S1BLTaFctZNQzGERpkCuA
@vercel

vercel Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
vibeframe Ready Ready Preview Oct 5, 2026 7:28am UTC

Request Review

@kiyeonjeon21
kiyeonjeon21 merged commit 6cf1c27 into main Oct 5, 2026
6 checks passed
@kiyeonjeon21
kiyeonjeon21 deleted the feat/speech-provider-contract branch October 5, 2026 07:32

This branch was successfully deployed

1 active deployment
Preview — 6248f616 Deployed Oct 5, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant