Quickstart: Krisp API
Transcribe a WAV file in real time with the Krisp Speech-to-Text API, from API key to first transcript.
In this quickstart you stream a WAV file to the /stt endpoint with the STT for Agents model and print the transcript and end-of-turn events as they arrive.
You need:
- Python 3.9 or later
- A 16 kHz, mono, 16-bit PCM WAV file. To convert any audio file with ffmpeg:
ffmpeg -i input.mp3 -ar 16000 -ac 1 -sample_fmt s16 sample.wav
RegionThe Krisp API currently runs in the US region. From other regions, expect extra latency. See Region and latency.
Get an API key
Sign up in the Developers Portal, then go to API Keys → Create key.
Export it as an environment variable. Keep the API key on your backend: never put it in a browser or mobile app.
export KRISP_API_KEY="your-api-key"setx KRISP_API_KEY "your-api-key"Install the dependencies
pip install requests "websockets>=14"Create the script
Save this as quickstart.py. It creates a short-lived session token from your API key, opens the /stt WebSocket, streams the file at real-time pace, and prints what the server sends back.
import asyncio
import json
import os
import sys
import wave
import requests
import websockets
URL = "wss://streaming.krisp.ai/stt"
CHUNK_MS = 80
def create_session_token() -> str:
resp = requests.post(
"https://api.developers.krisp.ai/v2/sdk/tokens/session",
json={"usage_type": "stt", "expiration_ttl": 100},
headers={"Authorization": f"api-key {os.environ['KRISP_API_KEY']}"},
)
resp.raise_for_status()
return resp.json()["data"]["session_key"]
async def main(path: str) -> None:
headers = {"Authorization": f"api-key {create_session_token()}"}
async with websockets.connect(URL, additional_headers=headers) as ws:
await ws.send(json.dumps({
"model": "krisp-realtime-stt-agents-v1",
"sample_rate": 16000,
"channels": 1,
"audio_format": "pcm_s16le",
"turn": {"prediction": True, "sensitivity": 0.9, "max_silence": 2000},
}))
hello = json.loads(await ws.recv())
if hello["type"] != "ready":
raise RuntimeError(hello)
async def send_audio() -> None:
with wave.open(path, "rb") as wav:
frames = 16000 * CHUNK_MS // 1000
while chunk := wav.readframes(frames):
await ws.send(chunk)
await asyncio.sleep(CHUNK_MS / 1000)
await ws.send(json.dumps({"type": "end_of_audio"}))
sender = asyncio.create_task(send_audio())
async for message in ws:
msg = json.loads(message)
if msg["type"] == "transcript":
kind = "final" if msg["transcript"]["isFinal"] else "partial"
text = "".join(w["text"] for w in msg["transcript"]["words"])
print(kind, text)
elif msg["type"] == "turn":
print("end of turn", msg["reason"], msg["confidence"])
elif msg["type"] == "end":
break
await sender
asyncio.run(main(sys.argv[1]))Run it
python quickstart.py sample.wavYou should see partial transcripts that grow as more audio arrives, final transcripts as words are committed, and an end-of-turn event when the speaker pauses. For a file that says "Hi, I would like to book a table for two people tomorrow evening. Is seven o'clock available?", the output looks like this:
partial Hi, I would like to book a table for two
partial Hi, I would like to book a table for two people
final Hi,
partial I would like to book a table for two people tomorrow
final I
final would
partial like to book a table for two people tomorrow
final like
final to book a table for two people tomorrow evening,
end of turn model 0.927
partial
partial Is
partial Is
partial Is seven
partial Is seven o'clock
partial Is seven o'clock
final Is seven o'clock available?
partial If the session token request fails, check that KRISP_API_KEY is set and that your team has access to Speech-to-Text. The Authentication page lists every error code.
Next steps
Updated 2 days ago

