> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://onepin.ai/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://onepin.ai/docs/_mcp/server.

# Generator

> The Onepin Generator node (operator_generator) — the TTS engine. Configure voice_map to assign a provider voice and a catalog model per language, and get the two identifiers right.

**Family: Operator · `type: operator_generator`**

The Generator is the TTS engine. It assigns a voice and model per language and synthesizes the audio — this is where speech is made, and it's required in every runnable workflow (Export needs the audio only the Generator produces).

## Config

The `voice_map` maps each language to one or more voice assignments:

```python
node["config"] = {"voice_map": {"en-us": [
    {"voice_id": voice.provider_voice_id,     # ⚠ the PROVIDER's voice id
     "provider": "elevenlabs",
     "model": "eleven_multilingual_v2"}       # the catalog model id
]}}
```

Workflows that translate into several languages have one `voice_map` entry per language. Leave a language's list **empty** (`"ko-kr": []`) and [auto-route](/docs/guides/auto-route) picks the best model for it from Onepin's continuous benchmarks.

> **Warning**
>
> Three identifiers to get right:
>
> 1. **`voice_id` is the provider's voice ID** (`provider_voice_id` on a voice object), *not* the Onepin voice UUID you see in `voices list`.
> 2. **`model` is the catalog model ID** — the Model ID shown on [Voices & Models](/docs/get-started/voices-models), which is what `GET /providers/{provider}/models` returns (e.g. `eleven_multilingual_v2`, `sonic-preview`). There is no separate provider-side name to pass here.
> 3. **An imported voice needs `catalog_voice_id` as well.** A voice with `source: "provider_imported"` ([BYOK](/docs/guides/bring-your-own-key)) carries a provider wire id that is unique per workspace, not globally, so the assignment must also carry the Onepin catalog UUID (`catalog_voice_id`). Without it the definition is rejected with rule `voice_imported_needs_catalog_id`.

## Shape the delivery

Each voice assignment takes optional `canonical_controls` — provider-agnostic knobs mapped to the model's native controls at synthesis time:

```python
{"voice_id": "...", "provider": "elevenlabs", "model": "eleven_multilingual_v2",
 "canonical_controls": {"speed": 60, "emotion": "cheerful"}}
```

| Control                                     | Values                                                                  |
| ------------------------------------------- | ----------------------------------------------------------------------- |
| `speed` · `pitch` · `volume` · `randomness` | 0–100, where 50 = the model's native default                            |
| `emotion`                                   | An enum that varies per model — check the model in the provider catalog |

A control the chosen model doesn't support is dropped with a warning, not an error.

## Get valid voice + model pairs

Pull the provider catalog to see which models a provider offers and which voices each model supports:

#### Python

```python
models = client.providers.list_catalog_provider_models("elevenlabs").data
voices = client.providers.list_catalog_provider_model_voices(
    "elevenlabs", "eleven_multilingual_v2").data
```

#### CLI

```bash
onepin voices list --provider elevenlabs
```

#### API

```bash
curl "https://api.onepin.ai/api/v1/providers/elevenlabs/models" \
  -H "Authorization: Bearer $ONEPIN_API_KEY"
```

## Inspect this node

#### Python

```python
client.nodes.get_node_detail(node_type="operator_generator").data
```

#### CLI

```bash
onepin nodes show operator_generator
```

#### API

```bash
curl https://api.onepin.ai/api/v2/nodes/operator_generator \
  -H "Authorization: Bearer $ONEPIN_API_KEY"
```

## Related

* [Browse voices](/docs/guides/browse-voices) — find a voice and its `provider_voice_id`
* [Voices & Models](/docs/get-started/voices-models) — the model catalog
* [Validators](/docs/workflow/validators) — check the audio before it ships