Update provider seeding logic and documentation to allow creation of admin/shared providers without requiring an API key. Adjust environment variable handling so that a blank or missing API_KEY is valid when API_BASE is set, enabling support for upstream TTS providers that do not require authentication. Remove defaulting to 'none' for API keys in API routes and ensure headers are omitted when no key is present. Add and update tests to verify correct handling of keyless providers. BREAKING CHANGE: Providers can now be seeded without an API key; API_KEY is no longer required if API_BASE is set. Existing deployments relying on a non-empty API_KEY for seeding should review their environment configuration.
1.7 KiB
1.7 KiB
| title |
|---|
| Other |
Use any OpenAI-compatible TTS service with OpenReader, including self-hosted servers not covered by a dedicated guide.
Requirements
Your service must expose these endpoints:
GET /v1/audio/voicesPOST /v1/audio/speech
Known compatible implementations: Kokoro-FastAPI, KittenTTS-FastAPI, Orpheus-FastAPI.
Setup
Recommended (auth + admin): Settings → Admin → Shared providers
- Add a shared provider with type
custom-openai. - Set
API_BASEto your service base URL (typically ending in/v1). - Set API key if your service requires authentication.
- Set a default model/voice supported by your backend.
Legacy bootstrap seed (optional, first boot only):
API_BASE=http://your-tts-server/v1
# API_KEY=optional-key-if-required
Or in-app via Settings → TTS Provider:
- Set provider to
Custom OpenAI-Like. - Set
API_BASEto your service's base URL (typically ending in/v1). - Set
API_KEYif your service requires authentication. - Choose a model and voice supported by your backend.
See TTS Providers for admin-shared vs per-user behavior.
:::warning TTS requests are server-side
API_BASE must be reachable from the Next.js server, not just the browser. In Docker, use container names or host.docker.internal.
:::
Troubleshooting
If voices don't load, check that /v1/audio/voices is reachable from the server and returns a valid response shape.