GET /ws/stream after you create a session. Unexpected closes usually come from auth, frame format, keep-alives, or ending the stream in the wrong order. Closing the socket alone does not end the ambient session or start note generation.
Common causes
- Opening
/ws/streambefore create succeeds, or after the session leavesCREATED(handshake returnsFailedPrecondition). - Bad handshake auth (wrong
Sec-WebSocket-Protocolorder or headers). - Binary frames, non-JSON payloads, or multiple JSON objects in one frame.
- No audio for 25 seconds while the stream is active, or no
KEEP_ALIVEwhile paused. - Missing
RU9G, or calling REST end without the documented end sequence.
Fix
1
Confirm Create and Session State
Create the ambient session first and store
ambient_session_id. Open /ws/stream only while status is CREATED. Reconnect with the same ID only while status stays CREATED. Otherwise the handshake returns FailedPrecondition.2
Authenticate the Handshake
In the browser, set
Sec-WebSocket-Protocol to SukiAmbientAuth,<sdp_suki_token>,<ambient_session_id> (token before session ID). Non-browser clients use the documented Ambient WebSocket upgrade headers.3
Send JSON Text Frames in Order
Send one UTF-8 JSON object per text frame. Order per segment:
START_TIME โ Base64 LINEAR16 PCM in AUDIO / data โ optional EVENT โ final AUDIO with "data": "RU9G". Do not send binary audio frames.4
Keep the Connection Alive
While audio is flowing, send audio at least every 25 seconds. While paused, send
{"type":"EVENT","event":"KEEP_ALIVE"} at least every 5 seconds. Ambient supports pauses of up to 30 minutes when keep-alives continue.5
End in Order
After the last PCM chunk, send
RU9G, close the WebSocket, then call REST end. Then poll status before you retrieve notes.