@exotel-npm-dev/webrtc-client-sdk 1.0.16 → 1.0.17

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.
package/Changelog CHANGED
@@ -1,6 +1,9 @@
1
1
  Change Log
2
2
 
3
- ## v1.0.15 21 November, 2024
3
+ ## v1.0.17 08 January, 2025
4
+ -[VST-865] Added option in websdk to select the codec preference
5
+
6
+ ## v1.0.16 21 November, 2024
4
7
  -[VST-885] Retry Support for SDK Websocket Connection
5
8
 
6
9
  ## v1.0.14 12 September, 2024
package/Makefile CHANGED
@@ -14,3 +14,5 @@ dep:
14
14
  npm uninstall @exotel-npm-dev/webrtc-core-sdk
15
15
  npm install @exotel-npm-dev/webrtc-core-sdk@latest
16
16
 
17
+ publish: build
18
+ npm publish
package/dist/exotelsdk.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  *
3
- * WebRTC CLient SIP version 1.0.16
3
+ * WebRTC CLient SIP version 1.0.17
4
4
  *
5
5
  */
6
6
  (function webpackUniversalModuleDefinition(root, factory) {
@@ -53,7 +53,7 @@ const audioDeviceManager = {
53
53
  resetOutputDevice: false,
54
54
  currentAudioInputDeviceId: "default",
55
55
  currentAudioOutputDeviceId: "default",
56
- mediaDevices: [],
56
+
57
57
 
58
58
  // Method to set the resetInputDevice flag
59
59
  setResetInputDeviceFlag(value) {
@@ -69,14 +69,14 @@ const audioDeviceManager = {
69
69
  logger.log(`SIPJSPhone:changeAudioInputDevice entry`);
70
70
  try {
71
71
  if (deviceId == audioDeviceManager.currentAudioInputDeviceId) {
72
- logger.log(`SIPJSPhone:changeAudioInputDevice current input device is same as ${deviceId} hence not changing`);
73
- if (onError) onError("current input device is same as " + deviceId + " hence not changing");
72
+ logger.log(`SIPJSPhone:changeAudioInputDevice current input device is same as ${deviceId}`);
74
73
  return;
75
74
  }
76
- const inputDevice = audioDeviceManager.mediaDevices.find(device => device.deviceId === deviceId && device.kind === 'audioinput');
75
+ const devices = await navigator.mediaDevices.enumerateDevices();
76
+ const inputDevice = devices.find(device => device.deviceId === deviceId && device.kind === 'audioinput');
77
77
  if (!inputDevice) {
78
78
  logger.error("input device id " + deviceId + "not found");
79
- if (onError) onError("deviceIdNotFound");
79
+ onError("deviceIdNotFound");
80
80
  return;
81
81
  }
82
82
  logger.log(`SIPJSPhone:changeAudioInputDevice acquiring input device ${deviceId} : ${inputDevice.label}`);
@@ -86,7 +86,7 @@ const audioDeviceManager = {
86
86
  onSuccess(stream);
87
87
  } catch (error) {
88
88
  logger.error('SIPJSPhone:changeAudioInputDevice Error changing input device:', error);
89
- if (onError) onError(error);
89
+ onError(error);
90
90
  }
91
91
  },
92
92
 
@@ -94,26 +94,19 @@ const audioDeviceManager = {
94
94
  logger.log(`audioDeviceManager:changeAudioOutputDevice : entry`);
95
95
  if (deviceId == audioDeviceManager.currentAudioOutputDeviceId) {
96
96
  logger.log(`SIPJSPhone:changeAudioOutputDevice current output device is same as ${deviceId}`);
97
- if (onError) onError("current output device is same as " + deviceId);
98
97
  return;
99
98
  }
100
99
  const audioElement = audioRemote;
101
100
  if (typeof audioElement.sinkId !== 'undefined') {
102
101
  try {
103
-
104
- if (!audioDeviceManager.mediaDevices || audioDeviceManager.mediaDevices.length == 0) {
105
- logger.error("audioDeviceManager:changeAudioOutputDevice mediaDeviceList is empty ");
106
- if (onError) logger.error(deviceId + "not found in mediaDeviceList in audioManager");
107
- return;
108
- }
109
- const outputDevice = audioDeviceManager.mediaDevices.find(device => device.deviceId === deviceId && device.kind === 'audiooutput');
102
+ const devices = await navigator.mediaDevices.enumerateDevices();
103
+ const outputDevice = devices.find(device => device.deviceId === deviceId && device.kind === 'audiooutput');
110
104
  if (!outputDevice) {
111
105
  logger.error("audioDeviceManager:changeAudioOutputDevice output device id " + deviceId + "not found");
112
- if (onError) onError("deviceIdNotFound");
106
+ onError("deviceIdNotFound");
113
107
  return;
114
108
  }
115
- logger.log(`audioDeviceManager:changeAudioOutputDevice acquiring output device ${deviceId} : ${outputDevice.label}`);
116
- // audioElement.load();
109
+ logger.log(`SIPJSPhone:changeAudioOutputDevice acquiring output device ${deviceId} : ${outputDevice.label}`);
117
110
  await audioElement.setSinkId(deviceId);
118
111
  audioDeviceManager.currentAudioOutputDeviceId = deviceId;
119
112
  logger.log(`audioDeviceManager:changeAudioOutputDevice Output device changed to: ${deviceId}`);
@@ -143,20 +136,21 @@ const audioDeviceManager = {
143
136
  async _resetAudioDevice(audioRemote, onInputDeviceChangeCallback, onOutputDeviceChangecallback, resetOutputDevice, resetInputDevice) {
144
137
  logger.log("audioDeviceManager:_resetAudioDevice entry");
145
138
  try {
139
+ const devices = await navigator.mediaDevices.enumerateDevices();
146
140
 
147
141
  if (resetOutputDevice) {
148
- const defaultOutputDevice = audioDeviceManager.mediaDevices.find(device => device.deviceId === "default" && device.kind === 'audiooutput');
149
- const outputDevice = audioDeviceManager.mediaDevices.find(device => device.groupId == defaultOutputDevice.groupId && device.kind === 'audiooutput' && device.deviceId != 'default');
142
+ const defaultOutputDevice = devices.find(device => device.deviceId === "default" && device.kind === 'audiooutput');
143
+ const outputDevice = devices.find(device => device.groupId == defaultOutputDevice.groupId && device.kind === 'audiooutput' && device.deviceId != 'default');
150
144
 
151
145
  audioDeviceManager.changeAudioOutputDevice(audioRemote,
152
146
  outputDevice.deviceId,
153
147
  () => onOutputDeviceChangecallback(outputDevice.deviceId),
154
- (error) => logger.error(`audioDeviceManager:_resetAudioDevice Failed to change output device: ${error}`)
148
+ (error) => logger.log(`audioDeviceManager:_resetAudioDevice Failed to change output device: ${error}`)
155
149
  );
156
150
  }
157
151
  if (resetInputDevice) {
158
- const defaultInputDevice = audioDeviceManager.mediaDevices.find(device => device.deviceId === "default" && device.kind === 'audioinput');
159
- const inputDevice = audioDeviceManager.mediaDevices.find(device => device.groupId == defaultInputDevice.groupId && device.kind === 'audioinput' && device.deviceId != 'default');
152
+ const defaultInputDevice = devices.find(device => device.deviceId === "default" && device.kind === 'audioinput');
153
+ const inputDevice = devices.find(device => device.groupId == defaultInputDevice.groupId && device.kind === 'audioinput' && device.deviceId != 'default');
160
154
  audioDeviceManager.changeAudioInputDevice(
161
155
  inputDevice.deviceId,
162
156
  (stream) => onInputDeviceChangeCallback(stream, inputDevice.deviceId),
@@ -164,23 +158,13 @@ const audioDeviceManager = {
164
158
  );
165
159
  }
166
160
  } catch (error) {
167
- logger.error("audioDeviceManager:_resetAudioDevice reset audio device failed", error);
161
+ logger.log("audioDeviceManager:_resetAudioDevice something went wrong", error);
168
162
  }
169
163
  },
170
164
 
171
- async enumerateDevices(callback) {
172
- logger.log("audioDeviceManager:enumerateDevices entry")
173
- try {
174
- audioDeviceManager.mediaDevices = await navigator.mediaDevices.enumerateDevices();
175
- } catch (e) {
176
- logger.log("audioDeviceManager:enumerateDevices device enumeration failed", e);
177
- }
178
- if (callback) callback();
179
- },
180
-
181
165
  };
182
166
 
183
- audioDeviceManager.enumerateDevices();
167
+
184
168
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (audioDeviceManager);
185
169
 
186
170
  /***/ }),
@@ -21233,6 +21217,90 @@ function postInit(onInitDoneCallback) {
21233
21217
  onInitDoneCallback();
21234
21218
  }
21235
21219
 
21220
+ const addPreferredCodec = (description) => {
21221
+ logger.log("sipjsphone:addPreferredCodec entry");
21222
+ // Ensure a preferred codec is set
21223
+ if (!SIPJSPhone.preferredCodec) {
21224
+ logger.info("sipjsphone:addPreferredCodec: No preferred codec set. Using default.");
21225
+ return Promise.resolve(description);
21226
+ }
21227
+
21228
+ const { payloadType, rtpMap, fmtp } = SIPJSPhone.preferredCodec;
21229
+ const codecRtpMap = `a=rtpmap:${payloadType} ${rtpMap}`;
21230
+ const codecFmtp = fmtp ? `a=fmtp:${payloadType} ${fmtp}` : "";
21231
+
21232
+ logger.log("sipjsphone:addPreferredCodec: Original SDP:", description.sdp);
21233
+
21234
+ // Parse SDP into lines
21235
+ let sdpLines = description.sdp.split("\r\n");
21236
+
21237
+ // Check if Opus is already in the SDP
21238
+ const existingOpusIndex = sdpLines.findIndex((line) => line.includes(`a=rtpmap`) && line.includes("opus/48000/2"));
21239
+ const audioMLineIndex = sdpLines.findIndex((line) => line.startsWith("m=audio"));
21240
+
21241
+ if (existingOpusIndex !== -1 && audioMLineIndex !== -1) {
21242
+ logger.log("sipjsphone:addPreferredCodec: Opus codec already exists. Prioritizing it.");
21243
+
21244
+ // Extract and modify the audio m-line
21245
+ let audioMLine = sdpLines[audioMLineIndex];
21246
+ audioMLine = audioMLine.replace("RTP/SAVP", "RTP/AVP");
21247
+
21248
+ const codecs = audioMLine.split(" ");
21249
+ const mLineStart = codecs.slice(0, 3); // "m=audio <port> <protocol>"
21250
+ const mLineCodecs = codecs.slice(3);
21251
+
21252
+ // Move existing Opus payload type to the top
21253
+ const opusPayloadType = sdpLines[existingOpusIndex].match(/a=rtpmap:(\d+)/)[1];
21254
+ const opusIndex = mLineCodecs.indexOf(opusPayloadType);
21255
+
21256
+ if (opusIndex !== -1) {
21257
+ // Remove Opus from its current position
21258
+ mLineCodecs.splice(opusIndex, 1);
21259
+ }
21260
+ // Add Opus to the beginning of the codec list
21261
+ mLineCodecs.unshift(opusPayloadType);
21262
+
21263
+ // Update the audio m-line
21264
+ sdpLines[audioMLineIndex] = `${mLineStart.join(" ")} ${mLineCodecs.join(" ")}`;
21265
+ } else if (audioMLineIndex !== -1) {
21266
+ logger.log("sipjsphone:addPreferredCodec: Opus codec not found. Adding it to SDP.");
21267
+
21268
+ // Extract and modify the audio m-line
21269
+ let audioMLine = sdpLines[audioMLineIndex];
21270
+ audioMLine = audioMLine.replace("RTP/SAVP", "RTP/AVP");
21271
+
21272
+ const codecs = audioMLine.split(" ");
21273
+ const mLineStart = codecs.slice(0, 3); // "m=audio <port> <protocol>"
21274
+ const mLineCodecs = codecs.slice(3);
21275
+
21276
+ // Add Opus payload type to the top
21277
+ mLineCodecs.unshift(payloadType.toString());
21278
+
21279
+ // Update the audio m-line
21280
+ sdpLines[audioMLineIndex] = `${mLineStart.join(" ")} ${mLineCodecs.join(" ")}`;
21281
+
21282
+ // Add Opus-specific attributes to the SDP
21283
+ if (!sdpLines.includes(codecRtpMap)) {
21284
+ sdpLines.splice(audioMLineIndex + 1, 0, codecRtpMap); // Add rtpmap after m=audio
21285
+ }
21286
+ if (fmtp && !sdpLines.includes(codecFmtp)) {
21287
+ sdpLines.splice(audioMLineIndex + 2, 0, codecFmtp); // Add fmtp after rtpmap
21288
+ }
21289
+ } else {
21290
+ logger.error("sipjsphone:addPreferredCodec: No audio m-line found in SDP. Cannot modify.");
21291
+ return Promise.resolve(description);
21292
+ }
21293
+
21294
+ // Remove any duplicate lines
21295
+ sdpLines = [...new Set(sdpLines)];
21296
+
21297
+ // Combine back into SDP
21298
+ description.sdp = sdpLines.join("\r\n");
21299
+ logger.log("sipjsphone:addPreferredCodec: Modified SDP:", description.sdp);
21300
+
21301
+ return Promise.resolve(description);
21302
+ };
21303
+
21236
21304
  function sipRegister() {
21237
21305
 
21238
21306
  lastRegistererState = "";
@@ -21951,6 +22019,23 @@ const SIPJSPhone = {
21951
22019
  return bMicEnable;
21952
22020
  },
21953
22021
 
22022
+ setPreferredCodec: (codecName) => {
22023
+ logger.log("sipjsphone:setPreferredCodec entry");
22024
+ const codecPayloadTypes = {
22025
+ opus: { payloadType: 111, rtpMap: "opus/48000/2", fmtp: "minptime=10;useinbandfec=1" },
22026
+ };
22027
+
22028
+ const preferredCodec = codecPayloadTypes[codecName.toLowerCase()];
22029
+ if (!preferredCodec) {
22030
+ logger.error("sipjsphone:setPreferredCodec: Unsupported code" + codecName + "specified.");
22031
+ SIPJSPhone.preferredCodec = null; // Clear codec details if unsupported
22032
+ return;
22033
+ }
22034
+
22035
+ SIPJSPhone.preferredCodec = preferredCodec;
22036
+ logger.log("sipjsphone:setPreferredCodec: Preferred codec set to " + codecName);
22037
+ },
22038
+
21954
22039
  pickPhoneCall: () => {
21955
22040
  var newSess = ctxSip.Sessions[ctxSip.callActiveID];
21956
22041
  logger.log("pickphonecall ", ctxSip.callActiveID);
@@ -21958,14 +22043,16 @@ const SIPJSPhone = {
21958
22043
  if (_audioDeviceManager_js__WEBPACK_IMPORTED_MODULE_0__.audioDeviceManager.currentAudioInputDeviceId != "default") {
21959
22044
  newSess.accept({
21960
22045
  sessionDescriptionHandlerOptions: {
21961
- constraints: { audio: { deviceId: _audioDeviceManager_js__WEBPACK_IMPORTED_MODULE_0__.audioDeviceManager.currentAudioInputDeviceId }, video: false }
21962
- }
22046
+ constraints: { audio: { deviceId: _audioDeviceManager_js__WEBPACK_IMPORTED_MODULE_0__.audioDeviceManager.currentAudioInputDeviceId }, video: false },
22047
+ },
22048
+ sessionDescriptionHandlerModifiers: [addPreferredCodec],
21963
22049
  }).catch((e) => {
21964
22050
  onUserSessionAcceptFailed(e);
21965
22051
  });
21966
22052
  } else {
21967
-
21968
- newSess.accept().catch((e) => {
22053
+ newSess.accept({
22054
+ sessionDescriptionHandlerModifiers: [addPreferredCodec]
22055
+ }).catch((e) => {
21969
22056
  onUserSessionAcceptFailed(e);
21970
22057
  });
21971
22058
  }
@@ -22048,30 +22135,21 @@ const SIPJSPhone = {
22048
22135
  onSuccess();
22049
22136
  } else {
22050
22137
  logger.error("SIPJSPhone:changeAudioInputDevice failed");
22051
- onError("replaceSenderTrack failed for webrtc");
22138
+ onError("something went wrong , try again");
22052
22139
  }
22053
22140
  }, onError);
22054
22141
  },
22055
- changeAudioOutputDeviceForAdditionalAudioElement(deviceId) {
22056
- const additionalAudioElements = [ringtone, beeptone, ringbacktone, dtmftone];
22057
- let i = 0;
22058
- let elem;
22059
- try {
22060
- for (i = 0; i < additionalAudioElements.length; i++) {
22061
- elem = additionalAudioElements[i];
22062
- elem.load();
22063
- elem.setSinkId(deviceId);
22064
- }
22065
- } catch (e) {
22066
- logger.error("sipjsphone:changeAudioOutputDeviceForAdditionalAudioElement failed to setSink for additonal AudioElements", e);
22067
- }
22142
+ onRemoteAudioOutputDeviceChanged(deviceId) {
22143
+ ringtone.setSinkId(deviceId).catch((e) => {
22144
+ logger.error("sipjsphone:onRemoteAudioOutputDeviceChanged ringtone changedevice failure ", e);
22145
+ });
22068
22146
  },
22069
22147
  changeAudioOutputDevice(deviceId, onSuccess, onError) {
22070
22148
  if (!ctxSip.callActiveID) {
22071
22149
  audioRemote = document.createElement("audio");
22072
22150
  }
22073
22151
  _audioDeviceManager_js__WEBPACK_IMPORTED_MODULE_0__.audioDeviceManager.changeAudioOutputDevice(audioRemote, deviceId, function () {
22074
- SIPJSPhone.changeAudioOutputDeviceForAdditionalAudioElement(deviceId);
22152
+ SIPJSPhone.onRemoteAudioOutputDeviceChanged(deviceId);
22075
22153
  onSuccess();
22076
22154
  }, onError);
22077
22155
  },
@@ -22123,12 +22201,11 @@ const SIPJSPhone = {
22123
22201
  },
22124
22202
  audioInputDeviceChangeCallback: null,
22125
22203
  audioOutputDeviceChangeCallback: null,
22126
- onDeviceChangeCallback: null,
22127
- registerAudioDeviceChangeCallback(audioInputDeviceChangeCallback, audioOutputDeviceChangeCallback, onDeviceChangeCallback) {
22204
+ registerAudioDeviceChangeCallback(audioInputDeviceChangeCallback, audioOutputDeviceChangeCallback) {
22128
22205
  logger.log(`SIPJSPhone:registerAudioDeviceChangeCallback entry`);
22129
22206
  SIPJSPhone.audioInputDeviceChangeCallback = audioInputDeviceChangeCallback;
22130
22207
  SIPJSPhone.audioOutputDeviceChangeCallback = audioOutputDeviceChangeCallback;
22131
- SIPJSPhone.onDeviceChangeCallback = onDeviceChangeCallback;
22208
+
22132
22209
  }
22133
22210
 
22134
22211
  };
@@ -22139,31 +22216,22 @@ navigator.mediaDevices.addEventListener('devicechange', function (event) {
22139
22216
  if (!ctxSip.callActiveID) {
22140
22217
  audioRemote = document.createElement("audio");
22141
22218
  }
22142
- _audioDeviceManager_js__WEBPACK_IMPORTED_MODULE_0__.audioDeviceManager.enumerateDevices(function () {
22143
-
22144
- if (SIPJSPhone.onDeviceChangeCallback) {
22145
- logger.info("SIPJSPhone:ondevicechange relaying event to callback");
22146
- SIPJSPhone.onDeviceChangeCallback(event);
22147
- return;
22148
- }
22149
- _audioDeviceManager_js__WEBPACK_IMPORTED_MODULE_0__.audioDeviceManager.onAudioDeviceChange(audioRemote,
22150
- function (stream, deviceId) {
22151
- const trackChanged = SIPJSPhone.replaceSenderTrack(stream, deviceId);
22152
- if (trackChanged) {
22153
- _audioDeviceManager_js__WEBPACK_IMPORTED_MODULE_0__.audioDeviceManager.currentAudioInputDeviceId = deviceId;
22154
- if (SIPJSPhone.audioInputDeviceChangeCallback) {
22155
- SIPJSPhone.audioInputDeviceChangeCallback(deviceId);
22156
- }
22157
- }
22158
- }, function (deviceId) {
22159
- SIPJSPhone.changeAudioOutputDeviceForAdditionalAudioElement(deviceId);
22160
- _audioDeviceManager_js__WEBPACK_IMPORTED_MODULE_0__.audioDeviceManager.currentAudioOutputDeviceId = deviceId;
22161
- if (SIPJSPhone.audioOutputDeviceChangeCallback) {
22162
- SIPJSPhone.audioOutputDeviceChangeCallback(deviceId);
22219
+ _audioDeviceManager_js__WEBPACK_IMPORTED_MODULE_0__.audioDeviceManager.onAudioDeviceChange(audioRemote,
22220
+ function (stream, deviceId) {
22221
+ const trackChanged = SIPJSPhone.replaceSenderTrack(stream, deviceId);
22222
+ if (trackChanged) {
22223
+ _audioDeviceManager_js__WEBPACK_IMPORTED_MODULE_0__.audioDeviceManager.currentAudioInputDeviceId = deviceId;
22224
+ if (SIPJSPhone.audioInputDeviceChangeCallback) {
22225
+ SIPJSPhone.audioInputDeviceChangeCallback(deviceId);
22163
22226
  }
22164
- });
22165
- });
22166
-
22227
+ }
22228
+ }, function (deviceId) {
22229
+ SIPJSPhone.onRemoteAudioOutputDeviceChanged(deviceId);
22230
+ _audioDeviceManager_js__WEBPACK_IMPORTED_MODULE_0__.audioDeviceManager.currentAudioOutputDeviceId = deviceId;
22231
+ if (SIPJSPhone.audioOutputDeviceChangeCallback) {
22232
+ SIPJSPhone.audioOutputDeviceChangeCallback(deviceId);
22233
+ }
22234
+ });
22167
22235
  } catch (e) {
22168
22236
  logger.error("SIPJSPhone:ondevicechange something went wrong during device change", e);
22169
22237
  }
@@ -22394,9 +22462,15 @@ const webrtcSIPPhone = {
22394
22462
  logger.log(`webrtcSIPPhone:changeAudioOutputDevice entry`);
22395
22463
  _sipjsphone__WEBPACK_IMPORTED_MODULE_1__["default"].changeAudioOutputDevice(deviceId, onSuccess, onError);
22396
22464
  },
22397
- registerAudioDeviceChangeCallback(audioInputDeviceChangeCallback, audioOutputDeviceChangeCallback, onDeviceChangeCallback) {
22465
+
22466
+ setPreferredCodec(codecName) {
22467
+ logger.log("webrtcSIPPhone:setPreferredCodec entry");
22468
+ _sipjsphone__WEBPACK_IMPORTED_MODULE_1__["default"].setPreferredCodec(codecName);
22469
+ },
22470
+
22471
+ registerAudioDeviceChangeCallback(audioInputDeviceChangeCallback, audioOutputDeviceChangeCallback) {
22398
22472
  logger.log(`webrtcSIPPhone:registerAudioDeviceChangeCallback entry`);
22399
- _sipjsphone__WEBPACK_IMPORTED_MODULE_1__["default"].registerAudioDeviceChangeCallback(audioInputDeviceChangeCallback, audioOutputDeviceChangeCallback, onDeviceChangeCallback);
22473
+ _sipjsphone__WEBPACK_IMPORTED_MODULE_1__["default"].registerAudioDeviceChangeCallback(audioInputDeviceChangeCallback, audioOutputDeviceChangeCallback);
22400
22474
  },
22401
22475
  getLogger() {
22402
22476
  return _coreSDKLogger__WEBPACK_IMPORTED_MODULE_0__["default"];
@@ -24326,6 +24400,10 @@ class ExotelWebClient {
24326
24400
  logger.log(`in changeAudioOutputDevice() of ExWebClient.js`);
24327
24401
  _exotel_npm_dev_webrtc_core_sdk__WEBPACK_IMPORTED_MODULE_8__.webrtcSIPPhone.changeAudioOutputDevice(deviceId, onSuccess, onError);
24328
24402
  }
24403
+ setPreferredCodec(codecName) {
24404
+ logger.log("ExWebClient:setPreferredCodec entry");
24405
+ _exotel_npm_dev_webrtc_core_sdk__WEBPACK_IMPORTED_MODULE_8__.webrtcSIPPhone.setPreferredCodec(codecName);
24406
+ }
24329
24407
  registerLoggerCallback(callback) {
24330
24408
  logger.registerLoggerCallback(callback);
24331
24409
  }