> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gradium.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate from Fish Audio

> Move Fish Audio TTS, voice cloning, and ASR integrations to Gradium endpoints, x-api-key auth, and JSON WebSocket messages.

To switch from Fish Audio to Gradium, you need a handful of mechanical
edits: point requests at Gradium URLs, send `x-api-key` instead of a
Bearer token, rename a few request fields, and replace MessagePack
WebSocket events with JSON messages, which removes the msgpack
dependency.

## Why choose Gradium over Fish Audio

* **Official voice catalog.** Gradium's
  [flagship voices](/guides/voices/flagship-voices) are first-party
  voices built with voice experts and researchers for every supported
  language. Fish Audio's library is community-uploaded models owned by
  individual accounts.
* **Streaming STT.** Gradium transcribes live audio over WebSocket with
  semantic VAD and adaptive delay for turn-taking. Fish Audio only
  offers batch transcription.
* **Speech-to-speech translation.** Gradium's
  [S2S endpoint](/guides/speech-to-speech) translates live speech into
  another language over one WebSocket: audio streams in, translated
  audio and transcript stream out. Fish Audio has no equivalent.
* **JSON everywhere.** All Gradium WebSocket messages are JSON, so
  clients drop the MessagePack dependency and work directly with
  `wscat`, browsers, and standard libraries.
* **Browser-safe auth.** Short-lived tokens from
  `GET /api/api-keys/token` let browser and mobile clients connect
  without embedding API keys; see
  [Browser WebSockets](/guides/browser-websockets).
* **Production controls.** [Multiplexing](/guides/multiplexing) with
  `client_req_id`, [pronunciation dictionaries](/api-reference/endpoint/list-pronunciations),
  [text rewriting](/guides/text-rewriting), and telephony formats
  (`ulaw_8000`, `alaw_8000`) are built into the same endpoints.

## Endpoint Swap

| Flow          | Fish Audio                           | Gradium                                           |
| ------------- | ------------------------------------ | ------------------------------------------------- |
| One-shot TTS  | `POST https://api.fish.audio/v1/tts` | `POST https://api.gradium.ai/api/post/speech/tts` |
| Streaming TTS | `wss://api.fish.audio/v1/tts/live`   | `wss://api.gradium.ai/api/speech/tts`             |
| Voice cloning | `POST https://api.fish.audio/model`  | `POST https://api.gradium.ai/api/voices/`         |
| List voices   | `GET https://api.fish.audio/model`   | `GET https://api.gradium.ai/api/voices/`          |
| Batch STT     | `POST https://api.fish.audio/v1/asr` | `POST https://api.gradium.ai/api/post/speech/asr` |
| Streaming STT | Not available                        | `wss://api.gradium.ai/api/speech/asr`             |

## Auth Mapping

| Fish Audio                                  | Gradium                                                                         |
| ------------------------------------------- | ------------------------------------------------------------------------------- |
| `Authorization: Bearer $FISH_API_KEY`       | `x-api-key: $GRADIUM_API_KEY`                                                   |
| `model` header (`s1`, `s2-pro`, `s2.1-pro`) | `model_name` field, default `default`                                           |
| API key in browser clients                  | Short-lived `?token=...`; see [Browser WebSockets](/guides/browser-websockets). |

`model_name` goes in the request body or `setup` message; `default`
always points at the current recommended model, so most integrations
never set it.

## Voice Catalog

Gradium's [flagship voice catalog](/guides/voices/flagship-voices)
covers all supported languages, including French, German, Spanish, and
Portuguese, plus regional variants such as Brazilian Portuguese and
Mexican Spanish.

| Fish Audio                                         | Gradium                                            |
| -------------------------------------------------- | -------------------------------------------------- |
| Community-uploaded clones, per-user ownership      | First-party flagship voices                        |
| Availability depends on the uploading account      | Stable `voice_id` values                           |
| Quality varies with the uploader's reference audio | Consistent studio-quality recordings               |
| Discovery by search, tags, and popularity          | Curated list with description, country, and gender |

Pick a replacement `voice_id` per language from the
[voice library](/guides/voices/flagship-voices), or clone a voice you
own as a private custom voice (see
[Voice Cloning Migration](#voice-cloning-migration)).

## Gradium POST TTS

With `only_audio: true`, the response is raw audio bytes, same as Fish
Audio's `/v1/tts`.

```bash Gradium theme={null}
curl -L -X POST https://api.gradium.ai/api/post/speech/tts \
  -H "x-api-key: $GRADIUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Hello from Gradium.",
    "voice_id": "YTpq7expH9539ERJ",
    "output_format": "wav",
    "only_audio": true
  }' \
  > output.wav
```

## TTS Field Mapping

| Fish Audio field                        | Gradium field                                                             |
| --------------------------------------- | ------------------------------------------------------------------------- |
| `text`                                  | `text`                                                                    |
| `reference_id`                          | `voice_id`                                                                |
| `model` header                          | `model_name`                                                              |
| `format` + `sample_rate`                | `output_format` string                                                    |
| `latency` (`low`, `balanced`, `normal`) | Not needed; use the WebSocket endpoint for low latency                    |
| `chunk_length` / `min_chunk_length`     | Send text in chunks over WebSocket; place `<flush>` at natural boundaries |
| `normalize`                             | `json_config.rewrite_rules`; see [Text Rewriting](/guides/text-rewriting) |
| `prosody.speed`                         | `json_config.padding_bonus` (negative is faster, positive is slower)      |
| `temperature`                           | `json_config.temp`                                                        |
| `top_p` / `repetition_penalty`          | No direct equivalent; tune `temp` and `cfg_coef`                          |
| `references` (inline zero-shot audio)   | Create a voice once with `POST /voices/`, then reuse its `voice_id`       |

`output_format` is one string instead of separate format and
sample-rate fields: `wav`, `pcm`, `opus`, `ulaw_8000`, `alaw_8000`, or
explicit PCM rates such as `pcm_16000` and `pcm_44100`.

<Note>
  Gradium does not return MP3. Replace `format: "mp3"` with `wav` for
  file output or `opus` for compressed streaming.
</Note>

## WebSocket TTS Migration

Fish Audio's `/v1/tts/live` socket uses MessagePack events. Gradium's
TTS socket uses JSON text messages.

```json Gradium messages theme={null}
{"type":"setup","voice_id":"YTpq7expH9539ERJ","model_name":"default","output_format":"pcm"}
{"type":"text","text":"Hello from Gradium."}
{"type":"end_of_stream"}
```

| Fish Audio event                       | Gradium message                                        |
| -------------------------------------- | ------------------------------------------------------ |
| `start` with a `request` config object | `setup` with `voice_id`, `model_name`, `output_format` |
| `text`                                 | `text`                                                 |
| `flush`                                | `<flush>` tag inside a `text` message                  |
| `stop`                                 | `end_of_stream`                                        |
| `audio` (binary payload)               | `audio` (base64 payload in JSON)                       |
| `finish` with `reason`                 | `end_of_stream` server message                         |

Gradium replies with `ready` after `setup`, streams `audio` messages,
and finishes with its own `end_of_stream`. For several logical requests
on one socket, add `client_req_id` to each message and set
`close_ws_on_eos: false`; see [Multiplexing](/guides/multiplexing).

## Voice Cloning Migration

Fish Audio clones a voice by creating a model from uploaded samples.
Gradium uses one `POST /voices/` call; the returned `uid` is the
`voice_id` for any TTS request.

```bash Gradium theme={null}
curl -X POST https://api.gradium.ai/api/voices/ \
  -H "x-api-key: $GRADIUM_API_KEY" \
  -F "audio_file=@voice_sample.wav" \
  -F "name=My Custom Voice" \
  -F "language=en"
```

| Fish Audio field                     | Gradium field                                             |
| ------------------------------------ | --------------------------------------------------------- |
| `voices` (one or more audio files)   | `audio_file` (one file; about 10 seconds of clean speech) |
| `texts` (transcripts of the samples) | Not required                                              |
| `title`                              | `name`                                                    |
| `train_mode` (`fast`)                | Not required; extraction runs on upload                   |
| `visibility`                         | Not required; voices are private to your account          |
| `type: "tts"`                        | Not required                                              |
| `enhance_audio_quality`              | Not required                                              |
| Returned `_id`                       | Returned `uid`, used as `voice_id`                        |

Manage clones with `GET`, `PUT`, and `DELETE` on
`/voices/{voice_uid}`; see [Custom Voices](/guides/voices/custom-voices).

## STT Migration

Fish Audio's `/v1/asr` takes MessagePack or multipart uploads and
returns one JSON object. Gradium's POST STT endpoint takes raw audio
bytes as the request body and streams newline-delimited JSON messages.

```bash Gradium theme={null}
curl -X POST https://api.gradium.ai/api/post/speech/asr \
  -H "x-api-key: $GRADIUM_API_KEY" \
  -H "Content-Type: audio/wav" \
  --data-binary @recording.wav
```

| Fish Audio ASR concept                | Gradium STT equivalent                                                      |
| ------------------------------------- | --------------------------------------------------------------------------- |
| MessagePack or multipart request body | Raw audio bytes with `Content-Type: audio/wav`, `audio/pcm`, or `audio/ogg` |
| `language` hint                       | `language` query parameter, or `json_config.language` on WebSocket          |
| `text` in the response                | Concatenate streamed `text` messages                                        |
| `segments` with start and end times   | Per-message segment timing                                                  |
| `ignore_timestamps`                   | Timing is always included in streamed messages                              |
| No streaming option                   | `wss://api.gradium.ai/api/speech/asr` with semantic VAD `step` messages     |

For live transcription, use the WebSocket endpoint; it emits `step`
messages with `inactivity_prob` for turn-taking. See
[Speech-to-Text](/guides/speech-to-text).

## Adapter Checklist

* Replace Fish Audio URLs with the matching Gradium endpoints.
* Change auth from `Authorization: Bearer` to `x-api-key`, or
  short-lived `?token=...` for browser WebSockets.
* Drop the `model` header; set `model_name` only for a specific model.
* Rename `reference_id` to `voice_id`, using flagship voices from the
  [voice library](/guides/voices/flagship-voices).
* Collapse `format` and `sample_rate` into one `output_format` string;
  replace MP3 with `wav` or `opus`.
* Replace MessagePack events (`start`, `text`, `stop`) with JSON
  messages (`setup`, `text`, `end_of_stream`).
* Re-create cloned voices with `POST /voices/` and use the returned
  `uid` values.
* Move prosody and sampling knobs into `json_config`; see
  [Voice Settings](/guides/voice-settings).
* For batch STT, send raw audio bytes and read streamed JSON messages.

## Next steps

<CardGroup cols={2}>
  <Card title="Gradium TTS WebSocket guide" icon="waveform-lines" href="/guides/text-to-speech">
    Streaming setup messages, audio messages, flush, and timestamps.
  </Card>

  <Card title="Custom Voices" icon="microphone" href="/guides/voices/custom-voices">
    Create, update, and manage cloned voices from reference audio.
  </Card>

  <Card title="Voice Settings" icon="sliders" href="/guides/voice-settings">
    Speed, temperature, and similarity controls via json\_config.
  </Card>

  <Card title="Speech-to-Text" icon="ear-listen" href="/guides/speech-to-text">
    Streaming transcription with semantic VAD and flush.
  </Card>
</CardGroup>
