UNPKG

@telnyx/webrtc

Version:
347 lines (346 loc) 11.6 kB
import { ILogEntry } from '../../../Modules/Verto/util/LogCollector'; import { type ITelnyxWarning } from '../../../Modules/Verto/util/errors'; export interface ILocalAudioTrackSnapshot { id?: string; label?: string; enabled?: boolean; muted?: boolean; readyState?: MediaStreamTrackState; contentHint?: string; settings?: { deviceId?: string; groupId?: string; channelCount?: number; sampleRate?: number; sampleSize?: number; latency?: number; echoCancellation?: boolean; noiseSuppression?: boolean; autoGainControl?: boolean; }; } export interface ILocalAudioSourceStats { id?: string; trackIdentifier?: string; audioLevel?: number; totalAudioEnergy?: number; totalSamplesDuration?: number; echoReturnLoss?: number; echoReturnLossEnhancement?: number; } interface ICECandidateInfo { id?: string; address?: string; port?: number; candidateType?: string; protocol?: string; networkType?: string; url?: string; relayProtocol?: string; } export interface IICECandidatePair { id?: string; localCandidateId?: string; remoteCandidateId?: string; state?: string; nominated?: boolean; writable?: boolean; currentRoundTripTime?: number; local?: ICECandidateInfo; remote?: ICECandidateInfo; requestsSent?: number; responsesReceived?: number; } export interface ITransportStats { iceState?: string; dtlsState?: string; srtpCipher?: string; tlsVersion?: string; selectedCandidatePairChanges?: number; selectedCandidatePairId?: string; } export interface ICallReportOptions { enabled: boolean; interval: number; intermediateReportInterval?: number; } export interface ILogCollectorOptions { enabled: boolean; level: 'debug' | 'info' | 'warn' | 'error'; maxEntries: number; } export interface IStatsInterval { intervalStartUtc: string; intervalEndUtc: string; audio?: { outbound?: { packetsSent?: number; bytesSent?: number; audioLevelAvg?: number; bitrateAvg?: number; localTrack?: ILocalAudioTrackSnapshot; mediaSource?: ILocalAudioSourceStats; retransmittedPacketsSent?: number; retransmittedBytesSent?: number; headerBytesSent?: number; nackCount?: number; targetBitrate?: number; totalPacketSendDelay?: number; active?: boolean; codec?: { mimeType?: string; clockRate?: number; channels?: number; payloadType?: number; sdpFmtpLine?: string; codecId?: string; }; }; inbound?: { packetsReceived?: number; bytesReceived?: number; packetsLost?: number; packetsDiscarded?: number; jitterBufferDelay?: number; jitterBufferEmittedCount?: number; totalSamplesReceived?: number; concealedSamples?: number; concealmentEvents?: number; audioLevelAvg?: number; jitterAvg?: number; bitrateAvg?: number; nackCount?: number; headerBytesReceived?: number; fecPacketsReceived?: number; fecPacketsDiscarded?: number; jitterBufferTargetDelay?: number; jitterBufferMinimumDelay?: number; totalSamplesDecoded?: number; samplesDecodedWithSilence?: number; samplesDecodedWithConcealment?: number; totalAudioEnergy?: number; totalSamplesDuration?: number; codec?: { mimeType?: string; clockRate?: number; channels?: number; payloadType?: number; sdpFmtpLine?: string; codecId?: string; }; }; }; connection?: { roundTripTimeAvg?: number; currentRoundTripTime?: number; roundTripTimeSource?: string; packetsSent?: number; packetsReceived?: number; bytesSent?: number; bytesReceived?: number; }; ice?: IICECandidatePair; transport?: ITransportStats; mediaPlayout?: { synthesizedSamples?: number; synthesizedDuration?: number; totalPlayoutDelay?: number; totalSampleCount?: number; }; remoteRtcp?: { inbound?: { packetsReceived?: number; packetsLost?: number; fractionLost?: number; jitter?: number; roundTripTime?: number; totalRoundTripTime?: number; roundTripTimeMeasurements?: number; roundTripTimeAvg?: number; nackCount?: number; reportsReceived?: number; packetsDiscarded?: number; }; outbound?: { packetsSent?: number; bytesSent?: number; reportsCount?: number; roundTripTime?: number; totalPacketSendDelay?: number; }; }; } export interface ICallSummary { callId: string; destinationNumber?: string; callerNumber?: string; direction?: 'inbound' | 'outbound'; state?: string; durationSeconds?: number; telnyxSessionId?: string; telnyxLegId?: string; voiceSdkSessionId?: string; sdkVersion?: string; startTimestamp?: string; endTimestamp?: string; clientSummary?: IClientSummary; } export interface IClientSummary { authentication?: { type?: 'anonymous_login' | 'login_token' | 'login_password' | 'token' | 'unknown'; anonymousLogin?: { targetType?: string; targetId?: string; targetVersionId?: string; targetParams?: SanitizedClientOption; }; }; connection?: { env?: string; host?: string; project?: string; region?: string; dc?: string; rtcIp?: string; rtcPort?: number; autoReconnect?: boolean; maxReconnectAttempts?: number; keepConnectionAliveOnSocketClose?: boolean; hangupOnBeforeUnload?: boolean; useCanaryRtcServer?: boolean; skipLastVoiceSdkId?: boolean; skipTrailing?: boolean; }; media?: { audio?: unknown; video?: unknown; mutedMicOnStart?: boolean; prefetchIceCandidates?: boolean; forceRelayCandidate?: boolean; trickleIce?: boolean; iceServers?: Array<{ urls?: string | string[]; hasUsername?: boolean; hasCredential?: boolean; }>; }; callReports?: { enabled?: boolean; intervalMs?: number; flushIntervalMs?: number; debugLogLevel?: string; debugLogMaxEntries?: number; }; } export declare type SanitizedClientOption = string | number | boolean | null | SanitizedClientOption[] | { [key: string]: SanitizedClientOption; }; export interface ICallReportFlushReason { type: 'buffer-limit' | 'manual' | 'socket-close' | 'socket-error' | 'page-unload'; socketClose?: { code?: number; codeName?: string; reason?: string; wasClean?: boolean; error?: string; }; } export interface ICallReportPayload { summary: ICallSummary; stats: IStatsInterval[]; logs?: ILogEntry[]; segment?: number; flushReason?: ICallReportFlushReason; } export declare class CallReportCollector { private options; private logCollectorOptions; private peerConnection; private intervalId; private statsBuffer; private intervalStartTime; private callStartTime; private callEndTime; private logCollector; private intervalAudioLevels; private intervalJitters; private intervalRTTs; private intervalBitrates; private previousStats; private previousCandidatePairSnapshot; private static readonly INITIAL_COLLECTION_INTERVAL_MS; private readonly MAX_BUFFER_SIZE; private static readonly STATS_FLUSH_THRESHOLD; private static readonly LOGS_FLUSH_THRESHOLD; private static readonly DEFAULT_INTERMEDIATE_REPORT_INTERVAL_MS; onFlushNeeded: (() => void) | null; onWarning: ((warning: ITelnyxWarning) => void) | null; private static readonly CONSECUTIVE_BREACHES_REQUIRED; private static readonly THRESHOLD_RTT_MS; private static readonly THRESHOLD_JITTER_MS; private static readonly THRESHOLD_PACKET_LOSS_PCT; private static readonly THRESHOLD_MOS; private static readonly THRESHOLD_LOCAL_AUDIO_LEVEL; private static readonly CONFIRMED_LOCAL_AUDIO_SILENCE_MS; private static readonly THRESHOLD_INBOUND_AUDIO_LEVEL; private _breachCounters; private _activeWarnings; private _lastWarningEmitted; private static readonly WARNING_THROTTLE_MS; private _prevPacketsReceived; private _prevPacketsLost; private _previousStatsEntryForWarnings; private _lastLocalAudioTrackSnapshotJson; private _hasConfirmedLocalAudio; private _confirmedLocalAudioSilenceMs; private _segmentIndex; private _lastIntermediateFlushTime; private _flushing; private _stopped; private static readonly RETRY_DELAYS_MS; private static readonly KEEPALIVE_BODY_LIMIT_BYTES; constructor(options: ICallReportOptions, logCollectorOptions?: ILogCollectorOptions); start(peerConnection: RTCPeerConnection): void; stop(): Promise<void>; flush(summary: ICallSummary, flushReason?: ICallReportFlushReason): ICallReportPayload | null; postReport(summary: ICallSummary, callReportId: string, host: string, voiceSdkId?: string): Promise<void>; sendPayload(payload: ICallReportPayload, callReportId: string, host: string, voiceSdkId?: string, forceKeepalive?: boolean): Promise<void>; private _sendPayload; getStatsBuffer(): IStatsInterval[]; shouldForceRelayCandidateForRecovery(): boolean; getLogs(): ILogEntry[]; private _positiveDelta; cleanup(): void; private _scheduleNextCollection; private _collectionIntervalFor; private _positiveInterval; private _collectStats; private _getIntermediateReportInterval; private _requestIntermediateFlushIfNeeded; private _checkQualityWarnings; private _trackLowLocalAudio; private _resetLowLocalAudioWarning; private _getStatsIntervalDurationMs; private _trackLowInboundAudio; private _trackBreach; private _emitWarningOncePerEpisode; private _emitWarning; private _createStatsEntry; private _resolveCandidate; private _getCodec; private _buildCodecSnapshot; private _getOutboundMediaSource; private _getLocalAudioTrackSnapshot; private _getOutboundAudioSourceStats; private _logLocalAudioTrackSnapshot; private _withoutUndefined; private _stableStringify; private _sortObjectKeys; private _getOutboundAudioLevel; private _getInboundAudioLevel; private _computeAudioLevelFromEnergy; private _getTrackAudioLevel; private _average; private _resetIntervalAccumulators; } export {};