feat: add Lokutor TTS plugin - #7256
Conversation
|
Thanks for the review β addressed the flagged issues in the latest commit:
|
There was a problem hiding this comment.
Devin Review found 1 new potential issue.
3 flags not posted on this PR by your GitHub settings β view them in Devin Review. (Configure)
| session.ws_connect( | ||
| self._opts.get_ws_url(), | ||
| max_msg_size=0, | ||
| headers={"X-API-Key": self._opts.api_key}, |
There was a problem hiding this comment.
π΄ Header authentication blocks all synthesis
Every TTS request sends X-API-Key, but Lokutor's WebSocket handshake accepts only the api_key query parameter. The upgrade fails before either synthesis path can emit audio.
Learn more
Lokutor authenticates /ws/tts during the WebSocket handshake. Its authentication and streaming API documentation specifies ?api_key=... for WebSockets; X-API-Key is documented for REST endpoints. The new request reaches the correct endpoint without the only supported WebSocket credential, so the server rejects it before any JSON synthesis request is sent.
Example: With api_key="sk_test", the plugin connects to wss://api.lokutor.com/ws/tts with an X-API-Key header. Lokutor expects wss://api.lokutor.com/ws/tts?api_key=sk_test, so both stream() and synthesize() fail during connection setup instead of returning audio.
Recommended fix: Confirm and adopt a Lokutor-supported WebSocket authentication mechanism that keeps credentials out of observable URLs. If header authentication is unavailable, coordinate provider support or add explicit sanitization around every URL-bearing exception and telemetry path before retaining query authentication.
Was this helpful? React with π or π to provide feedback.
Streaming + one-shot TTS integration for Lokutor (CPU-only voice AI, 10 voices, 32 languages) over Lokutor's WebSocket API. Follows the LiveKit plugin conventions (ConnectionPool, AudioEmitter, prewarm, typed error mapping), ships py.typed, sends the API key via header, pins the fixed 44.1 kHz output, and includes unit tests plus gated live-integration tests. Registered in the root workspace sources + uv.lock.
0327952 to
acaf2d1
Compare
|
Re: the "Header authentication blocks all synthesis" flag β this is a false positive. Lokutor's WebSocket handshake does accept the Verified against production
If the header were ignored, the header case would return The remaining red |
|
This is ready for a maintainer review whenever someone has a moment π Quick status recap:
Lokutor is a CPU-only TTS provider (10 voices, 32 languages); the plugin follows the standard conventions (ConnectionPool, AudioEmitter, prewarm, typed errors, py.typed) with unit + gated live-integration tests. Thanks for taking a look! |
Summary
Adds
livekit-plugins-lokutor, a TTS integration for Lokutor β a CPU-only voice-AI platform (no GPU) with 10 voices (F1βF5, M1βM5) and 32 languages.The plugin connects to Lokutor's WebSocket TTS API and supports both streaming (
stream()) and one-shot (synthesize()) synthesis, following the standard LiveKit plugin conventions:utils.ConnectionPoolfor pooled/prewarmed WebSocket connections (prewarm()supported)tts.AudioEmitterfor streaming PCM framesAPIStatusError/APITimeoutError/APIConnectionError)py.typed(PEP 561)Usage
Testing
tests/test_plugin_lokutor_tts.py) covering config, request building, and stream construction.tests/test_integration.py) that run against the real API whenLOKUTOR_API_KEYis set, exercising the full connect β request β binary audio βEOSpath.ruff checkandruff format --checkpass.Notes
Supersedes #5925 (that PR was opened from
main, had drifted into conflicts, and shipped an older revision). This one is a clean feature branch on top of currentmainand uses Lokutor's current canonical request vocabulary (voice/language/speed/steps), with all 32 languages. CLA is already signed.