Complete developer guide and best practices to help you get started quickly.
Speech recognition
Walks through the full speech recognition flow: encoding local audio as Base64, getting the full JSON result, attaching timestamps or subtitles, and streaming with SSE.
This tutorial centres on POST /api/v1/audio/transcriptions. The speech endpoint consumes Base64-encoded audio bytes and returns plain text plus optional timestamp data; it also supports SSE for incremental output.
Step 1: Prepare the audio payload
Read the audio into memory and Base64-encode it. The data:audio/...;base64, URI prefix must be stripped — the endpoint only accepts the raw Base64 payload. The server detects the format from the actual audio content, so the filename extension is irrelevant, but the bytes must be one of the supported formats.
- Supported formats: MP3, WAV, M4A, FLAC, OGG, WEBM.
- The JSON (Base64) path caps raw audio at 1 MB; exceeding returns 413 audio_too_long.
- For audio over 1 MB, upload the raw file via multipart/form-data instead (≤ 15 MB): the `params` JSON field (this tutorial's parameters minus audio_data) must precede the `audio` file field. See the ASR endpoint in the API reference for the full field list and error codes.
- Format detection failure returns 422 unsupported_audio_format; decode failure returns 422 asr_audio_decode_error.
Convert a local audio file to a single-line Base64 string. base64 -w 0 prevents line wrapping.
# Encode a local audio file (no line wrapping)
AUDIO_B64=$(base64 -w 0 ./meeting.mp3)
echo "$AUDIO_B64" | head -c 80
# Output (truncated): SUQzBAAAAAACSlBNTAAA...Step 2: Send a JSON-mode request
By default stream=false waits for transcription to finish and returns the full result in one response. language accepts a language code or "auto" to let the model detect; punctuation defaults to true, auto-completing punctuation in the transcript.
JSON-mode curl: use jq to inject the Base64 string so the shell does not mangle special characters.
curl -X POST "https://abemono.abestar.com.tw/api/v1/audio/transcriptions" \ -H "X-API-Key: $ABESTAR_API_KEY" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg a "$AUDIO_B64" '{ audio_data: $a, language: "zh-TW", timestamp_format: "json", diarization: true }')"
Successful response example (HTTP 200). When timestamp_format="json", segments is populated; switching to srt / webvtt populates the timestamps string instead.
{
"text": "今天的會議改到下午三點。",
"detected_language": "zh-TW",
"segments": [
{
"id": 0,
"start": 0.0,
"end": 2.4,
"text": "今天的會議改到下午三點。",
"speaker": "A"
}
],
"timestamps": null,
"usage": {
"quota_percent": {
"used": 35
}
},
"forced_replacement_count": 0,
"vocabulary_used": false
}Optional feature parameters
All parameters below are optional and can be combined freely with either JSON or SSE mode; omitted fields fall back to their defaults. The first seven rows are shared with the text translation endpoint; the last three are speech-only.
| Parameter | Type | Default | Description |
|---|---|---|---|
| model | string | "tranc-std-v1" | Transcription model code. Use GET /audio/models to list what is currently available. |
| domain | string | "general" | Domain hint such as "medical", "legal", or "finance", helping with domain terminology. |
| context | { speech: string }[] | [] | Scene background or prior dialogue, provided in chronological order. |
| harm_content_filter | boolean | false | Enables harmful-content filtering. Blocked audio returns 400 asr_content_policy_violation. |
| punctuation | boolean | true | Auto-completes punctuation in the transcript. Defaults to true — the opposite of the text translation endpoint's false. |
| number_format | "spoken" | "arabic" | "spoken" | Number transcription: spoken writes numbers out in words, arabic uses digits (1234). |
| date_format | "natural" | "yyyy-MM-dd" | "yyyy/MM/dd" | "MM/dd/yyyy" | "dd-MM-yyyy" | "natural" | Date presentation: natural follows the language's convention; the rest are fixed templates. |
| timestamp_format | "json" | "srt" | "webvtt" | omitted → no timestamps | Speech-only. "json" returns structured segments; "srt" / "webvtt" return a ready-to-use subtitle string. |
| diarization | boolean | false | Speech-only. When true, segments carry alphabetic speaker labels ("A" / "B" / "C"…) for multi-speaker meetings. |
| processing_mode | "fast" | "balanced" | "balanced" | Speech-only. fast is quicker; balanced is more accurate. Keep balanced for long audio or accuracy-critical work. |
punctuation defaults differ between the two endpoints
With dictionaries
The speech endpoint accepts the same two dictionary kinds as text translation: vocabulary is soft guidance — matching terms are offered to the model as preferred wording, which suits names, product names, and jargon — while forced_replacement performs string substitutions on the transcript after recognition finishes. Both are referenced by UUID via vocabulary_dictionary_id / forced_replacement_dictionary_id.
Both dictionaries can be attached in JSON mode. Note that language must be an explicit code — auto is not allowed here.
curl -X POST "https://abemono.abestar.com.tw/api/v1/audio/transcriptions" \ -H "X-API-Key: $ABESTAR_API_KEY" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg a "$AUDIO_B64" '{ audio_data: $a, language: "zh-TW", vocabulary_dictionary_id: "f3c1e9a2-9c2b-4f7a-9d3a-7e2b8a1c4d5e", forced_replacement_dictionary_id: "1d2e3f4a-5b6c-7d8e-9f0a-1b2c3d4e5f6a" }')"
vocabulary_used and forced_replacement_count in the response let you confirm the dictionaries actually took effect — this pair is speech-only; text translation returns just the latter.
{
"text": "請把這份合約交給法務組長確認。",
"detected_language": "zh-TW",
"segments": null,
"timestamps": null,
"usage": {
"quota_percent": {
"used": 35
}
},
"forced_replacement_count": 2,
"vocabulary_used": true
}A vocabulary dictionary cannot be combined with language: "auto"
Creating dictionaries and further details
SSE mode: streaming output
Set stream=true when you need live subtitles or progressive display. The response switches to text/event-stream and events flow as head (detected_language) → chunk* (text fragments, zero or more) → tail (optionally carrying segments) → meta (usage / vocabulary_used / forced_replacement_count). On failure, an error event replaces remaining events and closes the stream.
curl example in SSE mode. -N disables curl buffering so events stream out immediately.
curl -N -X POST "https://abemono.abestar.com.tw/api/v1/audio/transcriptions" \ -H "X-API-Key: $ABESTAR_API_KEY" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg a "$AUDIO_B64" '{ audio_data: $a, language: "auto", stream: true }')"

