@telnyx/webrtc 2.27.0-beta.2 → 2.27.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,6 +22,7 @@ export default abstract class BaseSession {
22
22
  invalidMethodErrorCode: number;
23
23
  authenticationRequiredErrorCode: number;
24
24
  callReportId: string | null;
25
+ callReportVoiceSdkId: string | null;
25
26
  dc: string | null;
26
27
  region: string | null;
27
28
  connection: Connection;
@@ -30,8 +31,11 @@ export default abstract class BaseSession {
30
31
  protected _reconnectTimeout: any;
31
32
  protected _autoReconnect: boolean;
32
33
  protected _idle: boolean;
34
+ protected _reconnectAttempts: number;
33
35
  private _tokenExpiryTimeout;
34
36
  private static readonly TOKEN_EXPIRY_WARNING_SECONDS;
37
+ private static readonly CALL_REPORT_UPLOAD_DRAIN_TIMEOUT_MS;
38
+ private _pendingCallReportUploads;
35
39
  private _executeQueue;
36
40
  private _pong;
37
41
  private registerAgent;
@@ -42,6 +46,8 @@ export default abstract class BaseSession {
42
46
  get reconnectDelay(): number;
43
47
  execute(msg: BaseMessage): Promise<any>;
44
48
  executeRaw(text: string): void;
49
+ trackCallReportUpload(upload: Promise<void>): void;
50
+ private _drainCallReportUploads;
45
51
  validateOptions(): boolean;
46
52
  broadcast(_params: BroadcastParams): void;
47
53
  disconnect(): Promise<void>;
@@ -54,6 +60,7 @@ export default abstract class BaseSession {
54
60
  off(eventName: SwEvent.Notification | 'telnyx.notification', callback?: (event: INotification) => void): this;
55
61
  off(eventName: string, callback?: Function): this;
56
62
  connect(): Promise<void>;
63
+ resetReconnectAttempts(): void;
57
64
  protected _handleLoginError(error: any): void;
58
65
  clearReconnectToken(): void;
59
66
  private _checkTokenExpiry;
@@ -66,7 +73,16 @@ export default abstract class BaseSession {
66
73
  }): Promise<void>;
67
74
  private _login;
68
75
  protected _onSocketOpen(): Promise<void>;
69
- onNetworkClose(): void;
76
+ private _flushIntermediateCallReports;
77
+ private _getSocketCloseCodeName;
78
+ private _getSocketCloseError;
79
+ private _createSocketCloseFlushReason;
80
+ onNetworkClose(event?: {
81
+ code?: number;
82
+ reason?: string;
83
+ wasClean?: boolean;
84
+ error?: unknown;
85
+ }): void;
70
86
  protected _onSocketMessage(_response: any): void;
71
87
  protected _removeSubscription(protocol: string, channel?: string): void;
72
88
  protected _addSubscription(protocol: string, handler: Function, channel: string): void;
@@ -28,6 +28,7 @@ export declare const TELNYX_WARNING_CODES: {
28
28
  readonly HIGH_JITTER: 31002;
29
29
  readonly HIGH_PACKET_LOSS: 31003;
30
30
  readonly LOW_MOS: 31004;
31
+ readonly LOW_LOCAL_AUDIO: 31005;
31
32
  readonly LOW_BYTES_RECEIVED: 32001;
32
33
  readonly LOW_BYTES_SENT: 32002;
33
34
  readonly ICE_CONNECTIVITY_LOST: 33001;
@@ -41,5 +42,5 @@ export declare const TELNYX_WARNING_CODES: {
41
42
  readonly SESSION_NOT_REATTACHED: 35001;
42
43
  };
43
44
  export declare const SDP_CREATE_OFFER_FAILED: 40001, SDP_CREATE_ANSWER_FAILED: 40002, SDP_SET_LOCAL_DESCRIPTION_FAILED: 40003, SDP_SET_REMOTE_DESCRIPTION_FAILED: 40004, SDP_SEND_FAILED: 40005, MEDIA_MICROPHONE_PERMISSION_DENIED: 42001, MEDIA_DEVICE_NOT_FOUND: 42002, MEDIA_GET_USER_MEDIA_FAILED: 42003, HOLD_FAILED: 44001, INVALID_CALL_PARAMETERS: 44002, BYE_SEND_FAILED: 44003, SUBSCRIBE_FAILED: 44004, PEER_CLOSED_DURING_INIT: 44005, WEBSOCKET_CONNECTION_FAILED: 45001, WEBSOCKET_ERROR: 45002, RECONNECTION_EXHAUSTED: 45003, GATEWAY_FAILED: 45004, LOGIN_FAILED: 46001, INVALID_CREDENTIALS: 46002, AUTHENTICATION_REQUIRED: 46003, ICE_RESTART_FAILED: 47001, NETWORK_OFFLINE: 48001, UNEXPECTED_ERROR: 49001;
44
- export declare const HIGH_RTT: 31001, HIGH_JITTER: 31002, HIGH_PACKET_LOSS: 31003, LOW_MOS: 31004, LOW_BYTES_RECEIVED: 32001, LOW_BYTES_SENT: 32002, ICE_CONNECTIVITY_LOST: 33001, ICE_GATHERING_TIMEOUT: 33002, ICE_GATHERING_EMPTY: 33003, PEER_CONNECTION_FAILED: 33004, ONLY_HOST_ICE_CANDIDATES: 33005, ANSWER_WHILE_PEER_ACTIVE: 33006, DUPLICATE_INBOUND_ANSWER: 33007, TOKEN_EXPIRING_SOON: 34001, SESSION_NOT_REATTACHED: 35001;
45
+ export declare const HIGH_RTT: 31001, HIGH_JITTER: 31002, HIGH_PACKET_LOSS: 31003, LOW_MOS: 31004, LOW_LOCAL_AUDIO: 31005, LOW_BYTES_RECEIVED: 32001, LOW_BYTES_SENT: 32002, ICE_CONNECTIVITY_LOST: 33001, ICE_GATHERING_TIMEOUT: 33002, ICE_GATHERING_EMPTY: 33003, PEER_CONNECTION_FAILED: 33004, ONLY_HOST_ICE_CANDIDATES: 33005, ANSWER_WHILE_PEER_ACTIVE: 33006, DUPLICATE_INBOUND_ANSWER: 33007, TOKEN_EXPIRING_SOON: 34001, SESSION_NOT_REATTACHED: 35001;
45
46
  export declare const HAS_NON_HOST_ICE_CANDIDATE_REGEX: RegExp;
@@ -40,6 +40,13 @@ export declare const SDK_WARNINGS: {
40
40
  readonly causes: readonly ["Combination of high latency, jitter, and/or packet loss", "Poor network conditions"];
41
41
  readonly solutions: readonly ["Check network connectivity", "Use a wired connection", "Close bandwidth-heavy applications"];
42
42
  };
43
+ readonly 31005: {
44
+ readonly name: "LOW_LOCAL_AUDIO";
45
+ readonly message: "Low local microphone audio detected";
46
+ 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.";
47
+ 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"];
48
+ 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"];
49
+ };
43
50
  readonly 32001: {
44
51
  readonly name: "LOW_BYTES_RECEIVED";
45
52
  readonly message: "No audio data received";
@@ -33,8 +33,10 @@ export interface IVertoOptions {
33
33
  rtcIp?: string;
34
34
  rtcPort?: number;
35
35
  mutedMicOnStart?: boolean;
36
+ maxReconnectAttempts?: number;
36
37
  enableCallReports?: boolean;
37
38
  callReportInterval?: number;
39
+ callReportFlushInterval?: number;
38
40
  debugLogLevel?: 'debug' | 'info' | 'warn' | 'error';
39
41
  debugLogMaxEntries?: number;
40
42
  skipLastVoiceSdkId?: boolean;
@@ -9,7 +9,7 @@ declare const streamIsValid: (stream: MediaStream) => boolean;
9
9
  declare const audioIsMediaTrackConstraints: (audio: boolean | MediaTrackConstraints) => boolean;
10
10
  declare const videoIsMediaTrackConstraints: (video: boolean | MediaTrackConstraints) => boolean;
11
11
  declare const attachMediaStream: (tag: any, stream: MediaStream) => void;
12
- declare const detachMediaStream: (tag: any) => void;
12
+ declare const detachMediaStream: (tag: any, stream?: MediaStream) => void;
13
13
  declare const muteMediaElement: (tag: any) => void;
14
14
  declare const unmuteMediaElement: (tag: any) => void;
15
15
  declare const toggleMuteMediaElement: (tag: any) => void;
@@ -5,7 +5,7 @@ declare const _enumerateDevices: () => any;
5
5
  declare const streamIsValid: (stream: MediaStream) => boolean;
6
6
  declare const getSupportedConstraints: () => {};
7
7
  declare const attachMediaStream: (htmlElementId: string, stream: MediaStream) => any;
8
- declare const detachMediaStream: (htmlElementId: string) => any;
8
+ declare const detachMediaStream: (htmlElementId: string, _stream?: MediaStream) => any;
9
9
  declare const muteMediaElement: (htmlElementId: string) => any;
10
10
  declare const unmuteMediaElement: (htmlElementId: string) => any;
11
11
  declare const toggleMuteMediaElement: (htmlElementId: string) => any;
@@ -1,4 +1,5 @@
1
1
  import BrowserSession from '../BrowserSession';
2
+ import { type ICallReportFlushReason } from './CallReportCollector';
2
3
  import Call from './Call';
3
4
  import Peer from './Peer';
4
5
  import { Direction, State } from './constants';
@@ -122,6 +123,8 @@ export default abstract class BaseCall implements IWebRTCCall {
122
123
  private _hasUsablePeerConnection;
123
124
  private _init;
124
125
  protected _finalize(): void;
126
+ private _getCallReportVoiceSdkId;
127
+ flushIntermediateCallReport(flushReason?: ICallReportFlushReason): void;
125
128
  private _flushIntermediateReport;
126
129
  private _postCallReport;
127
130
  private _startStats;
@@ -7,6 +7,7 @@ export interface ICallEstablishmentTimings {
7
7
  delta: number;
8
8
  }>;
9
9
  }
10
- export declare function collectCallEstablishmentTimings(mode: 'trickle' | 'non-trickle', direction: 'outbound' | 'inbound'): ICallEstablishmentTimings;
10
+ export declare function callMarkName(callId: string, suffix: string): string;
11
+ export declare function collectCallEstablishmentTimings(callId: string, mode: 'trickle' | 'non-trickle', direction: 'outbound' | 'inbound'): ICallEstablishmentTimings;
11
12
  export declare function logCallEstablishmentTimings(timings: ICallEstablishmentTimings): void;
12
- export declare function clearCallMarks(): void;
13
+ export declare function clearCallMarks(callId: string): void;
@@ -55,6 +55,7 @@ export interface ITransportStats {
55
55
  export interface ICallReportOptions {
56
56
  enabled: boolean;
57
57
  interval: number;
58
+ intermediateReportInterval?: number;
58
59
  }
59
60
  export interface ILogCollectorOptions {
60
61
  enabled: boolean;
@@ -112,11 +113,22 @@ export interface ICallSummary {
112
113
  startTimestamp?: string;
113
114
  endTimestamp?: string;
114
115
  }
116
+ export interface ICallReportFlushReason {
117
+ type: 'buffer-limit' | 'manual' | 'socket-close' | 'socket-error';
118
+ socketClose?: {
119
+ code?: number;
120
+ codeName?: string;
121
+ reason?: string;
122
+ wasClean?: boolean;
123
+ error?: string;
124
+ };
125
+ }
115
126
  export interface ICallReportPayload {
116
127
  summary: ICallSummary;
117
128
  stats: IStatsInterval[];
118
129
  logs?: ILogEntry[];
119
130
  segment?: number;
131
+ flushReason?: ICallReportFlushReason;
120
132
  }
121
133
  export declare class CallReportCollector {
122
134
  private options;
@@ -134,9 +146,12 @@ export declare class CallReportCollector {
134
146
  private intervalBitrates;
135
147
  private previousStats;
136
148
  private previousCandidatePairId;
149
+ private static readonly INITIAL_COLLECTION_INTERVAL_MS;
150
+ private static readonly INITIAL_COLLECTION_DURATION_MS;
137
151
  private readonly MAX_BUFFER_SIZE;
138
152
  private static readonly STATS_FLUSH_THRESHOLD;
139
153
  private static readonly LOGS_FLUSH_THRESHOLD;
154
+ private static readonly DEFAULT_INTERMEDIATE_REPORT_INTERVAL_MS;
140
155
  onFlushNeeded: (() => void) | null;
141
156
  onWarning: ((warning: ITelnyxWarning) => void) | null;
142
157
  private static readonly CONSECUTIVE_BREACHES_REQUIRED;
@@ -144,6 +159,8 @@ export declare class CallReportCollector {
144
159
  private static readonly THRESHOLD_JITTER_MS;
145
160
  private static readonly THRESHOLD_PACKET_LOSS_PCT;
146
161
  private static readonly THRESHOLD_MOS;
162
+ private static readonly THRESHOLD_LOCAL_AUDIO_LEVEL;
163
+ private static readonly CONFIRMED_LOCAL_AUDIO_SILENCE_MS;
147
164
  private _breachCounters;
148
165
  private _activeWarnings;
149
166
  private _lastWarningEmitted;
@@ -151,22 +168,37 @@ export declare class CallReportCollector {
151
168
  private _prevPacketsReceived;
152
169
  private _prevPacketsLost;
153
170
  private _lastLocalAudioTrackSnapshotJson;
171
+ private _hasConfirmedLocalAudio;
172
+ private _confirmedLocalAudioSilenceMs;
154
173
  private _segmentIndex;
174
+ private _lastIntermediateFlushTime;
155
175
  private _flushing;
156
- private static readonly RETRY_DELAY_MS;
176
+ private _stopped;
177
+ private static readonly RETRY_DELAYS_MS;
178
+ private static readonly KEEPALIVE_BODY_LIMIT_BYTES;
157
179
  constructor(options: ICallReportOptions, logCollectorOptions?: ILogCollectorOptions);
158
180
  start(peerConnection: RTCPeerConnection): void;
159
181
  stop(): Promise<void>;
160
- flush(summary: ICallSummary): ICallReportPayload | null;
182
+ flush(summary: ICallSummary, flushReason?: ICallReportFlushReason): ICallReportPayload | null;
161
183
  postReport(summary: ICallSummary, callReportId: string, host: string, voiceSdkId?: string): Promise<void>;
162
184
  sendPayload(payload: ICallReportPayload, callReportId: string, host: string, voiceSdkId?: string): Promise<void>;
163
185
  private _sendPayload;
164
186
  getStatsBuffer(): IStatsInterval[];
165
187
  getLogs(): ILogEntry[];
166
188
  cleanup(): void;
189
+ private _scheduleNextCollection;
190
+ private _collectionIntervalFor;
191
+ private _positiveInterval;
167
192
  private _collectStats;
193
+ private _getIntermediateReportInterval;
194
+ private _requestIntermediateFlushIfNeeded;
168
195
  private _checkQualityWarnings;
196
+ private _trackLowLocalAudio;
197
+ private _resetLowLocalAudioWarning;
198
+ private _getStatsIntervalDurationMs;
169
199
  private _trackBreach;
200
+ private _emitWarningOncePerEpisode;
201
+ private _emitWarning;
170
202
  private _createStatsEntry;
171
203
  private _resolveCandidate;
172
204
  private _getOutboundMediaSource;
@@ -1,3 +1,4 @@
1
+ import type { ICallReportFlushReason } from './CallReportCollector';
1
2
  import { State } from './constants';
2
3
  export interface IMediaSettings {
3
4
  useSdpASBandwidthKbps?: boolean;
@@ -109,6 +110,7 @@ export interface IWebRTCCall {
109
110
  invite: () => void;
110
111
  answer: (params: AnswerParams) => void;
111
112
  hangup: (params?: IHangupParams, execute?: boolean) => Promise<void>;
113
+ flushIntermediateCallReport?: (reason?: ICallReportFlushReason) => void;
112
114
  hold: () => void;
113
115
  unhold: () => void;
114
116
  toggleHold: () => void;
@@ -35,8 +35,10 @@ export interface IClientOptions {
35
35
  env?: Environment;
36
36
  iceServers?: RTCIceServer[];
37
37
  mutedMicOnStart?: boolean;
38
+ maxReconnectAttempts?: number;
38
39
  enableCallReports?: boolean;
39
40
  callReportInterval?: number;
41
+ callReportFlushInterval?: number;
40
42
  mediaPermissionsRecovery?: {
41
43
  enabled: boolean;
42
44
  timeout: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telnyx/webrtc",
3
- "version": "2.27.0-beta.2",
3
+ "version": "2.27.0-beta.4",
4
4
  "description": "Telnyx WebRTC Client",
5
5
  "keywords": [
6
6
  "telnyx",