UNPKG

@telnyx/webrtc

Version:
200 lines (199 loc) 21.2 kB
export interface ITelnyxWarning { code: SdkWarningCode; name: string; message: string; description: string; causes: string[]; solutions: string[]; } export interface ITelnyxWarningEvent { warning: ITelnyxWarning; sessionId: string; callId?: string; } export declare const SDK_WARNINGS: { readonly 31001: { readonly name: "HIGH_RTT"; readonly message: "High network latency detected"; readonly description: "Round-trip time (RTT) exceeded the threshold for multiple consecutive samples. High latency causes perceptible audio delays."; readonly causes: readonly ["Poor network connection", "Geographic distance to media server", "Network congestion"]; readonly solutions: readonly ["Check network connectivity", "Use a wired connection instead of Wi-Fi", "Close bandwidth-heavy applications"]; }; readonly 31002: { readonly name: "HIGH_JITTER"; readonly message: "High jitter detected"; readonly description: "Jitter (variability in packet arrival time) exceeded the threshold for multiple consecutive samples. High jitter causes crackling and choppy audio."; readonly causes: readonly ["Network congestion", "Unstable Wi-Fi connection", "Overloaded network equipment"]; readonly solutions: readonly ["Use a wired connection instead of Wi-Fi", "Close bandwidth-heavy applications", "Check network equipment"]; }; readonly 31003: { readonly name: "HIGH_PACKET_LOSS"; readonly message: "High packet loss detected"; readonly description: "Packet loss exceeded the threshold for multiple consecutive samples. High packet loss causes choppy audio or dropped calls."; readonly causes: readonly ["Network congestion", "Unstable connection", "Firewall or QoS misconfiguration"]; readonly solutions: readonly ["Check network connectivity", "Use a wired connection", "Contact network administrator"]; }; readonly 31004: { readonly name: "LOW_MOS"; readonly message: "Low call quality score"; readonly description: "Mean Opinion Score (MOS) dropped below the acceptable threshold for multiple consecutive samples. This is a composite indicator of overall call quality."; readonly causes: readonly ["Combination of high latency, jitter, and/or packet loss", "Poor network conditions"]; readonly solutions: readonly ["Check network connectivity", "Use a wired connection", "Close bandwidth-heavy applications"]; }; readonly 31005: { readonly name: "LOW_LOCAL_AUDIO"; readonly message: "Low local microphone audio detected"; readonly description: "Local outbound audio level stayed below the acceptable threshold before the microphone produced real audio, or stayed silent for a long continuous window after audio was confirmed. This may indicate that the microphone is not capturing enough audio even while RTP is being sent."; readonly causes: readonly ["Microphone input level is too low", "Wrong microphone selected", "Microphone is obstructed or too far from the speaker", "Operating system input gain is muted or very low"]; readonly solutions: readonly ["Check the selected microphone", "Increase microphone input gain", "Move closer to the microphone", "Verify the microphone is not muted at the operating system or hardware level"]; }; readonly 31006: { readonly name: "LOW_INBOUND_AUDIO"; readonly message: "Low inbound audio detected"; readonly description: "Inbound (remote) audio level stayed below the acceptable threshold for multiple consecutive stats intervals while RTP packets continued to flow. This may indicate the remote party is sending silence or comfort-noise (e.g. one-way audio caused by a media bridge issue), as opposed to LOW_BYTES_RECEIVED which fires when no bytes arrive at all."; readonly causes: readonly ["Remote party microphone is muted or capturing very low audio", "Media bridge or PBX is injecting comfort-noise/silence instead of forwarding real audio", "One-way audio where RTP flows but content is silent (server-side media issue)", "Remote party is on hold or not speaking"]; readonly solutions: readonly ["Verify the remote party is not muted and is actively speaking", "Check the media bridge / PBX for comfort-noise injection or transcoding issues", "Inspect PCAP RTP payload uniqueness to distinguish real audio from comfort-noise", "If the issue persists, report the call for server-side media investigation"]; }; readonly 32001: { readonly name: "LOW_BYTES_RECEIVED"; readonly message: "No audio data received"; readonly description: "No bytes have been received from the remote party for multiple consecutive seconds. This may indicate a network interruption or remote-side issue."; readonly causes: readonly ["Network interruption", "Remote party microphone issue", "Firewall blocking inbound media"]; readonly solutions: readonly ["Check network connectivity", "Ask remote party to check their microphone", "Check firewall rules for media ports"]; }; readonly 32002: { readonly name: "LOW_BYTES_SENT"; readonly message: "No audio data being sent"; readonly description: "No bytes have been sent for multiple consecutive seconds. This may indicate a local microphone issue or network interruption."; readonly causes: readonly ["Microphone muted or disconnected", "Network interruption", "Local media track ended"]; readonly solutions: readonly ["Check that the microphone is not muted", "Verify the microphone is still connected", "Check network connectivity"]; }; readonly 32003: { readonly name: "RECORDING_UNAVAILABLE"; readonly message: "Call recording is not available in this browser"; readonly description: "Call recording was enabled (enableCallRecording is true), but the browser does not support MediaStreamTrackProcessor (required to capture raw audio PCM). Recording is disabled for this call; the call proceeds normally. Currently affects Firefox and older Chromium (< 94)."; readonly causes: readonly ["Browser does not implement MediaStreamTrackProcessor (Firefox, Safari)", "Chromium version older than 94", "Recording enabled on an unsupported platform"]; readonly solutions: readonly ["Use a recent Chromium-based browser (Chrome 94+, Edge 94+) to capture recordings", "Disable enableCallRecording if recording is not required for this deployment", "See the enableCallRecording JSDoc for platform support details"]; }; readonly 32004: { readonly name: "RECORDING_BUFFER_OVERFLOW"; readonly message: "Call recording buffer overflow — oldest packets dropped"; readonly description: "The in-memory call recording buffer reached its maxBufferBytes cap before the next scheduled flush. The oldest captured RTP packets were dropped to keep memory bounded. This indicates the flush interval is too long for the call audio rate, or the upload endpoint is slow/unreachable. The recording continues with the remaining (newer) packets."; readonly causes: readonly ["Flush interval (callRecordingFlushIntervalMs) is larger than the buffer can hold at the current audio rate", "Upload endpoint (/call_recording) is slow or unreachable, so intermediate flushes back up", "A very long call with high sample rate filling the buffer between flushes"]; readonly solutions: readonly ["Reduce callRecordingFlushIntervalMs so flushes happen more frequently", "Increase callRecordingMaxBufferBytes if memory headroom allows", "Check the /call_recording endpoint health and network path to voice-sdk-proxy"]; }; readonly 33001: { readonly name: "ICE_CONNECTIVITY_LOST"; readonly message: "Connection interrupted"; readonly description: "The ICE connection transitioned to the disconnected state. The previously selected connection path was lost and renegotiation may be required. The connection may recover automatically."; readonly causes: readonly ["Temporary network interruption", "Network interface change (e.g. Wi-Fi to cellular)", "NAT rebinding"]; readonly solutions: readonly ["Wait for automatic recovery", "Check network connectivity"]; }; readonly 33002: { readonly name: "ICE_GATHERING_TIMEOUT"; readonly message: "ICE gathering timed out"; readonly description: "ICE candidate gathering did not complete within the safety timeout. This is typically caused by network restrictions blocking STUN/TURN. The call may still succeed if candidates arrive late."; readonly causes: readonly ["Firewall blocking STUN/TURN", "Network unreachable", "STUN/TURN server not responding"]; readonly solutions: readonly ["Check STUN/TURN server reachability", "Ensure UDP traffic is not blocked", "Try forceRelayCandidate option"]; }; readonly 33003: { readonly name: "ICE_GATHERING_EMPTY"; readonly message: "No ICE candidates gathered"; readonly description: "No ICE candidates were gathered after sending the initial SDP. This may indicate a firewall blocking all STUN/TURN traffic or no available network interface."; readonly causes: readonly ["Firewall blocking all STUN/TURN traffic", "No network interface available", "VPN blocking UDP"]; readonly solutions: readonly ["Check STUN/TURN server reachability", "Ensure UDP traffic is not blocked", "Use forceRelayCandidate option"]; }; readonly 33004: { readonly name: "PEER_CONNECTION_FAILED"; readonly message: "Connection failed"; readonly description: "RTCPeerConnection entered the failed state. This is a recoverable condition — the SDK may attempt ICE restart or the connection may recover. If it does not recover, the call will eventually be terminated."; readonly causes: readonly ["ICE failure", "DTLS handshake failure", "Prolonged network interruption"]; readonly solutions: readonly ["Wait for automatic recovery", "Check network connectivity", "Verify TURN server credentials"]; }; readonly 33005: { readonly name: "ONLY_HOST_ICE_CANDIDATES"; readonly message: "Only local network candidates available"; readonly description: "ICE gathering completed but only host (local network) candidates were collected — no server-reflexive (srflx) or relay (turn) candidates were found. This typically means the STUN/TURN servers are unreachable, which will prevent connections outside the local network."; readonly causes: readonly ["STUN/TURN servers unreachable", "Firewall blocking UDP traffic to STUN/TURN servers", "Incorrect TURN server configuration or credentials", "Restrictive corporate network or VPN"]; readonly solutions: readonly ["Verify STUN/TURN server URLs and credentials", "Ensure UDP traffic to STUN/TURN ports is not blocked", "Check firewall or VPN settings", "Try using TCP-based TURN as a fallback"]; }; readonly 33006: { readonly name: "ANSWER_WHILE_PEER_ACTIVE"; readonly message: "Call answer ignored because a peer connection is already active"; readonly description: "answer() was called on a call that already has an active or connecting peer connection. Creating a second peer connection for the same call would duplicate media negotiation, confuse the remote party, and break call reporting. This is typically caused by application code invoking answer() multiple times (e.g. from multiple event handlers)."; readonly causes: readonly ["Application called answer() twice on the same call object", "Multiple click handlers or event listeners triggering answer()"]; readonly solutions: readonly ["Ensure answer() is called only once per call", "Disable the answer button after the first click", "Check that answer() is not invoked from multiple event handlers"]; }; readonly 33008: { readonly name: "ICE_CANDIDATE_PAIR_CHANGED"; readonly message: "ICE candidate pair changed mid-call"; readonly description: "The selected ICE candidate pair changed during an active call. This indicates a network path shift — for example, a Wi-Fi to cellular handoff, a NAT rebinding, or a relay fallback. The call may continue normally, but the path change can briefly affect audio quality."; readonly causes: readonly ["Network interface change (e.g. Wi-Fi to cellular)", "NAT rebinding or IP address change", "Previous candidate pair failed and ICE selected an alternative", "Network topology change"]; readonly solutions: readonly ["Monitor for audio quality degradation after the path change", "Check network stability if changes are frequent", "Verify TURN server configuration for relay fallback"]; }; readonly 33007: { readonly name: "DUPLICATE_INBOUND_ANSWER"; readonly message: "Call answer ignored because another inbound call is already being answered"; readonly description: "answer() was called on an inbound call while another inbound call is already answering or active in this JavaScript runtime. Answering both legs can trigger SIP 486 USER_BUSY / LOSE_RACE when duplicate WebSocket registrations receive the same incoming call."; readonly causes: readonly ["Multiple TelnyxRTC instances in the same page", "Application code recreating a client without disconnecting the previous instance", "Duplicate inbound call notifications produced by duplicate WebSocket registrations"]; readonly solutions: readonly ["Keep a single active TelnyxRTC instance for inbound call handling", "Call disconnect() before replacing an SDK client instance", "Only call answer() for one inbound call notification at a time"]; }; readonly 34001: { readonly name: "TOKEN_EXPIRING_SOON"; readonly message: "Authentication token expiring soon"; readonly description: "The authentication token is approaching its expiration time. If the token expires the connection will be lost and calls will fail. A new token should be generated before expiration."; readonly causes: readonly ["Token was issued with a limited lifetime"]; readonly solutions: readonly ["Generate a new authentication token", "Reconnect with fresh credentials before the token expires"]; }; readonly 36003: { readonly name: "SIGNALING_RECOVERY_REQUIRED"; readonly message: "Signaling recovery required"; readonly description: "The signaling (WebSocket) path has been detected as unhealthy and the SDK will force-close the socket and reconnect. The source field in the warning payload indicates what triggered the recovery (probe, request, peer_failure, or no_rtp). Active calls will be recovered via reattach after reconnection."; readonly causes: readonly ["WebSocket probe timed out with no response", "Critical signaling request timed out", "Peer/media failure detected while signaling is also unhealthy"]; readonly solutions: readonly ["The SDK will automatically reconnect and recover the call", "Check for network interface changes or interruptions", "Verify firewall/NAT timeout settings"]; }; readonly 36004: { readonly name: "MEDIA_RECOVERY_REQUIRED"; readonly message: "Media recovery required"; readonly description: "The peer connection or media flow has been detected as unhealthy while signaling is healthy. The SDK will attempt ICE restart to recover the media path. No socket reconnection is needed."; readonly causes: readonly ["ICE connection state changed to failed", "RTCPeerConnection state changed to failed", "No RTP packets/bytes received while media should be active"]; readonly solutions: readonly ["The SDK will automatically attempt ICE restart", "Check network connectivity and ICE candidate availability", "Verify TURN server configuration"]; }; readonly 36005: { readonly name: "RECONNECTION_FAILED_WITH_NO_AUTO_RECONNECT"; readonly message: "Reconnection failed — auto-reconnect disabled"; readonly description: "The WebSocket was closed and auto-reconnect is disabled, so the SDK will not attempt to reconnect. This typically occurs after the user called disconnect() or after reconnection attempts were exhausted."; readonly causes: readonly ["Auto-reconnect was disabled by the application", "Reconnection attempts were previously exhausted", "The session was intentionally disconnected"]; readonly solutions: readonly ["Call connect() manually to re-establish the session", "Check if disconnect() was called intentionally", "Review maxReconnectAttempts configuration"]; }; readonly 33009: { readonly name: "AUDIO_INPUT_DEVICE_CHANGE_SKIPPED"; readonly message: "Audio input device change skipped"; readonly description: "The SDK could not change the microphone because the active peer connection has no audio RTP sender to replace. The existing local media and mute state were left unchanged."; readonly causes: readonly ["The call was created without an audio sender", "The peer connection was not ready when setAudioInDevice was called", "The call is already ending or the local media sender was removed"]; readonly solutions: readonly ["Retry after the call is active and local media is attached", "Verify the call was started with audio enabled", "Inspect call state and peer connection sender availability"]; }; readonly 33010: { readonly name: "MULTIPLE_ACTIVE_CALLS_DETECTED"; readonly message: "Multiple active calls detected in one SDK session"; readonly description: "A new call was created or received while another call is still active (ringing, answering, active, held, or recovering) in the same SDK session. This may be intentional for some applications (e.g. call waiting, transfer) but is often abnormal and makes call reports and application behavior harder to reason about. The new call proceeds normally — this warning is diagnostic only."; readonly causes: readonly ["Application created an outbound call while another call is active", "An inbound call arrived while another call is already active", "Application did not hang up the previous call before starting a new one", "Call waiting or multi-call scenario (may be intentional)"]; readonly solutions: readonly ["Verify this is the expected behavior for your application", "Ensure the previous call is hung up before creating a new one if only one call is expected", "Use call.hold() before starting a new call if needed", "Check the warning payload for call IDs to correlate which calls are involved"]; }; readonly 33011: { readonly name: "SHARED_REMOTE_ELEMENT_OVERWRITE"; readonly message: "Remote media element overwritten by another call"; readonly description: "A new MediaStream was attached to an HTML media element (audio/video) that already held a different MediaStream from another active call. The SDK overwrote the existing stream (last-writer-wins), which disrupts the other call remote media playout. This happens when two concurrent calls share a single remoteElement instead of each having its own. Use a per-call remoteElement (client.newCall({ remoteElement }) or call.answer({ remoteElement })) so each call owns a distinct element."; readonly causes: readonly ["Two concurrent calls share one remoteElement (legacy single-element app)", "Application did not pass a per-call remoteElement to newCall() or answer()", "A second inbound call rang into a session using one session-level remoteElement"]; readonly solutions: readonly ["Pass a distinct remoteElement per call via client.newCall({ remoteElement })", "For inbound calls, override at answer time via call.answer({ remoteElement })", "Give each call its own <audio>/<video> element so attach/detach lifecycles are independent"]; }; readonly 35002: { readonly name: "UNKNOWN_REATTACHED_SESSION"; readonly message: "Unknown reattach session after reconnect"; readonly description: "The WebSocket reconnected successfully and the server sent an Attach message for a session that does not match any active SDK call. The unknown Attach is ACK'd and ignored."; readonly causes: readonly ["Server sent an Attach for a call that no longer exists in the SDK", "Multiple Attach messages arrived and only the first was recovered", "Race condition between reconnection and new inbound call"]; readonly solutions: readonly ["Check application logic for multiple simultaneous calls", "Inspect the Attach callID in the warning payload for details", "If a call should be active, start a new call manually"]; }; }; export declare type SdkWarningCode = keyof typeof SDK_WARNINGS; export declare function createTelnyxWarning(code: SdkWarningCode, message?: string): ITelnyxWarning;