LiveKit docs › Build Agents › Models › TTS › Fish Audio

---

# Fish Audio TTS

> How to use the Fish Audio TTS plugin for LiveKit Agents.

- **[Use in Agent Builder](https://cloud.livekit.io/projects/p_/agents/builder/new?tts=fishaudio%2Fs2.1-pro)**: Create a new agent in your browser using fishaudio/s2.1-pro

## Overview

Fish Audio text-to-speech is available in LiveKit Agents through [LiveKit Inference](https://docs.livekit.io/agents/models/inference.md) and the [Fish Audio plugin](#plugin). With LiveKit Inference, your agent runs on LiveKit's infrastructure to minimize latency. No separate provider API key is required, and usage and rate limits are managed through LiveKit Cloud. Use the plugin instead if you want to manage your own billing and rate limits. Pricing for LiveKit Inference is available on the [pricing page](https://livekit.com/pricing/inference#tts).

This plugin allows you to use [Fish Audio](https://fish.audio/) as a TTS provider for your voice agents.

## LiveKit Inference

Use [LiveKit Inference](https://docs.livekit.io/agents/models/inference.md) to access Fish Audio TTS without a separate Fish Audio API key.

A checkmark in the **EU endpoint** column in the following tables means the model has a dedicated EU endpoint, in addition to the global endpoint. To learn more, see [Data residency](https://docs.livekit.io/agents/models/inference.md#data-residency).

| Model ID | Languages | EU endpoint |
| -------- | --------- | ------ |
| `fishaudio/drama-3` | `en`, `zh`, `ja`, `de`, `fr`, `es`, `ko`, `ar`, `ru`, `nl`, `it`, `pl`, `pt` |  |
| `fishaudio/s2-pro` | `en`, `zh`, `ja`, `de`, `fr`, `es`, `ko`, `ar`, `ru`, `nl`, `it`, `pl`, `pt` |  |
| `fishaudio/s2.1-pro` | `en`, `zh`, `ja`, `de`, `fr`, `es`, `ko`, `ar`, `ru`, `nl`, `it`, `pl`, `pt` |  |
| `fishaudio/s2.1-pro-free` **RETIRED** (retired September 25, 2026; use `fishaudio/s2.1-pro`) | `en`, `zh`, `ja`, `de`, `fr`, `es`, `ko`, `ar`, `ru`, `nl`, `it`, `pl`, `pt` |  |

> ⚠️ **Retired models**
> 
> Retired models are no longer accessible. If you're using a retired model, switch to a currently available model.

### Usage

To use Fish Audio, use the `TTS` class from the `inference` module:

**Python**:

```python
from livekit.agents import AgentSession, inference

session = AgentSession(
    tts=inference.TTS(
        model="fishaudio/s2.1-pro",
        voice="b347db033a6549378b48d00acb0d06cd",
        language="en",
        extra_kwargs={
            "speed": 1.5,
            "volume": 1.2,
        }
    ),
    # ... tts, stt, vad, turn_handling, etc.
)

```

---

**Node.js**:

```typescript
import { AgentSession, inference } from '@livekit/agents';

const session = new AgentSession({
    tts: new inference.TTS({
        model: "fishaudio/s2.1-pro",
        voice: "b347db033a6549378b48d00acb0d06cd",
        language: "en",
        modelOptions: {
            speed: 1.5,
            volume: 1.2,
        }
    }),
    // ... tts, stt, vad, turnHandling, etc.
});

```

### Parameters

- **`model`** _(string)_: The model ID from the [models list](#inference).

- **`voice`** _(string)_: See [voices](#voices) for guidance on selecting a voice.

- **`language`** _(LanguageCode)_ (optional): [Language code](https://docs.livekit.io/agents/models/tts.md#language-codes) for the input text. If not set, the model default applies.

- **`extra_kwargs`** _(dict)_ (optional): Additional parameters to pass to the Fish Audio TTS API. See [model parameters](#model-parameters) for supported fields.

In Node.js this parameter is called `modelOptions`.

#### Model parameters

Pass the following parameters inside `extra_kwargs` (Python) or `modelOptions` (Node.js):

| Parameter | Type | Default | Notes |
| latency | `"low" | "normal" | "balanced"` | `"balanced"` | Latency-quality trade-off. normal: best quality, balanced: reduced latency, low: lowest latency. |
| temperature | `float` | `0.7` | Sampling temperature that controls the randomness of the model's output. Higher values make the output more random, while lower values make it more focused and deterministic. Range of valid values can vary by model.

 Valid values are between `0.0` and `1.0`. |
| top_p | `float` | `0.7` | Nucleus sampling probability mass. Valid range: `0.0` to `1.0`. |
| speed | `float` | `1.0` | Speaking rate multiplier. Valid range: `0.5` to `2.0`. `1.0` = normal speed, `0.5` = half speed, `2.0` = double speed. Useful for adjusting pacing without regenerating audio. |
| volume | `float` | `0.0` | Volume adjustment in decibels (dB). `0` = no change, positive values = louder, negative values = quieter. |
| normalize | `boolean` | `True` | Normalizes text for numbers, dates and currency. Only available on English and Chinese. |
| normalize_loudness | `boolean` | `True` | Normalizes output loudness for more consistent volume. |
| chunk_length | `int` | `300` | Maximum number of characters per chunk for long text. Text longer than this will be split into multiple chunks and synthesized separately. Valid range: `100` to `300`. |
| min_chunk_length | `int` | `50` | Minimum number of characters before starting a new chunk. Valid range: `0` to `100`. |
| max_new_tokens | `int` | `1024` | Maximum number of audio tokens generated per text chunk. |
| condition_on_previous_chunks | `boolean` | `True` | Uses previously generated audio as context for later chunks to improve consistency. |
| early_stop_threshold | `float` | `1.0` | Early-stopping threshold used during batching. Valid range: `0.0` to `1.0`. |

### Voices

LiveKit Inference supports all of the default "Fish Audio Voices" available in the Fish Audio API. You can explore the available voices in the [Fish Audio voice library](https://fish.audio/app/discovery/) (free account required), and use the voice by copying its ID into your LiveKit agent session.

> ℹ️ **Custom & community voices**
> 
> Pre-existing custom Fish Audio voices are not available through LiveKit Inference. To use these, create your own Fish Audio account and use the [Fish Audio plugin](#plugin). To create a new custom voice through LiveKit, see [Custom voices](https://docs.livekit.io/agents/models/tts/custom-voices.md).

The following is a small sample of the Fish Audio voices available in LiveKit Inference.

| Provider | Name | Description | Language | ID |
| -------- | ---- | ----------- | -------- | -------- |
| Fish Audio | Adrian | Friendly, casual American male | `en-US` | `fishaudio/s2.1-pro:bf322df2096a46f18c579d0baa36f41d` |
| Fish Audio | Ethan | A curious explainer. | `en-US` | `fishaudio/s2.1-pro:536d3a5e000945adb7038665781a4aca` |
| Fish Audio | Hannah | A conversational specialist. | `en-US` | `fishaudio/s2.1-pro:9a9cf47702da476aa4629e2506d4a857` |
| Fish Audio | Jordan | A motivational speaker. | `en-US` | `fishaudio/s2.1-pro:79d0bd3e4e5444b18f7b6d89b5927bf1` |
| Fish Audio | Laura | A confident female narrator. | `en-US` | `fishaudio/s2.1-pro:e3cd384158934cc9a01029cd7d278634` |
| Fish Audio | Sarah | An engaged speaker. | `en-US` | `fishaudio/s2.1-pro:933563129e564b19a115bedd57b7406a` |
| Fish Audio | Selene | A meditative female voice. | `en-US` | `fishaudio/s2.1-pro:b347db033a6549378b48d00acb0d06cd` |

### String descriptors

As a shortcut, you can also pass a descriptor with the [model ID](#inference) and voice directly to the `tts` argument in your `AgentSession`:

**Python**:

```python
from livekit.agents import AgentSession

session = AgentSession(
    tts="fishaudio/s2.1-pro:b347db033a6549378b48d00acb0d06cd",
    # ... llm, stt, vad, turn_handling, etc.
)

```

---

**Node.js**:

```typescript
import { AgentSession } from '@livekit/agents';

const session = new AgentSession({
    tts: "fishaudio/s2.1-pro:b347db033a6549378b48d00acb0d06cd",
    // ... llm, stt, vad, turnHandling, etc.
});

```

## Plugin

LiveKit's plugin support for Fish Audio lets you connect directly to Fish Audio's TTS API with your own API key.

Available in:
- [ ] Node.js
- [x] Python

### Installation

Install the plugin:

**Python**:

```shell
uv add "livekit-agents[fishaudio]~=1.8"

```

---

**Node.js**:

```shell
pnpm add @livekit/agents-plugin-fishaudio@1.x

```

### Authentication

The Fish Audio plugin requires an API key from [Fish Audio](https://fish.audio/go-api/).

Set `FISH_API_KEY` in your `.env.local` file.

### Usage

Use Fish Audio TTS within an `AgentSession` or as a standalone speech generator. For example, you can use this TTS in the [Voice AI quickstart](https://docs.livekit.io/agents/start/voice-ai.md).

**Python**:

```python
from livekit.plugins import fishaudio

session = AgentSession(
    tts=fishaudio.TTS(
        model="s2.1-pro",
        voice_id="933563129e564b19a115bedd57b7406a",
    ),
    # ... llm, stt, etc.
)

```

---

**Node.js**:

```typescript
import * as fishaudio from '@livekit/agents-plugin-fishaudio';

const session = new AgentSession({
    tts: new fishaudio.TTS({
        model: "s2.1-pro",
        voiceId: "933563129e564b19a115bedd57b7406a",
    }),
    // ... llm, stt, etc.
});

```

The plugin enables Fish Audio's quality-guard reliability feature on every request. This server-side feature is always on and has no opt-out.

### Voices

Fish Audio identifies each voice by a reference ID. Browse the [Fish Audio playground](https://fish.audio/app/discovery/) to find a voice, or create your own custom voice model, then copy its ID into the `voice_id` parameter.

### Parameters

This section describes some of the available parameters. See the [plugin reference](https://docs.livekit.io/reference/python/v1/livekit/plugins/fishaudio.md) for a complete list of all available parameters.

In Node.js, use the equivalent option names, such as `voiceId`, `latencyMode`, and `topP`.

- **`model`** _(string)_ (optional) - Default: `s2.1-pro`: Fish Audio TTS model to use. Set to `s1`, `s2-pro`, or `s2.1-pro`.

- **`voice_id`** _(string)_ (optional): ID of the voice (reference ID) to use. Defaults to a built-in voice. See [Voices](#plugin-voices) to find or create voice IDs.

- **`output_format`** _(string)_ (optional) - Default: `wav`: Available in:
- [ ] Node.js
- [x] Python

Audio output format. Set to `wav`, `pcm`, `mp3`, or `opus`.

- **`latency_mode`** _(string)_ (optional) - Default: `balanced`: Tradeoff between synthesis latency and quality. Set to `normal`, `balanced`, or `low`.

- **`speed`** _(float)_ (optional): Speaking rate multiplier from `0.5` to `2.0`, where `1.0` is normal. Lower values slow speech down and higher values speed it up. When unset, the voice uses its natural pace.

- **`volume`** _(float)_ (optional): Loudness adjustment in decibels from `-20` to `20`, where `0` is the voice's natural level. Positive values make speech louder and negative values make it quieter. When unset, the level stays the same.

- **`temperature`** _(float)_ (optional) - Default: `0.7`: Sampling temperature from `0` to `1`. Higher values produce more varied, expressive speech and lower values are more stable and consistent.

- **`top_p`** _(float)_ (optional) - Default: `0.7`: Nucleus sampling probability mass from `0` to `1`. Lower values keep the output to the most likely results and higher values allow more variety.

- **`normalize`** _(boolean)_ (optional) - Default: `True`: Whether to normalize written-form text such as numbers, dates, and abbreviations into spoken form before synthesis.

- **`normalize_loudness`** _(boolean)_ (optional): Whether to normalize output loudness for more consistent volume. Supported only on the S2-Pro models (`s2-pro` and `s2.1-pro`). On `s1`, the plugin drops it and logs a warning. When unset, Fish Audio enables it by default.

- **`max_new_tokens`** _(int)_ (optional): Maximum number of audio tokens generated per text chunk. When unset, Fish Audio's default of `1024` applies.

- **`min_chunk_length`** _(int)_ (optional): Minimum number of characters before the text is split into a new chunk, from `0` to `100`. When unset, Fish Audio's default of `50` applies.

- **`condition_on_previous_chunks`** _(boolean)_ (optional): Whether to use previously generated audio as context for later chunks to keep the voice consistent. When unset, Fish Audio enables it by default.

- **`early_stop_threshold`** _(float)_ (optional): Early stopping threshold used during batch processing, from `0` to `1`. When unset, Fish Audio's default of `1.0` applies.

## Customizing pronunciation

Fish Audio supports inline phoneme tags that guide how the model pronounces a word. Use them for brand names and technical terms that the model mispronounces. To learn more, see [English Phoneme Control](https://docs.fish.audio/developer-guide/core-features/fine-grained-control/english) in the Fish Audio docs.

### Phoneme tags

Wrap the pronunciation of a single word in `<|phoneme_start|>` and `<|phoneme_end|>` tags, and keep any surrounding punctuation outside the tags. Write English pronunciations in Arpabet, the phonetic notation used by the Carnegie Mellon University (CMU) Pronouncing Dictionary. Separate the uppercase symbols with spaces. Fish Audio doesn't accept International Phonetic Alphabet (IPA) symbols in English phoneme tags.

Each vowel can optionally carry a stress digit: `0` for unstressed, `1` for primary stress, and `2` for secondary stress. To find the Arpabet pronunciation of a word, look it up in the [CMU Pronouncing Dictionary](http://www.speech.cs.cmu.edu/cgi-bin/cmudict).

```text
I am an <|phoneme_start|>EH1 N JH AH0 N IH1 R<|phoneme_end|>.

```

Phoneme tags work with the default `normalize` setting, so you don't need to turn off text normalization to use them.

Phoneme tags guide pronunciation but don't guarantee it, and the result can vary between requests for the same text. Listen to how your terms sound before you rely on them. If a term still sounds wrong, try writing it with and without stress digits.

### Adding phoneme tags to agent speech

To apply a pronunciation every time your agent says a term, map the term to its tagged pronunciation with the [replace text transform](https://docs.livekit.io/agents/multimodality/text.md#built-in-replace-transform). The transform rewrites the text before it reaches the TTS, so you don't need to prompt the LLM to write phoneme tags. For a term that sounds like more than one word, such as "LiveKit," use one tag for each spoken word.

**Python**:

```python
from livekit.agents import AgentSession, text_transforms

session = AgentSession(
    tts="fishaudio/s2.1-pro:b347db033a6549378b48d00acb0d06cd",
    # Setting tts_text_transforms replaces the defaults, so list them explicitly.
    tts_text_transforms=[
        "filter_emoji",
        "filter_markdown",
        text_transforms.replace({
            "LiveKit": "<|phoneme_start|>L AY V<|phoneme_end|> <|phoneme_start|>K IH T<|phoneme_end|>",
            "Kubernetes": "<|phoneme_start|>K UW2 B ER0 N EH1 T IY0 Z<|phoneme_end|>",
        }),
    ],
    # ... llm, stt, vad, turn_handling, etc.
)

```

---

**Node.js**:

```typescript
import { voice } from '@livekit/agents';

const session = new voice.AgentSession({
    tts: "fishaudio/s2.1-pro:b347db033a6549378b48d00acb0d06cd",
    // Setting ttsTextTransforms replaces the defaults, so list them explicitly.
    ttsTextTransforms: [
        'filter_emoji',
        'filter_markdown',
        voice.textTransforms.replace({
            'LiveKit': '<|phoneme_start|>L AY V<|phoneme_end|> <|phoneme_start|>K IH T<|phoneme_end|>',
            'Kubernetes': '<|phoneme_start|>K UW2 B ER0 N EH1 T IY0 Z<|phoneme_end|>',
        }),
    ],
    // ... llm, stt, vad, turnHandling, etc.
});

```

## Expressive mode

Fish Audio's `s2.1-pro` works with [expressive mode](https://docs.livekit.io/agents/models/tts/expressive.md), where the LLM marks up its replies and LiveKit renders the delivery. Fish sets an emotional tone, adds emphasis, inserts pauses, and produces non-verbal sounds such as laughs and throat-clears.

Turn it on with `expressive=True` on your `AgentSession`. To adjust the delivery, see [Customization](https://docs.livekit.io/agents/models/tts/expressive.md#customization).

## Additional resources

The following resources provide more information about using Fish Audio with LiveKit Agents.

- **[Expressive mode](https://docs.livekit.io/agents/models/tts/expressive.md)**: Let the LLM add emotion, pacing, and non-verbal sounds to Fish Audio speech automatically.

- **[Python package](https://pypi.org/project/livekit-plugins-fishaudio/)**: The `livekit-plugins-fishaudio` package on PyPI.

- **[Plugin reference](https://docs.livekit.io/reference/python/v1/livekit/plugins/fishaudio.md)**: Reference for the Fish Audio TTS plugin.

- **[GitHub repo](https://github.com/livekit/agents/tree/main/livekit-plugins/livekit-plugins-fishaudio)**: View the source or contribute to the LiveKit Fish Audio TTS plugin.

- **[Fish Audio docs](https://docs.fish.audio/)**: Fish Audio's full docs site.

---

This document was rendered at 2026-10-18T14:57:56.289Z.
For the latest version of this document, see [https://docs.livekit.io/agents/models/tts/fishaudio.md](https://docs.livekit.io/agents/models/tts/fishaudio.md).

To explore all LiveKit documentation, see [llms.txt](https://docs.livekit.io/llms.txt).