Getting startedEnd-to-end examples

Real-time meeting assistant

Stream audio from your microphone with speaker diarization and LLM Gateway to get live transcription and automatic summaries after each speaker turn.

Products used: Streaming STT + Universal-3 Pro + LLM Gateway

Model selection: Uses u3-rt-pro (Universal-3 Pro Streaming) for the lowest latency (~300ms) with the highest streaming accuracy.

1# pip install pyaudio websocket-client
2import pyaudio
3import websocket
4import json
5import threading
6import time
7from urllib.parse import urlencode
8
9# ── Config ────────────────────────────────────────────────────
10YOUR_API_KEY = "YOUR_API_KEY"
11
12PROMPT = (
13 "Summarize this speaker turn in one sentence, then list any "
14 "action items mentioned.\n\nTranscript: {{turn}}"
15)
16
17LLM_GATEWAY_CONFIG = {
18 "model": "claude-sonnet-4-5-20250929",
19 "messages": [{"role": "user", "content": PROMPT}],
20 "max_tokens": 500,
21}
22
23CONNECTION_PARAMS = {
24 "sample_rate": 16000,
25 "speech_model": "u3-rt-pro",
26 "format_turns": True,
27 "min_turn_silence": 560, # Wait longer for natural meeting pauses
28 "max_turn_silence": 2000,
29 "llm_gateway": json.dumps(LLM_GATEWAY_CONFIG),
30}
31
32API_ENDPOINT = f"wss://streaming.assemblyai.com/v3/ws?{urlencode(CONNECTION_PARAMS)}"
33
34# Audio settings
35FRAMES_PER_BUFFER = 800
36SAMPLE_RATE = 16000
37stop_event = threading.Event()
38
39def on_open(ws):
40 print("Connected — speak into your microphone. Press Ctrl+C to stop.\n")
41
42 def stream_audio():
43 audio = pyaudio.PyAudio()
44 stream = audio.open(
45 input=True, frames_per_buffer=FRAMES_PER_BUFFER,
46 channels=1, format=pyaudio.paInt16, rate=SAMPLE_RATE,
47 )
48 while not stop_event.is_set():
49 try:
50 data = stream.read(FRAMES_PER_BUFFER, exception_on_overflow=False)
51 ws.send(data, websocket.ABNF.OPCODE_BINARY)
52 except Exception:
53 break
54 stream.stop_stream()
55 stream.close()
56 audio.terminate()
57
58 threading.Thread(target=stream_audio, daemon=True).start()
59
60def on_message(ws, message):
61 data = json.loads(message)
62 msg_type = data.get("type")
63
64 if msg_type == "Turn":
65 transcript = data.get("transcript", "")
66 if data.get("end_of_turn") and transcript:
67 print(f"[Turn] {transcript}\n")
68 elif transcript:
69 print(f"\r ... {transcript[-80:]}", end="", flush=True)
70
71 elif msg_type == "LLMGatewayResponse":
72 content = data.get("data", {}).get("choices", [{}])[0].get("message", {}).get("content", "")
73 print(f"[Assistant] {content}\n")
74
75 elif msg_type == "Termination":
76 print(f"\nSession ended — {data.get('audio_duration_seconds', 0)}s of audio processed.")
77
78def on_error(ws, error):
79 print(f"Error: {error}")
80 stop_event.set()
81
82def on_close(ws, code, msg):
83 stop_event.set()
84
85ws_app = websocket.WebSocketApp(
86 API_ENDPOINT,
87 header={"Authorization": YOUR_API_KEY},
88 on_open=on_open, on_message=on_message,
89 on_error=on_error, on_close=on_close,
90)
91
92ws_thread = threading.Thread(target=ws_app.run_forever, daemon=True)
93ws_thread.start()
94
95try:
96 while ws_thread.is_alive():
97 time.sleep(0.1)
98except KeyboardInterrupt:
99 print("\nStopping...")
100 stop_event.set()
101 if ws_app.sock and ws_app.sock.connected:
102 ws_app.send(json.dumps({"type": "Terminate"}))
103 time.sleep(2)
104 ws_app.close()
Connected — speak into your microphone. Press Ctrl+C to stop.
[Turn] So the main thing we need to decide today is whether we're going
with vendor A or vendor B for the new analytics platform.
[Assistant] The speaker is initiating a decision discussion about choosing
between two analytics platform vendors.
Action items: None yet — decision pending.
[Turn] I think vendor A has better pricing but vendor B has the integrations
we need. Can someone pull the comparison spreadsheet by Friday?
[Assistant] The speaker compared vendor pricing vs. integrations and requested
a comparison document.
Action items:
- Pull the vendor comparison spreadsheet by Friday

See the End-to-end examples overview for all available pipelines.