Fish Audio speech on VoiceThere

Fish Audio Drama 3 TTS and transcribe-1 STT on VoiceThere cloud with AGENT_FISHAUDIO_API_KEY. STT sends finals only, no partials.

Overview of all vendors: STT & TTS vendors.

What it is

Fish Audio covers both legs. Drama 3 is the default TTS model and transcribe-1 is the STT model, so you can use Fish for either leg and pair it with another vendor for the other.

Home: Fish Audio docs

Set up on VoiceThere

  • Dashboard: Project Settings → Voice (STT / TTS). Pick fishaudio on the leg this vendor supports. Add project secrets from the list below, then Deploy to cloud.
  • Secrets: Store keys as AGENT_* project secrets (see Agent environment & secrets).
  • API: Patch stt_provider / tts_provider on the project before deploy. See Control plane API.

Project secrets for this vendor

  • AGENT_FISHAUDIO_API_KEY: Fish Audio API key. Fish Audio STT and TTS on the runner.

Optional env fields

  • AGENT_FISHAUDIO_VOICE_ID: Voice id. Fish voice id (reference_id). Leave empty for the model's default voice.

CLI (after secrets exist):

voicethere projects voice set --project YOUR_PROJECT_ID \
  --stt-provider fishaudio --tts-provider fishaudio \
  --stt-model transcribe-1 --tts-model drama-3

Models and voices you can pick

Project Voice settings in the dashboard lists every model and voice id VoiceThere accepts for this vendor. The same allowlists ship in the npm package @node-webrtc-rust/voice-catalog (pinned on your platform release).

STT examples: transcribe-1

TTS model examples: drama-3, s2.1-pro

Optional AGENT_FISHAUDIO_VOICE_ID sets the Fish voice id (reference_id). Leave it unset and Fish uses the default voice of the model.

What the implementation does

  • TTS streams audio over a chunked HTTP request to POST /v1/tts, with a WebSocket path as the fallback.
  • Drama 3 direction tags pass through in the text unchanged, for example [warm, friendly], [small laugh], <whisper>…</whisper> and <emphasis>…</emphasis>.
  • STT uses the Fish realtime socket. VoiceThere streams only the audio its voice activity detection marks as speech, so silence between turns is not sent to Fish.

Measured latency

We measured these from our CI against Fish's API on 2026-10-16, with one sentence of about 80 characters and three runs per path. They show what to expect, not what Fish guarantees.

  • Time to first audio over HTTP: 291 to 658 ms. Over WebSocket: 963 to 1035 ms. HTTP is the default for that reason.
  • STT final transcript: about 500 ms (494 to 505 ms) after the end of the turn.

Barge-in without partials

Fish STT sends no partial transcripts, only a final. Barge-in that waits for a partial could never fire, so for Fish STT VoiceThere always barges in on voice activity, and vad.bargeIn.requireSttPartial has no effect. See Advanced voice settings.

Long turns

Nothing is transcribed while the caller speaks. A turn ends when voice activity detection sees a pause (about 1.1 s of silence by default), and the transcript arrives about half a second later, so the agent's reply waits for that pause. There is no maximum turn length: a caller who talks for a minute without stopping gets one transcript at the end. Pick a streaming STT vendor such as Deepgram or ElevenLabs if you need text while the caller is still talking.

Limitations

  • No partial transcripts from Fish STT, only finals.
  • Fish Audio bills your own key, not VoiceThere speech credits. It bills STT for the audio streamed, which VoiceThere limits to detected speech.

Official docs

← All documentation