Configure Supertonic 3

You’ll create tts.py to turn the Spanish translation from Translate text with Gemma 4 E2B into spoken audio. The script will use Supertonic 3 through Sherpa-ONNX to synthesize speech, then sounddevice to play it through the default output device for your Mac.

You’ll first check the output device and create the script. You’ll then run it and paste in the Spanish text to test playback. The model will stay loaded so that you can try several sentences in the same session.

Continuing in the ~/voice-translator directory with the active virtual environment, list the output devices visible to Python:

    

        
        
python -m sounddevice

    

Confirm that the list contains your Mac speakers, headphones, or another output device.

Using a file editor of your choice, create a file named tts.py in the ~/voice-translator directory. Copy and paste the following code into the file and save it:

    

        
        
import argparse
from pathlib import Path

import sherpa_onnx
import sounddevice as sd

from languages import LANGUAGES


MODEL = Path("models/sherpa-onnx-supertonic-3-tts-int8-2026-05-11")


def create_tts():
    config = sherpa_onnx.OfflineTtsConfig(
        model=sherpa_onnx.OfflineTtsModelConfig(
            supertonic=sherpa_onnx.OfflineTtsSupertonicModelConfig(
                duration_predictor=str(
                    MODEL / "duration_predictor.int8.onnx"
                ),
                text_encoder=str(MODEL / "text_encoder.int8.onnx"),
                vector_estimator=str(
                    MODEL / "vector_estimator.int8.onnx"
                ),
                vocoder=str(MODEL / "vocoder.int8.onnx"),
                tts_json=str(MODEL / "tts.json"),
                unicode_indexer=str(MODEL / "unicode_indexer.bin"),
                voice_style=str(MODEL / "voice.bin"),
            ),
            num_threads=8,
            debug=False,
            provider="cpu",
        ),
    )

    if not config.validate():
        raise ValueError("model path")

    return sherpa_onnx.OfflineTts(config)


def synthesise(tts, text, language_code):
    config = sherpa_onnx.GenerationConfig()
    config.sid = 6
    config.speed = 1.0
    config.num_steps = 8
    config.extra = {"lang": language_code}

    audio = tts.generate(text, config)
    if len(audio.samples) == 0:
        raise RuntimeError("no audio generated")

    return audio


def speak(tts, text, language_code):
    audio = synthesise(tts, text, language_code)
    duration = len(audio.samples) / audio.sample_rate
    print(f"Playing {duration:.1f}s of audio...")
    sd.play(audio.samples, samplerate=audio.sample_rate)
    sd.wait()


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("language", choices=LANGUAGES)
    args = parser.parse_args()

    print("Loading Supertonic 3")
    tts = create_tts()

    while True:
        text = input(
            f"{args.language} text (press Enter to quit): "
        ).strip()
        if not text:
            break

        speak(tts, text, LANGUAGES[args.language])


if __name__ == "__main__":
    main()

    

create_tts() loads the model, synthesise() returns audio samples and their sample rate, and speak() plays them.

The model configuration uses the downloaded quantized files and selects the CPU with eight threads. config.validate() checks the configuration before the model is loaded.

The generation settings select voice preset 6 with sid, normal speed with speed=1.0, and eight generation steps with num_steps. config.extra receives the language code from LANGUAGES: {"lang": "es"} when you select Spanish. Assign the complete dictionary because modifying an item in config.extra doesn’t persist the change in this version of the Python bindings.

speak() uses the sample rate returned by Supertonic when calling sd.play(). It then waits for playback to finish before accepting another sentence.

Generate and play translated speech

Run the script with Spanish as the target language:

    

        
        
python tts.py Spanish

    

At the prompt, paste the Spanish translation:

    

        
        
¿Dónde está la estación de tren más cercana?

    

The script reports the duration and plays the sentence through the default output device. The output is similar to:

    

        
        Loading Supertonic 3
Spanish text (press Enter to quit): ¿Dónde está la estación de tren más cercana?
Playing 2.8s of audio...
Spanish text (press Enter to quit):

        
    

The duration varies with the generated speech. Confirm that you hear the complete sentence with Spanish pronunciation. Press Enter at an empty prompt to exit the script and return to the shell before continuing.

If you don’t hear audio, you might need to run python -m sounddevice again and confirm that macOS has selected the intended output device.

Note

The desktop application will collect all translation chunks before calling synthesise(). This gives Supertonic the complete text. It also means that you need to wait for translation and synthesis before hearing any audio. Only the displayed translation text streams in this implementation.

What you’ve accomplished and what’s next

You’ve generated and played translated speech using Supertonic 3. You can now test recording, translation, and playback separately with stt.py, translate.py, and tts.py.

Next, you’ll import the three functions into a Gradio application so that one English recording produces a transcript, Spanish translation, and spoken Spanish result.

Back
Next