Shared SDK for kreeader-studio TTS plugins: implements the studio HTTP contract (manifest/design/clone/speak/settings/voices + OpenAI-compat) so each engine plugin only writes a thin EngineAdapter.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Andrew Tyler be421daef2 sdk: run real engine calls off the event loop; document v0.3.0 contract
Review fixes (final review M8/M9):
- M9: design/clone/speak on a real EngineAdapter now run via
  starlette run_in_threadpool so one synthesis no longer blocks health,
  the panel, or other requests. The deterministic MockAdapter stays
  inline (no model work to isolate).
- M8: README updated to the v0.3.0 interface — design/clone return
  (bytes, metadata), speak receives a FrozenVoice, and clone requires a
  non-empty consent/rights field — with a breaking-change migration note.
  The consent requirement is an intentional voice-clone safeguard and is
  kept (this is the plugin fleet, not studio-dev's no-gate policy).

Tests: 15 passed.

Co-Authored-By: Sol via Codex <noreply@openai.com>
2026-08-14 16:01:00 -05:00
src/kreeader_tts_sdk sdk: run real engine calls off the event loop; document v0.3.0 contract 2026-08-14 16:01:00 -05:00
tests SDK v0.3.0: studio web panel served at / and /ui (registry#1) 2026-08-14 15:22:00 -05:00
.gitignore kreeader-tts-sdk: shared studio TTS-plugin contract + mock engine 2026-08-12 23:35:49 -05:00
CLAUDE.md kreeader-tts-sdk: shared studio TTS-plugin contract + mock engine 2026-08-12 23:35:49 -05:00
plugin.toml kreeader-tts-sdk: shared studio TTS-plugin contract + mock engine 2026-08-12 23:35:49 -05:00
pyproject.toml SDK v0.3.0: studio web panel served at / and /ui (registry#1) 2026-08-14 15:22:00 -05:00
README.md sdk: run real engine calls off the event loop; document v0.3.0 contract 2026-08-14 16:01:00 -05:00

kreeader TTS SDK

kreeader-tts-sdk implements the shared HTTP, manifest, settings, and frozen-voice contract for out-of-process kreeader-studio TTS plugins. Engine repositories only provide an EngineAdapter; this package never imports an engine or PyTorch.

Adapter contract

Version 0.3.0 is a breaking adapter/HTTP contract revision. Migrating from 0.2.x: return (wav_bytes, metadata) from design and clone, accept a FrozenVoice in speak, and send both affirmative consent and a non-empty rights field when cloning.

An adapter supplies capabilities() and settings_schema(), creates frozen WAV voices with design() and/or clone(), renders them with speak(), and reports health(). Unsupported voice sources raise NotSupported. All audio crossing this interface is a complete WAV byte string.

from kreeader_tts_sdk import EngineAdapter, FrozenVoice, NotSupported, create_app

class MyEngine(EngineAdapter):
    def capabilities(self): return {"voice_sources": ["sample"], "languages": ["en"], "emotion": "none", "speed_control": False, "streaming": False, "watermark": None, "hardware": {"cpu_ok": True}, "engine": {"name": "mine", "version": "1"}}
    def settings_schema(self): return {"properties": {}, "defaults": {}}
    def design(self, description, seed, lang, settings): raise NotSupported("sample only")
    def clone(self, reference_wav, transcript, settings):
        wav = my_engine.clone(reference_wav, transcript)
        return wav, {"engine_voice_id": my_engine.voice_id(wav)}
    def speak(self, voice: FrozenVoice, text, emotion, cues, rate, settings):
        return my_engine.speak(voice.wav, text, rate=rate)
    def health(self): return {"status": "ok", "engine": {"name": "mine", "version": "1"}}

app = create_app(MyEngine(), "plugin.toml", "./plugin-data")

The adapter runs behind FastAPI in its own Python process. Its plugin.toml holds stable plugin metadata—ID, display name, license, and artifact—while live adapter capabilities and PLUGIN_VERSION form the runtime manifest.

Mock server

From a source checkout:

PYTHONPATH=src python -m kreeader_tts_sdk.dev --adapter mock --port 8080

The mock supports both voice sources and generates deterministic PCM16 tones. It requires no model files and is useful in CI. Its temporary voice store can be made persistent with --data-dir PATH.

Endpoints

  • GET /studio/health
  • GET /studio/manifest
  • GET, PUT /studio/settings
  • GET /studio/voices
  • POST /studio/voices/design
  • POST /studio/voices/clone
  • DELETE /studio/voices/{voice_ref}
  • POST /studio/speak
  • POST /v1/audio/speech

Clone requests are multipart uploads and require an explicitly true consent field plus a non-empty license or source_rights field. Every frozen voice is stored as voices/<voice_ref>/voice.wav beside meta.json, including its SHA-256, source, provenance, creation time, and clone consent/license where applicable.