Knowledgebase › WebRTC softphones with FreePBX — sipml5/JsSIP, Asterisk WSS, common breakages

WebRTC softphones with FreePBX — sipml5/JsSIP, Asterisk WSS, common breakages

WebRTC lets a browser act as a SIP phone — no client install, no extension provisioning, just open a URL. FreePBX® supports this through Asterisk's WebSocket transport. This article covers the FreePBX-side setup, a sane choice of JavaScript SIP library, and the four problems that account for most "the browser phone doesn't work" tickets.

Architecture

WebRTC SIP over the browser uses:

  • SIP signaling over WebSocket Secure (WSS). SIP is wrapped in a WS frame and travels over TLS to Asterisk's HTTPS endpoint.
  • Media over SRTP. Browsers refuse plain RTP — SRTP is mandatory.
  • ICE for NAT traversal. Browser, STUN, TURN (if configured) negotiate audio path.
  • Opus codec — mandatory in WebRTC. Make sure Asterisk supports it (most modern distros do).

Asterisk-side configuration

In FreePBX:

  • Settings → Advanced Settings → HTTPS Enabled = Yes.
  • Settings → Asterisk SIP Settings → enable WebSocket.
  • Verify HTTPS port (default 8089) is reachable.

The HTTPS endpoint needs a valid TLS cert. Reuse the PBX's Let's Encrypt cert. Self-signed will work but browsers refuse self-signed for WSS from any page that's not also served from the same self-signed host.

For the WebRTC extension specifically:

  • Extension → Advanced tab:
  • Transport: WSS (or "All" if you want fallback).
  • Force AVP: No (let it negotiate SRTP).
  • Media Encryption: SRTP (DTLS).
  • Add Opus to the codecs.

STUN and TURN

  • STUN alone works for endpoints behind the standard cone NAT (most home routers). Asterisk needs a STUN server reference; a public one is fine: stun.l.google.com:19302.
  • TURN is needed for symmetric NAT or strict corporate firewalls that block direct UDP. Run coturn alongside FreePBX or use a hosted TURN service.

Without TURN, WebRTC calls from restrictive networks fail with media but no audio. With TURN, audio relays through your TURN server (extra bandwidth on the server) and works everywhere.

The browser side — pick a library

Two reasonable choices:

JsSIP

Modern, maintained, used in production by several commercial softphones. Browser code:

const socket = new JsSIP.WebSocketInterface('wss://pbx.example.com:8089/ws');
const ua = new JsSIP.UA({
    sockets: [socket],
    uri: 'sip:1001@pbx.example.com',
    password: 'extension-password',
});
ua.start();

// Make a call
ua.call('sip:1002@pbx.example.com', {
    mediaConstraints: { audio: true, video: false },
});

sipml5

Older, simpler API. Less maintained. Works fine for basic softphone use but lacks WebRTC features that have become standard.

For a new project: JsSIP. For an existing sipml5 codebase: keep it if it works.

The four common breakages

1. "Browser console shows mixed content"

You served the WebRTC page over HTTP but the WSS endpoint is HTTPS. Browser refuses to mix. Serve your page over HTTPS too.

2. "WebSocket connection failed — certificate error"

Your Asterisk HTTPS endpoint is using a self-signed or otherwise-untrusted cert. Browsers refuse WSS to untrusted servers without explicit user override.

Fix: use the same Let's Encrypt cert FreePBX uses for its admin GUI. Asterisk's HTTPS endpoint takes its cert config separately from FreePBX's web GUI; copy or symlink the cert files into /etc/asterisk/keys/ with the right permissions.

3. "Call connects but no audio"

Almost always one of:

  • STUN/TURN not configured — symmetric NAT can't negotiate direct media.
  • Codec mismatch — extension or trunk doesn't list Opus and the browser can't negotiate to G.711 (some browsers will, some won't — depends on which WebRTC implementation).
  • SRTP not enabled on the extension.

4. "Audio works for 30 seconds then drops"

NAT pinhole closing on the audio path. Configure RTP keepalive (see SIP trunk drops every 30 min) and enable TURN if you don't already.

Diagnosing from the browser

Chrome's chrome://webrtc-internals shows:

  • ICE candidate gathering — which interfaces and TURN servers the browser considered.
  • Selected candidate pair — which path got used for media.
  • RTP statistics — packets sent/received, jitter, packet loss.

If "selected candidate pair" never resolves, you have a NAT/firewall problem.

Diagnosing from Asterisk

asterisk -rvvv
pjsip set logger on
http show status

WebSocket connection from the browser appears in pjsip log as Transport <name> created (WSS, ...). Subsequent SIP messages flow through it as normal.

Production considerations

  • Don't use the FreePBX UCP's built-in softphone as a primary phone. It's adequate for occasional use but not robust enough for daily front-line work.
  • Plan for TURN bandwidth. If you have many WebRTC users on restricted networks, all their audio relays through your TURN — that adds up.
  • Browser permissions persist per origin. Once a user grants mic access to your WebRTC page, the browser remembers. Don't host your softphone on a domain you'd rather customers not bookmark.

Also Read

« « Back

Powered by WHMCompleteSolution