Build Live Captions with Speechall WebSockets

November 3, 2026

In this article

Loading table of contents...

Build a small live caption screen using a browser microphone, a local Node.js relay and Speechall’s WebSocket endpoint. The example keeps your API key out of browser code and sends the raw PCM format used by Speechall’s streaming guide.

The result displays the latest transcription text while you speak. It is a starting point for live interfaces; it does not promise a complete saved transcript, final-segment detection or subtitle timestamps.

How audio reaches Speechall

The browser captures microphone audio with Web Audio. An AudioWorklet converts samples into mono, signed 16-bit little-endian PCM at 16 kHz, batching 100 milliseconds per binary message. A loopback relay forwards those messages to wss://api.speechall.com/v1/transcribe with a bearer token held in its environment. Responses travel back to the page.

This avoids placing a shared API key in browser JavaScript or a browser-visible upstream URL. The example’s relay accepts only its exact local origin and binds to 127.0.0.1. A public application also needs user authentication, authorization, usage limits and deployment-specific origin validation.

Run the example locally

You need Node.js 22 or newer, a modern browser with AudioWorklet support, a microphone, and a Speechall API key with available credit. Actual streaming sessions send audio to Speechall and may incur usage charges.

Get the complete example from the website repository. From the checkout, run:

cd examples/live-captions
npm install
export SPEECHALL_API_KEY='your-key'
npm start

Open http://127.0.0.1:8787 exactly as printed by the server. Click Start, grant microphone permission and speak. The page displays the latest text result. Click Stop to release the microphone and close both connections. The relay also bounds each demo session to ten minutes; this is an example safeguard, not an API quota.

The default model is assemblyai.universal-3-5-pro, with English and JSON output. To choose a different model, set SPEECHALL_MODEL before starting the server, after checking the model catalogue for streaming support and the model’s audio/language requirements. File transcription support alone does not establish streaming support.

Understand the three files

live-captions-server.mjs serves the page and worklet, checks the local WebSocket origin, and opens the authenticated upstream connection. It sends a local ready message only after Speechall’s connection opens, so capture does not start forwarding before the upstream socket is ready.

live-captions-worklet.js converts float audio samples into little-endian PCM bytes. It sends 1,600 samples per message. This batching choice balances message frequency and buffering for the demo; it is not a guaranteed latency figure or required API packet size.

live-captions.html owns the Start/Stop controls, microphone permission and cleanup. It checks the AudioContext’s actual rate rather than trusting microphone constraints. If the browser cannot supply a 16 kHz context, the page fails clearly. Web Audio converts the microphone’s native rate into the context rate.

The worklet avoids the deprecated ScriptProcessorNode approach. It also avoids MediaRecorder: the browser’s default WebM/Opus recording output is not interchangeable with raw PCM binary frames.

Read results conservatively

Speechall’s existing streaming playground reads text from JSON results. This example follows that behavior and replaces the latest caption instead of appending every response. Appending repeated or revised text can duplicate words.

The published API schema does not define a portable WebSocket interim/final event contract or end-of-audio command. Do not copy a provider-specific finalization message into the unified endpoint without confirming it is supported. The relay’s ready, transcript and error envelopes belong to this local example; they are not Speechall event names.

For the same reason, this example does not generate SRT or VTT files. A reliable subtitle exporter needs confirmed final segments and timing semantics. For a complete transcript of a recorded asset, use file transcription.

Handle stop and failure deliberately

Stopping disconnects the audio node, stops microphone tracks, closes the AudioContext and closes the browser socket. The relay then closes its upstream socket. Errors and unexpected closes trigger the same browser cleanup. If either connection accumulates over one megabyte of queued audio, the demo ends the session so a slow network cannot grow an unlimited backlog.

A normal socket close is not a documented flush operation. Stopping can discard the last partial audio batch or a pending transcription response. Keep that limit visible when adapting the demo to your product.

Restart manually after resolving an error. Automatic reconnection needs an explicit policy for audio gaps, duplicate results and extra usage. This demo does not replay audio or hide a failed session behind a retry loop.

Frequently asked questions

Why does microphone access fail?

Check browser permissions and whether another application holds the device. Use the exact loopback URL shown by the example. Outside localhost, microphone capture generally requires HTTPS, and a deployed application should use secure WebSockets.

Why does the socket fail before I see text?

Confirm that the local server is running, the API key is valid, the account has credit and the chosen model supports streaming. The browser error event often lacks detailed upstream authentication information. The relay reports a general upstream failure without printing the key.

Can I use another provider or language?

Speechall offers multiple models, but availability and supported features vary. Check the models and streaming documentation before changing the model, language or audio encoding. The demo deliberately uses one model and English rather than claiming universal compatibility.

Can I deploy the local relay unchanged?

The relay is designed for one local user. Add authenticated sessions, per-user permissions and spending controls before exposing an upstream key through a public service. Configure TLS, origin validation and operational limits for your hosting environment.

Try your first caption session

Create your Speechall API key, run the example and compare its results with the playground. Keep the WebSocket reference nearby for audio constraints, authentication and lifecycle details.