@layercode/js-sdk 1.0.18 → 1.0.21

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.
@@ -3482,6 +3482,7 @@ class LayercodeClient {
3482
3482
  onUserAmplitudeChange: options.onUserAmplitudeChange || (() => { }),
3483
3483
  onAgentAmplitudeChange: options.onAgentAmplitudeChange || (() => { }),
3484
3484
  onStatusChange: options.onStatusChange || (() => { }),
3485
+ onUserIsSpeakingChange: options.onUserIsSpeakingChange || (() => { }),
3485
3486
  };
3486
3487
  this.AMPLITUDE_MONITORING_SAMPLE_RATE = 10;
3487
3488
  this._websocketUrl = 'wss://api.layercode.com/v1/pipelines/websocket';
@@ -3501,6 +3502,7 @@ class LayercodeClient {
3501
3502
  this.pushToTalkEnabled = false;
3502
3503
  this.canInterrupt = false;
3503
3504
  this.userIsSpeaking = false;
3505
+ this.endUserTurn = false;
3504
3506
  this.recorderStarted = false;
3505
3507
  this.readySent = false;
3506
3508
  // Bind event handlers
@@ -3517,6 +3519,7 @@ class LayercodeClient {
3517
3519
  console.log('silero vad model timeout');
3518
3520
  // TODO: send message to server to indicate that the vad model timed out
3519
3521
  this.userIsSpeaking = true; // allow audio to be sent to the server
3522
+ this.options.onUserIsSpeakingChange(true);
3520
3523
  }, 2000);
3521
3524
  if (!this.canInterrupt) {
3522
3525
  dist.MicVAD.new({
@@ -3530,17 +3533,15 @@ class LayercodeClient {
3530
3533
  onSpeechStart: () => {
3531
3534
  if (!this.wavPlayer.isPlaying) {
3532
3535
  this.userIsSpeaking = true;
3536
+ this.options.onUserIsSpeakingChange(true);
3533
3537
  }
3534
3538
  },
3535
3539
  onVADMisfire: () => {
3536
3540
  this.userIsSpeaking = false;
3541
+ this.options.onUserIsSpeakingChange(false);
3537
3542
  },
3538
3543
  onSpeechEnd: () => {
3539
- this.userIsSpeaking = false;
3540
- this._wsSend({
3541
- type: 'vad_events',
3542
- event: 'vad_end',
3543
- });
3544
+ this.endUserTurn = true; // Set flag to indicate that the user turn has ended, so we can send a vad_end event to the server
3544
3545
  },
3545
3546
  })
3546
3547
  .then((vad) => {
@@ -3575,6 +3576,7 @@ class LayercodeClient {
3575
3576
  console.log('onSpeechStart: WavPlayer is not playing, VAD will not pause.');
3576
3577
  }
3577
3578
  this.userIsSpeaking = true;
3579
+ this.options.onUserIsSpeakingChange(true);
3578
3580
  console.log('onSpeechStart: sending vad_start');
3579
3581
  this._wsSend({
3580
3582
  type: 'vad_events',
@@ -3584,6 +3586,7 @@ class LayercodeClient {
3584
3586
  onVADMisfire: () => {
3585
3587
  // If the speech detected was for less than minSpeechFrames, this is called instead of onSpeechEnd, and we should resume the assistant audio as it was a false interruption. We include a configurable delay so the assistant isn't too quick to start speaking again.
3586
3588
  this.userIsSpeaking = false;
3589
+ this.options.onUserIsSpeakingChange(false);
3587
3590
  if (this.vadPausedPlayer) {
3588
3591
  console.log('onSpeechEnd: VAD paused the player, resuming');
3589
3592
  this.wavPlayer.play();
@@ -3594,11 +3597,7 @@ class LayercodeClient {
3594
3597
  }
3595
3598
  },
3596
3599
  onSpeechEnd: () => {
3597
- this.userIsSpeaking = false;
3598
- this._wsSend({
3599
- type: 'vad_events',
3600
- event: 'vad_end',
3601
- });
3600
+ this.endUserTurn = true; // Set flag to indicate that the user turn has ended, so we can send a vad_end event to the server
3602
3601
  },
3603
3602
  })
3604
3603
  .then((vad) => {
@@ -3716,6 +3715,15 @@ class LayercodeClient {
3716
3715
  type: 'client.audio',
3717
3716
  content: base64,
3718
3717
  });
3718
+ if (this.endUserTurn) {
3719
+ this.endUserTurn = false;
3720
+ this.userIsSpeaking = false; // Reset userIsSpeaking to false so we don't send any more audio to the server
3721
+ this.options.onUserIsSpeakingChange(false);
3722
+ this._wsSend({
3723
+ type: 'vad_events',
3724
+ event: 'vad_end',
3725
+ });
3726
+ }
3719
3727
  }
3720
3728
  }
3721
3729
  catch (error) {
@@ -3861,6 +3869,25 @@ class LayercodeClient {
3861
3869
  getStream() {
3862
3870
  return this.wavRecorder.getStream();
3863
3871
  }
3872
+ /**
3873
+ * Switches the input device for the microphone and restarts recording
3874
+ * @param {string} deviceId - The deviceId of the new microphone
3875
+ */
3876
+ async setInputDevice(deviceId) {
3877
+ if (this.wavRecorder) {
3878
+ try {
3879
+ await this.wavRecorder.end();
3880
+ }
3881
+ catch (e) { }
3882
+ try {
3883
+ await this.wavRecorder.quit();
3884
+ }
3885
+ catch (e) { }
3886
+ }
3887
+ await this.wavRecorder.begin(deviceId);
3888
+ await this.wavRecorder.record(this._handleDataAvailable, 1638);
3889
+ this._setupAmplitudeMonitoring(this.wavRecorder, this.options.onUserAmplitudeChange, (amp) => (this.userAudioAmplitude = amp));
3890
+ }
3864
3891
  }
3865
3892
 
3866
3893
  export { LayercodeClient as default };