> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Speech recognition (ASR)

> Transcribe audio to text using on-device ASR models running on the Qualcomm NPU.

The ASR service transcribes audio to text using on-device models running fully on the Qualcomm NPU. It supports both file-based batch transcription and real-time streaming via WebSocket.

## Prerequisites

Ensure the Audio Analytics container is deployed and running. See [Running the Audio Analytics container](/ai-workflows/audio-analytics-overview) for setup instructions.

## Audio format requirements

| Property      | Requirement                                                                                                   |
| ------------- | ------------------------------------------------------------------------------------------------------------- |
| Format        | WAV only                                                                                                      |
| Sample rate   | 16 kHz required. If your audio is a different sample rate, declare it via `parameters` in the create request. |
| Channels      | Mono (auto-converted)                                                                                         |
| Max file size | 25 MB                                                                                                         |

## Available models

Query the models endpoint to get the list of available ASR models:

```bash theme={null}
curl http://localhost:8085/audio-analytics/v1/api/transcriptions/models
```

**Response:**

```json theme={null}
[
  {
    "name": "whisper-small-quantized",
    "display_name": "Whisper Small (Quantized)",
    "description": "OpenAI whisper-small-quantized model for general transcription"
  }
]
```

Use the `name` value from this response in your transcription requests.

## Endpoints

| Method | Endpoint                 | Description                                    |
| ------ | ------------------------ | ---------------------------------------------- |
| `GET`  | `/transcriptions/models` | List available ASR models                      |
| `POST` | `/transcriptions/create` | Transcribe a file or start a streaming session |
| `POST` | `/transcriptions/close`  | Close an active streaming session              |
| `POST` | `/transcriptions/flush`  | Force immediate processing of buffered audio   |

## File transcription

Upload a WAV file and receive the complete transcription in a single response:

```bash theme={null}
curl -X POST http://localhost:8085/audio-analytics/v1/api/transcriptions/create \
  -F "file=@recording.wav" \
  -F "model=whisper-small-quantized" \
  -F "language=en" \
  -F "stream=false"
```

**Response:**

```json theme={null}
{
  "text": "The transcribed text from your audio file.",
  "language": "en",
  "language_name": "English",
  "type": "transcript.text.done"
}
```

Set `language` to a language code supported by the model, or omit it for automatic detection.

## File transcription with streaming results

Upload a complete WAV file and receive transcription results via WebSocket as the file is processed:

```bash theme={null}
curl -X POST http://localhost:8085/audio-analytics/v1/api/transcriptions/create \
  -F "file=@recording.wav" \
  -F "model=whisper-small-quantized" \
  -F "language=en" \
  -F "stream=true"
```

The server acknowledges the upload and begins processing. Connect to the WebSocket to receive results.

**WebSocket results:**

```json theme={null}
{ "state": "connection_established" }
{ "type": "transcript.text.done", "text": "The transcribed text.", "language": "en", "language_name": "English", "state": "transcription" }
```

## Live audio streaming

Stream raw audio chunks in real time and receive transcription results as you speak.

### Step 1 - Create a session

Declare the audio format via `parameters` if your audio is not 16 kHz mono PCM:

```bash theme={null}
curl -X POST http://localhost:8085/audio-analytics/v1/api/transcriptions/create \
  -H "Content-Type: application/json" \
  -d '{
    "model": "whisper-small-quantized",
    "language": "en",
    "stream": true,
    "vad": 1200,
    "parameters": [
      {"key": "sampling_rate", "value": "44100"},
      {"key": "channels", "value": "1"},
      {"key": "format", "value": "pcm_s16le"}
    ]
  }'
```

**Response:**

```json theme={null}
{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "state": "asr_initialized",
  "text": "Successfully started Transcription Engine. Please connect to the WebSocket to send audio data & receive transcription output.",
  "language": "en",
  "type": "transcript.event"
}
```

The `vad` parameter sets the silence hangover in milliseconds before speech end is detected. Omit it to disable VAD and manage utterance end manually via `/transcriptions/flush` or `/transcriptions/close`.

### Step 2 - Connect to WebSocket and send audio

Connect to `ws://localhost:8085/stream`. The server sends a `connection_established` message on connect before any transcription messages arrive:

```json theme={null}
{ "state": "connection_established" }
```

Send audio in 8192-byte chunks via WebSocket:

```javascript theme={null}
const ws = new WebSocket('ws://localhost:8085/stream');

ws.send(JSON.stringify({
  "message_type": "transcriptions_session_audio",
  "message_source": "audio_analytics_api",
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "type": "input_audio",
  "data": "<BASE64_ENCODED_PCM>"
}));
```

### Step 3 - Receive results

The server emits the following sequence per utterance:

```json theme={null}
{ "type": "transcript.event", "state": "speech_start", "session_id": "..." }
{ "type": "transcript.text.delta", "text": "Partial text...", "language": "en", "session_id": "..." }
{ "type": "transcript.event", "state": "speech_end", "session_id": "..." }
{ "type": "transcript.text.done", "text": "Complete utterance text.", "language": "en", "state": "transcription", "session_id": "..." }
```

After `transcript.text.done` the engine resets and listens for the next utterance. The session stays open until you call `/transcriptions/close`.

### Step 4 - Close the session

```bash theme={null}
curl -X POST http://localhost:8085/audio-analytics/v1/api/transcriptions/close \
  -H "Content-Type: application/json" \
  -d '{"session_id": "550e8400-e29b-41d4-a716-446655440000"}'
```

**Response:**

```json theme={null}
{
  "text": "",
  "language": null,
  "type": "asr_closed",
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "state": "asr_closed"
}
```

<Note>Only one ASR session can be active at a time. Starting a second session while one is active returns HTTP `409 Conflict`. Close the existing session first.</Note>

## Voice Activity Detection (VAD)

VAD controls how the server detects the end of an utterance during a streaming session. When silence is detected for the configured duration, the server emits `speech_end` followed by `transcript.text.done` for the current utterance. The session remains open and resets for the next utterance — VAD does not close the session.

| Parameter | Description                                                                                                                                                                                                                                       |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `vad`     | Silence hangover in milliseconds before `speech_end` fires. For example, `1200` = 1.2 seconds of silence triggers end of utterance. Omit to disable VAD and manage utterance end manually via `/transcriptions/flush` or `/transcriptions/close`. |

<Note>If no audio is received for the duration set by `SESSION_TIMEOUT_S` (default: 30 seconds) in the container config, the session closes automatically regardless of VAD state.</Note>

## Flush buffered audio

Force immediate transcription of buffered audio without closing the session:

```bash theme={null}
curl -X POST http://localhost:8085/audio-analytics/v1/api/transcriptions/flush \
  -H "Content-Type: application/json" \
  -d '{"session_id": "550e8400-e29b-41d4-a716-446655440000"}'
```

## Python example

```python theme={null}
import requests

def transcribe_file(audio_file, language=None):
    url = "http://localhost:8085/audio-analytics/v1/api/transcriptions/create"
    data = {
        "model": "whisper-small-quantized",
        "stream": "false"
    }
    if language:
        data["language"] = language
    with open(audio_file, "rb") as f:
        response = requests.post(url, files={"file": f}, data=data, timeout=60)
    response.raise_for_status()
    return response.json()["text"]

print(transcribe_file("sample.wav"))
```

## Troubleshooting

**Poor transcription quality:** Use 16 kHz mono WAV files and ensure audio is clear with minimal background noise.

## Next steps

<CardGroup cols={2}>
  <Card title="Text-to-speech" icon="volume-high" href="/ai-workflows/tts-container">
    Synthesize speech from text on-device
  </Card>

  <Card title="Language translation" icon="language" href="/ai-workflows/language-translation">
    Translate text between languages on-device
  </Card>
</CardGroup>
