First prove whether an INVITE reached the application
Capture one authorized inbound attempt with timestamp and timezone, browser and operating-system versions, application and SIP.js build, page origin and visibility, WSS state, registration identity and expiry, protected calling and called identities, Call-ID and the first application event. SIP.js passes a received INVITE to the UserAgent delegate's onInvite handler as an Invitation.
If no onInvite occurs, follow WSS, registration, proxy routing and page lifecycle instead of changing ringtone code. A connected WebSocket or earlier successful REGISTER does not prove that the current contact remained selected or that the page was running when the call arrived.
Separate visible alert state from audible ringing
When onInvite occurs, preserve the invitation identity, current session state, application state transition, displayed caller-safe label, accept and reject controls and the ringtone request. The call can be actionable even when sound is blocked. Always keep an accessible visible alert and explicit answer or reject control rather than relying on audio as the only notification.
Do not auto-answer as a ringtone workaround. A visible incoming-call panel proves only application handling; it does not prove that the browser accepted playback, that the intended output device was selected or that the caller received ringback.
Handle the ringtone playback result
HTMLMediaElement.play() returns a promise and can reject with NotAllowedError when policy blocks script-initiated playback. Record the promise outcome and error name. Chrome documents audible autoplay as conditional on user interaction, engagement, installation or delegated permission; WebKit likewise keeps a user-gesture boundary for media with sound. These browser-specific policies must not be flattened into one universal rule.
Provide an explicit user action that initializes or resumes calling audio before relying on unattended sound. If Web Audio is used, record the AudioContext.state; a context created before user interaction can be suspended and requires resume() after the gesture. A fulfilled play or resume promise proves start, not audibility or correct output routing.
Keep page visibility and page existence distinct
Record document.visibilityState and its changes. A hidden document can indicate a background tab, minimized window or locked screen, but hidden does not mean closed, and visible does not prove SIP reachability. Browser scheduling, suspension and operating-system lifecycle can change while the server still retains an older registration contact.
SIP.js documents Chrome and Firefox on Android as compatible with SIP.js web applications; that foreground compatibility statement does not establish background wake-up, push delivery, locked-screen ringing or closed-page reachability. Define a fallback route for states the web application cannot own.
Treat answer and remote conversation audio as later media
After the user answers, follow Invitation acceptance and session state. SIP.js leaves much media handling to the application and documents attaching receiver tracks when the session becomes Established. The ringtone element, call-control state and remote conversation element are separate resources and should have independent cleanup.
Capture the offer and answer, receiver track, MediaStream attachment, remote element play result, selected input and output, RTP and decoded audio. A ringtone that worked does not prove remote audio; an established SIP session does not prove that the remote media element played.
Retest bounded policy and lifecycle cases
Retest a foreground call after an explicit user interaction, a fresh navigation with no prior interaction, a background-tab case, permission or policy rejection, answer, reject, caller cancellation and hangup cleanup. Include the supported browser and deployment policy matrix, but do not use developer flags or relaxed enterprise policy as production evidence unless that exact managed configuration is the approved design.
Remove temporary logs and protected identifiers, restore normal routing and keep the wrong-audio-device diagnostic for post-answer output faults. No browser, application, device, policy, PBX or call was validated for this diagnostic.
Sources & applicability
Primary references for the technical details above. Operational examples and planning checklists are VoIP.info editorial guidance.
- SIP.js receive-a-call guide ↗
- SIP.js user-agent and registration guide ↗
- SIP.js remote-media attachment guide ↗
- SIP.js mobile guide ↗
- MDN HTMLMediaElement play method ↗
- MDN autoplay guide for media and Web Audio ↗
- MDN AudioContext resume method ↗
- MDN document visibility state ↗
- Chrome autoplay policy ↗
- WebKit media autoplay policy ↗
Examples require adaptation to your topology. No live PBX or hardware testing is claimed.