@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.
|
|
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.
|
|
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 };
|