# Kotoba Speech-to-Text

> Accurate transcription of an audio clip in one request, with word timestamps, tuned for Japanese and East Asian languages.


## Overview

- **Endpoint**: `https://fal.run/kotoba-technologies/kotoba-stt/v1/speech-to-text`
- **Model ID**: `kotoba-technologies/kotoba-stt/v1/speech-to-text`
- **Category**: speech-to-text
- **Kind**: inference
**Description**: **Endpoint:** `POST https://fal.run/Kotoba-Technologies/kotoba-stt/v1/speech-to-text`

**Overview:** Upload an audio or video file of up to two minutes and receive the transcript in
a single JSON response, with optional per-word timestamps and the audio duration. The language
is set per request with the `language` parameter (`ja` by default; see the table below). An
optional parameter controls how personal names are written.

**Use cases**
- Voice memos, call segments, and short recordings.
- Subtitles and captions for short clips.
- Longer recordings (meetings, interviews, podcasts) split into chunks of up to two minutes.

**Technical specifications**
- Input: one audio or video file per request (wav, mp3, m4a, mp4, webm, ogg, flac, aac, or
  raw PCM), up to 120 seconds of audio; longer files are rejected. Recommended: 24 kHz, mono.
- Output: JSON with the transcript, word-level timestamps (when requested), and the audio
  duration.
- Options: word timestamps (`with_timestamps`), speaker diarization (`diarization`), katakana
  rendering of names.
- Speaker diarization: `diarization=true` attributes each word to a speaker (`speaker_id`:
  `speaker_1`, `speaker_2`, …, numbered in order of first appearance). Word times are null
  unless `with_timestamps=true` is also set. Beta: speaker attribution is produced by the model
  and can differ between runs on the same audio, for example a short turn merged into its
  neighbour; the transcript itself is unaffected. Works for every supported language; a word the
  model could not attribute has `speaker_id: null`. `words` is filled when either flag is set.
  A deployment whose model has no speaker tokens rejects the request.
- Client: any HTTP client, or the Kotoba Python SDK (`client.asr.transcribe`, 0.2.0+;
  `diarization=True` from 0.2.3).
- Supported languages — pass the code in the `language` parameter exactly as written
  (lowercase). Any other value returns an `unsupported_language` error.

| Language | `language` |
|---|---|
| Japanese (default) | `ja` |
| English | `en` |
| Korean | `ko` |
| Mandarin Chinese | `zh` |
| Mandarin Chinese (Taiwan) | `zh-tw` |
| Cantonese (Hong Kong) | `zh-hk` |
| Spanish | `es` |

**Example request**
```bash
curl -X POST https://fal.run/Kotoba-Technologies/kotoba-stt/v1/speech-to-text \
  -H "Authorization: Key $KOTOBA_API_KEY" \
  -F file=@clip.wav -F language=ja -F with_timestamps=true
```

**Example response**
```json
{
  "language_code": "ja",
  "language_probability": 1.0,
  "text": "おはようございます。今日は水曜日です。",
  "words": [
    {"text": "おはようございます", "type": "word", "start": 0.12, "end": 0.98},
    {"text": "今日は", "type": "word", "start": 1.10, "end": 1.42}
  ],
  "audio_duration_secs": 8.0
}
```

`language_code` echoes the language used for the request; `language_probability` is `1.0` when
a language was supplied and `0.0` otherwise (the endpoint does not detect languages).
`words` is filled when `with_timestamps=true` or `diarization=true`.

**Example response with `diarization=true` and `with_timestamps=true`** (two speakers)
```json
{
  "language_code": "ja",
  "language_probability": 1.0,
  "text": "おはようございます。\nはい、わかりました。",
  "words": [
    {"text": "おはようございます", "type": "word", "start": 0.00, "end": 1.40, "speaker_id": "speaker_1"},
    {"text": "。", "type": "word", "start": 1.40, "end": 1.42, "speaker_id": "speaker_1"},
    {"text": "はい", "type": "word", "start": 4.80, "end": 5.10, "speaker_id": "speaker_2"},
    {"text": "、わかりました。", "type": "word", "start": 5.10, "end": 6.10, "speaker_id": "speaker_2"}
  ],
  "audio_duration_secs": 9.0
}
```

With diarization on, `text` has a line break at each speaker change. With `diarization=true`
alone, `speaker_id` is set and `start` / `end` are null.

**Example (Python)**
```python
import os
import requests

r = requests.post(
    "https://fal.run/Kotoba-Technologies/kotoba-stt/v1/speech-to-text",
    headers={"Authorization": f"Key {os.environ['KOTOBA_API_KEY']}"},
    files={"file": open("clip.wav", "rb")},
    data={"language": "ja", "with_timestamps": "true"},
)
print(r.json()["text"])
```

**Example (Python SDK)**
```python
import kotoba

client = kotoba.KotobaClient()  # KOTOBA_API_KEY + KOTOBA_ASR_REST_URL from the environment
result = client.asr.transcribe("clip.wav", language="ja", with_timestamps=True)
print(result.text)
for segment in result.segments or []:
    print(segment.start, segment.end, segment.text)

# Speaker diarization (kotoba-sdk 0.2.3+): consecutive words grouped by speaker, in reading order
result = client.asr.transcribe("meeting.wav", language="ja", diarization=True, with_timestamps=True)
for u in result.utterances or []:
    print(f"{u.start:6.2f}  {u.speaker_id}: {u.text}")
```

**Pricing:** $0.25 per hour of input audio (unit: second of input audio, $0.0000694 per second).

## Using the Kotoba Python SDK

The `kotoba-sdk` package (PyPI, Python 3.10+, version 0.2.3 or newer) covers all four apps.
It sends the fal key with fal's `Authorization: Key` scheme automatically for `fal.run` URLs,
so use the fal key as the API key and point the per-route URLs at the apps.

```bash
pip install kotoba-sdk
export KOTOBA_API_KEY=<fal key>
export KOTOBA_ASR_REST_URL=https://fal.run/Kotoba-Technologies/kotoba-stt/v1
export KOTOBA_ASR_URL=wss://fal.run/Kotoba-Technologies/kotoba-streaming-stt/v1/realtime
export KOTOBA_TTS_URL=wss://fal.run/Kotoba-Technologies/kotoba-tts/v2/tts/ws
export KOTOBA_S2ST_URL=wss://fal.run/Kotoba-Technologies/kotoba-sts/v1/realtime_voice
```

An app that has been idle may boot a GPU runner on the first request, which can take a few
minutes. Allow for that in the request timeout or retry the first request; the SDK's default
timeouts are 30 seconds for HTTP requests (`KotobaClient(timeout=...)`) and 15 seconds for the
WebSocket handshake.


**Tags**: commercial-use, speech-to-text, japanese, multilingual



## Pricing

Kotoba STT: $0.25 per hour of input audio

For more details, see [fal.ai pricing](https://fal.ai/pricing).

## API Information

This model can be used via our HTTP API or more conveniently via our client libraries.
See the input and output schema below, as well as the usage examples.


### Input Schema

The API accepts the following input parameters:


- **`audio_url`** (`string`, _required_):
  Speech to transcribe: an https:// URL on fal's CDN (Playground uploads and microphone recordings) or a base64 data: URI. Up to 2 minutes.

- **`language`** (`LanguageEnum`, _required_):
  Language spoken in the audio.
  - Options: `"ja"`, `"en"`, `"ko"`, `"zh"`, `"es"`, `"zh-hk"`, `"zh-tw"`

- **`with_timestamps`** (`boolean`, _optional_):
  Return `words` with start and end times for each word.
  - Default: `false`

- **`diarization`** (`boolean`, _optional_):
  Attribute words to speakers (`speaker_id` on each word; models with speaker tokens only). Word times are null unless `with_timestamps` is also set.
  - Default: `false`



**Required Parameters Example**:

```json
{
  "audio_url": "",
  "language": "ja"
}
```


### Output Schema

The API returns the following output format:

- **`language_code`** (`string`, _required_)

- **`text`** (`string`, _required_)

- **`language_probability`** (`float`, _required_)

- **`words`** (`list<SpeechToTextWord>`, _required_)
  - Array of SpeechToTextWord

- **`audio_duration_secs`** (`float`, _optional_)



**Example Response**:

```json
{
  "language_code": "",
  "text": "",
  "words": [
    {
      "type": "word",
      "text": ""
    }
  ]
}
```


## Usage Examples

### cURL

```bash
curl --request POST \
  --url https://fal.run/kotoba-technologies/kotoba-stt/v1/speech-to-text \
  --header "Authorization: Key $FAL_KEY" \
  --header "Content-Type: application/json" \
  --data '{
     "audio_url": "",
     "language": "ja"
   }'
```

### Python

Ensure you have the Python client installed:

```bash
pip install fal-client
```

Then use the API client to make requests:

```python
import fal_client

def on_queue_update(update):
    if isinstance(update, fal_client.InProgress):
        for log in update.logs:
           print(log["message"])

result = fal_client.subscribe(
    "kotoba-technologies/kotoba-stt/v1/speech-to-text",
    arguments={
        "audio_url": "",
        "language": "ja"
    },
    with_logs=True,
    on_queue_update=on_queue_update,
)
print(result)
```

### JavaScript

Ensure you have the JavaScript client installed:

```bash
npm install --save @fal-ai/client
```

Then use the API client to make requests:

```javascript
import { fal } from "@fal-ai/client";

const result = await fal.subscribe("kotoba-technologies/kotoba-stt/v1/speech-to-text", {
  input: {
    audio_url: "",
    language: "ja"
  },
  logs: true,
  onQueueUpdate: (update) => {
    if (update.status === "IN_PROGRESS") {
      update.logs.map((log) => log.message).forEach(console.log);
    }
  },
});
console.log(result.data);
console.log(result.requestId);
```


## Additional Resources

### Documentation

- [Model Playground](https://fal.ai/models/kotoba-technologies/kotoba-stt/v1/speech-to-text)
- [API Documentation](https://fal.ai/models/kotoba-technologies/kotoba-stt/v1/speech-to-text/api)
- [OpenAPI Schema](https://fal.ai/api/openapi/queue/openapi.json?endpoint_id=kotoba-technologies/kotoba-stt/v1/speech-to-text)

### fal.ai Platform

- [Platform Documentation](https://fal.ai/docs/documentation)
- [Python Client](https://fal.ai/docs/api-reference/client-libraries/python)
- [JavaScript Client](https://fal.ai/docs/api-reference/client-libraries/javascript)

### Other agent-readable surfaces

This file covers one model. To find anything else:

- [Platform overview](https://fal.ai/llms.txt): Entry points and representative endpoint IDs
- [Documentation index](https://fal.ai/docs/llms.txt): Every documentation page
- [Full documentation text](https://fal.ai/docs/llms-full.txt): The whole documentation inlined
- Any other model: `https://fal.ai/models/<endpoint-id>/llms.txt`
