WebRTC Softphone Audio Failure on iOS Safari with STUN/TURN Config

Why is this setting causing the WebRTC softphone to fail audio negotiation on iOS Safari while working perfectly on Chrome and desktop clients? Our workforce management team has been pushing for better agent availability via mobile devices, especially for our Chicago-based agents who are frequently on the go between shifts or handling shift swaps. We have integrated the Genesys Cloud Web SDK (version 5.12.0) into our custom agent portal to allow agents to log in and take calls directly from their iPads and iPhones running iOS 17.4. The desktop experience is flawless, with crystal-clear audio and no latency issues. However, when agents attempt to connect via Safari on iOS, the call connects, the ringing is heard, but once answered, there is no two-way audio. The browser console throws a MediaStreamError: Could not start audio source followed by an ICE candidate gathering failed warning. We have verified that our STUN servers are reachable and our TURN servers are correctly configured with the proper credentials in the Genesys Cloud org settings. The getUserMedia permission is granted, yet the audio track remains null in the peer connection stats. We have tested this with multiple agents across different iOS devices, and the issue is consistent. The network trace shows that the initial SDP offer is sent, but the answer fails to include the audio m-line properly. We suspect this might be related to how Safari handles microphone access in the background or a specific permission scope issue with the Web SDK on iOS. We have also checked the agent’s device settings, and microphone access is enabled for Safari. Is there a specific configuration in the Genesys Cloud WebRTC settings or the SDK initialization that needs to be adjusted for iOS Safari? We are trying to avoid forcing agents to use the native mobile app, as the custom portal provides better visibility into their schedule adherence and shift trade status. Any insights into resolving this audio negotiation failure on iOS Safari would be greatly appreciated.

This is caused by iOS Safari enforcing strict STUN/TURN requirements that differ from Chrome. The Web SDK often defaults to a configuration that works on desktop but fails on iOS if the TURN credentials are not explicitly provided or if the STUN server is unreachable from the mobile network. Check the mediaConfiguration object in your SDK initialization.

const config = {
 mediaConfiguration: {
 iceServers: [
 { urls: 'stun:stun.l.google.com:19302' },
 { 
 urls: 'turn:your-turn-server.com',
 username: 'user',
 credential: 'pass'
 }
 ]
 }
};

Ensure the TURN server allows the specific IP ranges used by your agents’ mobile data connections. Also verify that the iceTransportPolicy is set to all rather than relay unless strictly required by your network firewall.

If you check the docs, they mention that iOS Safari handles ICE candidates differently than Chrome, often dropping connections if the TURN server isn’t explicitly configured with correct credentials. Here are some adjustments based on load testing patterns:

  • Ensure mediaConfiguration.iceServers includes a valid TURN server with username and credential. iOS is strict about this.
  • Set mediaConfiguration.iceTransportPolicy to all to force fallback if STUN fails.
  • Verify the TURN server allows traffic from mobile IPs. Corporate firewalls often block UDP on port 3478.
  • Check SDK logs for iceCandidateErrorEvent. This usually points to auth failures.

We saw similar issues during concurrent call volume spikes. The fix was adding explicit TURN config. Test with JMeter to simulate multiple agents joining simultaneously. This helps identify if the issue is scale-related. Also, ensure the Web SDK version supports the latest ICE standards. Older versions may have bugs.

The quickest way to solve this is…

Ensure the TURN server credentials are rotated within the Genesys Cloud instance before being passed to the SDK. iOS Safari caches ICE candidates aggressively, so stale credentials in the mediaConfiguration object cause immediate negotiation failures.

Verify the iceTransportPolicy is explicitly set to relay rather than all to force the use of the TURN server.