The server
Node.js 18 or later:npm install express.
server.mjs
endUserId, so Pearl remembers them and their calls are grouped in the call history.
The page
public/index.html
public/app.js
The audio
An AudioWorklet runs in real time, which gives the pacing the protocol asks for without any timer: it sends one 20 ms frame of the microphone every 20 ms, silence included when the end user is muted, and plays Pearl’s frames once 80 ms are buffered.public/pearl-audio.js
Run it
http://localhost:3000, click Talk to Pearl and allow the microphone.
- Browsers allow the microphone only on
https://pages and onlocalhost. AudioContext({ sampleRate: 24000 })makes the browser resample the microphone to 24 kHz. Chrome, Edge and Safari do this; check your other target browsers.- On a laptop, test with headphones: browser echo cancellation does not always cover audio played through Web Audio, and Pearl would hear itself.
Going further
- Phone quality: with
audioFormat: "ulaw_8000", create the context at 8000 Hz, use 160-sample frames, and encode and decode μ-law in the worklet. HD needs no codec at all, which is why this page uses it. - Hang-up button:
hangupis answered byended, then the socket closes andonclosereleases the microphone. - Transfers: a
transferevent carries the target set on your Pearl’s Transfer Call node. In a browser there is usually no phone line to pass on, so show the end user the next step instead, or let your server act on it.
Stream Call
Every message, audio format, event and limit.

