@elevenlabs/client 1.1.2 → 1.2.1

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.
Files changed (47) hide show
  1. package/dist/BaseConversation.d.ts +16 -2
  2. package/dist/BaseConversation.d.ts.map +1 -1
  3. package/dist/BaseConversation.js +2 -3
  4. package/dist/BaseConversation.js.map +1 -1
  5. package/dist/InputController.d.ts +13 -0
  6. package/dist/InputController.d.ts.map +1 -1
  7. package/dist/OutputController.d.ts +13 -0
  8. package/dist/OutputController.d.ts.map +1 -1
  9. package/dist/TextConversation.d.ts.map +1 -1
  10. package/dist/TextConversation.js +12 -4
  11. package/dist/TextConversation.js.map +1 -1
  12. package/dist/VoiceConversation.d.ts +3 -3
  13. package/dist/VoiceConversation.d.ts.map +1 -1
  14. package/dist/VoiceConversation.js +21 -42
  15. package/dist/VoiceConversation.js.map +1 -1
  16. package/dist/index.d.ts +2 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/internal.d.ts +2 -0
  20. package/dist/internal.d.ts.map +1 -1
  21. package/dist/internal.js +1 -0
  22. package/dist/internal.js.map +1 -1
  23. package/dist/lib.iife.js +179 -43
  24. package/dist/lib.iife.js.map +1 -1
  25. package/dist/utils/WebRTCConnection.d.ts +14 -2
  26. package/dist/utils/WebRTCConnection.d.ts.map +1 -1
  27. package/dist/utils/WebRTCConnection.js +83 -10
  28. package/dist/utils/WebRTCConnection.js.map +1 -1
  29. package/dist/utils/calculateVolume.d.ts +7 -0
  30. package/dist/utils/calculateVolume.d.ts.map +1 -0
  31. package/dist/utils/calculateVolume.js +17 -0
  32. package/dist/utils/calculateVolume.js.map +1 -0
  33. package/dist/utils/input.d.ts +3 -0
  34. package/dist/utils/input.d.ts.map +1 -1
  35. package/dist/utils/input.js +15 -0
  36. package/dist/utils/input.js.map +1 -1
  37. package/dist/utils/output.d.ts +3 -0
  38. package/dist/utils/output.d.ts.map +1 -1
  39. package/dist/utils/output.js +9 -0
  40. package/dist/utils/output.js.map +1 -1
  41. package/dist/utils/volumeProvider.d.ts +21 -0
  42. package/dist/utils/volumeProvider.d.ts.map +1 -0
  43. package/dist/utils/volumeProvider.js +51 -0
  44. package/dist/utils/volumeProvider.js.map +1 -0
  45. package/dist/version.d.ts +1 -1
  46. package/dist/version.js +1 -1
  47. package/package.json +1 -1
package/dist/lib.iife.js CHANGED
@@ -46,10 +46,11 @@ var ElevenLabsClient = (function(exports) {
46
46
  constructor(options, connection) {
47
47
  this.options = options;
48
48
  this.connection = connection;
49
- if (this.options.onConnect) this.options.onConnect({ conversationId: connection.conversationId });
50
49
  this.connection.onMessage(this.onMessage);
51
50
  this.connection.onDisconnect(this.endSessionWithDetails);
52
51
  this.connection.onModeChange((mode) => this.updateMode(mode));
52
+ }
53
+ markConnected() {
53
54
  this.updateStatus("connected");
54
55
  }
55
56
  endSession() {
@@ -383,7 +384,7 @@ var ElevenLabsClient = (function(exports) {
383
384
  //#region src/sourceInfo.ts
384
385
  let sourceInfo = Object.freeze({
385
386
  name: "js_sdk",
386
- version: "1.1.2"
387
+ version: "1.2.1"
387
388
  });
388
389
  //#endregion
389
390
  //#region src/utils/events.ts
@@ -21929,6 +21930,66 @@ class RawAudioProcessor extends AudioWorkletProcessor {
21929
21930
  }
21930
21931
  registerProcessor("rawAudioProcessor", RawAudioProcessor);
21931
21932
  `);
21933
+ //#endregion
21934
+ //#region src/utils/calculateVolume.ts
21935
+ /**
21936
+ * Calculate a scalar volume level (0–1) from byte frequency data.
21937
+ *
21938
+ * The value is the mean of all frequency bins normalised to [0, 1].
21939
+ */
21940
+ function calculateVolume(frequencyData) {
21941
+ if (frequencyData.length === 0) return 0;
21942
+ let volume = 0;
21943
+ for (let i = 0; i < frequencyData.length; i++) volume += frequencyData[i] / 255;
21944
+ volume /= frequencyData.length;
21945
+ return volume < 0 ? 0 : volume > 1 ? 1 : volume;
21946
+ }
21947
+ //#endregion
21948
+ //#region src/utils/volumeProvider.ts
21949
+ const NO_VOLUME = {
21950
+ getVolume: () => 0,
21951
+ getByteFrequencyData: () => {}
21952
+ };
21953
+ const MAX_VOICE_FREQUENCY = 8e3;
21954
+ /**
21955
+ * Resamples the voice-relevant portion of raw frequency data into an output
21956
+ * buffer using linear interpolation. This ensures both web and React Native
21957
+ * return comparable frequency data focused on the human voice range.
21958
+ */
21959
+ function resampleVoiceRange(raw, buffer, sampleRate) {
21960
+ const binCount = raw.length;
21961
+ const hzPerBin = sampleRate / 2 / binCount;
21962
+ const minBin = Math.floor(100 / hzPerBin);
21963
+ const maxBin = Math.min(Math.ceil(MAX_VOICE_FREQUENCY / hzPerBin), binCount);
21964
+ const voiceBinCount = maxBin - minBin;
21965
+ const outLen = buffer.length;
21966
+ for (let i = 0; i < outLen; i++) {
21967
+ const pos = i / outLen * voiceBinCount;
21968
+ const lo = minBin + Math.floor(pos);
21969
+ const hi = Math.min(lo + 1, maxBin - 1);
21970
+ const t = pos - Math.floor(pos);
21971
+ buffer[i] = Math.round(raw[lo] * (1 - t) + raw[hi] * t);
21972
+ }
21973
+ }
21974
+ function createAnalyserVolumeProvider(analyser, sampleRate) {
21975
+ const binCount = analyser.frequencyBinCount;
21976
+ let rawData;
21977
+ let voiceData;
21978
+ return {
21979
+ getVolume() {
21980
+ rawData ??= new Uint8Array(binCount);
21981
+ voiceData ??= new Uint8Array(binCount);
21982
+ analyser.getByteFrequencyData(rawData);
21983
+ resampleVoiceRange(rawData, voiceData, sampleRate);
21984
+ return calculateVolume(voiceData);
21985
+ },
21986
+ getByteFrequencyData(buffer) {
21987
+ rawData ??= new Uint8Array(binCount);
21988
+ analyser.getByteFrequencyData(rawData);
21989
+ resampleVoiceRange(rawData, buffer, sampleRate);
21990
+ }
21991
+ };
21992
+ }
21932
21993
  //#endregion
21933
21994
  //#region src/utils/WebRTCConnection.ts
21934
21995
  const DEFAULT_LIVEKIT_WS_URL = "wss://livekit.rtc.elevenlabs.io";
@@ -21946,8 +22007,11 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
21946
22007
  audioCaptureContext = null;
21947
22008
  audioElements = [];
21948
22009
  outputDeviceId = null;
22010
+ inputAnalyser = null;
22011
+ inputAudioContext = null;
22012
+ inputVolumeProvider = NO_VOLUME;
21949
22013
  outputAnalyser = null;
21950
- outputFrequencyData = null;
22014
+ outputVolumeProvider = NO_VOLUME;
21951
22015
  _isMuted = false;
21952
22016
  input = {
21953
22017
  close: async () => {
@@ -21970,6 +22034,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
21970
22034
  console.warn("Cannot set microphone muted: room not connected or no local participant");
21971
22035
  return;
21972
22036
  }
22037
+ this._isMuted = isMuted;
21973
22038
  const micTrackPublication = this.room.localParticipant.getTrackPublication(Track.Source.Microphone);
21974
22039
  if (micTrackPublication?.track) try {
21975
22040
  if (isMuted) await micTrackPublication.track.mute();
@@ -21978,10 +22043,24 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
21978
22043
  await this.room.localParticipant.setMicrophoneEnabled(!isMuted);
21979
22044
  }
21980
22045
  else await this.room.localParticipant.setMicrophoneEnabled(!isMuted);
21981
- this._isMuted = isMuted;
22046
+ if (!isMuted) {
22047
+ const track = this.room.localParticipant.getTrackPublication(Track.Source.Microphone)?.track;
22048
+ if (track) this.setupInputAnalyser(track.mediaStreamTrack);
22049
+ }
21982
22050
  },
21983
22051
  isMuted: () => this._isMuted,
21984
- getAnalyser: () => void 0
22052
+ getAnalyser: () => this.inputAnalyser ?? void 0,
22053
+ getVolume: () => {
22054
+ if (this._isMuted) return 0;
22055
+ return this.inputVolumeProvider.getVolume();
22056
+ },
22057
+ getByteFrequencyData: (buffer) => {
22058
+ if (this._isMuted) {
22059
+ buffer.fill(0);
22060
+ return;
22061
+ }
22062
+ this.inputVolumeProvider.getByteFrequencyData(buffer);
22063
+ }
21985
22064
  };
21986
22065
  output = {
21987
22066
  close: async () => {},
@@ -21995,7 +22074,11 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
21995
22074
  this.setAudioVolume(volume);
21996
22075
  },
21997
22076
  interrupt: (_resetDuration) => {},
21998
- getAnalyser: () => this.outputAnalyser ?? void 0
22077
+ getAnalyser: () => this.outputAnalyser ?? void 0,
22078
+ getVolume: () => this.outputVolumeProvider.getVolume(),
22079
+ getByteFrequencyData: (buffer) => {
22080
+ this.outputVolumeProvider.getByteFrequencyData(buffer);
22081
+ }
21999
22082
  };
22000
22083
  constructor(room, conversationId, inputFormat, outputFormat, config = {}) {
22001
22084
  super(config);
@@ -22043,6 +22126,8 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
22043
22126
  }
22044
22127
  });
22045
22128
  await micEnabled;
22129
+ const micTrack = room.localParticipant.getTrackPublication(Track.Source.Microphone)?.track;
22130
+ if (micTrack) connection.setupInputAnalyser(micTrack.mediaStreamTrack);
22046
22131
  if (room.name) connection.conversationId = room.name.match(/(conv_[a-zA-Z0-9]+)/)?.[0] || room.name;
22047
22132
  const overridesEvent = constructOverrides(config);
22048
22133
  connection.debug({
@@ -22126,6 +22211,13 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
22126
22211
  } catch (error) {
22127
22212
  console.warn("Error stopping local tracks:", error);
22128
22213
  }
22214
+ if (this.inputAudioContext) {
22215
+ this.inputAudioContext.close().catch((error) => {
22216
+ console.warn("Error closing input audio context:", error);
22217
+ });
22218
+ this.inputAudioContext = null;
22219
+ this.inputAnalyser = null;
22220
+ }
22129
22221
  if (this.audioCaptureContext) {
22130
22222
  this.audioCaptureContext.close().catch((error) => {
22131
22223
  console.warn("Error closing audio capture context:", error);
@@ -22162,6 +22254,35 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
22162
22254
  getRoom() {
22163
22255
  return this.room;
22164
22256
  }
22257
+ /**
22258
+ * (Re-)creates an AudioContext + AnalyserNode from the given track and
22259
+ * installs the corresponding VolumeProvider. Called once during create()
22260
+ * and again after an input device switch so the analyser follows the
22261
+ * active mic track.
22262
+ */
22263
+ setupInputAnalyser(mediaStreamTrack) {
22264
+ if (this.inputAudioContext) {
22265
+ this.inputAudioContext.close().catch(() => {});
22266
+ this.inputAudioContext = null;
22267
+ this.inputAnalyser = null;
22268
+ }
22269
+ try {
22270
+ const ctx = new AudioContext();
22271
+ const analyser = ctx.createAnalyser();
22272
+ ctx.createMediaStreamSource(new MediaStream([mediaStreamTrack])).connect(analyser);
22273
+ this.inputAnalyser = analyser;
22274
+ this.inputAudioContext = ctx;
22275
+ this.inputVolumeProvider = createAnalyserVolumeProvider(analyser, ctx.sampleRate);
22276
+ } catch (error) {
22277
+ console.warn("[ConversationalAI] Failed to set up input volume analyser:", error);
22278
+ }
22279
+ }
22280
+ setInputVolumeProvider(provider) {
22281
+ this.inputVolumeProvider = provider;
22282
+ }
22283
+ setOutputVolumeProvider(provider) {
22284
+ this.outputVolumeProvider = provider;
22285
+ }
22165
22286
  async setupAudioCapture(track) {
22166
22287
  try {
22167
22288
  const audioContext = new AudioContext();
@@ -22172,6 +22293,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
22172
22293
  const mediaStream = new MediaStream([track.mediaStreamTrack]);
22173
22294
  const source = audioContext.createMediaStreamSource(mediaStream);
22174
22295
  source.connect(this.outputAnalyser);
22296
+ this.setOutputVolumeProvider(createAnalyserVolumeProvider(this.outputAnalyser, audioContext.sampleRate));
22175
22297
  await loadRawAudioProcessor(audioContext.audioWorklet);
22176
22298
  const worklet = new AudioWorkletNode(audioContext, "rawAudioProcessor");
22177
22299
  this.outputAnalyser.connect(worklet);
@@ -22236,6 +22358,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
22236
22358
  name: "microphone",
22237
22359
  source: Track.Source.Microphone
22238
22360
  });
22361
+ this.setupInputAnalyser(audioTrack.mediaStreamTrack);
22239
22362
  } catch (error) {
22240
22363
  console.error("Failed to change input device:", error);
22241
22364
  try {
@@ -22246,12 +22369,6 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
22246
22369
  throw error;
22247
22370
  }
22248
22371
  }
22249
- getOutputByteFrequencyData() {
22250
- if (!this.outputAnalyser) return null;
22251
- this.outputFrequencyData ??= new Uint8Array(this.outputAnalyser.frequencyBinCount);
22252
- this.outputAnalyser.getByteFrequencyData(this.outputFrequencyData);
22253
- return this.outputFrequencyData;
22254
- }
22255
22372
  };
22256
22373
  //#endregion
22257
22374
  //#region src/utils/ConnectionFactory.ts
@@ -22299,7 +22416,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
22299
22416
  }
22300
22417
  //#endregion
22301
22418
  //#region src/TextConversation.ts
22302
- const EMPTY_FREQUENCY_DATA$1 = new Uint8Array(0);
22419
+ const EMPTY_FREQUENCY_DATA = new Uint8Array(0);
22303
22420
  var TextConversation = class TextConversation extends BaseConversation {
22304
22421
  type = "text";
22305
22422
  setVolume() {
@@ -22309,10 +22426,10 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
22309
22426
  throw new Error("setMicMuted is not supported in text conversations");
22310
22427
  }
22311
22428
  getInputByteFrequencyData() {
22312
- return EMPTY_FREQUENCY_DATA$1;
22429
+ return EMPTY_FREQUENCY_DATA;
22313
22430
  }
22314
22431
  getOutputByteFrequencyData() {
22315
- return EMPTY_FREQUENCY_DATA$1;
22432
+ return EMPTY_FREQUENCY_DATA;
22316
22433
  }
22317
22434
  getInputVolume() {
22318
22435
  return 0;
@@ -22327,13 +22444,21 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
22327
22444
  if (fullOptions.onModeChange) fullOptions.onModeChange({ mode: "listening" });
22328
22445
  if (fullOptions.onCanSendFeedbackChange) fullOptions.onCanSendFeedbackChange({ canSendFeedback: false });
22329
22446
  let connection = null;
22447
+ let conversation = null;
22330
22448
  try {
22331
22449
  await applyDelay(fullOptions.connectionDelay);
22332
22450
  connection = await createConnection(fullOptions);
22333
- return new TextConversation(fullOptions, connection);
22451
+ conversation = new TextConversation(fullOptions, connection);
22452
+ fullOptions.onConversationCreated?.(conversation);
22453
+ conversation.markConnected();
22454
+ fullOptions.onConnect?.({ conversationId: connection.conversationId });
22455
+ return conversation;
22334
22456
  } catch (error) {
22335
- if (fullOptions.onStatusChange) fullOptions.onStatusChange({ status: "disconnected" });
22336
- connection?.close();
22457
+ if (conversation) await conversation.endSession().catch(() => {});
22458
+ else {
22459
+ fullOptions.onStatusChange?.({ status: "disconnected" });
22460
+ connection?.close();
22461
+ }
22337
22462
  throw error;
22338
22463
  }
22339
22464
  }
@@ -22498,6 +22623,7 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
22498
22623
  volume = 1;
22499
22624
  interrupted = false;
22500
22625
  interruptTimeout = null;
22626
+ volumeProvider;
22501
22627
  constructor(context, analyser, gain, worklet, audioElement) {
22502
22628
  this.context = context;
22503
22629
  this.analyser = analyser;
@@ -22505,10 +22631,17 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
22505
22631
  this.worklet = worklet;
22506
22632
  this.audioElement = audioElement;
22507
22633
  this.worklet.port.start();
22634
+ this.volumeProvider = createAnalyserVolumeProvider(analyser, context.sampleRate);
22508
22635
  }
22509
22636
  getAnalyser() {
22510
22637
  return this.analyser;
22511
22638
  }
22639
+ getVolume() {
22640
+ return this.volumeProvider.getVolume();
22641
+ }
22642
+ getByteFrequencyData(buffer) {
22643
+ this.volumeProvider.getByteFrequencyData(buffer);
22644
+ }
22512
22645
  addListener(listener) {
22513
22646
  this.worklet.port.addEventListener("message", listener);
22514
22647
  }
@@ -22617,6 +22750,7 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
22617
22750
  return isIosDevice() ? { ideal: deviceId } : { exact: deviceId };
22618
22751
  }
22619
22752
  muted = false;
22753
+ volumeProvider;
22620
22754
  constructor(context, analyser, worklet, inputStream, mediaStreamSource, permissions, onError = console.error) {
22621
22755
  this.context = context;
22622
22756
  this.analyser = analyser;
@@ -22627,10 +22761,22 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
22627
22761
  this.onError = onError;
22628
22762
  this.permissions.addEventListener("change", this.handlePermissionsChange);
22629
22763
  this.worklet.port.start();
22764
+ this.volumeProvider = createAnalyserVolumeProvider(analyser, context.sampleRate);
22630
22765
  }
22631
22766
  getAnalyser() {
22632
22767
  return this.analyser;
22633
22768
  }
22769
+ getVolume() {
22770
+ if (this.muted) return 0;
22771
+ return this.volumeProvider.getVolume();
22772
+ }
22773
+ getByteFrequencyData(buffer) {
22774
+ if (this.muted) {
22775
+ buffer.fill(0);
22776
+ return;
22777
+ }
22778
+ this.volumeProvider.getByteFrequencyData(buffer);
22779
+ }
22634
22780
  isMuted() {
22635
22781
  return this.muted;
22636
22782
  }
@@ -22771,7 +22917,6 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
22771
22917
  let setupStrategy = webSessionSetup;
22772
22918
  //#endregion
22773
22919
  //#region src/VoiceConversation.ts
22774
- const EMPTY_FREQUENCY_DATA = new Uint8Array(0);
22775
22920
  var VoiceConversation = class VoiceConversation extends BaseConversation {
22776
22921
  type = "voice";
22777
22922
  static async requestWakeLock() {
@@ -22785,6 +22930,7 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
22785
22930
  if (fullOptions.onStatusChange) fullOptions.onStatusChange({ status: "connecting" });
22786
22931
  if (fullOptions.onCanSendFeedbackChange) fullOptions.onCanSendFeedbackChange({ canSendFeedback: false });
22787
22932
  let preliminaryInputStream = null;
22933
+ let conversation = null;
22788
22934
  const useWakeLock = options.useWakeLock ?? true;
22789
22935
  let wakeLock = null;
22790
22936
  if (useWakeLock) wakeLock = await VoiceConversation.requestWakeLock();
@@ -22796,12 +22942,17 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
22796
22942
  track.stop();
22797
22943
  });
22798
22944
  preliminaryInputStream = null;
22799
- return new VoiceConversation(fullOptions, sessionSetup.connection, sessionSetup.input, sessionSetup.output, sessionSetup.playbackEventTarget, sessionSetup.detach, wakeLock);
22945
+ conversation = new VoiceConversation(fullOptions, sessionSetup.connection, sessionSetup.input, sessionSetup.output, sessionSetup.playbackEventTarget, sessionSetup.detach, wakeLock);
22946
+ fullOptions.onConversationCreated?.(conversation);
22947
+ conversation.markConnected();
22948
+ fullOptions.onConnect?.({ conversationId: sessionSetup.connection.conversationId });
22949
+ return conversation;
22800
22950
  } catch (error) {
22801
- if (fullOptions.onStatusChange) fullOptions.onStatusChange({ status: "disconnected" });
22802
22951
  preliminaryInputStream?.getTracks().forEach((track) => {
22803
22952
  track.stop();
22804
22953
  });
22954
+ if (conversation) await conversation.endSession().catch(() => {});
22955
+ else fullOptions.onStatusChange?.({ status: "disconnected" });
22805
22956
  try {
22806
22957
  await wakeLock?.release();
22807
22958
  wakeLock = null;
@@ -22860,42 +23011,27 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
22860
23011
  this.updateMode("speaking");
22861
23012
  }
22862
23013
  }
22863
- calculateVolume = (frequencyData) => {
22864
- if (frequencyData.length === 0) return 0;
22865
- let volume = 0;
22866
- for (let i = 0; i < frequencyData.length; i++) volume += frequencyData[i] / 255;
22867
- volume /= frequencyData.length;
22868
- return volume < 0 ? 0 : volume > 1 ? 1 : volume;
22869
- };
23014
+ static FREQUENCY_BIN_COUNT = 1024;
22870
23015
  setMicMuted(isMuted) {
22871
23016
  this.input.setMuted(isMuted).catch((error) => {
22872
23017
  this.options.onError?.("Failed to set input muted state", error);
22873
23018
  });
22874
23019
  }
22875
23020
  getInputByteFrequencyData() {
22876
- const analyser = this.input.getAnalyser();
22877
- if (!analyser) return EMPTY_FREQUENCY_DATA;
22878
- this.inputFrequencyData ??= new Uint8Array(analyser.frequencyBinCount);
22879
- analyser.getByteFrequencyData(this.inputFrequencyData);
23021
+ this.inputFrequencyData ??= new Uint8Array(VoiceConversation.FREQUENCY_BIN_COUNT);
23022
+ this.input.getByteFrequencyData(this.inputFrequencyData);
22880
23023
  return this.inputFrequencyData;
22881
23024
  }
22882
23025
  getOutputByteFrequencyData() {
22883
- if (this.connection instanceof WebRTCConnection) {
22884
- const webrtcData = this.connection.getOutputByteFrequencyData();
22885
- if (webrtcData) return webrtcData;
22886
- return new Uint8Array(1024);
22887
- }
22888
- const analyser = this.output.getAnalyser();
22889
- if (!analyser) return EMPTY_FREQUENCY_DATA;
22890
- this.outputFrequencyData ??= new Uint8Array(analyser.frequencyBinCount);
22891
- analyser.getByteFrequencyData(this.outputFrequencyData);
23026
+ this.outputFrequencyData ??= new Uint8Array(VoiceConversation.FREQUENCY_BIN_COUNT);
23027
+ this.output.getByteFrequencyData(this.outputFrequencyData);
22892
23028
  return this.outputFrequencyData;
22893
23029
  }
22894
23030
  getInputVolume() {
22895
- return this.calculateVolume(this.getInputByteFrequencyData());
23031
+ return this.input.getVolume();
22896
23032
  }
22897
23033
  getOutputVolume() {
22898
- return this.calculateVolume(this.getOutputByteFrequencyData());
23034
+ return this.output.getVolume();
22899
23035
  }
22900
23036
  async changeInputDevice({ sampleRate, format, preferHeadphonesForIosDevices, inputDeviceId }) {
22901
23037
  try {