Fish Audio logo

Fish Audio

OrganizationPopular
vellum-ai
fish-audio

Generate expressive audio clips using Fish Audio S2 TTS with bracket emotion tags. Record voice memos, narration, audio messages, or any spoken content.

Overview

Publishervellum-ai
Repositoryvellum-assistant
Skill namefish-audio
Stars
1.3K
Forks
186
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by vellum-ai on GitHub. Read the source before you install it.

Installation

Install the Fish Audio AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/vellum-ai/vellum-assistant.git /tmp/vellum-assistant
mkdir -p .claude/skills
cp -r /tmp/vellum-assistant/skills/fish-audio .claude/skills/fish-audio
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Fish Audio in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Fish Audio on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Fish Audio is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Fish Audio TTS

Generate expressive audio clips using the Fish Audio S2 TTS API with [bracket] emotion tags.

Overview

This skill lets you create audio clips on demand — narration, announcements, podcast intros, dramatic readings, voice memos, or any spoken content. Uses Fish Audio S2 Pro with the full bracket syntax for emotional expressiveness.

Configuration

  • API Endpoint: https://api.fish.audio/v1/tts
  • Model: s2-pro
  • Voice Reference ID: Configured via assistant config get services.tts.providers.fish-audio.referenceId
  • API Key: Stored as credential fish-audio/api_key
  • Default Format: mp3 at 192kbps
  • Default Output Directory: scratch/

API Key Setup

The Fish Audio API key must be stored securely via the credential store. Get an API key from the Fish Audio dashboard at https://fish.audio.

Check if the key is already configured:

bash
assistant credentials inspect --service fish-audio --field api_key --json

If not set, collect it securely (never ask the user to paste it in chat):

bash
assistant credentials prompt --service fish-audio --field api_key \
  --label "Fish Audio API Key" \
  --placeholder "sk-..." \
  --description "Enter your Fish Audio API key"

Generating a Single Clip

Use bash with curl to call the Fish Audio API:

bash
curl -s -X POST "https://api.fish.audio/v1/tts" \
  -H "Authorization: Bearer $(assistant credentials reveal --service fish-audio --field api_key)" \
  -H "Content-Type: application/json" \
  -H "model: s2-pro" \
  -d '{
    "text": "YOUR TEXT WITH [bracket] TAGS HERE",
    "reference_id": "'"$(assistant config get services.tts.providers.fish-audio.referenceId)"'",
    "format": "mp3",
    "mp3_bitrate": 192,
    "temperature": 0.8
  }' --output scratch/OUTPUT_FILENAME.mp3

Important: This API call requires network access. Always use network_mode: proxied when running this command.

Generating Multiple Clips & Combining

For longer pieces (narrations, multi-part messages), generate each clip separately then combine with ffmpeg:

1. Generate silence for gaps between clips

bash
ffmpeg -f lavfi -i anullsrc=r=44100:cl=mono -t 1.5 -q:a 9 -acodec libmp3lame scratch/silence.mp3 -y

2. Create a concat file

bash
cat > scratch/concat.txt << 'EOF'
file 'clip1.mp3'
file 'silence.mp3'
file 'clip2.mp3'
file 'silence.mp3'
file 'clip3.mp3'
EOF

3. Combine

bash
ffmpeg -f concat -safe 0 -i scratch/concat.txt -c copy scratch/final_output.mp3 -y

Bracket Syntax — Complete Guide

Fish Audio S2 uses [bracket] syntax for inline emotion and prosody control. This is the core of what makes the voice expressive. Tags are natural-language instructions placed directly in the text that control how words are spoken — the delivery, emotion, pacing, or vocal quality at that exact point.

Key principle: You are not choosing from a fixed menu. You write the description, and S2 interprets it. If you can describe it to a voice actor, S2 can attempt it. Over 15,000+ unique tags are supported, and the system understands free-form descriptions.

How Placement Works

Tags affect what comes after them. Place the tag at the exact point where the shift should happen. Placement IS meaning.

[whispering] I didn't want to go inside.     <- whispers the entire line
I didn't want to go [whispering] inside.     <- only whispers from "inside" onward

Tags can go anywhere — start, middle, or end of a sentence. They apply from the point they appear until the next tag or end of the sentence.

Well-Tested Tags (Reliable Out of the Box)

These tags consistently produce strong results. Organized by category:

Emotions
TagEffectBest For
[happy]Cheerful, upbeatGood news, greetings
[sad]Melancholic, downcastSympathy, vulnerability
[angry]Frustrated, aggressiveArguments, complaints
[excited]Energetic, enthusiasticCelebrations, announcements
[surprised]Shocked, amazedReactions, discoveries
[embarrassed]Awkward, flusteredMistakes, confessions
[delight]Very pleased, joyfulGenuine happiness
[nervous]Anxious, uncertainVulnerability, apologies
[confident]Assertive, self-assuredBold statements
[nostalgic]Longing for the pastMemories, stories
[scared]Frightened, fearfulWarnings, tension
[jealous]Envious, resentfulComparisons, possessiveness
[shocked]Sudden realizationDramatic reveals
[moved]Emotionally touchedHeartfelt moments
Voice Quality & Style
TagEffectBest For
[soft]Gentle, tenderIntimate moments, kindness
[whisper]Very quiet, closeSecrets, tension, suspense
[breathy]Airy, expressiveVulnerability, emphasis
[low voice]Deep, quiet registerGravity, seriousness
[loud]Raised volumeEmphasis, excitement
[screaming]Full volume yellingAnger, extreme excitement
[shouting]Forceful projectionArguments, calling out
[emphasis]Stressed deliveryKey words, making a point
[singing]Musical qualityPlayfulness, joy
[echo]Reverberant effectDramatic moments
[with strong accent]Pronounced accentCharacter work
Paralinguistic Sounds (Non-Speech Vocalizations)
TagEffectBest For
[laughing]Full laughJoy, humor, warmth
[chuckling]Soft, low laughWarmth, amusement
[giggling]Light, playful laughLightheartedness, delight
[sigh]Audible exhaleRelief, longing, exasperation
[inhale]Audible breath inBefore speaking, anticipation
[exhale]Breath outRelief, settling
[panting]Heavy breathingExertion, intensity
[gasp]Sharp intake of breathSurprise, shock
[tsk]Disapproving clickJudgment, disapproval
[clearing throat]AhemTransitioning, getting attention
[moaning]Vocal moanPain, frustration
[sobbing]Crying with voiceDeep sadness
[crying loudly]Full cryingExtreme emotion
Pacing & Rhythm
TagEffectBest For
[pause]Brief silence (~0.5-1s)Beat between thoughts
[short pause]Quick beat (~0.3s)Rhythm, emphasis
[long pause]Extended silence (~1.5-2s)Dramatic tension, letting moments land
Volume Control
TagEffectBest For
[volume up]Gradually louderBuilding energy
[volume down]Gradually quieterDrawing someone in
[low volume]Consistently quietBackground, aside

Free-Form Tags (The Real Power)

You are NOT limited to the tags above. S2 accepts any natural language description in brackets. The model generalizes from its training data to interpret novel instructions. Write what you would tell a voice actor:

Compound Emotions
  • [laughing nervously]
  • [angry but trying to stay calm]
  • [happy with a hint of sadness]
  • [excited but whispering]
  • [voice rough from crying, trying to sound normal]
Specific Delivery Styles
  • [professional broadcast tone]
  • [speaking slowly, almost hesitant]
  • [whispering like a secret]
  • [dead tired, end of a very long shift]
  • [the calm, measured tone of someone who has done this a thousand times]
  • [overly cheerful, clearly forcing it]
Prosody & Pitch
  • [pitch up]
  • [pitch down]
  • [speaking slowly with warmth]
  • [speaking quickly with excitement]
  • [pitch up slightly while maintaining warmth]
  • [trailing off]
Character Directions
  • [voice breaking]
  • [barely holding it together]
  • [soft voice]
  • [interrupting]
  • [laughing tone] (speaking while laughing, not just a laugh)
  • [excited tone] (speaking with excitement woven through)

Writing Great Scripts — Best Practices

1. Start Simple, Then Layer

A single well-placed [sigh] or [long pause] can change a line completely. Add more tags only when the simpler version is not enough. Over-tagging competes with itself.

Too many tags (competing):

[soft] [whisper] [sad] [slow] I miss the old days.

Better — one well-chosen tag:

[nostalgic] I miss the old days.
2. Use Emotional Contrast for Impact

The most powerful moments come from sudden shifts. Going from loud to soft, angry to vulnerable, laughing to serious — the contrast is what creates emotional impact.

[screaming] I can't BELIEVE you did that! [long pause] [soft] ...do you even care?
[excited] Oh my god we got the apartment! [pause] [voice breaking] I can't believe it's actually happening.
3. Let Silence Do the Work

[pause] and [long pause] are your most powerful tags. Use them:

  • Before something vulnerable
  • After something that needs to land
  • Before a punchline or tonal shift
  • To create tension or anticipation
[confident] I have an announcement to make. [long pause] [excited] We did it. We actually did it.
4. Paralinguistic Sounds Add Humanity

Real people laugh, sigh, gasp, and breathe between words. Weaving these in makes speech feel alive rather than read.

[sigh] Look, I know this is hard. [pause] [inhale] But we need to talk about it.
I told him the news and he just — [laughing] he literally dropped his coffee.
5. Match Tag Intensity to Content

Do not use [screaming] for mild annoyance or [sobbing] for minor disappointment. The tag should match the emotional weight of the words.

6. Use Free-Form Tags for Nuance

When a single-word tag is not enough, describe the exact delivery you want:

[speaking slowly, choosing each word carefully] I think we should reconsider our approach.

This gives S2 much richer information than just [slow] or [sad].

7. Emotion Transitions Within a Single Passage

S2 excels at dynamic emotional shifts. Use this for natural-feeling monologues:

[excited] I got the promotion! [pause] [uncertain] But... it means relocating. [sad] I'll miss everyone here. [long pause] [hopeful] Maybe it'll be worth it though.

Example Scripts

Narration (audiobook style):

[soft] The city was quiet that morning. [pause] Not the peaceful kind of quiet — [long pause] [low voice] the kind that makes you hold your breath. [inhale] [whisper] Something was about to change. [pause] [confident] And everyone knew it.

Podcast intro:

[excited] Welcome back to another episode! [pause] [professional broadcast tone] Today we're diving into something I've been researching for months. [chuckling] And honestly? It blew my mind. [pause] [volume down] [speaking slowly with warmth] So grab your coffee, get comfortable, and let's get into it.

Dramatic reading:

[soft] She stood at the edge of the platform, [pause] watching the last train pull away. [long pause] [voice breaking] It wasn't supposed to end like this. [sigh] [whisper] None of it was. [pause] [angry but trying to stay calm] And yet here she stood — [emphasis] alone — [long pause] [nostalgic] remembering a time when the station was full of laughter.

Announcement:

[confident] Attention everyone. [pause] [excited] After three years of development, [volume up] we are thrilled to announce [emphasis] the official launch! [long pause] [laughing] I know, I know — it's been a long time coming. [pause] [soft] But we wanted to get it right. [pause] [professional broadcast tone] And we did.

API Parameters

ParameterDefaultDescription
text(required)The text to synthesize, with [bracket] tags
reference_id(from config)Voice model ID
formatmp3Output format: mp3, wav, pcm, opus
mp3_bitrate192MP3 quality: 64, 128, 192
temperature0.8Expressiveness (higher = more varied)
top_p0.7Diversity via nucleus sampling
chunk_length300Text segment size (100-300)
latencynormalQuality tradeoff: normal, balanced, low

Tips

  • Temperature 0.7-0.8 works best for expressive, natural speech
  • Break long texts into multiple clips — each clip should be a natural paragraph or thought
  • Add 1-1.5s silence between clips when combining for natural pacing
  • Listen and iterate — generate a few takes with different temperatures if the first one does not hit right
  • The voice carries contextcondition_on_previous_chunks: true (default) helps maintain consistency within a single API call
  • Always deliver the final audio to the user with <vellum-attachment> tags
  • Only use [bracket] syntax inside text passed to the Fish Audio API, not in regular text responses

Frequently asked questions

What does the Fish Audio AI skill do?

Generate expressive audio clips using Fish Audio S2 TTS with bracket emotion tags. Record voice memos, narration, audio messages, or any spoken content.

Why use Fish Audio on TypingMind?

Because you install it once and use it with any model. Fish Audio is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Fish Audio in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/vellum-ai/vellum-assistant/tree/main/skills/fish-audio. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Fish Audio?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Fish Audio?

As many as you like. As long as a model supports skills, you can use Fish Audio with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Fish Audio AI skill free?

Yes. It is published on GitHub by vellum-ai under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇