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
📘

Region

The 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.wav

You 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


Did this page help you?