Fish Audio S2 Pro Quick Start for Voice Cloning and Multilingual TTS

Fish Audio S2 Pro Quick Start for Voice Cloning and Multilingual TTS

Fish Audio S2 Pro is available on Novita AI as a hosted TTS API with no cold starts. This quick start covers the developer path: get your API key, confirm the endpoint, send your first TTS request with a cloned voice, and understand the parameters that matter for voice cloning and emotion control. S2 Pro is built on a Dual-Autoregressive architecture trained on a large multilingual corpus — the feature that separates it from generic TTS is that every voice you clone works across all supported languages without retraining.

When to Use This Quick Start

Use this guide if you need to:

  • Synthesize speech from text across a broad range of supported languages using a custom cloned voice.
  • Clone a voice from a 10–30 second audio sample and reuse it across requests at no additional per-request cost.
  • Control prosody and emotion inline using natural-language bracket tags ([whisper], [excited]).
  • Build pipelines that need multilingual TTS without separate per-language integrations.

If you only need basic English TTS with built-in voices and no cloning, evaluate the Fish Audio S1 model or GLM TTS first — S2 Pro’s advantage shows when you need cross-lingual cloning or fine-grained emotion control.

Step 1: Get Your Novita API Key

Create a Novita AI account and generate an API key from the Novita AI console. Store it as an environment variable:

export NOVITA_API_KEY="your_api_key_here"

Keep the key out of client-side code, frontend bundles, and public repositories.

Step 2: Confirm Model and Endpoint

The Novita AI documentation for Fish Audio S2 Pro TTS is at the Fish Audio S2 Pro API reference. Verify the current endpoint path and model identifier there before coding — the hosted endpoint URL and request schema are confirmed in that reference.

For voice cloning, three Novita endpoints are used across the workflow:

StepMethodEndpoint
Upload audio samplePOSThttps://api.novita.ai/v1/files
Create clone (async)POSThttps://api.novita.ai/v1/async/voice-cloning
Poll for resultGEThttps://api.novita.ai/v1/async/task-result
TTS with cloned voicePOSThttps://api.novita.ai/v4beta/txt2speech

Voice cloning uses the fish-audio-voice-cloning model for the clone creation step, separate from the TTS model.

Step 3: Clone a Voice

Voice cloning takes three API calls: upload a short audio sample, create the clone, then retrieve the voice_id. Once you have a voice_id, you can reuse it in TTS requests indefinitely at no additional cost.

Requirements for the audio sample:

  • Duration: 10–30 seconds gives the best results
  • Format: MP3 or WAV
  • Content: Clean speech with minimal background noise
  • Transcript: Providing the exact spoken text improves clone accuracy

Python: Full cloning workflow

import base64
import os
import time
import requests

API_KEY = os.environ["NOVITA_API_KEY"]
BASE_URL = "https://api.novita.ai"

# Step 1: Upload audio file
with open("voice_sample.mp3", "rb") as f:
    encoded_audio = base64.b64encode(f.read()).decode("utf-8")

upload_response = requests.post(
    f"{BASE_URL}/v1/files",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "file": encoded_audio,
        "purpose": "voice-cloning",
    },
)
upload_response.raise_for_status()
file_id = upload_response.json()["file_id"]
print(f"Uploaded file ID: {file_id}")

# Step 2: Create the voice clone
clone_response = requests.post(
    f"{BASE_URL}/v1/async/voice-cloning",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "model": "fish-audio-voice-cloning",
        "audio_file_id": file_id,
        "text": "Text spoken in the audio sample goes here.",
    },
)
clone_response.raise_for_status()
task_id = clone_response.json()["task_id"]
print(f"Clone task ID: {task_id}")

# Step 3: Poll for the voice_id
voice_id = None
while True:
    result = requests.get(
        f"{BASE_URL}/v1/async/task-result",
        headers={"Authorization": f"Bearer {API_KEY}"},
        params={"task_id": task_id},
    ).json()
    if result["status"].endswith("SUCCEED"):
        voice_id = result["result"]["voice_id"]
        print(f"Cloned voice ID: {voice_id}")
        break
    elif "FAILED" in result["status"]:
        raise RuntimeError(f"Clone failed: {result}")
    time.sleep(2)

Save the voice_id. You will use it as the reference_id in every TTS call.

cURL: Clone creation (after file upload)

curl -s -X POST https://api.novita.ai/v1/async/voice-cloning \
  -H "Authorization: Bearer $NOVITA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "fish-audio-voice-cloning",
    "audio_file_id": "YOUR_FILE_ID",
    "text": "Text spoken in the audio sample goes here."
  }'

Step 4: Send a TTS Request

Once you have a voice_id from Step 3, pass it as reference_id in the TTS request. The model generates speech in the cloned voice.

Python

import os
import requests

API_KEY = os.environ["NOVITA_API_KEY"]
VOICE_ID = "your_cloned_voice_id"  # from Step 3

response = requests.post(
    "https://api.novita.ai/v4beta/txt2speech",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "text": "Welcome to the demo. This voice was cloned from a short audio sample.",
        "reference_id": VOICE_ID,
        "format": "mp3",
        "sample_rate": 44100,
    },
)
response.raise_for_status()
audio_url = response.json()["audio_url"]
print(f"Audio URL: {audio_url}")

cURL

curl -s -X POST https://api.novita.ai/v4beta/txt2speech \
  -H "Authorization: Bearer $NOVITA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Welcome to the demo. This voice was cloned from a short audio sample.",
    "reference_id": "YOUR_CLONED_VOICE_ID",
    "format": "mp3",
    "sample_rate": 44100
  }'

The response contains an audio_url — a pre-signed URL pointing to the generated audio file.

Step 5: Check Pricing, Limits, and Common Errors

Pricing (verify current rates at novita.ai/pricing):

OperationPrice
TTS generation~$15.00 / 1M characters
Voice cloning$0.10 per voice (one-time)

Voice cloning is billed once per clone, not per TTS request. Once cloned, using the voice_id in TTS calls costs only the character-based TTS rate.

Per-request limits:

LimitValue
Max input length10,000 characters
Recommended sample for cloning10–30 seconds
Supported output formatsmp3, opus, wav, pcm
Audio sample rateUp to 44,100 Hz

Common errors:

ErrorCauseFix
401 UnauthorizedInvalid or missing API keyCheck NOVITA_API_KEY is set and correct
400 Bad Request on file uploadAudio file too large or wrong formatUse MP3/WAV, keep under a few MB
Clone task FAILED statusAudio sample too short or too noisyUse 10–30 s of clean speech
Empty or garbled audiotext field is empty or over limitKeep input under 10,000 characters

Emotion Control Tags

S2 Pro supports inline [bracket] tags that control how the model renders specific words or phrases. These are interpreted as natural-language instructions during generation — you are not limited to a fixed list of tokens.

text_with_emotion = (
    "[cheerful] Welcome back! [pause] "
    "I'm really glad you're here. "
    "[whisper] Just between us, this part is a secret. [normal] "
    "Anyway, let's get started."
)

response = requests.post(
    "https://api.novita.ai/v4beta/txt2speech",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "text": text_with_emotion,
        "reference_id": VOICE_ID,
        "format": "mp3",
        "sample_rate": 44100,
    },
)

Example bracket tags the model understands:

TagEffect
[whisper]Whispered delivery
[excited]Higher energy, faster pace
[calm]Slowed, measured tone
[laughs]Laughter embedded in speech
[professional broadcast tone]Newscaster delivery style
[pitch up]Raises pitch for the following text
[pause]Brief pause

Tags are free-form descriptions, not fixed enum values. The model learned tag-to-acoustic mappings from training data, so descriptive phrases work too. Experiment with specific tags for your use case; results may vary with unusual phrasing.

Key Parameters

ParameterTypeNotes
textstringRequired. Up to 10,000 characters.
reference_idstringRequired. Voice model ID — cloned voice_id or a system voice reference.
formatstringOutput format: mp3, opus, wav, pcm. Default: mp3.
sample_rateintegerAudio sample rate in Hz. 44100 recommended for high fidelity.
temperaturenumberControls generation randomness. Higher = more varied prosody.
top_pnumberNucleus sampling threshold.

For the full parameter schema and any additional S2 Pro-specific options, consult the Novita AI Fish Audio S2 Pro API reference.

Troubleshooting

The cloned voice sounds robotic or inconsistent. The sample was likely too short or had background noise. Record a clean 20–30 second clip with a consistent pace and no overlap. Providing the exact text transcript of the sample in the clone request improves phoneme alignment.

Audio URL returns 404 after polling. Pre-signed URLs expire. Download or process the audio promptly after receiving the URL.

Emotion tags are not producing the expected effect. Tag behavior depends on training data distributions. Try more descriptive phrasing — for example, [very softly, barely audible] instead of [quiet]. Some tags will work better than others; test with short inputs first.

Clone task status stays at a pending state. Add a poll interval (1–2 seconds between checks) to avoid rate limiting the task result endpoint. If the task stays pending for more than two minutes, check the file upload step — the file_id may have expired.

Need to use the same voice across languages. Pass the same voice_id with text in any supported language. S2 Pro applies the cloned voice timbre to the new language without requiring a separate clone. Check the S2 Pro API reference for the current list of supported languages.

FAQ

What makes S2 Pro different from Fish Audio S1? S2 Pro uses a larger Dual-Autoregressive architecture trained on a broad multilingual corpus. The practical differences: broader language support, inline emotion control via bracket tags, and multi-speaker synthesis capability not available in S1. See the S2 Pro API reference for the current language list.

Can I clone a voice once and use it for all supported languages? Yes. A voice cloned from an English sample can generate speech in Japanese, Spanish, Arabic, or any other supported language using the same voice_id. The model transfers voice timbre across languages without additional training.

How long should the voice sample be? 10–30 seconds of clean, consistent speech. Shorter samples can work but may produce less stable results. Samples over 30 seconds don’t meaningfully improve clone quality.

Is voice cloning billed per TTS request? No. The $0.10 voice cloning charge is a one-time fee per clone. After creation, using that voice_id in TTS requests costs only the per-character TTS rate.

What happens if I omit a reference_id? Check the S2 Pro API reference for the current default behavior — the model may use a default voice or require a reference.

How do I get an API key? Sign up at novita.ai and generate a key from the Novita AI console.