# Kotoba Realtime Speech-to-Text

> Live transcription over WebSocket, with partial results as the speaker talks.


## Overview

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

**Overview:** Open a WebSocket, stream audio in real time, and receive transcript updates
continuously while the speaker talks. When the client commits the stream, the server flushes
the remaining audio and acknowledges the end of the session. The protocol follows the OpenAI
Realtime transcription event format, so existing realtime clients port with minimal change.

**Use cases**
- Live captions for meetings, webinars, and broadcasts.
- Voice agents and IVR systems, including telephony.
- Note-taking and dictation apps that show text as it is spoken.
- Accessibility overlays in video calls.

**Technical specifications**
- Transport: WebSocket, JSON events with base64 audio.
- Input audio: 16-bit PCM, float32, or telephony 8 kHz mu-law; configurable sample rate.
  Recommended: 24 kHz, mono (other rates are resampled server-side).
- Output: transcript deltas while speaking; a committed acknowledgement once the stream
  has been flushed.
- Session options: `target_language` (the transcript language, required), audio format and
  sample rate, `turn_detection` (see below).
- Options: katakana rendering of names.
- Turn detection: `turn_detection` defaults to `{"type": "server_vad", "silence_duration_ms": 800}`.
  The server ends a turn after 800 ms in which the model produces no text (rounded up to whole
  80 ms chunks); it is judged from the model's output, not from audio energy. Each turn gets its
  own `item_id` (a UUID, created at the turn's first text) on its deltas and a
  `conversation.item.input_audio_transcription.completed` event with the turn's full transcript.
  Set `"turn_detection": false` to disable, or pass the object with another non-negative
  `silence_duration_ms`; `true` and `null` are rejected. The setting is fixed when the session
  opens. Stopping the audio does not end a turn: send `input_audio_buffer.commit` to flush, which
  completes the last turn and is answered by `input_audio_buffer.committed`.
- Supported languages: Japanese only — set `target_language` to `ja`.
- Client: any WebSocket client, or the Kotoba Python SDK.

**Example input** (turn detection disabled: one continuous transcript, ended by `commit`)
```json
{"type": "transcription_session.update",
 "session": {"input_audio_format": "pcm16", "input_audio_sample_rate": 24000,
             "input_audio_transcription": {"target_language": "ja"},
             "turn_detection": false}}
{"type": "input_audio_buffer.append", "audio": "<base64 pcm16>"}
{"type": "input_audio_buffer.commit"}
```

**Example output** with `turn_detection: false`
```json
{"type": "transcription_session.updated", "session": {...}}
{"type": "conversation.item.created", "event_id": "…"}
{"type": "conversation.item.input_audio_transcription.delta", "item_id": null, "delta": "おはよう"}
{"type": "conversation.item.input_audio_transcription.delta", "item_id": null, "delta": "ございます。"}
{"type": "input_audio_buffer.committed"}
```

**Example output** with the default turn detection (`turn_detection` omitted)
```json
{"type": "transcription_session.updated", "session": {...}}
{"type": "conversation.item.input_audio_transcription.delta", "item_id": "2f0c…", "delta": "おはよう"}
{"type": "conversation.item.input_audio_transcription.delta", "item_id": "2f0c…", "delta": "ございます。"}
{"type": "conversation.item.input_audio_transcription.completed", "item_id": "2f0c…", "transcript": "おはようございます。"}
{"type": "conversation.item.input_audio_transcription.delta", "item_id": "9b41…", "delta": "今日は"}
{"type": "input_audio_buffer.commit"}
{"type": "conversation.item.input_audio_transcription.completed", "item_id": "9b41…", "transcript": "今日は水曜日です。"}
{"type": "input_audio_buffer.committed"}
```

Deltas are append-only and never revised; `completed` repeats the turn's text in one piece.
Deltas sent before the first turn starts carry `item_id: null`. `item_id` is unrelated to the
`event_id` a client may put on its `append` messages.

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

client = kotoba.KotobaClient()  # KOTOBA_API_KEY + KOTOBA_ASR_URL from the environment
for delta in client.asr.transcribe_stream(mic_chunks(), language="ja"):  # PCM16 chunks in
    print(delta, end="", flush=True)

# Turn detection: turn_detection=False disables it; {"type": "server_vad", "silence_duration_ms": 1200}
# changes the threshold. Session-level API: a "final_transcript" event closes each turn.
```

**Pricing:** $0.39 per hour of session (unit: second of session, $0.000108 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, realtime, streaming



## Pricing

Kotoba Streaming STT: $0.39 per hour of input audio for the one-shot demo; billed per input audio second.

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

## API Information

This endpoint speaks its own message protocol over a WebSocket at `wss://fal.run/kotoba-technologies/kotoba-streaming-stt/v1/realtime`.
Open the connection with any WebSocket client and authenticate the upgrade with the `Authorization: Key $FAL_KEY` header.
Keep the API key on a server: browsers should connect through your own backend, which adds the header.


### Input Schema

The API accepts the following input parameters:





### Output Schema

The API returns the following output format:




## Usage Examples

### Python

```bash
pip install websockets
```

```python
import os

from websockets.sync.client import connect

with connect(
    "wss://fal.run/kotoba-technologies/kotoba-streaming-stt/v1/realtime",
    additional_headers={"Authorization": f"Key {os.environ['FAL_KEY']}"},
) as ws:
    # Send the app's first message here.
    for message in ws:
        if isinstance(message, bytes):
            continue  # binary frame, e.g. audio
        print(message)  # the app's messages, shown as text
```

### JavaScript (Node.js)

```bash
npm install ws
```

```javascript
import WebSocket from "ws";

// Keep the API key on your server; a browser connects through your
// own backend, which adds the header. Use the "ws" package: Node's
// global WebSocket ignores the headers option and the upgrade gets 401.
const ws = new WebSocket("wss://fal.run/kotoba-technologies/kotoba-streaming-stt/v1/realtime", {
  headers: { Authorization: "Key " + process.env.FAL_KEY },
});

ws.on("open", () => {
  // Send the app's first message here.
});
ws.on("message", (data, isBinary) => {
  if (isBinary) return; // binary frame, e.g. audio
  console.log(data.toString()); // the app's messages, shown as text
});
ws.on("error", console.error);
```


## Additional Resources

### Documentation

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

### 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`
