Try the new DeepSeek V4 Pro 0813 today. Frontier intelligence at a fraction of the cost. Here
Transcription

Qwen LogoQwen3 ASR 1.7B Streaming

Real-time streaming speech-to-text from Qwen3-ASR 1.7B over WebSocket, featuring batch-level accuracy, sub-second finals, and 30+ languages.

Model details

Qwen3-ASR 1.7B (Streaming) is a real-time speech-to-text service that runs Alibaba's open-weight Qwen3-ASR model behind Baseten's streaming harness over WebSocket. Because Qwen3-ASR is an offline audio model, the server uses growing-window re-inference: within each speech turn it re-decodes the utterance so far with full acoustic context to produce revisable live partials, then does a full-context decode at the endpoint for a high-accuracy final. Server-side voice-activity detection ends turns automatically, and an explicit commit also finalizes a turn.

This recovers full batch-level accuracy in a streaming setting — roughly 10% macro semantic WER across a 5-locale telephony benchmark (≈4% en-US), while delivering sub-second final latency and low time-to-first-partial, sustaining real-time streaming at high concurrency on a single GPU. It auto-detects language across 30+ languages (52 including Chinese dialects) and can be pinned to a specific language. Responses use the same envelope as Baseten's streaming-Whisper model, so an existing Whisper WebSocket client can switch to it with only a change to the audio-send path (base64 append/commit).

Ideal for voice agents, live captioning, and multilingual customer-support transcription.

Accuracy vs latency — semantic word-error-rate vs median time-to-final-segment (single stream), plotted against closed-source providers.Accuracy vs latency — semantic word-error-rate vs median time-to-final-segment (single stream), plotted against closed-source providers.
Latency vs concurrency — how median latency holds up as concurrent streams scale, by GPU.Latency vs concurrency — how median latency holds up as concurrent streams scale, by GPU.

Stream 16 kHz mono PCM16 audio over a WebSocket as base64 input_audio_buffer.append frames and end a turn with input_audio_buffer.commit or automatic voice-activity detection (VAD). The server returns type:"transcription" messages — revisable partials (is_final:false) during the turn and a final (is_final:true) at each endpoint. Responses match the streaming-Whisper format.

We've shown that Qwen3-ASR-1.7B can comfortably keep real-time through up to 64 concurrent streams on both NVIDIA RTX 6000 and H100 GPUs, with P95 finalization latency under 0.50 seconds.

Input
1import asyncio, base64, json, os, wave
2import websockets
3
4URL = "wss://model-<id>.api.baseten.co/environments/production/websocket"
5KEY = os.environ["BASETEN_API_KEY"]
6SR = 16_000
7CHUNK = int(SR * 0.1) * 2  # 100 ms of PCM16
8HEADERS = {"Authorization": f"Api-Key {KEY}"}
9
10
11async def transcribe(path):
12    with wave.open(path, "rb") as w:  # 16 kHz mono PCM16 WAV
13        pcm = w.readframes(w.getnframes())
14    async with websockets.connect(URL, additional_headers=HEADERS) as ws:
15        await ws.send(json.dumps({
16            "whisper_params": {"audio_language": "auto"},
17            "streaming_params": {
18                "enable_partial_transcripts": True,
19                "partial_transcript_interval_s": 0.5,
20            },
21        }))
22
23        async def send():
24            for i in range(0, len(pcm), CHUNK):
25                chunk = base64.b64encode(pcm[i:i + CHUNK]).decode()
26                await ws.send(json.dumps({
27                    "type": "input_audio_buffer.append",
28                    "audio": chunk,
29                }))
30                await asyncio.sleep(0.1)  # real-time pace
31            await ws.send(json.dumps(
32                {"type": "input_audio_buffer.commit"}
33            ))
34
35        asyncio.create_task(send())
36        while True:
37            msg = json.loads(await ws.recv())
38            if msg.get("type") != "transcription":
39                continue
40            text = " ".join(s["text"] for s in msg.get("segments", []))
41            print(("final:" if msg["is_final"] else "partial:"), text)
42            if msg.get("is_final") and msg.get("is_end_of_audio_flush"):
43                break
44
45
46asyncio.run(transcribe("example.wav"))
JSON output
1{
2    "type": "transcription",
3    "is_final": false,
4    "transcription_num": 0,
5    "language_code": "English",
6    "segments": [
7        {
8            "start_time": 0,
9            "end_time": 3.2,
10            "text": "<current hypothesis>"
11        }
12    ]
13}

🔥 Trending models