# How to Customize TTS Voice and Speaker Settings in the Hugging Face Speech‑to‑Speech Repository

> Easily customize TTS voice and speaker settings in the Hugging Face speech-to-speech repository. Learn to configure voice, speaker, language, and cloning arguments with our modular handler pattern.

- Repository: [Hugging Face/speech-to-speech](https://github.com/huggingface/speech-to-speech)
- Tags: how-to-guide
- Published: 2026-08-06

---

The huggingface/speech-to-speech repository provides a **modular handler pattern** where every TTS engine exposes its own argument dataclass for voice, speaker, language, and voice-cloning configuration.

Each TTS backend inherits from the abstract `BaseHandler` class and declares its customization surface through a dedicated arguments dataclass. This design lets you control voice output via CLI flags when running the full pipeline or programmatically when building custom workflows.

## TTS Handler Architecture

The repository isolates voice synthesis behind three core components:

- **Argument dataclasses** — Define CLI/API options per engine (e.g., `Qwen3TTSHandlerArguments`, `PocketTTSHandlerArguments`, `KokoroTTSHandlerArguments`)
- **Handler implementations** — Consume arguments, load models, resolve speakers, and stream audio blocks
- **Pipeline orchestration** — Parses prefixed arguments with `HfArgumentParser` and injects configured objects into handlers

All TTS handlers in `src/speech_to_speech/TTS/` inherit from `BaseHandler` in [`src/speech_to_speech/baseHandler.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/baseHandler.py), which enforces a unified `setup()` / `generate()` contract.

## Customizing Voice and Speaker by Engine

### Qwen-3-TTS: Preset Speakers and Voice Cloning

The `Qwen3TTSHandler` in [`src/speech_to_speech/TTS/qwen3_tts_handler.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/TTS/qwen3_tts_handler.py) supports two modes: preset speaker selection and zero-shot voice cloning.

**CLI: Select a preset speaker**

```bash
python -m speech_to_speech.s2s_pipeline \
  --qwen3_tts_speaker "Jordan" \
  --qwen3_tts_language "en" \
  --qwen3_tts_ref_audio ""

```

The `qwen3_tts_speaker` argument accepts any value from `_supported_speakers()`. When `speaker` is `None` or empty, the handler falls back to the first supported speaker (lines 575–588 in [`qwen3_tts_handler.py`](https://github.com/huggingface/speech-to-speech/blob/main/qwen3_tts_handler.py)).

**CLI: Voice cloning with reference audio**

```bash
python -m speech_to_speech.s2s_pipeline \
  --qwen3_tts_ref_audio /path/to/my_voice.wav \
  --qwen3_tts_ref_text "Hello, I am your custom avatar." \
  --qwen3_tts_speaker ""

```

Explicitly emptying `--qwen3_tts_speaker` triggers cloning mode. The handler extracts speaker characteristics from the reference file and associated transcript (lines 92–118).

**Python: Direct handler instantiation with preset speaker**

```python
from speech_to_speech.TTS.qwen3_tts_handler import Qwen3TTSHandler
from threading import Event

handler = Qwen3TTSHandler()
handler.setup(
    should_listen=Event(),
    speaker="Aiden",
    language="en",
    device="cuda"
)

for chunk in handler.generate("Hello, world!"):
    # chunk: NumPy array of audio samples

    play(chunk)

```

**Python: Voice cloning with pre-computed embedding**

```python
from speech_to_speech.TTS.qwen3_tts_handler import Qwen3TTSHandler
from threading import Event

handler = Qwen3TTSHandler()
handler.setup(
    should_listen=Event(),
    ref_audio="/data/my_voice.wav",
    ref_text="I am a synthetic narrator.",
    speaker=None,  # triggers cloning path

    device="cuda"
)

```

### Pocket-TTS: Lightweight Voice Selection

The `PocketTTSHandler` in [`src/speech_to_speech/TTS/pocket_tts_handler.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/TTS/pocket_tts_handler.py) uses a simpler `pocket_tts_voice` string argument.

**CLI usage:**

```bash
python -m speech_to_speech.s2s_pipeline \
  --pocket_tts_voice "cosette"

```

**Python programmatic configuration:**

```python
from speech_to_speech.arguments_classes.pocket_tts_arguments import PocketTTSHandlerArguments
from speech_to_speech.s2s_pipeline import parse_arguments

# Pre-configure before pipeline parsing

pocket_args = PocketTTSHandlerArguments(pocket_tts_voice="cosette")
args = parse_arguments()
args.pocket_tts_handler_kwargs = pocket_args

```

The argument dataclass is defined in [`src/speech_to_speech/arguments_classes/pocket_tts_arguments.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/arguments_classes/pocket_tts_arguments.py).

### Kokoro TTS: Voice and Language Code Pairs

The `KokoroTTSHandler` in [`src/speech_to_speech/TTS/kokoro_handler.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/TTS/kokoro_handler.py) requires both `voice` and `lang_code` parameters (defined in `KokoroTTSHandlerArguments`).

**CLI example:**

```bash
python -m speech_to_speech.s2s_pipeline \
  --kokoro_tts_voice "af_bella" \
  --kokoro_tts_lang_code "en-us"

```

## Argument Parsing and Pipeline Wire-Up

The central entry point [`src/speech_to_speech/s2s_pipeline.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/s2s_pipeline.py) uses `HfArgumentParser` to collect all TTS-specific arguments. Each engine prefixes its flags to avoid collision:

| Engine | Prefix | Example Flag |
|--------|--------|--------------|
| Qwen-3-TTS | `--qwen3_tts_*` | `--qwen3_tts_speaker` |
| Pocket-TTS | `--pocket_tts_*` | `--pocket_tts_voice` |
| Kokoro TTS | `--kokoro_tts_*` | `--kokoro_tts_voice` |

After parsing, the pipeline instantiates handlers and passes the configured argument objects to each `setup()` method.

## Key Files for Voice Customization

| Path | Purpose |
|------|---------|
| [`src/speech_to_speech/arguments_classes/qwen3_tts_arguments.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/arguments_classes/qwen3_tts_arguments.py) | `Qwen3TTSHandlerArguments` dataclass with all Qwen-3-TTS options |
| [`src/speech_to_speech/TTS/qwen3_tts_handler.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/TTS/qwen3_tts_handler.py) | Speaker resolution, voice cloning, and streaming logic |
| [`src/speech_to_speech/arguments_classes/pocket_tts_arguments.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/arguments_classes/pocket_tts_arguments.py) | `PocketTTSHandlerArguments` for Pocket-TTS voice selection |
| [`src/speech_to_speech/TTS/pocket_tts_handler.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/TTS/pocket_tts_handler.py) | Lightweight TTS handler implementation |
| [`src/speech_to_speech/TTS/kokoro_handler.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/TTS/kokoro_handler.py) | Kokoro TTS with `voice` + `lang_code` pairing |
| [`src/speech_to_speech/s2s_pipeline.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/s2s_pipeline.py) | Central parser and handler graph construction |
| [`src/speech_to_speech/baseHandler.py`](https://github.com/huggingface/speech-to-speech/blob/main/src/speech_to_speech/baseHandler.py) | Abstract base class enforcing `setup`/`generate` contract |

## Summary

- **TTS voice customization** flows through engine-specific argument dataclasses parsed by `HfArgumentParser` in the pipeline entry point
- **Qwen-3-TTS** supports preset speakers via `qwen3_tts_speaker` or voice cloning via `qwen3_tts_ref_audio` and `qwen3_tts_ref_text`
- **Pocket-TTS** uses a single `pocket_tts_voice` string for speaker selection
- **Kokoro TTS** requires paired `voice` and `lang_code` arguments
- **Direct handler instantiation** bypasses CLI parsing and enables programmatic control of all speaker/voice parameters

## Frequently Asked Questions

### How do I list available preset speakers for Qwen-3-TTS?

Call `_supported_speakers()` on an initialized `Qwen3TTSHandler` instance. The method queries the backend and returns valid speaker names. If you pass an invalid speaker name to `setup()`, the handler will raise a validation error before generation begins.

### Can I use voice cloning with Pocket-TTS or Kokoro?

No. Voice cloning is only implemented in `Qwen3TTSHandler`. The cloning pipeline requires reference audio processing and speaker embedding extraction that the other engines do not support. For Pocket-TTS and Kokoro, restrict yourself to the built-in voice presets.

### What happens if I omit the speaker argument entirely?

Each handler has a fallback strategy. In `Qwen3TTSHandler`, `None` triggers the first supported speaker via `_resolve_speakers()`. Check the specific handler's `setup()` implementation in the source file to understand its default behavior.

### How do I change voice settings at runtime without restarting the pipeline?

Instantiate handlers directly rather than through the CLI pipeline. Call `handler.setup()` with new parameters, or maintain multiple handler instances with different configurations. The `BaseHandler` contract in [`baseHandler.py`](https://github.com/huggingface/speech-to-speech/blob/main/baseHandler.py) ensures consistent re-initialization semantics across all engines.