diff --git a/backend/python/pocket-tts/backend.py b/backend/python/pocket-tts/backend.py index d372d0d11..ef073ad0c 100644 --- a/backend/python/pocket-tts/backend.py +++ b/backend/python/pocket-tts/backend.py @@ -102,9 +102,17 @@ class BackendServicer(backend_pb2_grpc.BackendServicer): self.default_voice_url = self.options.get("default_voice", None) self._voice_cache = {} + # Pocket TTS ships a separate model per language (english, french, + # german, ...) and load_model() falls back to English when no language + # is given, so the option has to reach the loader to pick another one. + load_kwargs = {} + language = self.options.get("language") + if language: + load_kwargs["language"] = str(language) + try: - print("Loading Pocket TTS model", file=sys.stderr) - self.tts_model = TTSModel.load_model() + print(f"Loading Pocket TTS model (language: {load_kwargs.get('language', 'default')})", file=sys.stderr) + self.tts_model = TTSModel.load_model(**load_kwargs) print(f"Model loaded successfully. Sample rate: {self.tts_model.sample_rate}", file=sys.stderr) # Pre-load default voice if specified diff --git a/backend/python/pocket-tts/test.py b/backend/python/pocket-tts/test.py index 34efa1080..8f9b18ba1 100644 --- a/backend/python/pocket-tts/test.py +++ b/backend/python/pocket-tts/test.py @@ -6,6 +6,7 @@ import subprocess import time import os import tempfile +from unittest import mock import backend_pb2 import backend_pb2_grpc @@ -139,3 +140,33 @@ class TestBackendServicer(unittest.TestCase): self.fail("TTS service with default voice failed") finally: self.tearDown() + + +class TestLanguageOption(unittest.TestCase): + """ + Checks that the language option reaches TTSModel.load_model without + downloading any weights. + """ + def _load_model(self, options): + import backend + + fake_model = mock.MagicMock() + fake_model.sample_rate = 24000 + with mock.patch.object(backend.TTSModel, "load_model", return_value=fake_model) as load_model: + response = backend.BackendServicer().LoadModel( + backend_pb2.ModelOptions(Options=options), None + ) + self.assertTrue(response.success, response.message) + return load_model + + def test_language_option_selects_model(self): + load_model = self._load_model(["language:french"]) + load_model.assert_called_once_with(language="french") + + def test_versioned_language_option(self): + load_model = self._load_model(["language:english_2026-04"]) + load_model.assert_called_once_with(language="english_2026-04") + + def test_no_language_keeps_library_default(self): + load_model = self._load_model(["default_voice:azelma"]) + load_model.assert_called_once_with() diff --git a/docs/content/features/text-to-audio.md b/docs/content/features/text-to-audio.md index 4b7140600..8d070e1e3 100644 --- a/docs/content/features/text-to-audio.md +++ b/docs/content/features/text-to-audio.md @@ -701,6 +701,19 @@ curl http://localhost:8080/tts -H "Content-Type: application/json" -d '{ }' | aplay ``` +#### Languages + +Pocket TTS has a separate model for each language and loads the English one by default. Set the `language` option to load another: + +```yaml +name: pocket-tts-french +backend: pocket-tts +options: + - "language:french" +``` + +Supported values depend on the installed `pocket-tts` version; current releases accept `english`, `french`, `german`, `italian`, `spanish`, `portuguese` and `dutch`, plus variants such as `french_24l` and `english_2026-04`. The built-in voice names are resolved against the selected language model. + ### Qwen3-TTS [Qwen3-TTS](https://github.com/QwenLM/Qwen3-TTS) is a high-quality text-to-speech model that supports three modes: custom voice (predefined speakers), voice design (natural language instructions), and voice cloning (from reference audio). diff --git a/gallery/pocket-tts.yaml b/gallery/pocket-tts.yaml index f4edb130b..63c035f17 100644 --- a/gallery/pocket-tts.yaml +++ b/gallery/pocket-tts.yaml @@ -35,3 +35,6 @@ config_file: |- # If set, this voice will be loaded when the model loads for faster first generation - "default_voice:azelma" # - "default_voice:hf://kyutai/tts-voices/alba-mackenna/casual.wav" + # Language model to load (defaults to English), e.g. french, german, + # italian, spanish, portuguese, dutch + # - "language:french"