Core SDK
Voice messages
Upload voice clips to a room with optional transcription.
FluxyChat supports async voice messages (record → upload → optional AI transcription). There is no useHuddle hook in @fluxy-chat/react today — live WebRTC huddles are not part of the public SDK.
Enable the feature on the Worker:
FEATURE_VOICE_MESSAGES=trueBind R2 for attachments (ATTACHMENTS in wrangler.toml).
Upload from the client
POST /messages/voice accepts multipart form data with a member JWT (same auth as POST /messages):
const form = new FormData();
form.append("audio", blob, "recording.webm");
form.append("roomId", roomId);
form.append("durationMs", String(durationMs));
const res = await fetch(`${baseUrl}/messages/voice`, {
method: "POST",
headers: { Authorization: `Bearer ${token}` },
body: form,
});
const { messageId, audioUrl, transcriptionStatus } = await res.json();
// transcriptionStatus: "pending" → later "ready" via message_updated WS eventSupported formats: webm, ogg, mp3, m4a, wav. Size and duration limits return 413 when exceeded.
Realtime updates
After upload, the Worker broadcasts a message_updated event when transcription completes. Subscribe via the room WebSocket or poll message history if the socket is down.
Rate limits and quotas
Voice uploads consume message quota and respect RATE_LIMIT_VOICE_MESSAGES_PER_MINUTE (default 10/min per user).
Live voice / huddles
joinVoiceStage / leaveVoiceStage on useChat is stage signaling (speaker vs listener on the room WebSocket). Scaffold: --example voice-stage.
It is not WebRTC audio. Console: /voice-ai. Media for huddles is LiveKit. Voice AI latency: load report and GET /admin/voice-ai/stats. Product SLO P95 ≤ 300ms is a target; treat tables as unit-bench until stats are populated. Async clips remain POST /messages/voice.