curl --no-buffer --request POST \
--url https://api.fish.audio/v1/tts/stream/with-timestamp \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'model: s2.1-pro-free' \
--data '{
"text": "[happy] I can’t believe it’s been this long. It feels like forever since we last really talked. I’ve missed hearing your voice, your stories, even the little things you used to say. How have you been? I’ve thought about calling you so many times, but I never knew where to start. Seeing you again now makes me realize just how much I’ve missed you. We have so much to catch up on, and I don’t even know which part of my life to tell you about first.",
"format": "opus",
"normalize": true,
"temperature": 0.9,
"chunk_length": 100,
"top_p": 0.9,
"latency": "balanced",
"sample_rate": 48000,
"reference_id": "fbe02f8306fc4d3d915e9871722a39d5"
}'
Stream generated speech with timestamp alignment snapshots
POST
/
v1
/
tts
/
stream
/
with-timestamp
Stream With Timestamps
curl --no-buffer --request POST \
--url https://api.fish.audio/v1/tts/stream/with-timestamp \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'model: s2.1-pro-free' \
--data '{
"text": "[happy] I can’t believe it’s been this long. It feels like forever since we last really talked. I’ve missed hearing your voice, your stories, even the little things you used to say. How have you been? I’ve thought about calling you so many times, but I never knew where to start. Seeing you again now makes me realize just how much I’ve missed you. We have so much to catch up on, and I don’t even know which part of my life to tell you about first.",
"format": "opus",
"normalize": true,
"temperature": 0.9,
"chunk_length": 100,
"top_p": 0.9,
"latency": "balanced",
"sample_rate": 48000,
"reference_id": "fbe02f8306fc4d3d915e9871722a39d5"
}'
This endpoint returns text/event-stream. Each SSE message event contains
one JSON payload with a base64-encoded audio chunk.
Use this endpoint when you need both progressive audio delivery and
text-to-audio alignment data, such as karaoke-style highlighting, word or
phrase progress indicators, captions synchronized to generated speech, or
timeline editing.
The response is a Server-Sent Events stream. Every event includes:
Field
Type
Description
audio_base64
string
One base64-encoded audio chunk. Concatenate all chunks in arrival order to reconstruct the complete audio.
content
string
Text content described by this event’s latest alignment snapshot. Long input can be split into multiple content chunks.
alignment
object | null
Latest cumulative timestamp snapshot for chunk_seq. When present, replace the previous snapshot for that chunk_seq; do not append segments.
chunk_seq
integer
Sequence number of the text chunk described by alignment. Bucket alignment snapshots by this value.
chunk_audio_offset_sec
number
Absolute start time of this text chunk within the full audio, in seconds. Add this to segment-local start and end values for a global audio timeline.
audio_base64 is the transport stream. alignment is a metadata snapshot for
chunk_seq. They are delivered together in the same SSE event, but the
alignment is not a per-audio-packet delta.When latency is set to balanced, long input can be split into several text
chunks. A chunk may produce multiple non-null alignment snapshots as more audio
is rendered. Each newer snapshot supersedes the previous snapshot for the same
chunk_seq.
Store alignments in a map keyed by chunk_seq. On every non-null alignment,
replace the stored value for that key. Do not collect every non-null alignment
as a separate final result.
start and end are measured in seconds from the start of that text chunk’s
generated audio. Add chunk_audio_offset_sec to get timestamps on the complete
audio timeline.alignment can be null before the first snapshot is available or when
alignment is unavailable. After a snapshot exists, later audio events may repeat
the latest snapshot so clients can continue using a simple latest-wins update
model.
The stream payload uses standard SSE framing. Parse each data: line as JSON,
append every decoded audio_base64 chunk to your audio buffer, and replace the
latest alignment snapshot for chunk_seq whenever alignment is non-null.
Python
Node.js
import base64import jsonimport requestsresponse = requests.post( "https://api.fish.audio/v1/tts/stream/with-timestamp", headers={ "Authorization": "Bearer <token>", "Content-Type": "application/json", "model": "s2-pro", }, json={ "text": "Hello! Welcome to Fish Audio.", "reference_id": "model-id", "format": "opus", "latency": "balanced", }, stream=True,)audio_chunks = []alignment_by_chunk = {}for line in response.iter_lines(decode_unicode=True): if not line or not line.startswith("data: "): continue event = json.loads(line.removeprefix("data: ")) audio_chunks.append(base64.b64decode(event["audio_base64"])) if event["alignment"] is not None: alignment_by_chunk[event["chunk_seq"]] = { "content": event["content"], "offset": event["chunk_audio_offset_sec"], "alignment": event["alignment"], }audio = b"".join(audio_chunks)
Long input can produce multiple text chunks. Treat audio and alignment as two
related streams:
Append every decoded audio_base64 chunk in event order. Do this even when alignment is null.
For non-null alignment, replace the stored snapshot for chunk_seq.
Convert each snapshot’s local segment times into global times by adding chunk_audio_offset_sec.
audio_base64 chunks are transport chunks, not sentence or word boundaries.
Do not try to align each audio chunk individually. Use alignment.segments
plus chunk_audio_offset_sec for text timing.
For example, if an event has chunk_audio_offset_sec: 16.24, add 16.24
seconds to every segment in that event’s alignment before rendering it on the
complete audio timeline.
Python
Node.js
def build_global_timeline(alignment_by_chunk): timeline = [] for chunk_seq, item in sorted(alignment_by_chunk.items()): offset_seconds = item["offset"] alignment = item["alignment"] for segment in alignment["segments"]: timeline.append({ "text": segment["text"], "start": segment["start"] + offset_seconds, "end": segment["end"] + offset_seconds, "chunk_seq": chunk_seq, }) return timeline
function buildGlobalTimeline(alignmentByChunk) { const timeline = []; for (const [chunkSeq, item] of [...alignmentByChunk.entries()].sort( ([a], [b]) => a - b )) { for (const segment of item.alignment.segments) { timeline.push({ text: segment.text, start: segment.start + item.offset, end: segment.end + item.offset, chunk_seq: chunkSeq, }); } } return timeline;}
For timestamped streaming, we recommend opus with the default 48 kHz sample
rate when your client supports it. Opus is designed for streaming and gives the
best balance of quality, latency, and bandwidth for this endpoint.wav and pcm avoid lossy codec artifacts and are straightforward to align,
but they produce much larger payloads. Use them when you need uncompressed
audio, direct sample-level processing, or a playback pipeline that already
expects raw audio.
Use mp3 only when broad playback compatibility is more important than the
cleanest streaming boundaries. MP3 encoding uses overlapping audio windows, so
its encoded chunks may not line up as neatly with timestamp snapshot updates
as Opus.
This endpoint accepts the same TTS request fields as the Text to Speech API, including reference_id, references, prosody, temperature, top_p, chunk_length, format, and latency.
Specify which TTS model to use. Use s2.1-pro-free for the free developer tier. If omitted or set to an unrecognized value, the request falls back to s2.1-pro.
Available options:
s1,
s2-pro,
s2.1-pro,
s2.1-pro-free,
drama-3
Body
application/jsonapplication/msgpack
Request body for streaming text-to-speech synthesis with timestamp alignment. The request fields match the standard TTS endpoint, but the response is delivered as a Server-Sent Events stream. Each SSE payload includes an audio chunk and, when available, the latest cumulative alignment snapshot for a chunk_seq. Clients should concatenate audio_base64 chunks in arrival order and replace the stored alignment for each chunk_seq whenever a newer snapshot is received.
Rewrites numbers, dates, units and symbols as spoken words before synthesis, improving stability. Uses language when it is set and otherwise detects the language of each text chunk.
BCP-47 language tag of the text, for example en, es-MX or zh-CN. Case-insensitive, and _ is read as -. Used only by text normalization (how numbers, dates, units and symbols are spelled out before synthesis) and by word-timestamp alignment. It is not passed to the speech model and does not change the voice, accent or audio quality; a wrong tag only changes how those tokens are spelled out. Omit it, or send auto or an empty string, to detect the language per chunk. A tag without dedicated normalization rules skips normalization instead of failing. Without a region, Spanish follows Spain conventions; send es-MX for Mexican readings. When normalize is false it only affects word timestamps. For text that mixes languages, leave it unset.
Optional request-scoped TTS feature flags forwarded verbatim to the inference backend. Use ["quality-guard"] to enable the quality guard for this synthesis request. Feature availability is determined by the inference backend.
Reference to a server-managed pronunciation dictionary. The server resolves contents via the platform pronunciation-dictionaries API and forwards the full merged dictionary to the inference engine, which performs the substitution.
PronunciationDictionaryRef · object[]
PronunciationDictionaryInline · object[]
Show child attributes
Response
Server-Sent Events stream. Each message event contains a JSON payload with one base64 audio chunk. Concatenate every audio_base64 chunk in arrival order to reconstruct the complete audio. alignment is the latest cumulative timestamp snapshot for chunk_seq; clients should replace the previous snapshot for that chunk instead of appending segments. chunk_audio_offset_sec can be added to segment times to derive absolute timestamps in the full audio.
One Server-Sent Events message payload for streaming TTS with timestamps. Each event contains one audio chunk. Concatenate all audio_base64 chunks in arrival order to reconstruct the complete audio. alignment is the latest cumulative timestamp snapshot for the reported chunk_seq; clients should replace the previous snapshot for that chunk instead of appending segments.
Latest cumulative timestamp snapshot for chunk_seq. When present, replace the previous alignment for the same chunk_seq; do not append segments. Null means no alignment snapshot has been produced yet or alignment is unavailable.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Fish Audio","description":"Documentation for Fish Audio APIs, SDKs, models, voice cloning, real-time streaming, and self-hosting.","colors":{"primary":"#0e0e0e","light":"#9b90e8","dark":"#09090b"},"logo":{"light":"https://mintcdn.com/hanabiaiinc/amYp9Dj31LtlHliX/logo/light.png?fit=max\u0026auto=format\u0026n=amYp9Dj31LtlHliX\u0026q=85\u0026s=305973cd6a8d11dbf36d1ec682ee845e","dark":"https://mintcdn.com/hanabiaiinc/amYp9Dj31LtlHliX/logo/dark.png?fit=max\u0026auto=format\u0026n=amYp9Dj31LtlHliX\u0026q=85\u0026s=b79bd889db9ac1aae939834596e8a22f"},"favicon":"https://mintcdn.com/hanabiaiinc/-WxHANLOAmlTUwdM/favicon.svg?fit=max\u0026auto=format\u0026n=-WxHANLOAmlTUwdM\u0026q=85\u0026s=dc65d9f44bda0f5b8277c48dd9c979c3","navbar":{"links":[{"href":"https://discord.gg/dF9Db2Tt3Y","label":"Community"},{"href":"mailto:support@fish.audio","label":"Support"}],"primary":{"type":"button","label":"Sign Up","href":"https://fish.audio/app/developers/get-started/?utm_source=docs\u0026utm_medium=navbar\u0026utm_content=sign-up"}},"footer":{"socials":{"website":"https://fish.audio","github":"https://github.com/fishaudio","x":"https://x.com/fishaudio","linkedin":"https://www.linkedin.com/company/fish-audio","discord":"https://discord.gg/dF9Db2Tt3Y"},"links":[{"header":"About","items":[{"label":"Research","href":"https://openaudio.com/"},{"label":"Careers","href":"mailto:hr@fish.audio"},{"label":"Blog","href":"https://fish.audio/blog"}]},{"header":"Resources","items":[{"label":"API Status","href":"https://status.fish.audio"},{"label":"Open Source","href":"https://github.com/fishaudio"},{"label":"Changelog","href":"https://docs.fish.audio/developer-guide/getting-started/changelog"}]},{"header":"Legal","items":[{"label":"Privacy Policy","href":"https://fish.audio/privacy"},{"label":"Terms of Service","href":"https://fish.audio/terms"},{"label":"Report Abuse","href":"mailto:support@fish.audio?subject=%5BReport+Abuse%5D+MODEL+NAME\u0026amp;body=Please+provide+a+detailed+description+of+the+abuse+you+are+reporting."}]}]},"fonts":{"family":"Onest"},"integrations":{"amplitude":{"apiKey":"39daf30712f00da6ea5283bc21e7084e"}},"contextual":{"options":["copy","view","chatgpt","claude","perplexity"],"display":"header"},"interaction":{"drilldown":true},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"hanabiaiinc","hasAudioNarration":false,"actualSubdomain":"hanabiaiinc","customDomains":["docs.fish.audio"],"gitSource":{"type":"github","owner":"fishaudio","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":false,"mountPath":"","label":""},"feedback":{"thumbs":true,"edits":true,"issues":true},"entitlements":{"AI_CHAT":{"status":"DISABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"DISABLED"}},"buildId":"6af41da638207fc3fedd4984","clientVersion":"0.0.4111","searchFilterCounts":[{"language":"default","tag":"API Reference","count":88},{"language":"default","tag":"Agents API","count":49},{"language":"default","tag":"Agents","count":48},{"language":"default","tag":"Resources","count":40},{"language":"default","tag":"Overview","count":31},{"language":"default","tag":"REST API","count":24},{"language":"default","tag":"Core Features","count":14},{"language":"default","tag":"Tests","count":13},{"language":"default","tag":"Cookbook","count":12},{"language":"default","tag":"Build","count":11}]},"assistantConfig":{"enableAskAiButton":true,"enableAskAiSearchBar":true,"deflection":{"enabled":true,"email":"support@fish.audio","showHelpButton":true}},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":true},"customCss":[{"filePath":"custom.css","content":"*{scrollbar-width:thin;scrollbar-color:rgba(120,120,120,0.4) transparent}::-webkit-scrollbar{width:6px;height:6px;background:transparent!important}::-webkit-scrollbar-thumb{background:rgba(120,120,120,0.5);border-radius:999px}::-webkit-scrollbar-thumb{opacity:0;transition:opacity 0.2s ease}:hover::-webkit-scrollbar-thumb,*:active::-webkit-scrollbar-thumb{opacity:1}img[src*=\"/images/\"]{background:transparent!important}.prompt-card{display:grid;cursor:pointer;outline:none}.prompt-card .card{transition:border-color 0.15s ease}.prompt-card:hover .card,.prompt-card:focus-visible .card{border-color:rgb(var(--primary))!important}.dark .prompt-card:hover .card,.dark .prompt-card:focus-visible .card{border-color:rgb(var(--primary-light))!important}.prompt-card-hint{position:absolute;top:1rem;right:1rem;padding:0.3rem 0.6rem;border-radius:9999px;font-size:0.75rem;line-height:1;color:rgb(var(--gray-500));background:rgba(120, 120, 120, 0.12);opacity:0;transition:opacity 0.15s ease;pointer-events:none}.prompt-card:hover .prompt-card-hint,.prompt-card:focus-visible .prompt-card-hint,.prompt-card[data-state=\"copied\"] .prompt-card-hint,.prompt-card[data-state=\"failed\"] .prompt-card-hint{opacity:1}.prompt-card[data-state=\"copied\"] .prompt-card-hint{color:rgb(var(--primary));background:rgb(var(--primary) / 0.12)}.dark .prompt-card[data-state=\"copied\"] .prompt-card-hint{color:rgb(var(--primary-light));background:rgb(var(--primary-light) / 0.16)}"}],"page":{"pagePath":"api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps","slug":"/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps","pageMetadata":{"openapi":"post /v1/tts/stream/with-timestamp","title":"Text to Speech Stream with Timestamps","description":"Stream generated speech with timestamp alignment snapshots","icon":"waveform-lines","iconType":"solid","href":"/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Stream generated speech with timestamp alignment snapshots\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,span:`span`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,..._provideComponents(),...props.components},{CodeBlock,Heading,Note,Tab,Table,Tabs,Tip,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Note)_missingMdxReference(`Note`,true);if(!Tab)_missingMdxReference(`Tab`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Tabs)_missingMdxReference(`Tabs`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(Warning,{children:_jsxs(_components.p,{children:[`This endpoint returns `,_jsx(_components.code,{children:`text/event-stream`}),`. Each SSE `,_jsx(_components.code,{children:`message`}),` event contains\none JSON payload with a base64-encoded audio chunk.`]})}),`\n`,_jsx(Note,{children:_jsx(_components.p,{children:`Use this endpoint when you need both progressive audio delivery and\ntext-to-audio alignment data, such as karaoke-style highlighting, word or\nphrase progress indicators, captions synchronized to generated speech, or\ntimeline editing.`})}),`\n`,_jsx(Heading,{level:`2`,id:`how-the-stream-works`,children:`How the Stream Works`}),`\n`,_jsx(_components.p,{children:`The response is a Server-Sent Events stream. Every event includes:`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Field`}),_jsx(_components.th,{children:`Type`}),_jsx(_components.th,{children:`Description`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`audio_base64`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`string`})}),_jsx(_components.td,{children:`One base64-encoded audio chunk. Concatenate all chunks in arrival order to reconstruct the complete audio.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`content`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`string`})}),_jsx(_components.td,{children:`Text content described by this event’s latest alignment snapshot. Long input can be split into multiple content chunks.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`alignment`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`object | null`})}),_jsxs(_components.td,{children:[`Latest cumulative timestamp snapshot for `,_jsx(_components.code,{children:`chunk_seq`}),`. When present, replace the previous snapshot for that `,_jsx(_components.code,{children:`chunk_seq`}),`; do not append segments.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`chunk_seq`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`integer`})}),_jsxs(_components.td,{children:[`Sequence number of the text chunk described by `,_jsx(_components.code,{children:`alignment`}),`. Bucket alignment snapshots by this value.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`chunk_audio_offset_sec`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`number`})}),_jsxs(_components.td,{children:[`Absolute start time of this text chunk within the full audio, in seconds. Add this to segment-local `,_jsx(_components.code,{children:`start`}),` and `,_jsx(_components.code,{children:`end`}),` values for a global audio timeline.`]})]})]})]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`audio_base64`}),` is the transport stream. `,_jsx(_components.code,{children:`alignment`}),` is a metadata snapshot for\n`,_jsx(_components.code,{children:`chunk_seq`}),`. They are delivered together in the same SSE event, but the\nalignment is not a per-audio-packet delta.`]}),`\n`,_jsxs(_components.p,{children:[`When `,_jsx(_components.code,{children:`latency`}),` is set to `,_jsx(_components.code,{children:`balanced`}),`, long input can be split into several text\nchunks. A chunk may produce multiple non-null alignment snapshots as more audio\nis rendered. Each newer snapshot supersedes the previous snapshot for the same\n`,_jsx(_components.code,{children:`chunk_seq`}),`.`]}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[`Store alignments in a map keyed by `,_jsx(_components.code,{children:`chunk_seq`}),`. On every non-null `,_jsx(_components.code,{children:`alignment`}),`,\nreplace the stored value for that key. Do not collect every non-null alignment\nas a separate final result.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`alignment-shape`,children:`Alignment Shape`}),`\n`,_jsxs(_components.p,{children:[`Each non-null `,_jsx(_components.code,{children:`alignment`}),` contains the current cumulative timing segments for a\nsingle text chunk:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`21`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`21`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"audio_base64\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"SUQzBAAAAAAA...\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"content\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Hello world\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"chunk_seq\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`0`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"chunk_audio_offset_sec\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`0.0`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"alignment\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"audio_duration\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`0.86`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"segments\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Hello\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"start\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`0`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"end\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`0.42`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"world\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"start\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`0.42`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"end\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`0.86`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`start`}),` and `,_jsx(_components.code,{children:`end`}),` are measured in seconds from the start of that text chunk’s\ngenerated audio. Add `,_jsx(_components.code,{children:`chunk_audio_offset_sec`}),` to get timestamps on the complete\naudio timeline.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`alignment`}),` can be `,_jsx(_components.code,{children:`null`}),` before the first snapshot is available or when\nalignment is unavailable. After a snapshot exists, later audio events may repeat\nthe latest snapshot so clients can continue using a simple latest-wins update\nmodel.`]}),`\n`,_jsx(Heading,{level:`2`,id:`minimal-request`,children:`Minimal Request`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`11`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`11`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`curl`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` --no-buffer --request POST \\\\`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` --url https://api.fish.audio/v1/tts/stream/with-timestamp \\\\`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` --header `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'Authorization: Bearer \u003ctoken>'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` --header `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'Content-Type: application/json'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` --header `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'model: s2-pro'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` --data `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'{`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"text\": \"Hello! Welcome to Fish Audio.\",`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"reference_id\": \"model-id\",`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"format\": \"opus\",`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"latency\": \"balanced\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` }'`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`parsing-the-stream`,children:`Parsing the Stream`}),`\n`,_jsxs(_components.p,{children:[`The stream payload uses standard SSE framing. Parse each `,_jsx(_components.code,{children:`data:`}),` line as JSON,\nappend every decoded `,_jsx(_components.code,{children:`audio_base64`}),` chunk to your audio buffer, and replace the\nlatest alignment snapshot for `,_jsx(_components.code,{children:`chunk_seq`}),` whenever `,_jsx(_components.code,{children:`alignment`}),` is non-null.`]}),`\n`,_jsxs(Tabs,{children:[_jsx(Tab,{title:`Python`,id:`python`,children:_jsx(CodeBlock,{filename:``,numberOfLines:`38`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`38`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` base64`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` json`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` requests`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`response = requests.post(`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"https://api.fish.audio/v1/tts/stream/with-timestamp\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` headers={`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Authorization\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Bearer \u003ctoken>\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Content-Type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"application/json\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"model\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"s2-pro\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` json={`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Hello! Welcome to Fish Audio.\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"reference_id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"model-id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"format\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"opus\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"latency\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"balanced\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` stream=`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`True`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`audio_chunks = []`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`alignment_by_chunk = {}`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`for`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` line `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`in`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` response.iter_lines(decode_unicode=`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`True`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`):`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` not`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` line `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`or`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` not`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` line.startswith(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"data: \"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`):`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` continue`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` event = json.loads(line.removeprefix(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"data: \"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`))`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` audio_chunks.append(base64.b64decode(event[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"audio_base64\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]))`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` event[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"alignment\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`is`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` not`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` None`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` alignment_by_chunk[event[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"chunk_seq\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]] = {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"content\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: event[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"content\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`],`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"offset\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: event[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"chunk_audio_offset_sec\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`],`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"alignment\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: event[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"alignment\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`],`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`audio = b`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.join(audio_chunks)`})]}),`\n`]})})})}),_jsx(Tab,{title:`Node.js`,id:`node-js`,children:_jsx(CodeBlock,{filename:``,numberOfLines:`49`,language:`javascript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`javascript`,children:_jsxs(_components.code,{language:`javascript`,numberOfLines:`49`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` response = `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` fetch(`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"https://api.fish.audio/v1/tts/stream/with-timestamp\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` method: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"POST\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` headers: {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` Authorization: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Bearer \u003ctoken>\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Content-Type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"application/json\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` model: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"s2-pro\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` body: JSON.stringify({`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` text: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Hello! Welcome to Fish Audio.\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` reference_id: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"model-id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` format: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"opus\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` latency: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"balanced\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }),`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` audioChunks = [];`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` alignmentByChunk = `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`new`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` Map();`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` decoder = `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`new`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` TextDecoder();`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` buffer = `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`for`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` chunk `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`of`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` response.body) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` buffer += decoder.decode(chunk, { stream: `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`true`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` events = buffer.split(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"\\\\n\\\\n\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` buffer = events.pop() ?? `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` for`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` eventText `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`of`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` events) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` dataLine = eventText`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` .split(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"\\\\n\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` .find((line) => line.startsWith(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"data: \"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`));`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (!dataLine) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`continue`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` event = JSON.parse(dataLine.slice(6));`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` audioChunks.push(Buffer.`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`from`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(event.audio_base64, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"base64\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`));`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (event.alignment !== `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`null`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` alignmentByChunk.set(event.chunk_seq, {`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` content: event.content,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` offset: event.chunk_audio_offset_sec,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` alignment: event.alignment,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` audio = Buffer.concat(audioChunks);`})]}),`\n`]})})})})]}),`\n`,_jsx(Heading,{level:`2`,id:`handling-split-content-chunks`,children:`Handling Split Content Chunks`}),`\n`,_jsx(_components.p,{children:`Long input can produce multiple text chunks. Treat audio and alignment as two\nrelated streams:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Append every decoded `,_jsx(_components.code,{children:`audio_base64`}),` chunk in event order. Do this even when `,_jsx(_components.code,{children:`alignment`}),` is `,_jsx(_components.code,{children:`null`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`For non-null `,_jsx(_components.code,{children:`alignment`}),`, replace the stored snapshot for `,_jsx(_components.code,{children:`chunk_seq`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Convert each snapshot’s local segment times into global times by adding `,_jsx(_components.code,{children:`chunk_audio_offset_sec`}),`.`]}),`\n`]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`audio_base64`}),` chunks are transport chunks, not sentence or word boundaries.\nDo not try to align each audio chunk individually. Use `,_jsx(_components.code,{children:`alignment.segments`}),`\nplus `,_jsx(_components.code,{children:`chunk_audio_offset_sec`}),` for text timing.`]})}),`\n`,_jsxs(_components.p,{children:[`For example, if an event has `,_jsx(_components.code,{children:`chunk_audio_offset_sec: 16.24`}),`, add `,_jsx(_components.code,{children:`16.24`}),`\nseconds to every segment in that event’s `,_jsx(_components.code,{children:`alignment`}),` before rendering it on the\ncomplete audio timeline.`]}),`\n`,_jsxs(Tabs,{children:[_jsx(Tab,{title:`Python`,id:`python-2`,children:_jsx(CodeBlock,{filename:``,numberOfLines:`16`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`16`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`def`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` build_global_timeline(alignment_by_chunk):`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` timeline = []`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` for`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` chunk_seq, item `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`in`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sorted(alignment_by_chunk.items()):`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` offset_seconds = item[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"offset\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` alignment = item[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"alignment\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` for`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` segment `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`in`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` alignment[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"segments\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]:`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` timeline.append({`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: segment[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`],`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"start\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: segment[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"start\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] + offset_seconds,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"end\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: segment[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"end\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] + offset_seconds,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"chunk_seq\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: chunk_seq,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` })`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` timeline`})]}),`\n`]})})})}),_jsx(Tab,{title:`Node.js`,id:`node-js-2`,children:_jsx(CodeBlock,{filename:``,numberOfLines:`18`,language:`javascript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`javascript`,children:_jsxs(_components.code,{language:`javascript`,numberOfLines:`18`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`function`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` buildGlobalTimeline(alignmentByChunk) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` timeline = [];`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` for`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` [chunkSeq, item] `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`of`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` [...alignmentByChunk.entries()].sort(`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ([a], [b]) => a - b`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` )) {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` for`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` segment `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`of`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` item.alignment.segments) {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` timeline.push({`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` text: segment.text,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` start: segment.start + item.offset,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` end: segment.end + item.offset,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` chunk_seq: chunkSeq,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` timeline;`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})})})]}),`\n`,_jsx(Heading,{level:`2`,id:`format-guidance`,children:`Format Guidance`}),`\n`,_jsxs(_components.p,{children:[`For timestamped streaming, we recommend `,_jsx(_components.code,{children:`opus`}),` with the default 48 kHz sample\nrate when your client supports it. Opus is designed for streaming and gives the\nbest balance of quality, latency, and bandwidth for this endpoint.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`wav`}),` and `,_jsx(_components.code,{children:`pcm`}),` avoid lossy codec artifacts and are straightforward to align,\nbut they produce much larger payloads. Use them when you need uncompressed\naudio, direct sample-level processing, or a playback pipeline that already\nexpects raw audio.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`Use `,_jsx(_components.code,{children:`mp3`}),` only when broad playback compatibility is more important than the\ncleanest streaming boundaries. MP3 encoding uses overlapping audio windows, so\nits encoded chunks may not line up as neatly with timestamp snapshot updates\nas Opus.`]})}),`\n`,_jsxs(_components.p,{children:[`This endpoint accepts the same TTS request fields as the `,_jsx(_components.a,{href:`/api-reference/endpoint/openapi-v1/text-to-speech`,children:`Text to Speech API`}),`, including `,_jsx(_components.code,{children:`reference_id`}),`, `,_jsx(_components.code,{children:`references`}),`, `,_jsx(_components.code,{children:`prosody`}),`, `,_jsx(_components.code,{children:`temperature`}),`, `,_jsx(_components.code,{children:`top_p`}),`, `,_jsx(_components.code,{children:`chunk_length`}),`, `,_jsx(_components.code,{children:`format`}),`, and `,_jsx(_components.code,{children:`latency`}),`.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"openapi":"post /v1/tts/stream/with-timestamp","title":"Text to Speech Stream with Timestamps","description":"Stream generated speech with timestamp alignment snapshots","icon":"waveform-lines","iconType":"solid","href":"/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"How the Stream Works","slug":"how-the-stream-works","depth":2,"children":[]},{"title":"Alignment Shape","slug":"alignment-shape","depth":2,"children":[]},{"title":"Minimal Request","slug":"minimal-request","depth":2,"children":[]},{"title":"Parsing the Stream","slug":"parsing-the-stream","depth":2,"children":[]},{"title":"Handling Split Content Chunks","slug":"handling-split-content-chunks","depth":2,"children":[]},{"title":"Format Guidance","slug":"format-guidance","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"summary":"Text to Speech Stream with Timestamps","security":["8ed29a3b-1b89-4280-b3c0-d43d418c6ea4"],"parameters":["0055f367-c7bc-4919-9403-6dea5dd5c8a7"],"requestBody":"93024c1f-e3a5-40b3-9282-fabe649fd3f0","responses":{"200":"53cb10b3-8d1d-480b-8166-bedef02b1c71","401":"c8b9e49d-c28b-427a-a973-2fb0ce806774","402":"c8c00c83-c488-4011-8295-5e774dc4d0f1","503":"e1fc02fe-8b75-452e-b6f3-23e955b4b8f0"},"tags":["OpenAPI v1"],"x-codeSamples":[{"lang":"bash","label":"Stream With Timestamps","source":"curl --no-buffer --request POST \\\n --url https://api.fish.audio/v1/tts/stream/with-timestamp \\\n --header 'Authorization: Bearer \u003ctoken>' \\\n --header 'Content-Type: application/json' \\\n --header 'model: s2.1-pro-free' \\\n --data '{\n \"text\": \"[happy] I can’t believe it’s been this long. It feels like forever since we last really talked. I’ve missed hearing your voice, your stories, even the little things you used to say. How have you been? I’ve thought about calling you so many times, but I never knew where to start. Seeing you again now makes me realize just how much I’ve missed you. We have so much to catch up on, and I don’t even know which part of my life to tell you about first.\",\n \"format\": \"opus\",\n \"normalize\": true,\n \"temperature\": 0.9,\n \"chunk_length\": 100,\n \"top_p\": 0.9,\n \"latency\": \"balanced\",\n \"sample_rate\": 48000,\n \"reference_id\": \"fbe02f8306fc4d3d915e9871722a39d5\"\n }'"}],"method":"post","type":"path","servers":["4c05306a-8a2b-4dca-ae0d-0b87050df242"],"path":"/v1/tts/stream/with-timestamp","baseUrlOptions":["https://api.fish.audio"],"title":"Text to Speech Stream with Timestamps","description":"Stream generated speech with timestamp alignment snapshots","codeSamples":[{"label":"Stream With Timestamps","lang":"bash","source":"curl --no-buffer --request POST \\\n --url https://api.fish.audio/v1/tts/stream/with-timestamp \\\n --header 'Authorization: Bearer \u003ctoken>' \\\n --header 'Content-Type: application/json' \\\n --header 'model: s2.1-pro-free' \\\n --data '{\n \"text\": \"[happy] I can’t believe it’s been this long. It feels like forever since we last really talked. I’ve missed hearing your voice, your stories, even the little things you used to say. How have you been? I’ve thought about calling you so many times, but I never knew where to start. Seeing you again now makes me realize just how much I’ve missed you. We have so much to catch up on, and I don’t even know which part of my life to tell you about first.\",\n \"format\": \"opus\",\n \"normalize\": true,\n \"temperature\": 0.9,\n \"chunk_length\": 100,\n \"top_p\": 0.9,\n \"latency\": \"balanced\",\n \"sample_rate\": 48000,\n \"reference_id\": \"fbe02f8306fc4d3d915e9871722a39d5\"\n }'"}],"requiredOnlyExamples":false,"requestExampleType":"codeSamples","responseExampleType":"generated"},"dependencies":{"parameters":{"0055f367-c7bc-4919-9403-6dea5dd5c8a7":{"in":"header","name":"model","description":"Specify which TTS model to use. Use `s2.1-pro-free` for the free developer tier. If omitted or set to an unrecognized value, the request falls back to `s2.1-pro`.","required":false,"schema":{"default":"s2.1-pro","enum":["s1","s2-pro","s2.1-pro","s2.1-pro-free","drama-3"],"title":"Model","type":"string","isRequired":false,"description":"Specify which TTS model to use. Use `s2.1-pro-free` for the free developer tier. If omitted or set to an unrecognized value, the request falls back to `s2.1-pro`.","uniqueKey":"","typeLabel":"enum\u003cstring>"},"deprecated":false}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"description":"Request body for streaming text-to-speech synthesis with timestamp alignment. The request fields match the standard TTS endpoint, but the response is delivered as a Server-Sent Events stream. Each SSE payload includes an audio chunk and, when available, the latest cumulative alignment snapshot for a `chunk_seq`. Clients should concatenate `audio_base64` chunks in arrival order and replace the stored alignment for each `chunk_seq` whenever a newer snapshot is received.","properties":{"text":{"description":"Text to convert to speech.","title":"Text","type":"string","isRequired":true,"uniqueKey":"text","typeLabel":"string"},"temperature":{"default":0.7,"description":"Controls expressiveness. Higher is more varied, lower is more consistent.","maximum":1,"minimum":0,"title":"Temperature","type":"number","uniqueKey":"temperature","typeLabel":"number"},"top_p":{"default":0.7,"description":"Controls diversity via nucleus sampling.","maximum":1,"minimum":0,"title":"Top P","type":"number","uniqueKey":"top_p","typeLabel":"number"},"references":{"oneOf":[{"type":"array","items":{"description":"A voice sample with its transcript, used for zero-shot voice cloning. The model will attempt to match the voice characteristics from the audio sample.","properties":{"audio":{"description":"Raw audio bytes of the voice sample. Supported formats: WAV, MP3, FLAC. For best results, use 10-30 seconds of clear speech with minimal background noise.","format":"binary","title":"Audio","type":"string","isRequired":true,"uniqueKey":"references.oneOf.0.items.[INDEX].audio","typeLabel":"file"},"text":{"description":"The exact transcript of what is spoken in the audio sample. Accuracy is important for voice cloning quality.","title":"Text","type":"string","isRequired":true,"uniqueKey":"references.oneOf.0.items.[INDEX].text","typeLabel":"string"}},"required":["audio","text"],"title":"ReferenceAudio","type":"object","uniqueKey":"references.oneOf.0.items.[INDEX]","typeLabel":"ReferenceAudio · object"},"title":"References","description":"Single speaker: array of reference audio samples","uniqueKey":"references.oneOf.0","typeLabel":"ReferenceAudio · object[]"},{"type":"array","items":{"items":{"description":"A voice sample with its transcript, used for zero-shot voice cloning. The model will attempt to match the voice characteristics from the audio sample.","properties":{"audio":{"description":"Raw audio bytes of the voice sample. Supported formats: WAV, MP3, FLAC. For best results, use 10-30 seconds of clear speech with minimal background noise.","format":"binary","title":"Audio","type":"string","isRequired":true,"uniqueKey":"references.oneOf.1.items.[INDEX].items.[INDEX].audio","typeLabel":"file"},"text":{"description":"The exact transcript of what is spoken in the audio sample. Accuracy is important for voice cloning quality.","title":"Text","type":"string","isRequired":true,"uniqueKey":"references.oneOf.1.items.[INDEX].items.[INDEX].text","typeLabel":"string"}},"required":["audio","text"],"title":"ReferenceAudio","type":"object","uniqueKey":"references.oneOf.1.items.[INDEX].items.[INDEX]","typeLabel":"ReferenceAudio · object"},"type":"array","uniqueKey":"references.oneOf.1.items.[INDEX]","typeLabel":"ReferenceAudio · object[]"},"title":"References","description":"Multiple speakers: array of arrays, where each inner array contains reference samples for one speaker","uniqueKey":"references.oneOf.1","typeLabel":"ReferenceAudio · object[][]"},{"type":"null","title":"References","description":"Inline voice references for zero-shot cloning. Requires MessagePack (not JSON). For single speaker, provide an array of ReferenceAudio objects. For multiple speakers, provide an array of arrays where each inner array contains references for one speaker. **Multi-speaker is available with the S2 family (`s2-pro`, `s2.1-pro`, `s2.1-pro-free`) and `drama-3`, not `s1`.** The speaker index corresponds to the index in reference_id array. Example for multi-speaker: [[{audio, text}], [{audio, text}, {audio, text}]] for 2 speakers where speaker 1 has 2 reference samples.","uniqueKey":"references.oneOf.2","typeLabel":"null"}],"uniqueKey":"references","typeLabel":"ReferenceAudio · object[] | ReferenceAudio · object[][] | null"},"reference_id":{"oneOf":[{"type":"string","title":"Reference Id","description":"Single speaker: voice model ID string","uniqueKey":"reference_id.oneOf.0","typeLabel":"string"},{"type":"array","items":{"type":"string","uniqueKey":"reference_id.oneOf.1.items.[INDEX]","typeLabel":"string"},"title":"Reference Id","description":"Multiple speakers: array of voice model IDs, one per speaker","uniqueKey":"reference_id.oneOf.1","typeLabel":"string[]"},{"type":"null","title":"Reference Id","description":"Voice model ID(s) from Fish Audio library or your custom models. For single-speaker synthesis, provide a string. For multi-speaker synthesis (dialogue), provide an array of model IDs. **Multi-speaker is available with the S2 family (`s2-pro`, `s2.1-pro`, `s2.1-pro-free`) and `drama-3`, not `s1`.** When using multiple speakers, use speaker tags in your text like `\u003c|speaker:0|>` and `\u003c|speaker:1|>` to indicate speaker changes. Example: `\u003c|speaker:0|>Hello!\u003c|speaker:1|>Hi there!\u003c|speaker:0|>How are you?` with `reference_id: [\"speaker-a-id\", \"speaker-b-id\"]`.","uniqueKey":"reference_id.oneOf.2","typeLabel":"null"}],"uniqueKey":"reference_id","typeLabel":"string | string[] | null"},"prosody":{"oneOf":[{"type":"object","title":"ProsodyControl","description":"Speed and volume adjustments for the output.","properties":{"speed":{"default":1,"description":"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.","title":"Speed","type":"number","uniqueKey":"prosody.oneOf.0.speed","typeLabel":"number"},"volume":{"default":0,"description":"Volume adjustment in decibels (dB). 0 = no change, positive values = louder, negative values = quieter.","title":"Volume","type":"number","uniqueKey":"prosody.oneOf.0.volume","typeLabel":"number"},"normalize_loudness":{"default":true,"description":"Normalize output loudness for more consistent perceived volume. Applies to the S2 family (`s2-pro`, `s2.1-pro`, `s2.1-pro-free`); on `s1` it is accepted but has no effect.","title":"Normalize Loudness","type":"boolean","uniqueKey":"prosody.oneOf.0.normalize_loudness","typeLabel":"boolean"}},"uniqueKey":"prosody.oneOf.0","typeLabel":"ProsodyControl · object"},{"type":"null","description":"Speed and volume adjustments for the output.","uniqueKey":"prosody.oneOf.1","typeLabel":"null"}],"uniqueKey":"prosody","typeLabel":"ProsodyControl · object | null"},"chunk_length":{"default":300,"description":"Text segment size for processing.","maximum":300,"minimum":100,"title":"Chunk Length","type":"integer","uniqueKey":"chunk_length","typeLabel":"integer"},"normalize":{"default":true,"description":"Rewrites numbers, dates, units and symbols as spoken words before synthesis, improving stability. Uses `language` when it is set and otherwise detects the language of each text chunk.","title":"Normalize","type":"boolean","uniqueKey":"normalize","typeLabel":"boolean"},"language":{"oneOf":[{"type":"string","title":"Language","description":"BCP-47 language tag of the text, for example `en`, `es-MX` or `zh-CN`. Case-insensitive, and `_` is read as `-`. Used only by text normalization (how numbers, dates, units and symbols are spelled out before synthesis) and by word-timestamp alignment. It is not passed to the speech model and does not change the voice, accent or audio quality; a wrong tag only changes how those tokens are spelled out. Omit it, or send `auto` or an empty string, to detect the language per chunk. A tag without dedicated normalization rules skips normalization instead of failing. Without a region, Spanish follows Spain conventions; send `es-MX` for Mexican readings. When `normalize` is false it only affects word timestamps. For text that mixes languages, leave it unset.","maxLength":35,"pattern":"^[A-Za-z0-9_-]*$","example":"en","uniqueKey":"language.oneOf.0","typeLabel":"string"},{"type":"null","title":"Language","description":"BCP-47 language tag of the text, for example `en`, `es-MX` or `zh-CN`. Case-insensitive, and `_` is read as `-`. Used only by text normalization (how numbers, dates, units and symbols are spelled out before synthesis) and by word-timestamp alignment. It is not passed to the speech model and does not change the voice, accent or audio quality; a wrong tag only changes how those tokens are spelled out. Omit it, or send `auto` or an empty string, to detect the language per chunk. A tag without dedicated normalization rules skips normalization instead of failing. Without a region, Spanish follows Spain conventions; send `es-MX` for Mexican readings. When `normalize` is false it only affects word timestamps. For text that mixes languages, leave it unset.","example":"en","uniqueKey":"language.oneOf.1","typeLabel":"null"}],"uniqueKey":"language","typeLabel":"string | null"},"format":{"default":"mp3","description":"Output audio format.","enum":["wav","pcm","mp3","opus"],"title":"Format","type":"string","uniqueKey":"format","typeLabel":"enum\u003cstring>"},"sample_rate":{"oneOf":[{"type":"integer","title":"Sample Rate","description":"Audio sample rate in Hz. When null, uses the format's default (44100 Hz for most formats, 48000 Hz for opus).","uniqueKey":"sample_rate.oneOf.0","typeLabel":"integer"},{"type":"null","title":"Sample Rate","description":"Audio sample rate in Hz. When null, uses the format's default (44100 Hz for most formats, 48000 Hz for opus).","uniqueKey":"sample_rate.oneOf.1","typeLabel":"null"}],"uniqueKey":"sample_rate","typeLabel":"integer | null"},"mp3_bitrate":{"default":128,"description":"MP3 bitrate in kbps. Only applies when format is mp3.","enum":[64,128,192],"title":"Mp3 Bitrate","type":"integer","uniqueKey":"mp3_bitrate","typeLabel":"enum\u003cinteger>"},"opus_bitrate":{"default":-1000,"description":"Opus bitrate in bps. -1000 for automatic. Only applies when format is opus.","enum":[-1000,24000,32000,48000,64000],"title":"Opus Bitrate","type":"integer","uniqueKey":"opus_bitrate","typeLabel":"enum\u003cinteger>"},"latency":{"default":"normal","description":"Latency-quality trade-off. normal: best quality, balanced: reduced latency, low: lowest latency.","enum":["low","normal","balanced"],"title":"Latency","type":"string","uniqueKey":"latency","typeLabel":"enum\u003cstring>"},"max_new_tokens":{"default":1024,"description":"Maximum audio tokens to generate per text chunk.","title":"Max New Tokens","type":"integer","uniqueKey":"max_new_tokens","typeLabel":"integer"},"repetition_penalty":{"default":1.2,"description":"Penalty for repeating audio patterns. Values above 1.0 reduce repetition.","title":"Repetition Penalty","type":"number","uniqueKey":"repetition_penalty","typeLabel":"number"},"min_chunk_length":{"default":50,"description":"Minimum characters before splitting into a new chunk.","maximum":100,"minimum":0,"title":"Min Chunk Length","type":"integer","uniqueKey":"min_chunk_length","typeLabel":"integer"},"condition_on_previous_chunks":{"default":true,"description":"Use previous audio as context for voice consistency.","title":"Condition On Previous Chunks","type":"boolean","uniqueKey":"condition_on_previous_chunks","typeLabel":"boolean"},"early_stop_threshold":{"default":1,"description":"Early stopping threshold for batch processing.","maximum":1,"minimum":0,"title":"Early Stop Threshold","type":"number","uniqueKey":"early_stop_threshold","typeLabel":"number"},"features":{"default":[],"description":"Optional request-scoped TTS feature flags forwarded verbatim to the inference backend. Use [\"quality-guard\"] to enable the quality guard for this synthesis request. Feature availability is determined by the inference backend.","items":{"type":"string","uniqueKey":"features.items.[INDEX]","typeLabel":"string"},"title":"Features","type":"array","uniqueKey":"features","typeLabel":"string[]"},"pronunciation_dictionary":{"oneOf":[{"type":"array","items":{"additionalProperties":false,"description":"Reference to a server-managed pronunciation dictionary. The server resolves contents via the platform pronunciation-dictionaries API and forwards the full merged dictionary to the inference engine, which performs the substitution.","properties":{"id":{"description":"Dictionary identifier as registered on the platform.","pattern":"^[A-Za-z0-9_-]{1,128}$","title":"Id","type":"string","isRequired":true,"uniqueKey":"pronunciation_dictionary.oneOf.0.items.[INDEX].id","typeLabel":"string"},"version":{"description":"Immutable version identifier for the dictionary. Version is required — there is no implicit `latest`.","pattern":"^[A-Za-z0-9_-]{1,128}$","title":"Version","type":"string","isRequired":true,"uniqueKey":"pronunciation_dictionary.oneOf.0.items.[INDEX].version","typeLabel":"string"}},"required":["id","version"],"title":"PronunciationDictionaryRef","type":"object","uniqueKey":"pronunciation_dictionary.oneOf.0.items.[INDEX]","typeLabel":"PronunciationDictionaryRef · object"},"title":"Pronunciation Dictionary","description":"Reference form: list of pointers to platform pronunciation dictionaries. Each entry identifies a dictionary by `id` and `version`; the server resolves the contents from the platform service before forwarding them to the inference engine.","maxItems":3,"uniqueKey":"pronunciation_dictionary.oneOf.0","typeLabel":"PronunciationDictionaryRef · object[]"},{"type":"array","items":{"additionalProperties":false,"description":"Inline literal pronunciation dictionary. The server forwards the entries directly to the inference engine without contacting the platform.","properties":{"items":{"description":"Replacement entries for this dictionary. See the top-level `pronunciation_dictionary` field description for replacement semantics.","items":{"additionalProperties":false,"description":"A single key/value entry in a pronunciation dictionary. The inference engine replaces every occurrence of `key` in the request text with `value` during synthesis. With the default `type: \"phoneme\"` the value is spoken as a phonetic form; with `type: \"alias\"` it is substituted as plain text.","properties":{"key":{"description":"Source substring to match. Pure substring match — no tokenization, no regex. Overlapping matches resolve leftmost-longest. For CJK text include enough context to disambiguate. For `type: \"alias\"` the key must not start or end with whitespace and must not contain control characters, `\u003c`, `>`, `(`, `)`, `[` or `]`.","maxLength":256,"minLength":1,"title":"Key","type":"string","isRequired":true,"uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items.items.[INDEX].key","typeLabel":"string"},"value":{"description":"Replacement for the key during synthesis. For `type: \"phoneme\"` this is a phonetic representation; dictionary authors should NOT include the `\u003c|phoneme_start|>` / `\u003c|phoneme_end|>` markers themselves, because the inference engine wraps the value with those markers internally so the body is treated as phonemes rather than orthographic text. For `type: \"alias\"` this is plain text substituted verbatim (then normalized with the rest of the request text) and must not contain `\u003c|` or `|>`. Requests whose key or value contain either phoneme marker are rejected.","maxLength":1024,"minLength":1,"title":"Value","type":"string","isRequired":true,"uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items.items.[INDEX].value","typeLabel":"string"},"type":{"default":"phoneme","description":"How `value` replaces `key`. `phoneme` (default) speaks the value as a phonetic form. `alias` substitutes the literal text, which then goes through the same text normalization as the rest of the request. Omitted or `null` means `phoneme`, so existing dictionaries and clients keep their behaviour. Any other value is rejected. Usage is billed on the text actually synthesized, with alias replacements counted: an alias that expands a key is billed for the longer text, one that shortens it is billed for the shorter text; phoneme rules never change billing.","enum":["phoneme","alias"],"title":"Type","type":"string","uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items.items.[INDEX].type","typeLabel":"enum\u003cstring>"},"case_sensitive":{"default":false,"description":"When true the match is case-sensitive; when false ASCII case folding is applied.","title":"Case Sensitive","type":"boolean","uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items.items.[INDEX].case_sensitive","typeLabel":"boolean"}},"required":["key","value"],"title":"PronunciationItem","type":"object","uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items.items.[INDEX]","typeLabel":"PronunciationItem · object"},"maxItems":5000,"title":"Items","type":"array","isRequired":true,"uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items","typeLabel":"PronunciationItem · object[]"}},"required":["items"],"title":"PronunciationDictionaryInline","type":"object","uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX]","typeLabel":"PronunciationDictionaryInline · object"},"title":"Pronunciation Dictionary","description":"Inline form: list of literal pronunciation dictionaries. Each dictionary carries an `items` array of `{key, value, type?, case_sensitive?}` entries.","maxItems":3,"uniqueKey":"pronunciation_dictionary.oneOf.1","typeLabel":"PronunciationDictionaryInline · object[]"},{"type":"null","title":"Pronunciation Dictionary","description":"Optional list of up to 3 pronunciation dictionaries to apply during synthesis. Provide either references to platform-managed dictionaries OR inline literal dictionaries (the two forms are mutually exclusive in a single request). The server resolves and merges the dictionaries, then forwards the full merged dictionary to the inference engine, which performs the substitution. Each entry sets `type` to `phoneme` (default: the value is spoken as a phonetic form) or `alias` (plain text replacement). Usage is billed on the text actually synthesized, with alias replacements counted: an alias that expands a key is billed for the longer text, one that shortens it is billed for the shorter text; phoneme rules never change billing. Matching is plain substring matching, leftmost-longest, and case-insensitive unless an entry sets `case_sensitive`. Missing or unresolvable references are silently dropped — the request still succeeds. Use `application/json` or `application/msgpack` content-type; nested arrays are not representable in `multipart/form-data`.","uniqueKey":"pronunciation_dictionary.oneOf.2","typeLabel":"null"}],"uniqueKey":"pronunciation_dictionary","typeLabel":"PronunciationDictionaryRef · object[] | PronunciationDictionaryInline · object[] | null"}},"required":["text"],"title":"TTSStreamWithTimestampRequest","type":"object","uniqueKey":"","typeLabel":"TTSStreamWithTimestampRequest · object"},"examples":{"Example":{"title":"Example","value":{"text":"\u003cstring>","temperature":0.7,"top_p":0.7,"references":[{"audio":"\u003cstring>","text":"\u003cstring>"}],"reference_id":"\u003cstring>","prosody":{"speed":1,"volume":0,"normalize_loudness":true},"chunk_length":300,"normalize":true,"language":"en","format":"mp3","sample_rate":123,"mp3_bitrate":128,"opus_bitrate":-1000,"latency":"normal","max_new_tokens":1024,"repetition_penalty":1.2,"min_chunk_length":50,"condition_on_previous_chunks":true,"early_stop_threshold":1,"features":[],"pronunciation_dictionary":[{"id":"\u003cstring>","version":"\u003cstring>"}]}}},"exampleType":"generated"},"application/msgpack":{"schema":{"description":"Request body for streaming text-to-speech synthesis with timestamp alignment. The request fields match the standard TTS endpoint, but the response is delivered as a Server-Sent Events stream. Each SSE payload includes an audio chunk and, when available, the latest cumulative alignment snapshot for a `chunk_seq`. Clients should concatenate `audio_base64` chunks in arrival order and replace the stored alignment for each `chunk_seq` whenever a newer snapshot is received.","properties":{"text":{"description":"Text to convert to speech.","title":"Text","type":"string","isRequired":true,"uniqueKey":"text","typeLabel":"string"},"temperature":{"default":0.7,"description":"Controls expressiveness. Higher is more varied, lower is more consistent.","maximum":1,"minimum":0,"title":"Temperature","type":"number","uniqueKey":"temperature","typeLabel":"number"},"top_p":{"default":0.7,"description":"Controls diversity via nucleus sampling.","maximum":1,"minimum":0,"title":"Top P","type":"number","uniqueKey":"top_p","typeLabel":"number"},"references":{"oneOf":[{"type":"array","items":{"description":"A voice sample with its transcript, used for zero-shot voice cloning. The model will attempt to match the voice characteristics from the audio sample.","properties":{"audio":{"description":"Raw audio bytes of the voice sample. Supported formats: WAV, MP3, FLAC. For best results, use 10-30 seconds of clear speech with minimal background noise.","format":"binary","title":"Audio","type":"string","isRequired":true,"uniqueKey":"references.oneOf.0.items.[INDEX].audio","typeLabel":"file"},"text":{"description":"The exact transcript of what is spoken in the audio sample. Accuracy is important for voice cloning quality.","title":"Text","type":"string","isRequired":true,"uniqueKey":"references.oneOf.0.items.[INDEX].text","typeLabel":"string"}},"required":["audio","text"],"title":"ReferenceAudio","type":"object","uniqueKey":"references.oneOf.0.items.[INDEX]","typeLabel":"ReferenceAudio · object"},"title":"References","description":"Single speaker: array of reference audio samples","uniqueKey":"references.oneOf.0","typeLabel":"ReferenceAudio · object[]"},{"type":"array","items":{"items":{"description":"A voice sample with its transcript, used for zero-shot voice cloning. The model will attempt to match the voice characteristics from the audio sample.","properties":{"audio":{"description":"Raw audio bytes of the voice sample. Supported formats: WAV, MP3, FLAC. For best results, use 10-30 seconds of clear speech with minimal background noise.","format":"binary","title":"Audio","type":"string","isRequired":true,"uniqueKey":"references.oneOf.1.items.[INDEX].items.[INDEX].audio","typeLabel":"file"},"text":{"description":"The exact transcript of what is spoken in the audio sample. Accuracy is important for voice cloning quality.","title":"Text","type":"string","isRequired":true,"uniqueKey":"references.oneOf.1.items.[INDEX].items.[INDEX].text","typeLabel":"string"}},"required":["audio","text"],"title":"ReferenceAudio","type":"object","uniqueKey":"references.oneOf.1.items.[INDEX].items.[INDEX]","typeLabel":"ReferenceAudio · object"},"type":"array","uniqueKey":"references.oneOf.1.items.[INDEX]","typeLabel":"ReferenceAudio · object[]"},"title":"References","description":"Multiple speakers: array of arrays, where each inner array contains reference samples for one speaker","uniqueKey":"references.oneOf.1","typeLabel":"ReferenceAudio · object[][]"},{"type":"null","title":"References","description":"Inline voice references for zero-shot cloning. Requires MessagePack (not JSON). For single speaker, provide an array of ReferenceAudio objects. For multiple speakers, provide an array of arrays where each inner array contains references for one speaker. **Multi-speaker is available with the S2 family (`s2-pro`, `s2.1-pro`, `s2.1-pro-free`) and `drama-3`, not `s1`.** The speaker index corresponds to the index in reference_id array. Example for multi-speaker: [[{audio, text}], [{audio, text}, {audio, text}]] for 2 speakers where speaker 1 has 2 reference samples.","uniqueKey":"references.oneOf.2","typeLabel":"null"}],"uniqueKey":"references","typeLabel":"ReferenceAudio · object[] | ReferenceAudio · object[][] | null"},"reference_id":{"oneOf":[{"type":"string","title":"Reference Id","description":"Single speaker: voice model ID string","uniqueKey":"reference_id.oneOf.0","typeLabel":"string"},{"type":"array","items":{"type":"string","uniqueKey":"reference_id.oneOf.1.items.[INDEX]","typeLabel":"string"},"title":"Reference Id","description":"Multiple speakers: array of voice model IDs, one per speaker","uniqueKey":"reference_id.oneOf.1","typeLabel":"string[]"},{"type":"null","title":"Reference Id","description":"Voice model ID(s) from Fish Audio library or your custom models. For single-speaker synthesis, provide a string. For multi-speaker synthesis (dialogue), provide an array of model IDs. **Multi-speaker is available with the S2 family (`s2-pro`, `s2.1-pro`, `s2.1-pro-free`) and `drama-3`, not `s1`.** When using multiple speakers, use speaker tags in your text like `\u003c|speaker:0|>` and `\u003c|speaker:1|>` to indicate speaker changes. Example: `\u003c|speaker:0|>Hello!\u003c|speaker:1|>Hi there!\u003c|speaker:0|>How are you?` with `reference_id: [\"speaker-a-id\", \"speaker-b-id\"]`.","uniqueKey":"reference_id.oneOf.2","typeLabel":"null"}],"uniqueKey":"reference_id","typeLabel":"string | string[] | null"},"prosody":{"oneOf":[{"type":"object","title":"ProsodyControl","description":"Speed and volume adjustments for the output.","properties":{"speed":{"default":1,"description":"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.","title":"Speed","type":"number","uniqueKey":"prosody.oneOf.0.speed","typeLabel":"number"},"volume":{"default":0,"description":"Volume adjustment in decibels (dB). 0 = no change, positive values = louder, negative values = quieter.","title":"Volume","type":"number","uniqueKey":"prosody.oneOf.0.volume","typeLabel":"number"},"normalize_loudness":{"default":true,"description":"Normalize output loudness for more consistent perceived volume. Applies to the S2 family (`s2-pro`, `s2.1-pro`, `s2.1-pro-free`); on `s1` it is accepted but has no effect.","title":"Normalize Loudness","type":"boolean","uniqueKey":"prosody.oneOf.0.normalize_loudness","typeLabel":"boolean"}},"uniqueKey":"prosody.oneOf.0","typeLabel":"ProsodyControl · object"},{"type":"null","description":"Speed and volume adjustments for the output.","uniqueKey":"prosody.oneOf.1","typeLabel":"null"}],"uniqueKey":"prosody","typeLabel":"ProsodyControl · object | null"},"chunk_length":{"default":300,"description":"Text segment size for processing.","maximum":300,"minimum":100,"title":"Chunk Length","type":"integer","uniqueKey":"chunk_length","typeLabel":"integer"},"normalize":{"default":true,"description":"Rewrites numbers, dates, units and symbols as spoken words before synthesis, improving stability. Uses `language` when it is set and otherwise detects the language of each text chunk.","title":"Normalize","type":"boolean","uniqueKey":"normalize","typeLabel":"boolean"},"language":{"oneOf":[{"type":"string","title":"Language","description":"BCP-47 language tag of the text, for example `en`, `es-MX` or `zh-CN`. Case-insensitive, and `_` is read as `-`. Used only by text normalization (how numbers, dates, units and symbols are spelled out before synthesis) and by word-timestamp alignment. It is not passed to the speech model and does not change the voice, accent or audio quality; a wrong tag only changes how those tokens are spelled out. Omit it, or send `auto` or an empty string, to detect the language per chunk. A tag without dedicated normalization rules skips normalization instead of failing. Without a region, Spanish follows Spain conventions; send `es-MX` for Mexican readings. When `normalize` is false it only affects word timestamps. For text that mixes languages, leave it unset.","maxLength":35,"pattern":"^[A-Za-z0-9_-]*$","example":"en","uniqueKey":"language.oneOf.0","typeLabel":"string"},{"type":"null","title":"Language","description":"BCP-47 language tag of the text, for example `en`, `es-MX` or `zh-CN`. Case-insensitive, and `_` is read as `-`. Used only by text normalization (how numbers, dates, units and symbols are spelled out before synthesis) and by word-timestamp alignment. It is not passed to the speech model and does not change the voice, accent or audio quality; a wrong tag only changes how those tokens are spelled out. Omit it, or send `auto` or an empty string, to detect the language per chunk. A tag without dedicated normalization rules skips normalization instead of failing. Without a region, Spanish follows Spain conventions; send `es-MX` for Mexican readings. When `normalize` is false it only affects word timestamps. For text that mixes languages, leave it unset.","example":"en","uniqueKey":"language.oneOf.1","typeLabel":"null"}],"uniqueKey":"language","typeLabel":"string | null"},"format":{"default":"mp3","description":"Output audio format.","enum":["wav","pcm","mp3","opus"],"title":"Format","type":"string","uniqueKey":"format","typeLabel":"enum\u003cstring>"},"sample_rate":{"oneOf":[{"type":"integer","title":"Sample Rate","description":"Audio sample rate in Hz. When null, uses the format's default (44100 Hz for most formats, 48000 Hz for opus).","uniqueKey":"sample_rate.oneOf.0","typeLabel":"integer"},{"type":"null","title":"Sample Rate","description":"Audio sample rate in Hz. When null, uses the format's default (44100 Hz for most formats, 48000 Hz for opus).","uniqueKey":"sample_rate.oneOf.1","typeLabel":"null"}],"uniqueKey":"sample_rate","typeLabel":"integer | null"},"mp3_bitrate":{"default":128,"description":"MP3 bitrate in kbps. Only applies when format is mp3.","enum":[64,128,192],"title":"Mp3 Bitrate","type":"integer","uniqueKey":"mp3_bitrate","typeLabel":"enum\u003cinteger>"},"opus_bitrate":{"default":-1000,"description":"Opus bitrate in bps. -1000 for automatic. Only applies when format is opus.","enum":[-1000,24000,32000,48000,64000],"title":"Opus Bitrate","type":"integer","uniqueKey":"opus_bitrate","typeLabel":"enum\u003cinteger>"},"latency":{"default":"normal","description":"Latency-quality trade-off. normal: best quality, balanced: reduced latency, low: lowest latency.","enum":["low","normal","balanced"],"title":"Latency","type":"string","uniqueKey":"latency","typeLabel":"enum\u003cstring>"},"max_new_tokens":{"default":1024,"description":"Maximum audio tokens to generate per text chunk.","title":"Max New Tokens","type":"integer","uniqueKey":"max_new_tokens","typeLabel":"integer"},"repetition_penalty":{"default":1.2,"description":"Penalty for repeating audio patterns. Values above 1.0 reduce repetition.","title":"Repetition Penalty","type":"number","uniqueKey":"repetition_penalty","typeLabel":"number"},"min_chunk_length":{"default":50,"description":"Minimum characters before splitting into a new chunk.","maximum":100,"minimum":0,"title":"Min Chunk Length","type":"integer","uniqueKey":"min_chunk_length","typeLabel":"integer"},"condition_on_previous_chunks":{"default":true,"description":"Use previous audio as context for voice consistency.","title":"Condition On Previous Chunks","type":"boolean","uniqueKey":"condition_on_previous_chunks","typeLabel":"boolean"},"early_stop_threshold":{"default":1,"description":"Early stopping threshold for batch processing.","maximum":1,"minimum":0,"title":"Early Stop Threshold","type":"number","uniqueKey":"early_stop_threshold","typeLabel":"number"},"features":{"default":[],"description":"Optional request-scoped TTS feature flags forwarded verbatim to the inference backend. Use [\"quality-guard\"] to enable the quality guard for this synthesis request. Feature availability is determined by the inference backend.","items":{"type":"string","uniqueKey":"features.items.[INDEX]","typeLabel":"string"},"title":"Features","type":"array","uniqueKey":"features","typeLabel":"string[]"},"pronunciation_dictionary":{"oneOf":[{"type":"array","items":{"additionalProperties":false,"description":"Reference to a server-managed pronunciation dictionary. The server resolves contents via the platform pronunciation-dictionaries API and forwards the full merged dictionary to the inference engine, which performs the substitution.","properties":{"id":{"description":"Dictionary identifier as registered on the platform.","pattern":"^[A-Za-z0-9_-]{1,128}$","title":"Id","type":"string","isRequired":true,"uniqueKey":"pronunciation_dictionary.oneOf.0.items.[INDEX].id","typeLabel":"string"},"version":{"description":"Immutable version identifier for the dictionary. Version is required — there is no implicit `latest`.","pattern":"^[A-Za-z0-9_-]{1,128}$","title":"Version","type":"string","isRequired":true,"uniqueKey":"pronunciation_dictionary.oneOf.0.items.[INDEX].version","typeLabel":"string"}},"required":["id","version"],"title":"PronunciationDictionaryRef","type":"object","uniqueKey":"pronunciation_dictionary.oneOf.0.items.[INDEX]","typeLabel":"PronunciationDictionaryRef · object"},"title":"Pronunciation Dictionary","description":"Reference form: list of pointers to platform pronunciation dictionaries. Each entry identifies a dictionary by `id` and `version`; the server resolves the contents from the platform service before forwarding them to the inference engine.","maxItems":3,"uniqueKey":"pronunciation_dictionary.oneOf.0","typeLabel":"PronunciationDictionaryRef · object[]"},{"type":"array","items":{"additionalProperties":false,"description":"Inline literal pronunciation dictionary. The server forwards the entries directly to the inference engine without contacting the platform.","properties":{"items":{"description":"Replacement entries for this dictionary. See the top-level `pronunciation_dictionary` field description for replacement semantics.","items":{"additionalProperties":false,"description":"A single key/value entry in a pronunciation dictionary. The inference engine replaces every occurrence of `key` in the request text with `value` during synthesis. With the default `type: \"phoneme\"` the value is spoken as a phonetic form; with `type: \"alias\"` it is substituted as plain text.","properties":{"key":{"description":"Source substring to match. Pure substring match — no tokenization, no regex. Overlapping matches resolve leftmost-longest. For CJK text include enough context to disambiguate. For `type: \"alias\"` the key must not start or end with whitespace and must not contain control characters, `\u003c`, `>`, `(`, `)`, `[` or `]`.","maxLength":256,"minLength":1,"title":"Key","type":"string","isRequired":true,"uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items.items.[INDEX].key","typeLabel":"string"},"value":{"description":"Replacement for the key during synthesis. For `type: \"phoneme\"` this is a phonetic representation; dictionary authors should NOT include the `\u003c|phoneme_start|>` / `\u003c|phoneme_end|>` markers themselves, because the inference engine wraps the value with those markers internally so the body is treated as phonemes rather than orthographic text. For `type: \"alias\"` this is plain text substituted verbatim (then normalized with the rest of the request text) and must not contain `\u003c|` or `|>`. Requests whose key or value contain either phoneme marker are rejected.","maxLength":1024,"minLength":1,"title":"Value","type":"string","isRequired":true,"uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items.items.[INDEX].value","typeLabel":"string"},"type":{"default":"phoneme","description":"How `value` replaces `key`. `phoneme` (default) speaks the value as a phonetic form. `alias` substitutes the literal text, which then goes through the same text normalization as the rest of the request. Omitted or `null` means `phoneme`, so existing dictionaries and clients keep their behaviour. Any other value is rejected. Usage is billed on the text actually synthesized, with alias replacements counted: an alias that expands a key is billed for the longer text, one that shortens it is billed for the shorter text; phoneme rules never change billing.","enum":["phoneme","alias"],"title":"Type","type":"string","uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items.items.[INDEX].type","typeLabel":"enum\u003cstring>"},"case_sensitive":{"default":false,"description":"When true the match is case-sensitive; when false ASCII case folding is applied.","title":"Case Sensitive","type":"boolean","uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items.items.[INDEX].case_sensitive","typeLabel":"boolean"}},"required":["key","value"],"title":"PronunciationItem","type":"object","uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items.items.[INDEX]","typeLabel":"PronunciationItem · object"},"maxItems":5000,"title":"Items","type":"array","isRequired":true,"uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX].\\items","typeLabel":"PronunciationItem · object[]"}},"required":["items"],"title":"PronunciationDictionaryInline","type":"object","uniqueKey":"pronunciation_dictionary.oneOf.1.items.[INDEX]","typeLabel":"PronunciationDictionaryInline · object"},"title":"Pronunciation Dictionary","description":"Inline form: list of literal pronunciation dictionaries. Each dictionary carries an `items` array of `{key, value, type?, case_sensitive?}` entries.","maxItems":3,"uniqueKey":"pronunciation_dictionary.oneOf.1","typeLabel":"PronunciationDictionaryInline · object[]"},{"type":"null","title":"Pronunciation Dictionary","description":"Optional list of up to 3 pronunciation dictionaries to apply during synthesis. Provide either references to platform-managed dictionaries OR inline literal dictionaries (the two forms are mutually exclusive in a single request). The server resolves and merges the dictionaries, then forwards the full merged dictionary to the inference engine, which performs the substitution. Each entry sets `type` to `phoneme` (default: the value is spoken as a phonetic form) or `alias` (plain text replacement). Usage is billed on the text actually synthesized, with alias replacements counted: an alias that expands a key is billed for the longer text, one that shortens it is billed for the shorter text; phoneme rules never change billing. Matching is plain substring matching, leftmost-longest, and case-insensitive unless an entry sets `case_sensitive`. Missing or unresolvable references are silently dropped — the request still succeeds. Use `application/json` or `application/msgpack` content-type; nested arrays are not representable in `multipart/form-data`.","uniqueKey":"pronunciation_dictionary.oneOf.2","typeLabel":"null"}],"uniqueKey":"pronunciation_dictionary","typeLabel":"PronunciationDictionaryRef · object[] | PronunciationDictionaryInline · object[] | null"}},"required":["text"],"title":"TTSStreamWithTimestampRequest","type":"object","uniqueKey":"","typeLabel":"TTSStreamWithTimestampRequest · object"},"examples":{"Example":{"title":"Example","value":{"text":"\u003cstring>","temperature":0.7,"top_p":0.7,"references":[{"audio":"\u003cstring>","text":"\u003cstring>"}],"reference_id":"\u003cstring>","prosody":{"speed":1,"volume":0,"normalize_loudness":true},"chunk_length":300,"normalize":true,"language":"en","format":"mp3","sample_rate":123,"mp3_bitrate":128,"opus_bitrate":-1000,"latency":"normal","max_new_tokens":1024,"repetition_penalty":1.2,"min_chunk_length":50,"condition_on_previous_chunks":true,"early_stop_threshold":1,"features":[],"pronunciation_dictionary":[{"id":"\u003cstring>","version":"\u003cstring>"}]}}},"exampleType":"generated"}},"exampleType":"generated"},"responses":{"53cb10b3-8d1d-480b-8166-bedef02b1c71":{"description":"Server-Sent Events stream. Each `message` event contains a JSON payload with one base64 audio chunk. Concatenate every `audio_base64` chunk in arrival order to reconstruct the complete audio. `alignment` is the latest cumulative timestamp snapshot for `chunk_seq`; clients should replace the previous snapshot for that chunk instead of appending segments. `chunk_audio_offset_sec` can be added to segment times to derive absolute timestamps in the full audio.","headers":{"Transfer-Encoding":{"schema":{"type":"string"},"description":"chunked"}},"content":{"text/event-stream":{"schema":{"description":"One Server-Sent Events message payload for streaming TTS with timestamps. Each event contains one audio chunk. Concatenate all `audio_base64` chunks in arrival order to reconstruct the complete audio. `alignment` is the latest cumulative timestamp snapshot for the reported `chunk_seq`; clients should replace the previous snapshot for that chunk instead of appending segments.","examples":[{"alignment":{"audio_duration":16.24,"segments":[{"end":0.16,"start":0,"text":"I"},{"end":0.48,"start":0.16,"text":"can't"},{"end":0.8,"start":0.48,"text":"believe"},{"end":1.12,"start":0.8,"text":"its"},{"end":1.44,"start":1.2,"text":"been"},{"end":1.76,"start":1.44,"text":"this"},{"end":2.48,"start":1.76,"text":"long"},{"end":2.64,"start":2.56,"text":"It"},{"end":3.04,"start":2.72,"text":"feels"},{"end":3.28,"start":3.12,"text":"like"},{"end":4,"start":3.36,"text":"forever"},{"end":4.32,"start":4,"text":"since"},{"end":4.48,"start":4.32,"text":"we"},{"end":4.96,"start":4.48,"text":"last"},{"end":5.28,"start":4.96,"text":"really"},{"end":5.84,"start":5.28,"text":"talked"},{"end":6.24,"start":6,"text":"Ive"},{"end":6.64,"start":6.24,"text":"missed"},{"end":6.96,"start":6.64,"text":"hearing"},{"end":7.2,"start":6.96,"text":"your"},{"end":7.76,"start":7.2,"text":"voice"},{"end":7.92,"start":7.76,"text":"your"},{"end":8.48,"start":7.92,"text":"stories"},{"end":8.72,"start":8.48,"text":"even"},{"end":8.8,"start":8.72,"text":"the"},{"end":9.2,"start":8.8,"text":"little"},{"end":9.52,"start":9.2,"text":"things"},{"end":9.68,"start":9.52,"text":"you"},{"end":10,"start":9.68,"text":"used"},{"end":10.08,"start":10,"text":"to"},{"end":10.64,"start":10.08,"text":"say"},{"end":10.96,"start":10.64,"text":"How"},{"end":11.12,"start":10.96,"text":"have"},{"end":11.36,"start":11.12,"text":"you"},{"end":11.92,"start":11.36,"text":"been"},{"end":12.24,"start":12,"text":"Ive"},{"end":12.48,"start":12.24,"text":"thought"},{"end":12.8,"start":12.48,"text":"about"},{"end":13.2,"start":12.8,"text":"calling"},{"end":13.36,"start":13.2,"text":"you"},{"end":13.68,"start":13.36,"text":"so"},{"end":13.92,"start":13.68,"text":"many"},{"end":14.56,"start":13.92,"text":"times"},{"end":14.72,"start":14.56,"text":"but"},{"end":14.88,"start":14.72,"text":"I"},{"end":15.2,"start":14.88,"text":"never"},{"end":15.36,"start":15.2,"text":"knew"},{"end":15.6,"start":15.36,"text":"where"},{"end":15.6,"start":15.6,"text":"to"},{"end":16.24,"start":15.68,"text":"start"}]},"audio_base64":"SUQzBAAAAAAA...","chunk_audio_offset_sec":0,"chunk_seq":0,"content":"I can’t believe it’s been this long. It feels like forever since we last really talked. I’ve missed hearing your voice, your stories, even the little things you used to say. How have you been? I’ve thought about calling you so many times, but I never knew where to start."},{"alignment":{"audio_duration":16.24,"segments":[{"end":0.16,"start":0,"text":"I"},{"end":0.48,"start":0.16,"text":"can't"},{"end":0.8,"start":0.48,"text":"believe"},{"end":1.12,"start":0.8,"text":"its"},{"end":1.44,"start":1.2,"text":"been"},{"end":1.76,"start":1.44,"text":"this"},{"end":2.48,"start":1.76,"text":"long"},{"end":2.64,"start":2.56,"text":"It"},{"end":3.04,"start":2.72,"text":"feels"},{"end":3.28,"start":3.12,"text":"like"},{"end":4,"start":3.36,"text":"forever"},{"end":4.32,"start":4,"text":"since"},{"end":4.48,"start":4.32,"text":"we"},{"end":4.96,"start":4.48,"text":"last"},{"end":5.28,"start":4.96,"text":"really"},{"end":5.84,"start":5.28,"text":"talked"},{"end":6.24,"start":6,"text":"Ive"},{"end":6.64,"start":6.24,"text":"missed"},{"end":6.96,"start":6.64,"text":"hearing"},{"end":7.2,"start":6.96,"text":"your"},{"end":7.76,"start":7.2,"text":"voice"},{"end":7.92,"start":7.76,"text":"your"},{"end":8.48,"start":7.92,"text":"stories"},{"end":8.72,"start":8.48,"text":"even"},{"end":8.8,"start":8.72,"text":"the"},{"end":9.2,"start":8.8,"text":"little"},{"end":9.52,"start":9.2,"text":"things"},{"end":9.68,"start":9.52,"text":"you"},{"end":10,"start":9.68,"text":"used"},{"end":10.08,"start":10,"text":"to"},{"end":10.64,"start":10.08,"text":"say"},{"end":10.96,"start":10.64,"text":"How"},{"end":11.12,"start":10.96,"text":"have"},{"end":11.36,"start":11.12,"text":"you"},{"end":11.92,"start":11.36,"text":"been"},{"end":12.24,"start":12,"text":"Ive"},{"end":12.48,"start":12.24,"text":"thought"},{"end":12.8,"start":12.48,"text":"about"},{"end":13.2,"start":12.8,"text":"calling"},{"end":13.36,"start":13.2,"text":"you"},{"end":13.68,"start":13.36,"text":"so"},{"end":13.92,"start":13.68,"text":"many"},{"end":14.56,"start":13.92,"text":"times"},{"end":14.72,"start":14.56,"text":"but"},{"end":14.88,"start":14.72,"text":"I"},{"end":15.2,"start":14.88,"text":"never"},{"end":15.36,"start":15.2,"text":"knew"},{"end":15.6,"start":15.36,"text":"where"},{"end":15.6,"start":15.6,"text":"to"},{"end":16.24,"start":15.68,"text":"start"}]},"audio_base64":"//uSxOAAF...","chunk_audio_offset_sec":0,"chunk_seq":0,"content":"I can’t believe it’s been this long. It feels like forever since we last really talked. I’ve missed hearing your voice, your stories, even the little things you used to say. How have you been? I’ve thought about calling you so many times, but I never knew where to start."},{"alignment":{"audio_duration":10.48,"segments":[{"end":0.8,"start":0.4,"text":"Seeing"},{"end":0.96,"start":0.8,"text":"you"},{"end":1.44,"start":0.96,"text":"again"},{"end":1.68,"start":1.44,"text":"now"},{"end":2.08,"start":1.68,"text":"makes"},{"end":2.24,"start":2.08,"text":"me"},{"end":2.8,"start":2.24,"text":"realize"},{"end":3.12,"start":2.8,"text":"just"},{"end":3.28,"start":3.12,"text":"how"},{"end":3.6,"start":3.28,"text":"much"},{"end":3.76,"start":3.6,"text":"Ive"},{"end":4.24,"start":3.84,"text":"missed"},{"end":4.56,"start":4.24,"text":"you"},{"end":4.8,"start":4.64,"text":"We"},{"end":5.04,"start":4.8,"text":"have"},{"end":5.36,"start":5.04,"text":"so"},{"end":5.76,"start":5.36,"text":"much"},{"end":5.76,"start":5.76,"text":"to"},{"end":6.16,"start":5.76,"text":"catch"},{"end":6.4,"start":6.16,"text":"up"},{"end":6.72,"start":6.4,"text":"on"},{"end":6.96,"start":6.8,"text":"and"},{"end":7.04,"start":6.96,"text":"I"},{"end":7.36,"start":7.04,"text":"dont"},{"end":7.6,"start":7.36,"text":"even"},{"end":7.84,"start":7.6,"text":"know"},{"end":8.08,"start":7.84,"text":"which"},{"end":8.4,"start":8.08,"text":"part"},{"end":8.48,"start":8.4,"text":"of"},{"end":8.72,"start":8.56,"text":"my"},{"end":8.96,"start":8.72,"text":"life"},{"end":9.12,"start":9.12,"text":"to"},{"end":9.44,"start":9.12,"text":"tell"},{"end":9.6,"start":9.44,"text":"you"},{"end":10,"start":9.6,"text":"about"},{"end":10.48,"start":10.08,"text":"first"}]},"audio_base64":"//uSxImAl...","chunk_audio_offset_sec":16.24,"chunk_seq":1,"content":"Seeing you again now makes me realize just how much I’ve missed you. We have so much to catch up on, and I don’t even know which part of my life to tell you about first."}],"properties":{"audio_base64":{"description":"Base64 encoded audio chunk. Concatenate every chunk in event order to reconstruct the full audio.","title":"Audio Base64","type":"string","isRequired":true,"uniqueKey":"audio_base64","typeLabel":"string"},"content":{"description":"Text content described by this event's latest alignment snapshot. Long input may be split into multiple content chunks in one stream.","title":"Content","type":"string","isRequired":true,"uniqueKey":"content","typeLabel":"string"},"alignment":{"oneOf":[{"type":"object","title":"TTSTimestampAlignment","description":"Latest cumulative timestamp snapshot for `chunk_seq`. When present, replace the previous alignment for the same `chunk_seq`; do not append segments. Null means no alignment snapshot has been produced yet or alignment is unavailable.","required":["segments","audio_duration"],"properties":{"segments":{"description":"Ordered text timing segments for the generated audio.","items":{"properties":{"text":{"description":"Text segment covered by this timing entry.","title":"Text","type":"string","isRequired":true,"uniqueKey":"alignment.oneOf.0.segments.items.[INDEX].text","typeLabel":"string"},"start":{"description":"Segment start time in seconds.","title":"Start","type":"number","isRequired":true,"uniqueKey":"alignment.oneOf.0.segments.items.[INDEX].start","typeLabel":"number"},"end":{"description":"Segment end time in seconds.","title":"End","type":"number","isRequired":true,"uniqueKey":"alignment.oneOf.0.segments.items.[INDEX].end","typeLabel":"number"}},"required":["text","start","end"],"title":"TTSTimestampSegment","type":"object","uniqueKey":"alignment.oneOf.0.segments.items.[INDEX]","typeLabel":"TTSTimestampSegment · object"},"title":"Segments","type":"array","isRequired":true,"uniqueKey":"alignment.oneOf.0.segments","typeLabel":"TTSTimestampSegment · object[]"},"audio_duration":{"description":"Audio duration in seconds for this alignment's content chunk.","title":"Audio Duration","type":"number","isRequired":true,"uniqueKey":"alignment.oneOf.0.audio_duration","typeLabel":"number"}},"isRequired":true,"uniqueKey":"alignment.oneOf.0","typeLabel":"TTSTimestampAlignment · object"},{"type":"null","description":"Latest cumulative timestamp snapshot for `chunk_seq`. When present, replace the previous alignment for the same `chunk_seq`; do not append segments. Null means no alignment snapshot has been produced yet or alignment is unavailable.","isRequired":true,"uniqueKey":"alignment.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"alignment","typeLabel":"TTSTimestampAlignment · object | null"},"chunk_seq":{"description":"Sequence number of the text chunk described by `alignment`. Clients should bucket alignment snapshots by this value.","minimum":0,"title":"Chunk Seq","type":"integer","isRequired":true,"uniqueKey":"chunk_seq","typeLabel":"integer"},"chunk_audio_offset_sec":{"description":"Absolute start time of this text chunk within the full audio, in seconds.","minimum":0,"title":"Chunk Audio Offset Sec","type":"number","isRequired":true,"uniqueKey":"chunk_audio_offset_sec","typeLabel":"number"}},"required":["audio_base64","content","alignment","chunk_seq","chunk_audio_offset_sec"],"title":"TTSTimestampStreamEvent","type":"object","uniqueKey":"","typeLabel":"TTSTimestampStreamEvent · object"},"examples":{"first_event":{"title":"first_event","value":"data: {\"audio_base64\": \"SUQzBAAAAAAA...\", \"content\": \"I can’t believe it’s been this long. It feels like forever since we last really talked. I’ve missed hearing your voice, your stories, even the little things you used to say. How have you been? I’ve thought about calling you so many times, but I never knew where to start.\", \"alignment\": {\"segments\": [{\"text\": \"I\", \"start\": 0.0, \"end\": 0.16}, {\"text\": \"can't\", \"start\": 0.16, \"end\": 0.48}, {\"text\": \"believe\", \"start\": 0.48, \"end\": 0.8}, {\"text\": \"its\", \"start\": 0.8, \"end\": 1.12}, {\"text\": \"been\", \"start\": 1.2, \"end\": 1.44}, {\"text\": \"this\", \"start\": 1.44, \"end\": 1.76}, {\"text\": \"long\", \"start\": 1.76, \"end\": 2.48}, {\"text\": \"It\", \"start\": 2.56, \"end\": 2.64}, {\"text\": \"feels\", \"start\": 2.72, \"end\": 3.04}, {\"text\": \"like\", \"start\": 3.12, \"end\": 3.28}, {\"text\": \"forever\", \"start\": 3.36, \"end\": 4.0}, {\"text\": \"since\", \"start\": 4.0, \"end\": 4.32}, {\"text\": \"we\", \"start\": 4.32, \"end\": 4.48}, {\"text\": \"last\", \"start\": 4.48, \"end\": 4.96}, {\"text\": \"really\", \"start\": 4.96, \"end\": 5.28}, {\"text\": \"talked\", \"start\": 5.28, \"end\": 5.84}, {\"text\": \"Ive\", \"start\": 6.0, \"end\": 6.24}, {\"text\": \"missed\", \"start\": 6.24, \"end\": 6.64}, {\"text\": \"hearing\", \"start\": 6.64, \"end\": 6.96}, {\"text\": \"your\", \"start\": 6.96, \"end\": 7.2}, {\"text\": \"voice\", \"start\": 7.2, \"end\": 7.76}, {\"text\": \"your\", \"start\": 7.76, \"end\": 7.92}, {\"text\": \"stories\", \"start\": 7.92, \"end\": 8.48}, {\"text\": \"even\", \"start\": 8.48, \"end\": 8.72}, {\"text\": \"the\", \"start\": 8.72, \"end\": 8.8}, {\"text\": \"little\", \"start\": 8.8, \"end\": 9.2}, {\"text\": \"things\", \"start\": 9.2, \"end\": 9.52}, {\"text\": \"you\", \"start\": 9.52, \"end\": 9.68}, {\"text\": \"used\", \"start\": 9.68, \"end\": 10.0}, {\"text\": \"to\", \"start\": 10.0, \"end\": 10.08}, {\"text\": \"say\", \"start\": 10.08, \"end\": 10.64}, {\"text\": \"How\", \"start\": 10.64, \"end\": 10.96}, {\"text\": \"have\", \"start\": 10.96, \"end\": 11.12}, {\"text\": \"you\", \"start\": 11.12, \"end\": 11.36}, {\"text\": \"been\", \"start\": 11.36, \"end\": 11.92}, {\"text\": \"Ive\", \"start\": 12.0, \"end\": 12.24}, {\"text\": \"thought\", \"start\": 12.24, \"end\": 12.48}, {\"text\": \"about\", \"start\": 12.48, \"end\": 12.8}, {\"text\": \"calling\", \"start\": 12.8, \"end\": 13.2}, {\"text\": \"you\", \"start\": 13.2, \"end\": 13.36}, {\"text\": \"so\", \"start\": 13.36, \"end\": 13.68}, {\"text\": \"many\", \"start\": 13.68, \"end\": 13.92}, {\"text\": \"times\", \"start\": 13.92, \"end\": 14.56}, {\"text\": \"but\", \"start\": 14.56, \"end\": 14.72}, {\"text\": \"I\", \"start\": 14.72, \"end\": 14.88}, {\"text\": \"never\", \"start\": 14.88, \"end\": 15.2}, {\"text\": \"knew\", \"start\": 15.2, \"end\": 15.36}, {\"text\": \"where\", \"start\": 15.36, \"end\": 15.6}, {\"text\": \"to\", \"start\": 15.6, \"end\": 15.6}, {\"text\": \"start\", \"start\": 15.68, \"end\": 16.24}], \"audio_duration\": 16.24}, \"chunk_seq\": 0, \"chunk_audio_offset_sec\": 0.0}\n\n"},"following_event":{"title":"following_event","value":"data: {\"audio_base64\": \"//uSxOAAF...\", \"content\": \"I can’t believe it’s been this long. It feels like forever since we last really talked. I’ve missed hearing your voice, your stories, even the little things you used to say. How have you been? I’ve thought about calling you so many times, but I never knew where to start.\", \"alignment\": {\"segments\": [{\"text\": \"I\", \"start\": 0.0, \"end\": 0.16}, {\"text\": \"can't\", \"start\": 0.16, \"end\": 0.48}, {\"text\": \"believe\", \"start\": 0.48, \"end\": 0.8}, {\"text\": \"its\", \"start\": 0.8, \"end\": 1.12}, {\"text\": \"been\", \"start\": 1.2, \"end\": 1.44}, {\"text\": \"this\", \"start\": 1.44, \"end\": 1.76}, {\"text\": \"long\", \"start\": 1.76, \"end\": 2.48}, {\"text\": \"It\", \"start\": 2.56, \"end\": 2.64}, {\"text\": \"feels\", \"start\": 2.72, \"end\": 3.04}, {\"text\": \"like\", \"start\": 3.12, \"end\": 3.28}, {\"text\": \"forever\", \"start\": 3.36, \"end\": 4.0}, {\"text\": \"since\", \"start\": 4.0, \"end\": 4.32}, {\"text\": \"we\", \"start\": 4.32, \"end\": 4.48}, {\"text\": \"last\", \"start\": 4.48, \"end\": 4.96}, {\"text\": \"really\", \"start\": 4.96, \"end\": 5.28}, {\"text\": \"talked\", \"start\": 5.28, \"end\": 5.84}, {\"text\": \"Ive\", \"start\": 6.0, \"end\": 6.24}, {\"text\": \"missed\", \"start\": 6.24, \"end\": 6.64}, {\"text\": \"hearing\", \"start\": 6.64, \"end\": 6.96}, {\"text\": \"your\", \"start\": 6.96, \"end\": 7.2}, {\"text\": \"voice\", \"start\": 7.2, \"end\": 7.76}, {\"text\": \"your\", \"start\": 7.76, \"end\": 7.92}, {\"text\": \"stories\", \"start\": 7.92, \"end\": 8.48}, {\"text\": \"even\", \"start\": 8.48, \"end\": 8.72}, {\"text\": \"the\", \"start\": 8.72, \"end\": 8.8}, {\"text\": \"little\", \"start\": 8.8, \"end\": 9.2}, {\"text\": \"things\", \"start\": 9.2, \"end\": 9.52}, {\"text\": \"you\", \"start\": 9.52, \"end\": 9.68}, {\"text\": \"used\", \"start\": 9.68, \"end\": 10.0}, {\"text\": \"to\", \"start\": 10.0, \"end\": 10.08}, {\"text\": \"say\", \"start\": 10.08, \"end\": 10.64}, {\"text\": \"How\", \"start\": 10.64, \"end\": 10.96}, {\"text\": \"have\", \"start\": 10.96, \"end\": 11.12}, {\"text\": \"you\", \"start\": 11.12, \"end\": 11.36}, {\"text\": \"been\", \"start\": 11.36, \"end\": 11.92}, {\"text\": \"Ive\", \"start\": 12.0, \"end\": 12.24}, {\"text\": \"thought\", \"start\": 12.24, \"end\": 12.48}, {\"text\": \"about\", \"start\": 12.48, \"end\": 12.8}, {\"text\": \"calling\", \"start\": 12.8, \"end\": 13.2}, {\"text\": \"you\", \"start\": 13.2, \"end\": 13.36}, {\"text\": \"so\", \"start\": 13.36, \"end\": 13.68}, {\"text\": \"many\", \"start\": 13.68, \"end\": 13.92}, {\"text\": \"times\", \"start\": 13.92, \"end\": 14.56}, {\"text\": \"but\", \"start\": 14.56, \"end\": 14.72}, {\"text\": \"I\", \"start\": 14.72, \"end\": 14.88}, {\"text\": \"never\", \"start\": 14.88, \"end\": 15.2}, {\"text\": \"knew\", \"start\": 15.2, \"end\": 15.36}, {\"text\": \"where\", \"start\": 15.36, \"end\": 15.6}, {\"text\": \"to\", \"start\": 15.6, \"end\": 15.6}, {\"text\": \"start\", \"start\": 15.68, \"end\": 16.24}], \"audio_duration\": 16.24}, \"chunk_seq\": 0, \"chunk_audio_offset_sec\": 0.0}\n\n"},"later_text_chunk_event":{"title":"later_text_chunk_event","value":"data: {\"audio_base64\": \"//uSxImAl...\", \"content\": \"Seeing you again now makes me realize just how much I’ve missed you. We have so much to catch up on, and I don’t even know which part of my life to tell you about first.\", \"alignment\": {\"segments\": [{\"text\": \"Seeing\", \"start\": 0.4, \"end\": 0.8}, {\"text\": \"you\", \"start\": 0.8, \"end\": 0.96}, {\"text\": \"again\", \"start\": 0.96, \"end\": 1.44}, {\"text\": \"now\", \"start\": 1.44, \"end\": 1.68}, {\"text\": \"makes\", \"start\": 1.68, \"end\": 2.08}, {\"text\": \"me\", \"start\": 2.08, \"end\": 2.24}, {\"text\": \"realize\", \"start\": 2.24, \"end\": 2.8}, {\"text\": \"just\", \"start\": 2.8, \"end\": 3.12}, {\"text\": \"how\", \"start\": 3.12, \"end\": 3.28}, {\"text\": \"much\", \"start\": 3.28, \"end\": 3.6}, {\"text\": \"Ive\", \"start\": 3.6, \"end\": 3.76}, {\"text\": \"missed\", \"start\": 3.84, \"end\": 4.24}, {\"text\": \"you\", \"start\": 4.24, \"end\": 4.56}, {\"text\": \"We\", \"start\": 4.64, \"end\": 4.8}, {\"text\": \"have\", \"start\": 4.8, \"end\": 5.04}, {\"text\": \"so\", \"start\": 5.04, \"end\": 5.36}, {\"text\": \"much\", \"start\": 5.36, \"end\": 5.76}, {\"text\": \"to\", \"start\": 5.76, \"end\": 5.76}, {\"text\": \"catch\", \"start\": 5.76, \"end\": 6.16}, {\"text\": \"up\", \"start\": 6.16, \"end\": 6.4}, {\"text\": \"on\", \"start\": 6.4, \"end\": 6.72}, {\"text\": \"and\", \"start\": 6.8, \"end\": 6.96}, {\"text\": \"I\", \"start\": 6.96, \"end\": 7.04}, {\"text\": \"dont\", \"start\": 7.04, \"end\": 7.36}, {\"text\": \"even\", \"start\": 7.36, \"end\": 7.6}, {\"text\": \"know\", \"start\": 7.6, \"end\": 7.84}, {\"text\": \"which\", \"start\": 7.84, \"end\": 8.08}, {\"text\": \"part\", \"start\": 8.08, \"end\": 8.4}, {\"text\": \"of\", \"start\": 8.4, \"end\": 8.48}, {\"text\": \"my\", \"start\": 8.56, \"end\": 8.72}, {\"text\": \"life\", \"start\": 8.72, \"end\": 8.96}, {\"text\": \"to\", \"start\": 9.12, \"end\": 9.12}, {\"text\": \"tell\", \"start\": 9.12, \"end\": 9.44}, {\"text\": \"you\", \"start\": 9.44, \"end\": 9.6}, {\"text\": \"about\", \"start\": 9.6, \"end\": 10.0}, {\"text\": \"first\", \"start\": 10.08, \"end\": 10.48}], \"audio_duration\": 10.48}, \"chunk_seq\": 1, \"chunk_audio_offset_sec\": 16.24}\n\n"}},"exampleType":"examples"}},"exampleType":"examples"},"c8b9e49d-c28b-427a-a973-2fb0ce806774":{"description":"No permission -- see authorization schemes","headers":{},"content":{"application/json":{"schema":{"properties":{"status":{"title":"Status","type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"message":{"title":"Message","type":"string","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"reason":{"oneOf":[{"type":"string","title":"Reason","uniqueKey":"reason.oneOf.0","typeLabel":"string"},{"type":"null","title":"Reason","uniqueKey":"reason.oneOf.1","typeLabel":"null"}],"uniqueKey":"reason","typeLabel":"string | null"}},"required":["status","message"],"type":"object","uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"status":123,"message":"\u003cstring>","reason":"\u003cstring>"}}},"exampleType":"generated"}},"exampleType":"generated"},"c8c00c83-c488-4011-8295-5e774dc4d0f1":{"description":"No payment -- see charging schemes","headers":{},"content":{"application/json":{"schema":{"properties":{"status":{"title":"Status","type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"message":{"title":"Message","type":"string","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"reason":{"oneOf":[{"type":"string","title":"Reason","uniqueKey":"reason.oneOf.0","typeLabel":"string"},{"type":"null","title":"Reason","uniqueKey":"reason.oneOf.1","typeLabel":"null"}],"uniqueKey":"reason","typeLabel":"string | null"}},"required":["status","message"],"type":"object","uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"status":123,"message":"\u003cstring>","reason":"\u003cstring>"}}},"exampleType":"generated"}},"exampleType":"generated"},"e1fc02fe-8b75-452e-b6f3-23e955b4b8f0":{"description":"The server cannot process the request due to a high load","headers":{},"content":{"application/json":{"schema":{"properties":{"status":{"title":"Status","type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"message":{"title":"Message","type":"string","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"reason":{"oneOf":[{"type":"string","title":"Reason","uniqueKey":"reason.oneOf.0","typeLabel":"string"},{"type":"null","title":"Reason","uniqueKey":"reason.oneOf.1","typeLabel":"null"}],"uniqueKey":"reason","typeLabel":"string | null"}},"required":["status","message"],"type":"object","uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"status":123,"message":"\u003cstring>","reason":"\u003cstring>"}}},"exampleType":"generated"}},"exampleType":"generated"}},"security":{"8ed29a3b-1b89-4280-b3c0-d43d418c6ea4":{"BearerAuth":{"type":"http","scheme":"bearer","scopes":[],"schemeName":"BearerAuth"}}},"servers":{"4c05306a-8a2b-4dca-ae0d-0b87050df242":{"description":"Fish Audio API","url":"https://api.fish.audio"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"http","scheme":"bearer","scopes":[],"schemeName":"BearerAuth"},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"Bearer authentication header of the form `Bearer \u003ctoken>`, where `\u003ctoken>` is your auth token.","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"BearerAuth","name":"Authorization"}],"title":"BearerAuth"}]},"originalFileLocation":"api-reference/openapi.json"},"subdomain":"hanabiaiinc","siteName":"Fish Audio","title":"Text to Speech Stream with Timestamps - Fish Audio","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-05-12T11:48:00.164Z","originalFileLocation":"api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Stream generated speech with timestamp alignment snapshots\">\u003cmeta data-mint-head name=\"application-name\" content=\"Fish Audio\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/hanabiaiinc/rHJNuwD9FcQhvMwX/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/hanabiaiinc/rHJNuwD9FcQhvMwX/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/hanabiaiinc/rHJNuwD9FcQhvMwX/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/hanabiaiinc/rHJNuwD9FcQhvMwX/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/hanabiaiinc/rHJNuwD9FcQhvMwX/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/hanabiaiinc/rHJNuwD9FcQhvMwX/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/hanabiaiinc/rHJNuwD9FcQhvMwX/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/hanabiaiinc/rHJNuwD9FcQhvMwX/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/hanabiaiinc/rHJNuwD9FcQhvMwX/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Text to Speech Stream with Timestamps - Fish Audio\">\u003cmeta data-mint-head property=\"og:description\" content=\"Stream generated speech with timestamp alignment snapshots\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Fish Audio\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://hanabiaiinc.mintlify.site/_mintlify/api/og/v2?division=TTS+%28v1%29\u0026amp;title=Text+to+Speech+Stream+with+Timestamps\u0026amp;description=Stream+generated+speech+with+timestamp+alignment+snapshots\u0026amp;theme=61fce384ffd542cc270fb190\u0026amp;signature=f0cb94bf30ffa7a8f4bde684307ec3c9f29fdc7ce55c917e3997c3e0b77cd3e6\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Text to Speech Stream with Timestamps - Fish Audio\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Stream generated speech with timestamp alignment snapshots\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://hanabiaiinc.mintlify.site/_mintlify/api/og/v2?division=TTS+%28v1%29\u0026amp;title=Text+to+Speech+Stream+with+Timestamps\u0026amp;description=Stream+generated+speech+with+timestamp+alignment+snapshots\u0026amp;theme=61fce384ffd542cc270fb190\u0026amp;signature=f0cb94bf30ffa7a8f4bde684307ec3c9f29fdc7ce55c917e3997c3e0b77cd3e6\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/hanabiaiinc/rHJNuwD9FcQhvMwX/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Fish Audio\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0e0e0e\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.fish.audio/#organization\",\"name\":\"Fish Audio\",\"url\":\"https://docs.fish.audio\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/hanabiaiinc/amYp9Dj31LtlHliX/logo/light.png?fit=max\u0026auto=format\u0026n=amYp9Dj31LtlHliX\u0026q=85\u0026s=305973cd6a8d11dbf36d1ec682ee845e\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.fish.audio#website\",\"name\":\"Fish Audio\",\"url\":\"https://docs.fish.audio\",\"publisher\":{\"@id\":\"https://docs.fish.audio/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps#webpage\",\"url\":\"https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps\",\"name\":\"Text to Speech Stream with Timestamps\",\"description\":\"Stream generated speech with timestamp alignment snapshots\",\"dateModified\":\"2026-05-12T11:48:00.164Z\",\"isPartOf\":{\"@id\":\"https://docs.fish.audio#website\"},\"breadcrumb\":{\"@id\":\"https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"REST API\",\"item\":\"https://docs.fish.audio/api-reference/endpoint/wallet/get-api-credit\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"TTS (v1)\",\"item\":\"https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Text to Speech Stream with Timestamps\",\"item\":\"https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps#apireference\",\"headline\":\"Text to Speech Stream with Timestamps\",\"name\":\"Text to Speech Stream with Timestamps\",\"description\":\"Stream generated speech with timestamp alignment snapshots\",\"url\":\"https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps\",\"mainEntityOfPage\":{\"@id\":\"https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps#webpage\"},\"dateModified\":\"2026-05-12T11:48:00.164Z\",\"publisher\":{\"@id\":\"https://docs.fish.audio/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.fish.audio#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Fish Audio\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Fish Audio\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps.md","siteName":"Fish Audio","nav":{"global":null,"tabs":[{"tab":"Overview","pages":[{"title":"Overview","href":"/overview/capabilities"}]},{"tab":"Agents","pages":[{"title":"Agents","href":"/agents/overview"}]},{"tab":"Resources","pages":[{"title":"Resources","href":"/developer-guide/sdk-guide/quickstart"}]},{"tab":"API Reference","groups":[{"group":"API Reference","pages":[{"title":"Introduction","icon":"book","iconType":"solid","href":"/api-reference/introduction"},{"title":"Tracing \u0026 Performance Analysis","icon":"chart-line","iconType":"solid","href":"/api-reference/observability"},{"title":"Errors","icon":"triangle-exclamation","href":"/api-reference/errors"}]},{"group":"REST API","pages":[{"group":"Wallet","icon":"wallet","pages":[{"openapi":"get /wallet/{user_id}/api-credit","title":"Get API Credit","icon":"wallet","iconType":"solid","href":"/api-reference/endpoint/wallet/get-api-credit"},{"openapi":"get /wallet/{user_id}/package","title":"Get User Package","icon":"star","iconType":"solid","href":"/api-reference/endpoint/wallet/get-user-package"}]},{"group":"Voice Models","icon":"cube","pages":[{"openapi":"get /model","title":"List Models","icon":"list","iconType":"solid","href":"/api-reference/endpoint/model/list-models"},{"openapi":"post /model","title":"Create Model","icon":"circle-plus","iconType":"solid","href":"/api-reference/endpoint/model/create-model"},{"openapi":"get /model/{id}","title":"Get Model","icon":"circle-info","iconType":"solid","href":"/api-reference/endpoint/model/get-model"},{"openapi":"delete /model/{id}","title":"Delete Model","icon":"trash","iconType":"solid","href":"/api-reference/endpoint/model/delete-model"},{"openapi":"patch /model/{id}","title":"Update Model","icon":"pen-to-square","iconType":"solid","href":"/api-reference/endpoint/model/update-model"}]},{"group":"Pronunciation Dictionaries","icon":"book-open","pages":[{"openapi":"get /v1/pronunciation-dictionaries","title":"List Dictionaries","icon":"list","iconType":"solid","href":"/api-reference/endpoint/pronunciation-dictionary/list-dictionaries"},{"openapi":"post /v1/pronunciation-dictionaries","title":"Create Dictionary","icon":"circle-plus","iconType":"solid","href":"/api-reference/endpoint/pronunciation-dictionary/create-dictionary"},{"openapi":"get /v1/pronunciation-dictionaries/{dictionary_id}","title":"Get Dictionary","icon":"book-open","iconType":"solid","href":"/api-reference/endpoint/pronunciation-dictionary/get-dictionary"},{"openapi":"patch /v1/pronunciation-dictionaries/{dictionary_id}","title":"Update Dictionary","icon":"pen-to-square","iconType":"solid","href":"/api-reference/endpoint/pronunciation-dictionary/update-dictionary"},{"openapi":"delete /v1/pronunciation-dictionaries/{dictionary_id}","title":"Delete Dictionary","icon":"trash","iconType":"solid","href":"/api-reference/endpoint/pronunciation-dictionary/delete-dictionary"},{"openapi":"get /v1/pronunciation-dictionaries/{dictionary_id}/versions","title":"List Versions","icon":"clock-rotate-left","iconType":"solid","href":"/api-reference/endpoint/pronunciation-dictionary/list-versions"},{"openapi":"post /v1/pronunciation-dictionaries/{dictionary_id}/versions","title":"Publish Version","icon":"upload","iconType":"solid","href":"/api-reference/endpoint/pronunciation-dictionary/create-version"},{"openapi":"get /v1/pronunciation-dictionaries/{dictionary_id}/versions/{version_id}","title":"Get Version","icon":"file-lines","iconType":"solid","href":"/api-reference/endpoint/pronunciation-dictionary/get-version"},{"openapi":"get /v1/pronunciation-dictionaries/{dictionary_id}/versions/{version_id}/compare","title":"Compare Versions","icon":"code-compare","iconType":"solid","href":"/api-reference/endpoint/pronunciation-dictionary/compare-versions"},{"openapi":"delete /v1/pronunciation-dictionaries/{dictionary_id}/versions/{version_id}","title":"Delete Version","icon":"trash-can","iconType":"solid","href":"/api-reference/endpoint/pronunciation-dictionary/delete-version"}]},{"group":"TTS (v1)","icon":"code","pages":[{"openapi":"post /v1/tts","title":"Text to Speech","description":"Convert text to speech","icon":"comment-dots","iconType":"solid","href":"/api-reference/endpoint/openapi-v1/text-to-speech"},{"openapi":"post /v1/tts/stream/with-timestamp","title":"Text to Speech Stream with Timestamps","icon":"waveform-lines","iconType":"solid","href":"/api-reference/endpoint/openapi-v1/text-to-speech-stream-with-timestamps"},{"asyncapi":"api-reference/asyncapi.yml ttsLive","title":"WebSocket TTS Streaming","description":"Real-time text-to-speech streaming via WebSocket","icon":"webhook","iconType":"solid","href":"/api-reference/endpoint/websocket/tts-live"},{"asyncapi":"api-reference/asyncapi.yml ttsLiveWithTimestamps","title":"WebSocket TTS with Timestamps","icon":"webhook","iconType":"solid","href":"/api-reference/endpoint/openapi-v1/text-to-speech-live-with-timestamps"}]},{"group":"ASR (v1)","icon":"microphone","pages":[{"openapi":"post /v1/asr","title":"Speech to Text","icon":"microphone","iconType":"solid","href":"/api-reference/endpoint/openapi-v1/speech-to-text"},{"asyncapi":"api-reference/asyncapi-asr-realtime.yml asrRealtime","title":"WebSocket Realtime Speech to Text","icon":"webhook","iconType":"solid","tag":"Preview","href":"/api-reference/endpoint/websocket/asr-realtime"}]},{"group":"Voice Design","icon":"wand-magic-sparkles","pages":[{"openapi":"post /v1/voice-design","title":"Voice Design","icon":"wand-magic-sparkles","iconType":"solid","href":"/api-reference/endpoint/openapi-v1/voice-design"}]}]},{"group":"Agents API","pages":[{"title":"Agents API Errors","icon":"triangle-exclamation","href":"/api-reference/agent-errors"},{"group":"Agents","icon":"robot","pages":[{"openapi":"get /v1/agent/agents","title":"List Agents","icon":"robot","iconType":"solid","href":"/api-reference/endpoint/agent/list-agents"},{"openapi":"post /v1/agent/agents","title":"Create Agent","icon":"robot","iconType":"solid","href":"/api-reference/endpoint/agent/create-agent"},{"openapi":"get /v1/agent/agents/{agent_id}","title":"Get Agent","icon":"robot","iconType":"solid","href":"/api-reference/endpoint/agent/get-agent"},{"openapi":"patch /v1/agent/agents/{agent_id}","title":"Update Agent","icon":"robot","iconType":"solid","href":"/api-reference/endpoint/agent/update-agent"},{"openapi":"delete /v1/agent/agents/{agent_id}","title":"Delete Agent","icon":"robot","iconType":"solid","href":"/api-reference/endpoint/agent/delete-agent"},{"openapi":"get /v1/agent/agents/{agent_id}/config","title":"Get Draft Config","icon":"robot","iconType":"solid","href":"/api-reference/endpoint/agent/get-draft-config"},{"openapi":"patch /v1/agent/agents/{agent_id}/config","title":"Update Draft Config","icon":"robot","iconType":"solid","href":"/api-reference/endpoint/agent/update-draft-config"},{"openapi":"post /v1/agent/agents/{agent_id}/publish","title":"Publish Agent","icon":"robot","iconType":"solid","href":"/api-reference/endpoint/agent/publish-agent"},{"openapi":"get /v1/agent/agents/{agent_id}/versions","title":"List Agent Versions","icon":"robot","iconType":"solid","href":"/api-reference/endpoint/agent/list-agent-versions"},{"openapi":"get /v1/agent/agents/{agent_id}/versions/{version_number}","title":"Get Agent Version","icon":"robot","iconType":"solid","href":"/api-reference/endpoint/agent/get-agent-version"},{"openapi":"get /v1/agent/agents/{agent_id}/widget","title":"Get Widget Config","icon":"robot","iconType":"solid","href":"/api-reference/endpoint/agent/get-widget-config"}]},{"group":"Sessions","icon":"headset","pages":[{"openapi":"post /v1/agent/sessions","title":"Create Agent Session","icon":"headset","iconType":"solid","href":"/api-reference/endpoint/agent/create-agent-session"},{"openapi":"get /v1/agent/sessions","title":"List Agent Sessions","icon":"headset","iconType":"solid","href":"/api-reference/endpoint/agent/list-agent-sessions"},{"openapi":"get /v1/agent/sessions/{session_id}","title":"Get Agent Session","icon":"headset","iconType":"solid","href":"/api-reference/endpoint/agent/get-agent-session"},{"openapi":"get /v1/agent/sessions/{session_id}/recording","title":"Get Agent Session Recording","icon":"headset","iconType":"solid","href":"/api-reference/endpoint/agent/get-agent-session-recording"},{"openapi":"post /v1/agent/sessions/{session_id}/end","title":"End Agent Session","icon":"headset","iconType":"solid","href":"/api-reference/endpoint/agent/end-agent-session"}]},{"group":"Tools","icon":"wrench","pages":[{"openapi":"get /v1/agent/tools","title":"List Tools","icon":"wrench","iconType":"solid","href":"/api-reference/endpoint/agent/list-tools"},{"openapi":"post /v1/agent/tools","title":"Create Tool","icon":"wrench","iconType":"solid","href":"/api-reference/endpoint/agent/create-tool"},{"openapi":"get /v1/agent/tools/{tool_id}","title":"Get Tool","icon":"wrench","iconType":"solid","href":"/api-reference/endpoint/agent/get-tool"},{"openapi":"patch /v1/agent/tools/{tool_id}","title":"Update Tool","icon":"wrench","iconType":"solid","href":"/api-reference/endpoint/agent/update-tool"},{"openapi":"delete /v1/agent/tools/{tool_id}","title":"Delete Tool","icon":"wrench","iconType":"solid","href":"/api-reference/endpoint/agent/delete-tool"},{"openapi":"get /v1/agent/tools/{tool_id}/agents","title":"List Agents Using Tool","icon":"wrench","iconType":"solid","href":"/api-reference/endpoint/agent/list-agents-using-tool"}]},{"group":"Tests","icon":"flask","pages":[{"openapi":"get /v1/agent/tests","title":"List Tests","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/list-tests"},{"openapi":"post /v1/agent/tests","title":"Create Test","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/create-test"},{"openapi":"get /v1/agent/tests/{test_id}","title":"Get Test","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/get-test"},{"openapi":"patch /v1/agent/tests/{test_id}","title":"Update Test","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/update-test"},{"openapi":"delete /v1/agent/tests/{test_id}","title":"Delete Test","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/delete-test"},{"openapi":"put /v1/agent/agents/{agent_id}/tests/{test_id}","title":"Attach Test","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/attach-test"},{"openapi":"delete /v1/agent/agents/{agent_id}/tests/{test_id}","title":"Detach Test","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/detach-test"},{"openapi":"get /v1/agent/agents/{agent_id}/test-tools","title":"List Test Tools","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/list-test-tools"},{"openapi":"post /v1/agent/agents/{agent_id}/tests/run","title":"Run Tests","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/run-tests"},{"openapi":"get /v1/agent/agents/{agent_id}/test-batches","title":"List Test Batches","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/list-test-batches"},{"openapi":"get /v1/agent/agents/{agent_id}/test-batches/{batch_id}","title":"Get Test Batch","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/get-test-batch"},{"openapi":"get /v1/agent/test-runs","title":"List Test Runs","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/list-test-runs"},{"openapi":"get /v1/agent/test-runs/{run_id}","title":"Get Test Run","icon":"flask","iconType":"solid","href":"/api-reference/endpoint/agent/get-test-run"}]},{"group":"Knowledge Sources","icon":"book","pages":[{"openapi":"get /v1/agent/knowledge-sources","title":"List Knowledge Sources","icon":"book","iconType":"solid","href":"/api-reference/endpoint/agent/list-knowledge-sources"},{"openapi":"post /v1/agent/knowledge-sources","title":"Create Knowledge Source","icon":"book","iconType":"solid","href":"/api-reference/endpoint/agent/create-knowledge-source"},{"openapi":"get /v1/agent/knowledge-sources/{source_id}","title":"Get Knowledge Source","icon":"book","iconType":"solid","href":"/api-reference/endpoint/agent/get-knowledge-source"},{"openapi":"patch /v1/agent/knowledge-sources/{source_id}","title":"Update Knowledge Source","icon":"book","iconType":"solid","href":"/api-reference/endpoint/agent/update-knowledge-source"},{"openapi":"delete /v1/agent/knowledge-sources/{source_id}","title":"Delete Knowledge Source","icon":"book","iconType":"solid","href":"/api-reference/endpoint/agent/delete-knowledge-source"},{"openapi":"get /v1/agent/knowledge-sources/{source_id}/agents","title":"List Agents Using Knowledge Source","icon":"book","iconType":"solid","href":"/api-reference/endpoint/agent/list-agents-using-knowledge-source"}]},{"group":"Phone Numbers","icon":"phone","pages":[{"openapi":"get /v1/agent/available-phone-numbers","title":"Search Available Phone Numbers","icon":"phone","iconType":"solid","href":"/api-reference/endpoint/agent/search-available-phone-numbers"},{"openapi":"get /v1/agent/phone-numbers","title":"List Phone Numbers","icon":"phone","iconType":"solid","href":"/api-reference/endpoint/agent/list-phone-numbers"},{"openapi":"post /v1/agent/phone-numbers","title":"Purchase Phone Number","icon":"phone","iconType":"solid","href":"/api-reference/endpoint/agent/purchase-phone-number"},{"openapi":"get /v1/agent/phone-numbers/{phone_number_id}","title":"Get Phone Number","icon":"phone","iconType":"solid","href":"/api-reference/endpoint/agent/get-phone-number"},{"openapi":"patch /v1/agent/phone-numbers/{phone_number_id}","title":"Update Phone Number","icon":"phone","iconType":"solid","href":"/api-reference/endpoint/agent/update-phone-number"},{"openapi":"delete /v1/agent/phone-numbers/{phone_number_id}","title":"Release Phone Number","icon":"phone","iconType":"solid","href":"/api-reference/endpoint/agent/release-phone-number"}]},{"group":"Phone Calls","icon":"phone-arrow-up-right","pages":[{"openapi":"post /v1/agent/phone-calls","title":"Create Phone Call","icon":"phone-arrow-up-right","iconType":"solid","href":"/api-reference/endpoint/agent/create-phone-call"}]}]},{"group":"SDK Reference","pages":[{"group":"Python SDK","icon":"python","pages":[{"title":"Overview","icon":"python","href":"/api-reference/sdk/python/overview"},{"group":"Reference","icon":"book-open","pages":[{"title":null,"href":"/api-reference/sdk/python/client"},{"title":null,"href":"/api-reference/sdk/python/resources"},{"title":null,"href":"/api-reference/sdk/python/types"},{"title":null,"href":"/api-reference/sdk/python/core"},{"title":null,"href":"/api-reference/sdk/python/utils"},{"title":null,"href":"/api-reference/sdk/python/exceptions"}]},{"title":"Legacy","icon":"clock-rotate-left","href":"/archive/python-sdk-legacy/index"}]},{"group":"JavaScript SDK","icon":"js","pages":[{"title":"JavaScript SDK Reference","sidebarTitle":"Reference","icon":"book","href":"/api-reference/sdk/javascript/api-reference"}]}]}]}]},"basePath":"","title":"Text to Speech Stream with Timestamps - Fish Audio","buildId":"dpl_DqYu5MPb49gWBBbUGgpHQUmCHY3P","deploymentId":"dpl_DqYu5MPb49gWBBbUGgpHQUmCHY3P","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-CybtLBIt.js","utils-BMLj2fvV.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-B6In562Y.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-Dr8Mfhp9.js","snippetPresets-2rmQvMVl.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","conditional-requirements-CFM0id0Q.js","ApiExamples-WMqJYdZj.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-CJ-MlPHu.js","shallow-dY3TMRCk.js","getApiPlaygroundDisplay-v-1B2bKm.js","CodeSnippet-BDhiTB7U.js","CodeSnippets-D9hnzQcS.js","Page-C4GwDT3_.js","getPastedJson-Th2V45jI.js","icon-BQXch1W9.js","MethodPill-BCqUneP3.js","DuplicateIcon-Q_-bhurZ.js","createIcon-DUjLHRqp.js","DynamicMarkdown-B-f2cqXQ.js","SectionHeading-Da5NsV4v.js","axios-vUo_bRtp.js","Markdown-D13FWkIM.js","clsx-D3Isdib3.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-C-XZBk9h.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink--qIqmmVG.js"]}