Why WebRTC is different
WebRTC lets a browser place and receive calls with no plugin and no softphone install — the single biggest reduction in friction available in telephony. A support agent works from a browser tab; a customer clicks "call us" on a web page and is connected.
The catch is that WebRTC is not just SIP in a browser. It mandates things traditional SIP treats as optional, and those mandates are where every configuration attempt fails:
- Encryption is compulsory. Browsers will not do unencrypted media. DTLS-SRTP is required, not preferred.
- Signalling runs over WebSocket, not UDP.
- ICE is required for connectivity, rather than the ad-hoc NAT handling traditional SIP uses.
- The AVPF RTP profile is expected, not plain AVP.
Miss any one and the browser silently refuses to connect. There is rarely a helpful error.
The setting that does most of the work
Asterisk provides a shortcut that saves a great deal of trial and error. Setting webrtc=yes on a PJSIP endpoint enables rtcp_mux, use_avpf, ice_support and use_received_transport — the flags needed for basic WebRTC support — in one line.
It is worth knowing what each of those means, because when something breaks you are debugging them individually:
- rtcp_mux — multiplexes RTP and RTCP on a single port, which WebRTC expects.
- use_avpf — uses the AVP/AVPF/SAVP/SAVPF RTP profile family for media offers, including DTLS-SRTP streams.
- ice_support — enables ICE negotiation for NAT traversal.
- use_received_transport — responds on the transport the request arrived on.
Note also that webrtc=yes does more than shortcut those flags — it carries additional behaviour needed for proper SFU support, so prefer it over setting the individual options by hand.
A working endpoint
[transport-wss]
type=transport
protocol=wss
bind=0.0.0.0
[webrtc-user]
type=endpoint
transport=transport-wss
context=from-internal
disallow=all
allow=opus,ulaw
webrtc=yes
dtls_auto_generate_cert=yes
auth=webrtc-user
aors=webrtc-user
[webrtc-user]
type=auth
auth_type=userpass
username=webrtc-user
password=a-long-random-secret
[webrtc-user]
type=aor
max_contacts=5
remove_existing=yesPoints worth being deliberate about:
Use WSS, not WS. To use WSS as the transport rather than plain WS, the WebSocket URL must use the wss prefix and Asterisk's HTTP daemon must be configured for TLS. This is not merely good practice — browsers block insecure WebSocket connections from pages served over HTTPS, so a plain WS setup cannot work from a real site.
Offer Opus. It is what WebRTC is built around and what browsers do best. Keep ulaw as a fallback for legs that touch traditional telephony.
Raise max_contacts. Browser users open multiple tabs. With the default of 1, a second tab knocks the first offline and the user reports the system as unreliable.
Certificates: dtls_auto_generate_cert=yes is convenient for getting started. In production, use a real certificate — the same one serving your site is usually the right answer.
The HTTP server matters
WebRTC signalling arrives over Asterisk's built-in HTTP server, so it must be enabled with TLS in http.conf:
[general]
enabled = yes
bindaddr = 0.0.0.0
tlsenable = yes
tlsbindaddr = 0.0.0.0:8089
tlscertfile = /etc/asterisk/keys/asterisk.pemPort 8089 is the convention for the secure WebSocket. It must be open in the firewall, and the certificate must be one the browser trusts — a self-signed certificate produces a connection the browser rejects without a clear message, which is a frequent cause of "it just does not connect".
Where it goes wrong
- Browser will not connect at all. Nearly always TLS: an untrusted certificate, or WS where WSS is required. Check the browser console, which reports this far more clearly than Asterisk does.
- Registers but no audio. ICE or DTLS. Confirm
webrtc=yesis set, and that the RTP port range is open — WebRTC still needs those UDP ports. - Works on the LAN, fails externally. ICE cannot find a working path. A STUN server helps; behind symmetric NAT you may need TURN.
- Second tab kills the first.
max_contactstoo low. - One-way audio to PSTN legs. Codec mismatch — Opus on the browser side, G.711 on the trunk, with transcoding needed in between. Ensure both are permitted.
Getting started without writing a client
You do not need to build a browser client to test the server side. Asterisk's documentation includes tutorials using existing WebRTC clients — SIPML5 and CyberMegaPhone among them — which let you confirm the configuration works before investing in application code. Prove Asterisk is right first; debugging a new client against an unverified server is twice the work.
For production, a JavaScript SIP library gives you a maintainable base rather than implementing SIP over WebSocket yourself.
Frequently asked questions
What does webrtc=yes actually do?
It enables rtcp_mux, use_avpf, ice_support and use_received_transport — plus additional behaviour for SFU support — in a single setting.
Can I use plain WS instead of WSS?
Not realistically. Browsers block insecure WebSocket connections from pages served over HTTPS, so a production deployment needs WSS with Asterisk's HTTP daemon configured for TLS.
Why does the browser register but have no audio?
Usually ICE or DTLS. Verify webrtc=yes, ensure the RTP range is open, and add STUN for external users — WebRTC still needs a working media path.
Why does opening a second tab log out the first?
max_contacts on the AOR is too low. Browser users routinely have several tabs open; allow multiple contacts.