User Facing Diagnostics

When working with calls in Azure Communication Services, you may encounter issues that affect your customers. To help with this, Azure Communication Services provides a feature called "User Facing Diagnostics" (UFD) that can be used to examine various properties of a call to determine what the issue might be. User Facing Diagnostics are events that are fired off that could indicate due to some underlying issue (poor network, user has their microphone muted) that a user might have a poor experience. After a User Facing Diagnostic is fired, you should consider giving feedback to an end-user that they might be having some underlying issue. However, the User Facing Diagnostic output is informational only, and the calling stack does not make any changes based on a User Facing Diagnostic being fired.

Diagnostic values

The following user-facing diagnostics are available:

Network values

Name Description Possible values Use cases Mitigation steps
noNetwork There's no network available. - Set to True when a call fails to start because there's no network available.
- Set to False when there are ICE candidates present.
Device isn't connected to a network. Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network optimization section.
networkRelaysNotReachable Problems with a network. - Set to True when the network has some constraint that isn't allowing you to reach Azure Communication Services relays.
- Set to False upon making a new call.
During a call when the WiFi signal goes on and off. Ensure that firewall rules and network routing allow client to reach Microsoft turn servers. For more information, see the Firewall configuration section.
networkReconnect The connection was lost and we are reconnecting to the network. - Set toBad when the network is disconnected
- Set to Poorwhen the media transport connectivity is lost
- Set to Good when a new session is connected.
Low bandwidth, no internet Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section.
networkReceiveQuality An indicator regarding incoming stream quality. - Set toBad when there's a severe problem with receiving the stream.
- Set to Poor when there's a mild problem with receiving the stream.
- Set to Good when there's no problem with receiving the stream.
Low bandwidth Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section. Suggest that the end user turn off their camera to conserve available internet bandwidth.
networkSendQuality An indicator regarding outgoing stream quality. - Set toBad when there's a severe problem with sending the stream.
- Set to Poor when there's a mild problem with sending the stream.
- Set to Good when there's no problem with sending the stream.
Low bandwidth Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section. Also, suggest that the end user turn off their camera to conserve available internet bandwidth.

Audio values

Name Description Possible values Use cases Mitigation steps
noSpeakerDevicesEnumerated there's no audio output device (speaker) on the user's system. - Set to True when there are no speaker devices on the system, and speaker selection is supported.
- Set to False when there's a least one speaker device on the system, and speaker selection is supported.
All speakers are unplugged When value set to True, consider giving visual notification to end user that their current call session doesn't have any speakers available.
speakingWhileMicrophoneIsMuted Speaking while being on mute. - Set to True when local microphone is muted and the local user is speaking.
- Set to False when local user either stops speaking, or unmutes the microphone.
* Note: Currently, this option isn't supported on Safari because the audio level samples are taken from WebRTC stats.
During a call, mute your microphone and speak into it. When value set to True consider giving visual notification to end user that they might be talking and not realizing that their audio is muted.
noMicrophoneDevicesEnumerated No audio capture devices (microphone) on the user's system - Set to True when there are no microphone devices on the system.
- Set to False when there's at least one microphone device on the system.
All microphones are unplugged during the call. When value set to True consider giving visual notification to end user that their current call session doesn't have a microphone. For more information, see enable microphone from device manger section.
microphoneNotFunctioning Microphone isn't functioning. - Set to True when we fail to start sending local audio stream because the microphone device may have been disabled in the system or it is being used by another process. This UFD takes about 10 seconds to get raised.
- Set to False when microphone starts to successfully send audio stream again.
No microphones available, microphone access disabled in a system When value set to True give visual notification to end user that there's a problem with their microphone.
microphoneMuteUnexpectedly Microphone is muted - Set to True when microphone enters muted state unexpectedly.
- Set to False when microphone starts to successfully send audio stream
Microphone is muted from the system. Most cases happen when user is on an Azure Communication Services call on a mobile device and a phone call comes in. In most cases, the operating system mutes the Azure Communication Services call so a user can answer the phone call. When value is set to True, give visual notification to end user that their call was muted because a phone call came in. For more information, see how to best handle OS muting an Azure Communication Services call section for more details.
microphonePermissionDenied there's low volume from device or it’s almost silent on macOS. - Set to True when audio permission is denied from the system settings (audio).
- Set to False on successful stream acquisition.
Note: This diagnostic only works on macOS.
Microphone permissions are disabled in the Settings. When value is set to True, give visual notification to end user that they did not enable permission to use microphone for an Azure Communication Services call.

Camera values

Name Description Possible values Use cases Mitigation steps
cameraFreeze Camera stops producing frames for more than 5 seconds. - Set to True when the local video stream is frozen. This diagnostic means that the remote side is seeing your video frozen on their screen or it means that the remote participants are not rendering your video on their screen.
- Set to False when the freeze ends and users can see your video as per normal.
The Camera was lost during the call or bad network caused the camera to freeze. When value is set to True, consider giving notification to end user that the remote participant network might be bad - possibly suggest that they turn off their camera to conserve bandwidth. For more information, see Network bandwidth requirement section on needed internet abilities for an Azure Communication Services call.
cameraStartFailed Generic camera failure. - Set to True when we fail to start sending local video because the camera device may have been disabled in the system or it is being used by another process~.
- Set to False when selected camera device successfully sends local video again.
Camera failures When value is set to True, give visual notification to end user that their camera failed to start.
cameraStartTimedOut Common scenario where camera is in bad state. - Set to True when camera device times out to start sending video stream.
- Set to False when selected camera device successfully sends local video again.
Camera failures When value is set to True, give visual notification to end user that their camera is possibly having problems. (When value is set back to False remove notification).
cameraPermissionDenied Camera permissions were denied in settings. - Set to True when camera permission is denied from the system settings (video).
- Set to False on successful stream acquisition.
Note: This diagnostic only works on macOS Chrome.
Camera permissions are disabled in the settings. When value is set to True, give visual notification to end user that they did not enable permission to use camera for an Azure Communication Services call.
cameraStoppedUnexpectedly Camera malfunction - Set to True when camera enters stopped state unexpectedly.
- Set to False when camera starts to successfully send video stream again.
Check camera is functioning correctly. When value is set to True, give visual notification to end user that their camera is possibly having problems. (When value is set back to False remove notification).

Misc values

Name Description Possible values Use cases Mitigation Steps
screenshareRecordingDisabled System screen sharing was denied from the preferences in Settings. - Set to True when screen sharing permission is denied from the system settings (sharing).
- Set to False on successful stream acquisition.
Note: This diagnostic only works on macOS.Chrome.
Screen recording is disabled in Settings. When value is set to True, give visual notification to end user that they did not enable permission to share their screen for an Azure Communication Services call.
capturerStartFailed System screen sharing failed. - Set to True when we fail to start capturing the screen.
- Set to False when capturing the screen can start successfully.
When value is set to True, give visual notification to end user that there was possibly a problem sharing their screen. (When value is set back to False, remove notification).
capturerStoppedUnexpectedly System screen sharing malfunction - Set to True when screen capturer enters stopped state unexpectedly.
- Set to False when screen capturer starts to successfully capture again.
Check screen sharing is functioning correctly When value is set to True, give visual notification to end user that there possibly a problem that causes sharing their screen to stop. (When value is set back to False remove notification).

Accessing diagnostics

User-facing diagnostics is an extended feature of the core Call API and allows you to diagnose an active call.

const userFacingDiagnostics = call.feature(Features.UserFacingDiagnostics);

User Facing Diagnostic events

  • Subscribe to the diagnosticChanged event to monitor when any user-facing diagnostic changes.
/**
 *  Each diagnostic has the following data:
 * - diagnostic is the type of diagnostic, e.g. NetworkSendQuality, DeviceSpeakWhileMuted, etc...
 * - value is DiagnosticQuality or DiagnosticFlag:
 *     - DiagnosticQuality = enum { Good = 1, Poor = 2, Bad = 3 }.
 *     - DiagnosticFlag = true | false.
 * - valueType = 'DiagnosticQuality' | 'DiagnosticFlag'
 */
const diagnosticChangedListener = (diagnosticInfo: NetworkDiagnosticChangedEventArgs | MediaDiagnosticChangedEventArgs) => {
    console.log(`Diagnostic changed: ` +
        `Diagnostic: ${diagnosticInfo.diagnostic}` +
        `Value: ${diagnosticInfo.value}` +
        `Value type: ${diagnosticInfo.valueType}`);

    if (diagnosticInfo.valueType === 'DiagnosticQuality') {
        if (diagnosticInfo.value === DiagnosticQuality.Bad) {
            console.error(`${diagnosticInfo.diagnostic} is bad quality`);

        } else if (diagnosticInfo.value === DiagnosticQuality.Poor) {
            console.error(`${diagnosticInfo.diagnostic} is poor quality`);
        }

    } else if (diagnosticInfo.valueType === 'DiagnosticFlag') {
        if (diagnosticInfo.value === true) {
            console.error(`${diagnosticInfo.diagnostic}`);
        }
    }
};

userFacingDiagnostics.network.on('diagnosticChanged', diagnosticChangedListener);
userFacingDiagnostics.media.on('diagnosticChanged', diagnosticChangedListener);

Get the latest User Facing Diagnostics

  • Get the latest diagnostic values that were raised. If a diagnostic is undefined, that is because it was never raised.
const latestNetworkDiagnostics = userFacingDiagnostics.network.getLatest();

console.log(
  `noNetwork: ${latestNetworkDiagnostics.noNetwork.value}, ` +
    `value type = ${latestNetworkDiagnostics.noNetwork.valueType}`
);

console.log(
  `networkReconnect: ${latestNetworkDiagnostics.networkReconnect.value}, ` +
    `value type = ${latestNetworkDiagnostics.networkReconnect.valueType}`
);

console.log(
  `networkReceiveQuality: ${latestNetworkDiagnostics.networkReceiveQuality.value}, ` +
    `value type = ${latestNetworkDiagnostics.networkReceiveQuality.valueType}`
);

const latestMediaDiagnostics = userFacingDiagnostics.media.getLatest();

console.log(
  `speakingWhileMicrophoneIsMuted: ${latestMediaDiagnostics.speakingWhileMicrophoneIsMuted.value}, ` +
    `value type = ${latestMediaDiagnostics.speakingWhileMicrophoneIsMuted.valueType}`
);

console.log(
  `cameraStartFailed: ${latestMediaDiagnostics.cameraStartFailed.value}, ` +
    `value type = ${latestMediaDiagnostics.cameraStartFailed.valueType}`
);

console.log(
  `microphoneNotFunctioning: ${latestMediaDiagnostics.microphoneNotFunctioning.value}, ` +
    `value type = ${latestMediaDiagnostics.microphoneNotFunctioning.valueType}`
);

Diagnostic values

The following user-facing diagnostics are available:

Network values

Name Description Possible values Use cases Mitigation steps
networkUnavailable There's no network available. - Set to True when a call fails to start because there's no network available.
- Set to False when there are ICE candidates present.
Device isn't connected to a network. Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network optimization section.
networkRelaysUnreachable Problems with a network. - Set to True when the network has some constraint that isn't allowing you to reach Azure Communication Services relays.
- Set to False upon making a new call.
During a call when the WiFi signal goes on and off. Ensure that firewall rules and network routing allow client to reach Microsoft turn servers. For more information, see the Firewall configuration section.
networkReconnectionQuality The connection was lost and we're reconnecting to the network. - Set toBad when the network is disconnected
- Set to Poorwhen the media transport connectivity is lost
- Set to Good when a new session is connected.
Low bandwidth, no internet Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section.
networkReceiveQuality An indicator regarding incoming stream quality. - Set toBad when there's a severe problem with receiving the stream.
- Set to Poor when there's a mild problem with receiving the stream.
- Set to Good when there's no problem with receiving the stream.
- It's only visible if there's an active audio flow in the call, which means a participant is actively speaking for period of time.
Low bandwidth Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section. Suggest that the end user turn-off their camera to conserve available internet bandwidth.
networkSendQuality An indicator regarding outgoing stream quality. - Set toBad when there's a severe problem with sending the stream.
- Set to Poor when there's a mild problem with sending the stream.
- Set to Good when there's no problem with sending the stream.
- Similar to receive quality diagnostic it's only visible if there's an active audio flow in the call, which means a participant is actively speaking for period of time. But, it only works in a 1:1 call as it relies on information from the other side in order to verify quality. Where the other side has to signal the data that was received.
Low bandwidth Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section. Also, suggest that the end user turn-off their camera to conserve available internet bandwidth.

Audio values

Name Description Possible values Use cases Mitigation steps
noSpeakerDevicesAvailable there's no audio output device (speaker) on the user's system. - Set to True when there are no speaker devices on the system, and speaker selection is supported.
- Set to False when there's a least one speaker device on the system, and speaker selection is supported.
All speakers are unplugged When value set to True, consider giving visual notification to end user that their current call session doesn't have any speakers available.
speakingWhileMicrophoneIsMuted Speaking while being on mute. - Set to True when local microphone is muted and the local user is speaking.
- Set to False when local user either stops speaking, or unmutes the microphone.
- This diagnostic event can be automatically disabled if it is triggered for a certain amount of times without any user action to avoid noise and provide a better user experience. It will be re-enabled again when a new mute action occurs.
During a call, mute your microphone and speak into it. When value set to True consider giving visual notification to end user that they might be talking and not realizing that their audio is muted.
noMicrophoneDevicesAvailable No audio capture devices (microphone) on the user's system - Set to True when there are no microphone devices on the system.
- Set to False when there's at least one microphone device on the system.
All microphones are unplugged during the call. When value set to True consider giving visual notification to end user that their current call session doesn't have a microphone. For more information, see enable microphone from device manger section.
microphoneNotFunctioning Microphone isn't functioning. - Set to True when we fail to start sending local audio stream because the microphone device may have been disabled in the system or it's being used by another process. This UFD takes about 10 seconds to get raised.
- Set to False when microphone starts to successfully send audio stream again.
No microphones available, microphone access disabled in a system When value set to True give visual notification to end user that there's a problem with their microphone.
microphoneMuteUnexpectedly Microphone is muted - Set to True when microphone enters muted state unexpectedly.
- Set to False when microphone starts to successfully send audio stream
Microphone is muted from the system. Most cases happen when user is on an Azure Communication Services call on a mobile device and a phone call comes in. In most cases, the operating system mutes the Azure Communication Services call so a user can answer the phone call. When value is set to True, give visual notification to end user that their call was muted because a phone call came in. For more information, see how to best handle OS muting an Azure Communication Services call section for more details.
microphonePermissionDenied there's low volume from device or it’s almost silent on macOS. - Set to True when audio permission is denied from the system settings (audio).
- Set to False on successful stream acquisition.
Note: This diagnostic only works on macOS.
Microphone permissions are disabled in the Settings. When value is set to True, give visual notification to end user that they didn't enable permission to use microphone for an Azure Communication Services call.

Camera values

Name Description Possible values Use cases Mitigation steps
cameraFrozen Camera stops producing frames for more than 5 seconds. - Set to True when the local video stream is frozen. This diagnostic means that the remote side is seeing your video frozen on their screen or it means that the remote participants aren't rendering your video on their screen.
- Set to False when the freeze ends and users can see your video as per normal.
The Camera was lost during the call or bad network caused the camera to freeze. When value is set to True, consider giving notification to end user that the remote participant network might be bad - possibly suggest that they turn off their camera to conserve bandwidth. For more information, see Network bandwidth requirement section on needed internet abilities for an Azure Communication Services call.
cameraStartFailed Generic camera failure. - Set to True when we fail to start sending local video because the camera device may have been disabled in the system or it's being used by another process~.
- Set to False when selected camera device successfully sends local video again.
Camera failures When value is set to True, give visual notification to end user that their camera failed to start.
cameraStartTimedOut Common scenario where camera is in bad state. - Set to True when camera device times out to start sending video stream.
- Set to False when selected camera device successfully sends local video again.
Camera failures When value is set to True, give visual notification to end user that their camera is possibly having problems. (When value is set back to False remove notification).
cameraPermissionDenied Camera permissions were denied in settings. - Set to True when camera permission is denied from the system settings (video).
- Set to False on successful stream acquisition.
Note: This diagnostic only works on macOS Chrome.
Camera permissions are disabled in the settings. When value is set to True, give visual notification to end user that they didn't enable permission to use camera for an Azure Communication Services call.
cameraStoppedUnexpectedly Camera malfunction - Set to True when camera enters stopped state unexpectedly.
- Set to False when camera starts to successfully send video stream again.
Check camera is functioning correctly. When value is set to True, give visual notification to end user that their camera is possibly having problems. (When value is set back to False remove notification).

Native only

Name Description Possible values Use cases Mitigation Steps
speakerVolumeIsZero Zero volume on a device (speaker). - Set to True when the speaker volume is zero.
- Set to False when speaker volume isn't zero.
Not hearing audio from participants on call. When value is set to True, you may have accidentally the volume at lowest(zero).
speakerMuted Speaker device is muted. - Set to True when the speaker device is muted.
- Set to False when the speaker device isn't muted.
Not hearing audio from participants on call. When value is set to True, you may have accidentally muted the speaker.
speakerBusy Speaker is already in use. Either the device is being used in exclusive mode, or the device is being used in shared mode and the caller asked to use the device in exclusive mode. - Set to True when the speaker device stream acquisition times out (audio).
- Set to False when speaker acquisition is successful.
Not hearing audio from participants on call through speaker. When value is set to True, give visual notification to end user so they can check if another application is using the speaker and try closing it.
speakerNotFunctioning Speaker isn't functioning (failed to initialize the audio device client or device became inactive for more than 5 sec) - Set to True when speaker is unavailable, or device stream acquisition times out (audio).
- Set to False when speaker acquisition is successful.
Not hearing audio from participants on call through speaker. Try checking the state of the speaker device.
microphoneBusy Microphone is already in use. Either the device is being used in exclusive mode, or the device is being used in shared mode and the caller asked to use the device in exclusive mode. - Set to True when the microphone device stream acquisition times out (audio).
- Set to False when microphone acquisition is successful.
Your audio not reaching other participants in the call. When value is set to True, give visual notification to end user so they can check if another application is using the microphone and try closing it.

Accessing diagnostics

User-facing diagnostics is an extended feature of the core Call API and allows you to diagnose an active call.

DiagnosticsCallFeature diagnosticsCallFeature = call.feature(Features.LOCAL_USER_DIAGNOSTICS);

User Facing Diagnostic events

  • Get feature object and add listeners to the diagnostics events.
DiagnosticsCallFeature diagnosticsCallFeature = call.feature(Features.LOCAL_USER_DIAGNOSTICS);

/* NetworkDiagnostic */
FlagDiagnosticChangedListener listener = (FlagDiagnosticChangedEvent args) -> {
  Boolean mediaValue = args.getValue();
  // Handle new value for no network diagnostic.
};

NetworkDiagnostics networkDiagnostics = diagnosticsCallFeature.getNetworkDiagnostics();
networkDiagnostics.addOnNetworkUnreachableChangedListener(listener);

// To remove listener for network quality event
networkDiagnostics.removeOnNetworkUnreachableChangedListener(listener);

// Quality Diagnostics
DiagnosticsCallFeature diagnosticsCallFeature = call.feature(Features.LOCAL_USER_DIAGNOSTICS);
QualityDiagnosticChangedListener listener = (QualityDiagnosticChangedEvent args) -> {
  DiagnosticQuality diagnosticQuality = args.getValue();
  // Handle new value for network reconnect diagnostic.
};

NetworkDiagnostics networkDiagnostics = diagnosticsCallFeature.getNetworkDiagnostics();
networkDiagnostics.addOnNetworkReconnectionQualityChangedListener(listener);

// To remove listener for media flag event
networkDiagnostics.removeOnNetworkReconnectionQualityChangedListener(listener);

/* MediaDiagnostic */
DiagnosticsCallFeature diagnosticsCallFeature = call.feature(Features.LOCAL_USER_DIAGNOSTICS);
FlagDiagnosticChangedListener listener = (FlagDiagnosticChangedEvent args) -> {
  Boolean mediaValue = args.getValue();
  // Handle new value for speaker not functioning diagnostic.
};

MediaDiagnostics mediaDiagnostics = diagnosticsCallFeature.getMedia();
mediaDiagnostics.addOnIsSpeakerNotFunctioningChangedListener(listener);

// To remove listener for media flag event
mediaDiagnostics.removeOnIsSpeakerNotFunctioningChangedListener(listener);

Get the latest User Facing Diagnostics

  • Get the latest diagnostic values that were raised in current call. If we still didn't receive a value for the diagnostic, an exception is thrown.
DiagnosticsCallFeature diagnosticsCallFeature = call.feature(Features.LOCAL_USER_DIAGNOSTICS);
NetworkDiagnostics networkDiagnostics = diagnosticsCallFeature.getNetwork();
MediaDiagnostics mediaDiagnostics = diagnosticsCallFeature.getMedia();

NetworkDiagnosticValues latestNetwork = networkDiagnostics.getLatestDiagnostics();
Boolean lastNetworkValue = latestNetwork.isNetworkUnavailable(); // null if there isn't a value for this diagnostic.
DiagnosticQuality lastReceiveQualityValue = latestNetwork.getNetworkReceiveQuality(); //  UNKNOWN if there isn't a value for this diagnostic.

MediaDiagnosticValues latestMedia = networkDiagnostics.getLatestDiagnostics();
Boolean lastSpeakerNotFunctionValue = latestMedia.isSpeakerNotFunctioning(); // null if there isn't a value for this diagnostic.

// Use the last values ...

Diagnostic values

The following user-facing diagnostics are available:

Network values

Name Description Possible values Use cases Mitigation steps
networkUnavailable There's no network available. - Set to True when a call fails to start because there's no network available.
- Set to False when there are ICE candidates present.
Device isn't connected to a network. Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network optimization section.
networkRelaysUnreachable Problems with a network. - Set to True when the network has some constraint that isn't allowing you to reach Azure Communication Services relays.
- Set to False upon making a new call.
During a call when the WiFi signal goes on and off. Ensure that firewall rules and network routing allow client to reach Microsoft turn servers. For more information, see the Firewall configuration section.
networkReconnectionQuality The connection was lost and we're reconnecting to the network. - Set toBad when the network is disconnected
- Set to Poorwhen the media transport connectivity is lost
- Set to Good when a new session is connected.
Low bandwidth, no internet Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section.
networkReceiveQuality An indicator regarding incoming stream quality. - Set toBad when there's a severe problem with receiving the stream.
- Set to Poor when there's a mild problem with receiving the stream.
- Set to Good when there's no problem with receiving the stream.
- It's only visible if there's an active audio flow in the call, which means a participant is actively speaking for period of time.
Low bandwidth Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section. Suggest that the end user turn-off their camera to conserve available internet bandwidth.
networkSendQuality An indicator regarding outgoing stream quality. - Set toBad when there's a severe problem with sending the stream.
- Set to Poor when there's a mild problem with sending the stream.
- Set to Good when there's no problem with sending the stream.
- Similar to receive quality diagnostic it's only visible if there's an active audio flow in the call, which means a participant is actively speaking for period of time. But, it only works in a 1:1 call as it relies on information from the other side in order to verify quality. Where the other side has to signal the data that was received.
Low bandwidth Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section. Also, suggest that the end user turn-off their camera to conserve available internet bandwidth.

Audio values

Name Description Possible values Use cases Mitigation steps
noSpeakerDevicesAvailable there's no audio output device (speaker) on the user's system. - Set to True when there are no speaker devices on the system, and speaker selection is supported.
- Set to False when there's a least one speaker device on the system, and speaker selection is supported.
All speakers are unplugged When value set to True, consider giving visual notification to end user that their current call session doesn't have any speakers available.
speakingWhileMicrophoneIsMuted Speaking while being on mute. - Set to True when local microphone is muted and the local user is speaking.
- Set to False when local user either stops speaking, or unmutes the microphone.
- This diagnostic event can be automatically disabled if it is triggered for a certain amount of times without any user action to avoid noise and provide a better user experience. It will be re-enabled again when a new mute action occurs.
During a call, mute your microphone and speak into it. When value set to True consider giving visual notification to end user that they might be talking and not realizing that their audio is muted.
noMicrophoneDevicesAvailable No audio capture devices (microphone) on the user's system - Set to True when there are no microphone devices on the system.
- Set to False when there's at least one microphone device on the system.
All microphones are unplugged during the call. When value set to True consider giving visual notification to end user that their current call session doesn't have a microphone. For more information, see enable microphone from device manger section.
microphoneNotFunctioning Microphone isn't functioning. - Set to True when we fail to start sending local audio stream because the microphone device may have been disabled in the system or it's being used by another process. This UFD takes about 10 seconds to get raised.
- Set to False when microphone starts to successfully send audio stream again.
No microphones available, microphone access disabled in a system When value set to True give visual notification to end user that there's a problem with their microphone.
microphoneMuteUnexpectedly Microphone is muted - Set to True when microphone enters muted state unexpectedly.
- Set to False when microphone starts to successfully send audio stream
Microphone is muted from the system. Most cases happen when user is on an Azure Communication Services call on a mobile device and a phone call comes in. In most cases, the operating system mutes the Azure Communication Services call so a user can answer the phone call. When value is set to True, give visual notification to end user that their call was muted because a phone call came in. For more information, see how to best handle OS muting an Azure Communication Services call section for more details.
microphonePermissionDenied there's low volume from device or it’s almost silent on macOS. - Set to True when audio permission is denied from the system settings (audio).
- Set to False on successful stream acquisition.
Note: This diagnostic only works on macOS.
Microphone permissions are disabled in the Settings. When value is set to True, give visual notification to end user that they didn't enable permission to use microphone for an Azure Communication Services call.

Camera values

Name Description Possible values Use cases Mitigation steps
cameraFrozen Camera stops producing frames for more than 5 seconds. - Set to True when the local video stream is frozen. This diagnostic means that the remote side is seeing your video frozen on their screen or it means that the remote participants aren't rendering your video on their screen.
- Set to False when the freeze ends and users can see your video as per normal.
The Camera was lost during the call or bad network caused the camera to freeze. When value is set to True, consider giving notification to end user that the remote participant network might be bad - possibly suggest that they turn off their camera to conserve bandwidth. For more information, see Network bandwidth requirement section on needed internet abilities for an Azure Communication Services call.
cameraStartFailed Generic camera failure. - Set to True when we fail to start sending local video because the camera device may have been disabled in the system or it's being used by another process~.
- Set to False when selected camera device successfully sends local video again.
Camera failures When value is set to True, give visual notification to end user that their camera failed to start.
cameraStartTimedOut Common scenario where camera is in bad state. - Set to True when camera device times out to start sending video stream.
- Set to False when selected camera device successfully sends local video again.
Camera failures When value is set to True, give visual notification to end user that their camera is possibly having problems. (When value is set back to False remove notification).
cameraPermissionDenied Camera permissions were denied in settings. - Set to True when camera permission is denied from the system settings (video).
- Set to False on successful stream acquisition.
Note: This diagnostic only works on macOS Chrome.
Camera permissions are disabled in the settings. When value is set to True, give visual notification to end user that they didn't enable permission to use camera for an Azure Communication Services call.
cameraStoppedUnexpectedly Camera malfunction - Set to True when camera enters stopped state unexpectedly.
- Set to False when camera starts to successfully send video stream again.
Check camera is functioning correctly. When value is set to True, give visual notification to end user that their camera is possibly having problems. (When value is set back to False remove notification).

Native only

Name Description Possible values Use cases Mitigation Steps
speakerVolumeIsZero Zero volume on a device (speaker). - Set to True when the speaker volume is zero.
- Set to False when speaker volume isn't zero.
Not hearing audio from participants on call. When value is set to True, you may have accidentally the volume at lowest(zero).
speakerMuted Speaker device is muted. - Set to True when the speaker device is muted.
- Set to False when the speaker device isn't muted.
Not hearing audio from participants on call. When value is set to True, you may have accidentally muted the speaker.
speakerBusy Speaker is already in use. Either the device is being used in exclusive mode, or the device is being used in shared mode and the caller asked to use the device in exclusive mode. - Set to True when the speaker device stream acquisition times out (audio).
- Set to False when speaker acquisition is successful.
Not hearing audio from participants on call through speaker. When value is set to True, give visual notification to end user so they can check if another application is using the speaker and try closing it.
speakerNotFunctioning Speaker isn't functioning (failed to initialize the audio device client or device became inactive for more than 5 sec) - Set to True when speaker is unavailable, or device stream acquisition times out (audio).
- Set to False when speaker acquisition is successful.
Not hearing audio from participants on call through speaker. Try checking the state of the speaker device.
microphoneBusy Microphone is already in use. Either the device is being used in exclusive mode, or the device is being used in shared mode and the caller asked to use the device in exclusive mode. - Set to True when the microphone device stream acquisition times out (audio).
- Set to False when microphone acquisition is successful.
Your audio not reaching other participants in the call. When value is set to True, give visual notification to end user so they can check if another application is using the microphone and try closing it.

Accessing diagnostics

User-facing diagnostics is an extended feature of the core Call API and allows you to diagnose an active call.

let userFacingDiagnostics = self.call?.feature(Features.localUserDiagnostics)

User Facing Diagnostic events

  • Implement the delegates for media and network diagnostic sources. MediaDiagnosticsDelegate and NetworkDiagnosticsDelegate respectively.
extension CallObserver: MediaDiagnosticsDelegate {
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsCameraFrozen args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsSpeakerMuted args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsCameraStartFailed args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsSpeakerVolumeZero args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsSpeakerNotFunctioning args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsCameraPermissionDenied args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsMicrophoneNotFunctioning args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsCameraStartTimedOut args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsMicrophoneMutedUnexpectedly args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsZeroSpeakerDevicesAvailable args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...                            
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsZeroMicrophoneDevicesAvailable args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsSpeakingWhileMicrophoneIsMuted args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsSpeakerBusy args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func mediaDiagnostics(_ mediaDiagnostics: MediaDiagnostics,
                        didChangeIsMicrophoneBusy args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
}

extension CallObserver: NetworkDiagnosticsDelegate {
  func networkDiagnostics(_ networkDiagnostics: NetworkDiagnostics,
                          didChangeIsNetworkRelaysUnreachable args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func networkDiagnostics(_ networkDiagnostics: NetworkDiagnostics,
                          didChangeNetworkReconnectionQuality args: DiagnosticQualityChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func networkDiagnostics(_ networkDiagnostics: NetworkDiagnostics,
                          didChangeNetworkSendQuality args: DiagnosticQualityChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func networkDiagnostics(_ networkDiagnostics: NetworkDiagnostics,
                          didChangeIsNetworkUnavailable args: DiagnosticFlagChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
    
  func networkDiagnostics(_ networkDiagnostics: NetworkDiagnostics,
                          didChangeNetworkReceiveQuality args: DiagnosticQualityChangedEventArgs) {
    let newValue = args.value
    // Handle the diagnostic event value changed...
  }
}
  • Hold a reference to media and network diagnostics and set delegate object for listening to events.
self.mediaDiagnostics = userFacingDiagnostics?.media
self.networkDiagnostics = userFacingDiagnostics?.network
self.mediaDiagnostics?.delegate = self.callObserver
self.networkDiagnostics?.delegate = self.callObserver

Note

If you have CallKit enabled via SDK or implement CallKit integration in your application, reporting mute state to CallKit can result in the OS making the application loose the hold to microphone due to privacy reasons which would cause the didIsSpeakingWhileMicrophoneIsMuted event not to work as expected because we cannot capture input from microphone device to detect that the user is speaking.

Get the latest User Facing Diagnostics

  • Get the latest diagnostic values that were raised. If we still didn't receive a value for the diagnostic, nil or .unknown is returned.
let lastSpeakerNotFunctionValue = self.mediaDiagnostics.latest.isSpeakerNotFunctioning // Boolean?
let lastNetworkRelayNotReachableValue = self.networkDiagnostics.latest.networkRelaysUnreachable // Boolean?
let lastReceiveQualityValue = self.networkDiagnostics.latest.networkReceiveQuality // DiagnosticQuality (.good, .poor, .bad)
// or .unknown if there isn't a diagnostic for this.

Diagnostic values

The following user-facing diagnostics are available:

Network values

Name Description Possible values Use cases Mitigation steps
networkUnavailable There's no network available. - Set to True when a call fails to start because there's no network available.
- Set to False when there are ICE candidates present.
Device isn't connected to a network. Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network optimization section.
networkRelaysUnreachable Problems with a network. - Set to True when the network has some constraint that isn't allowing you to reach Azure Communication Services relays.
- Set to False upon making a new call.
During a call when the WiFi signal goes on and off. Ensure that firewall rules and network routing allow client to reach Microsoft turn servers. For more information, see the Firewall configuration section.
networkReconnectionQuality The connection was lost and we're reconnecting to the network. - Set toBad when the network is disconnected
- Set to Poorwhen the media transport connectivity is lost
- Set to Good when a new session is connected.
Low bandwidth, no internet Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section.
networkReceiveQuality An indicator regarding incoming stream quality. - Set toBad when there's a severe problem with receiving the stream.
- Set to Poor when there's a mild problem with receiving the stream.
- Set to Good when there's no problem with receiving the stream.
- It's only visible if there's an active audio flow in the call, which means a participant is actively speaking for period of time.
Low bandwidth Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section. Suggest that the end user turn-off their camera to conserve available internet bandwidth.
networkSendQuality An indicator regarding outgoing stream quality. - Set toBad when there's a severe problem with sending the stream.
- Set to Poor when there's a mild problem with sending the stream.
- Set to Good when there's no problem with sending the stream.
- Similar to receive quality diagnostic it's only visible if there's an active audio flow in the call, which means a participant is actively speaking for period of time. But, it only works in a 1:1 call as it relies on information from the other side in order to verify quality. Where the other side has to signal the data that was received.
Low bandwidth Ensure that the call has a reliable internet connection that can sustain a voice call. For more information, see the Network bandwidth requirement section. Also, suggest that the end user turn-off their camera to conserve available internet bandwidth.

Audio values

Name Description Possible values Use cases Mitigation steps
noSpeakerDevicesAvailable there's no audio output device (speaker) on the user's system. - Set to True when there are no speaker devices on the system, and speaker selection is supported.
- Set to False when there's a least one speaker device on the system, and speaker selection is supported.
All speakers are unplugged When value set to True, consider giving visual notification to end user that their current call session doesn't have any speakers available.
speakingWhileMicrophoneIsMuted Speaking while being on mute. - Set to True when local microphone is muted and the local user is speaking.
- Set to False when local user either stops speaking, or unmutes the microphone.
- This diagnostic event can be automatically disabled if it is triggered for a certain amount of times without any user action to avoid noise and provide a better user experience. It will be re-enabled again when a new mute action occurs.
During a call, mute your microphone and speak into it. When value set to True consider giving visual notification to end user that they might be talking and not realizing that their audio is muted.
noMicrophoneDevicesAvailable No audio capture devices (microphone) on the user's system - Set to True when there are no microphone devices on the system.
- Set to False when there's at least one microphone device on the system.
All microphones are unplugged during the call. When value set to True consider giving visual notification to end user that their current call session doesn't have a microphone. For more information, see enable microphone from device manger section.
microphoneNotFunctioning Microphone isn't functioning. - Set to True when we fail to start sending local audio stream because the microphone device may have been disabled in the system or it's being used by another process. This UFD takes about 10 seconds to get raised.
- Set to False when microphone starts to successfully send audio stream again.
No microphones available, microphone access disabled in a system When value set to True give visual notification to end user that there's a problem with their microphone.
microphoneMuteUnexpectedly Microphone is muted - Set to True when microphone enters muted state unexpectedly.
- Set to False when microphone starts to successfully send audio stream
Microphone is muted from the system. Most cases happen when user is on an Azure Communication Services call on a mobile device and a phone call comes in. In most cases, the operating system mutes the Azure Communication Services call so a user can answer the phone call. When value is set to True, give visual notification to end user that their call was muted because a phone call came in. For more information, see how to best handle OS muting an Azure Communication Services call section for more details.
microphonePermissionDenied there's low volume from device or it’s almost silent on macOS. - Set to True when audio permission is denied from the system settings (audio).
- Set to False on successful stream acquisition.
Note: This diagnostic only works on macOS.
Microphone permissions are disabled in the Settings. When value is set to True, give visual notification to end user that they didn't enable permission to use microphone for an Azure Communication Services call.

Camera values

Name Description Possible values Use cases Mitigation steps
cameraFrozen Camera stops producing frames for more than 5 seconds. - Set to True when the local video stream is frozen. This diagnostic means that the remote side is seeing your video frozen on their screen or it means that the remote participants aren't rendering your video on their screen.
- Set to False when the freeze ends and users can see your video as per normal.
The Camera was lost during the call or bad network caused the camera to freeze. When value is set to True, consider giving notification to end user that the remote participant network might be bad - possibly suggest that they turn off their camera to conserve bandwidth. For more information, see Network bandwidth requirement section on needed internet abilities for an Azure Communication Services call.
cameraStartFailed Generic camera failure. - Set to True when we fail to start sending local video because the camera device may have been disabled in the system or it's being used by another process~.
- Set to False when selected camera device successfully sends local video again.
Camera failures When value is set to True, give visual notification to end user that their camera failed to start.
cameraStartTimedOut Common scenario where camera is in bad state. - Set to True when camera device times out to start sending video stream.
- Set to False when selected camera device successfully sends local video again.
Camera failures When value is set to True, give visual notification to end user that their camera is possibly having problems. (When value is set back to False remove notification).
cameraPermissionDenied Camera permissions were denied in settings. - Set to True when camera permission is denied from the system settings (video).
- Set to False on successful stream acquisition.
Note: This diagnostic only works on macOS Chrome.
Camera permissions are disabled in the settings. When value is set to True, give visual notification to end user that they didn't enable permission to use camera for an Azure Communication Services call.
cameraStoppedUnexpectedly Camera malfunction - Set to True when camera enters stopped state unexpectedly.
- Set to False when camera starts to successfully send video stream again.
Check camera is functioning correctly. When value is set to True, give visual notification to end user that their camera is possibly having problems. (When value is set back to False remove notification).

Native only

Name Description Possible values Use cases Mitigation Steps
speakerVolumeIsZero Zero volume on a device (speaker). - Set to True when the speaker volume is zero.
- Set to False when speaker volume isn't zero.
Not hearing audio from participants on call. When value is set to True, you may have accidentally the volume at lowest(zero).
speakerMuted Speaker device is muted. - Set to True when the speaker device is muted.
- Set to False when the speaker device isn't muted.
Not hearing audio from participants on call. When value is set to True, you may have accidentally muted the speaker.
speakerBusy Speaker is already in use. Either the device is being used in exclusive mode, or the device is being used in shared mode and the caller asked to use the device in exclusive mode. - Set to True when the speaker device stream acquisition times out (audio).
- Set to False when speaker acquisition is successful.
Not hearing audio from participants on call through speaker. When value is set to True, give visual notification to end user so they can check if another application is using the speaker and try closing it.
speakerNotFunctioning Speaker isn't functioning (failed to initialize the audio device client or device became inactive for more than 5 sec) - Set to True when speaker is unavailable, or device stream acquisition times out (audio).
- Set to False when speaker acquisition is successful.
Not hearing audio from participants on call through speaker. Try checking the state of the speaker device.
microphoneBusy Microphone is already in use. Either the device is being used in exclusive mode, or the device is being used in shared mode and the caller asked to use the device in exclusive mode. - Set to True when the microphone device stream acquisition times out (audio).
- Set to False when microphone acquisition is successful.
Your audio not reaching other participants in the call. When value is set to True, give visual notification to end user so they can check if another application is using the microphone and try closing it.

Accessing diagnostics

User-facing diagnostics is an extended feature of the core Call API and allows you to diagnose an active call.

this.diagnosticsCallFeature = call.Features.LocalUserDiagnostics;

User Facing Diagnostic events

  • Implement listeners for diagnostic events.
private async void Call__OnNetworkUnavailableChanged(object sender, FlagDiagnosticChangedEventArgs args)
{
  var value = args.Value;
  // Handle the diagnostic event value changed...
}

// Listen to other network diagnostics

private async void Call__OnMediaSpeakerNotFunctioningChanged(object sender, FlagDiagnosticChangedEventArgs args)
{
  var value = args.Value;
  // Handle the diagnostic event value changed...
}

// Listen to other media diagnostics
  • Set event methods for listening to events.
this.diagnosticsCallFeature = call.Features.LocalUserDiagnostics;
this.networkDiagnostics = diagnosticsCallFeature.Network;
this.mediaDiagnostics = diagnosticsCallFeature.Media;

this.networkDiagnostics.NetworkUnavailableChanged += Call__OnNetworkUnavailableChanged;
// Listen to other network events as well ... 

this.mediaDiagnostics.SpeakerNotFunctioningChanged += Call__OnMediaSpeakerNotFunctioningChanged;
// Listen to other media events as well ... 

// Removing listeners

this.networkDiagnostics.NetworkUnavailable -= Call__NetworkUnavailableChanged;
// Remove the other listeners as well ... 

this.mediaDiagnostics.SpeakerNotFunctioningChanged -= Call__OnMediaSpeakerNotFunctioningChanged;
// Remove the other listeners as well ... 

Get the latest User Facing Diagnostics

  • Get the latest diagnostic values that were raised in current call. If we still didn't receive a value for the diagnostic, null or .unknown for is returned.
this.diagnosticsCallFeature = call.Features.LocalUserDiagnostics;
this.networkDiagnostics = diagnosticsCallFeature.Network;
this.mediaDiagnostics = diagnosticsCallFeature.Media;

bool? lastSpeakerNotFunctionValue = this.mediaDiagnostics.GetLatestDiagnostics().IsSpeakerNotFunctioning; // Boolean?
bool? lastNetworkRelayNotReachableValue = this.networkDiagnostics.GetLatestDiagnostics().IsNetworkRelaysUnreachable; // Boolean?
DiagnosticQuality lastReceiveQualityValue = this.networkDiagnostics.GetLatestDiagnostics().NetworkReceiveQuality; // DiagnosticQuality (.good, .poor, .bad)
// or .unknown if there isn't a diagnostic for this.