Skip to main content

Web Client Overview

The web client (@llmrtc/llmrtc-web-client) is a browser library that handles WebRTC signaling, audio/video capture, and event emission for voice AI applications.


Architecture​

The web client manages the browser-side connection:


Core Features​

Connection Management​

  • WebSocket signaling with automatic reconnection
  • WebRTC peer connection setup
  • ICE candidate handling
  • Session persistence across reconnects

Audio Handling​

  • Microphone capture via getUserMedia
  • TTS playback through WebRTC tracks
  • Speech state events (start/end)
  • Barge-in support

Video & Vision​

  • Camera capture with frame extraction
  • Screen sharing support
  • Automatic attachment queuing
  • FPS control for bandwidth management

Event System​

  • Rich event API for UI integration
  • Transcript and LLM response events
  • Tool call notifications
  • Connection state changes

Basic Usage​

import { LLMRTCWebClient } from '@llmrtc/llmrtc-web-client';

// Create client
const client = new LLMRTCWebClient({
signallingUrl: 'wss://your-server.com'
});

// Set up event handlers
client.on('stateChange', (state) => {
console.log('Connection state:', state);
});

client.on('transcript', (text) => {
console.log('User said:', text);
});

client.on('llmChunk', (chunk) => {
process.stdout.write(chunk);
});

client.on('ttsStart', () => {
console.log('Assistant speaking...');
});

client.on('ttsComplete', () => {
console.log('Assistant finished.');
});

// Start connection
await client.start();

// Share microphone
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const controller = client.shareAudio(stream);

// Later: cleanup
controller.stop();
await client.close();

Connection States​

The client moves through defined states:

StateDescription
disconnectedInitial state, not connected
connectingEstablishing WebSocket and WebRTC
connectedFully connected and operational
reconnectingConnection lost, attempting recovery
failedConnection failed, no more retries
closedExplicitly closed by application

Events​

The client emits events for UI integration:

Connection Events​

EventPayloadDescription
stateChangeConnectionStateConnection state changed
reconnecting{ attempt, maxAttempts }Reconnection attempt
errorClientErrorError occurred

Speech Events​

EventPayloadDescription
speechStart-User started speaking
speechEnd-User stopped speaking
transcriptstringFinal transcription

Response Events​

EventPayloadDescription
llmstringComplete LLM response
llmChunkstringStreaming LLM chunk
ttsStart-TTS audio started
ttsComplete-TTS audio finished
ttsCancelled-TTS interrupted (barge-in)
ttsTrackMediaStreamWebRTC audio track

Playbook Events​

EventPayloadDescription
stageChange{ from, to, reason }Stage transition
toolCallStart{ name, callId, arguments }Tool execution started
toolCallEnd{ callId, result, error, durationMs }Tool execution completed

Constructor Options​

interface WebClientConfig {
// Required
signallingUrl: string; // WebSocket server URL

// WebRTC
iceServers?: RTCIceServer[]; // Custom ICE servers (optional)
useWebRTC?: boolean; // Force WebRTC transport

// Reconnection
reconnection?: {
enabled?: boolean; // Enable auto-reconnect (default: true)
maxRetries?: number; // Max retry attempts (default: 5)
baseDelayMs?: number; // Initial delay (default: 1000)
maxDelayMs?: number; // Max delay (default: 30000)
jitterFactor?: number; // Jitter (0-1) (default: 0.3)
};
}
Audio Playback

The client does not auto-play TTS audio. You must handle the ttsTrack or tts event and connect the audio to an <audio> element yourself. See Audio Handling for details.


Methods​

Connection​

MethodDescription
start()Establish connection to server
close()Close connection and cleanup

Audio​

MethodDescription
shareAudio(stream)Share microphone audio, returns controller

Video & Vision​

MethodDescription
shareVideo(stream, intervalMs?)Share camera with frame capture (intervalMs between frames)
shareScreen(stream, intervalMs?)Share screen with frame capture (intervalMs between frames)
sendAttachments()Send queued attachments to server

Framework Integration​

React​

import { useEffect, useState, useRef } from 'react';
import { LLMRTCWebClient } from '@llmrtc/llmrtc-web-client';

function useVoiceClient(url: string) {
const clientRef = useRef<LLMRTCWebClient | null>(null);
const [state, setState] = useState('disconnected');
const [transcript, setTranscript] = useState('');

useEffect(() => {
const client = new LLMRTCWebClient({ signallingUrl: url });
clientRef.current = client;

client.on('stateChange', setState);
client.on('transcript', setTranscript);

return () => {
client.close();
};
}, [url]);

return { client: clientRef.current, state, transcript };
}

Vue​

import { ref, onMounted, onUnmounted } from 'vue';
import { LLMRTCWebClient } from '@llmrtc/llmrtc-web-client';

export function useVoiceClient(url: string) {
const client = ref<LLMRTCWebClient | null>(null);
const state = ref('disconnected');

onMounted(() => {
client.value = new LLMRTCWebClient({ signallingUrl: url });
client.value.on('stateChange', (s) => state.value = s);
});

onUnmounted(() => {
client.value?.close();
});

return { client, state };
}

Browser Requirements​

BrowserMinimum Version
Chrome74+
Firefox78+
Safari14.1+
Edge79+

Required APIs:

  • WebSocket
  • WebRTC (RTCPeerConnection)
  • getUserMedia
  • MediaStream