Use SDK preflight checks to inspect browser prerequisites, then collect call statistics when an actual call has a WebRTC peer connection. These answer different questions: a reachable signaling server does not prove that audio flows, and a statistics sample does not explain every possible audio problem.
This guide is for developers supporting SDK 1.4.2 integrations. Use an existing authorized phone instance. Ask the user before requesting microphone access, and keep diagnostic output private. Preflight can access the microphone briefly and opens a WebSocket reachability probe; it is not a passive screenshot of settings.
1. Record the context before changing anything
Record the SDK version, browser/version, selected region, time and user-observed symptom. Distinguish inability to obtain authorization, failed connection, failed registration, no incoming ringing and one-way or poor audio. Avoid treating all of them as “WebRTC broken.”
Keep account credentials, bootstrap responses and browser tokens out of logs. An error after key rotation deserves a credential investigation; missing incoming routing is a separate issue from microphone permission.
2. Run preflight through an explicit diagnostic action
async function preflightSummary(phone) {
const result = await phone.runPreflight({
checkMedia: true,
enumerateDevices: true,
checkWebSocket: true,
timeoutMs: 5000
});
return {
ok: result.ok,
checkedAt: result.timestamp,
checks: Object.fromEntries(
Object.entries(result.checks).map(([name, check]) => [
name, { ok: check.ok === true, code: check.code }
])
)
};
}Call this from your diagnostic button and display a handled error if the operation rejects. The summary deliberately excludes device names/IDs, account identity and connection credentials. Do not simply serialize the entire bootstrap or diagnostic object into a public support form.
Media checks establish whether microphone access can be obtained, not whether the microphone captures the intended speaker at a useful level. Device enumeration describes available device information, which the browser may restrict. The WebSocket check tests reachability, not successful SIP authentication.
The TURN check in this SDK verifies that ICE-server entries are configured. It does not establish a successful TURN allocation or a working relay path. If a check was disabled or no applicable server was available, inspect which checks actually ran; do not interpret a missing check as a pass.
3. Collect a bounded sample from the exact active call
async function callStatsSummary(phone, callId) {
const stats = await phone.getCallStats(callId);
return {
sampledAt: stats.generatedAt,
connectionState: stats.connectionState,
iceConnectionState: stats.iceConnectionState,
inbound: stats.inboundAudio && {
packetsReceived: stats.inboundAudio.packetsReceived,
packetsLost: stats.inboundAudio.packetsLost,
jitterSeconds: stats.inboundAudio.jitter
},
outbound: stats.outboundAudio && {
packetsSent: stats.outboundAudio.packetsSent
}
};
}Supply the call ID from the current SDK call object, not a public historical call reference or Voice API control ID. Handle call_not_found, stats_unavailable and stats_failed without creating another call. A call may end between your state check and the statistics request.
Take a small number of time-separated samples through a bounded diagnostic workflow. Cancel sampling when the call ends or the UI is disposed. Avoid an unbounded interval or overlapping requests when one statistics call is slow.
4. Interpret the fields cautiously
Compare packet counters across samples rather than treating a cumulative packet-loss count as a current percentage. Jitter is reported in seconds; if your display uses milliseconds, convert it explicitly. Null audio entries mean the summary has no corresponding audio record, not necessarily that the network has zero traffic.
The SDK summary normalizes some missing numeric values to zero. Zero is therefore not always a measured ideal value. The selected-candidate summary is a simplified view of browser statistics, not an authoritative diagnosis of every route used during the call.
If outbound counters increase but the other party hears nothing, check mute, input device and remote-path evidence. If inbound counters increase but the user hears nothing, investigate output selection, local hold and playback restrictions. Those observations narrow the investigation; they do not establish a single cause.
5. Share only the evidence Support needs
Provide the sanitized check codes, time, SDK/browser version, symptom and bounded counter samples. Candidate addresses and device identifiers can reveal private network or device information; the example intentionally omits them. Do not include an API key, token, SIP password or full bootstrap response.
A separately authorized live call is needed to verify actual audio. Local fixtures can confirm the redaction and rendering logic without a paid call. For repeatable acceptance, compare the same supported browser and device under a controlled scenario instead of changing several settings at once.
Related guides and reference
- Troubleshoot the webphone
- Diagnose choppy IllyVoIP calls: jitter, packet loss and network load
- Add microphone and speaker selection to the IllyVoIP WebRTC SDK
- SDK diagnostics and call statistics
Reviewed 10 October 2026 against the current IllyVoIP reference and implementation. SDK examples target version 1.4.2 where applicable. Local example checks do not certify a completed live call, routing change or third-party integration.