All connections require a valid JWT token. Obtain a token by logging in via
POST /api/auth/login with username and password.
The token must be included in all requests:
Include an
Authorization: Bearer <jwt> header in the
POST request to /api/ingest. The built-in
BroadcastStream adds this automatically when using the app.
Append ?token=<jwt> to the WebSocket URL:
const wsUrl = 'wss://example.com/api/ingest/stream?token=' + encodeURIComponent(token) const ws = new WebSocket(wsUrl)
The easiest way to integrate with Squawk broadcasting is using the
BroadcastStream class. This standalone ES module
handles microphone access, audio recording, and HTTP streaming to the Squawk ingest
endpoint.
https://example.com/lib/broadcast_standalone.js
BroadcastStream is the recommended high-level API
for broadcasting. It manages the microphone, streams audio to
/api/ingest, and provides connection status
updates.
import { BroadcastStream } from 'https://example.com/lib/broadcast_standalone.js' // Store token for auth_headers() const token = 'your_jwt_token' sessionStorage.setItem('squawk_token', token) const stream = new BroadcastStream('/api/ingest', { on_status_change: (status) => { console.log('Status:', status) // 'disconnected' | 'connected' | 'streaming' | 'error' document.getElementById('status').textContent = status }, on_listener_count: (count) => { console.log('Stream reached', count, 'listeners') }, on_error: (message) => { console.error('Error:', message) }, on_recording_complete: (stats) => { console.log(`Streamed ${stats.bytes_streamed} bytes to ${stats.dispatched_to} listeners`) }, on_level_change: (level) => { // Update VU meter (0.0 to 1.0) document.getElementById('level').style.width = `${level * 100}%` }, }) // Start streaming to specific channels const channels = ['equities', 'fixed_income'] await stream.start_recording(channels) // Stop streaming stream.stop()
High-level class that manages the complete broadcast workflow. Handles microphone access, HTTP streaming to the ingest endpoint, and connection state management.
new BroadcastStream(url: string, callbacks: BroadcastStreamCallbacks)
| Parameter | Type | Required | Description |
|---|---|---|---|
url |
string | Required | The ingest endpoint URL (e.g., '/api/ingest') |
callbacks |
BroadcastStreamCallbacks | Required | Callback functions for stream events |
| Method | Parameters | Description |
|---|---|---|
start_recording() |
channels: string[] | Start recording and streaming. Channels are prefixed with 'asset:' and sent as keywords |
stop() |
none | Stop recording and close the stream |
| Property | Type | Description |
|---|---|---|
streaming |
boolean | Whether currently streaming |
| Callback | Parameters | Description |
|---|---|---|
on_status_change |
(status: ConnectionStatus) | Called when connection status changes: 'disconnected' | 'connected' | 'streaming' | 'error' |
on_listener_count |
(count: number) | Called when stream ends with the number of listeners who received the audio |
on_error |
(message: string) | Called when an error occurs |
on_recording_complete |
(stats: object) | Called when recording completes with bytes_streamed and dispatched_to stats |
on_level_change |
(level: number) | Called with audio level 0.0-1.0 for VU meter updates |
High-level recorder that handles microphone access and audio recording. Manages the MediaStream lifecycle and provides a simple start/stop interface.
new MicrophoneRecorder(callbacks: RecorderCallbacks)
| Method | Parameters | Description |
|---|---|---|
start() |
timeslice?: number | Start recording. Timeslice is chunk duration in ms (default: 100) |
stop() |
none | Stop recording and release microphone |
| Property | Type | Description |
|---|---|---|
is_recording |
boolean | Whether currently recording |
mime_type |
string | null | The MIME type being used for recording (e.g., "audio/webm;codecs=opus") |
Lower-level recorder that works with an existing MediaStream. Use this if you need more control over the audio source.
new AudioRecorder(stream: MediaStream, callbacks: RecorderCallbacks)
| Method | Parameters | Description |
|---|---|---|
start() |
timeslice?: number | Start recording from the provided stream |
stop() |
none | Stop recording |
All callbacks are optional but at minimum you should handle
on_chunk.
| Callback | Parameters | Description |
|---|---|---|
on_chunk |
(data: ArrayBuffer) | Called for each audio chunk (based on timeslice) |
on_stop |
none | Called when recording stops |
on_error |
(message: string) | Called on errors (e.g., microphone denied) |
on_level_change |
(level: number) | Called with audio level 0.0-1.0 for VU meter |
/api/ingest/stream
Connect to this endpoint to stream audio to the Squawk server as a broadcaster. The server expects a JSON authentication message followed by binary audio chunks.
/api/ingest/streamMust be sent immediately after connection. Replace with your actual broadcaster credentials.
{ "type": "auth", "broadcaster_id": "your_broadcaster_id", "api_key": "your_api_key" }
Signals the start of a broadcast. Keywords determine which listeners receive the audio.
{ "type": "stream_start", "keywords": ["asset:equities", "region:us"], "content_type": "audio/webm;codecs=opus" }
Signals the end of the broadcast.
{ "type": "stream_end" }
Keep the connection alive.
{ "type": "ping" }
After sending the stream_start message, send audio
chunks as binary ArrayBuffer messages. The server
accepts WebM/Opus format. Use the
MicrophoneRecorder class to handle recording and
chunking.
Authentication successful.
{ "type": "authenticated", "broadcaster_id": "your_broadcaster_id" }
Server acknowledges stream start.
{ "type": "stream_started", "session_id": "550e8400-e29b-41d4-a716-446655440000", "keywords": ["asset:equities"] }
Server acknowledges stream end.
{ "type": "stream_ended", "session_id": "550e8400-e29b-41d4-a716-446655440000" }
Sent when an error occurs.
{ "type": "error", "message": "Invalid authentication" }
This demo uses the BroadcastStream class to
record and stream to /api/ingest. Select
channels below, then start recording to broadcast.