@@ -731,27 +731,35 @@ class LayercodeClient implements ILayercodeClient {
731731 */
732732 private _handleDataAvailable ( data : { mono : Int16Array < ArrayBufferLike > } ) : void {
733733 try {
734- const base64 = arrayBufferToBase64 ( data . mono ) ;
735-
736- // Don't send audio if muted
734+ // Don't send or buffer audio if muted. Also clear any stale buffer so we
735+ // don't accidentally flush old audio after unmute.
737736 if ( this . isMuted ) {
737+ this . audioBuffer = [ ] ;
738738 return ;
739739 }
740740
741741 // Determine if we should gate audio based on VAD configuration
742- const shouldGateAudio = this . vadConfig ?. gate_audio !== false ; // Default to true if not specified
743- const bufferFrames = this . vadConfig ?. buffer_frames ?? 10 ; // Default to 10 if not specified
742+ const shouldGateAudio = this . vadConfig ?. gate_audio !== false ; // default true
743+ const bufferFrames = this . vadConfig ?. buffer_frames ?? 10 ; // default 10
744+
745+ // If VAD is disabled or failed to init, gating would deadlock (userIsSpeaking never flips true).
746+ // Only gate if we actually have a running VAD instance.
747+ const vadEnabledByConfig = this . vadConfig ?. enabled !== false ; // default true
748+ const vadAvailable = vadEnabledByConfig && ! ! this . vad && ! this . pushToTalkEnabled ;
744749
745750 let sendAudio : boolean ;
746751 if ( this . pushToTalkEnabled ) {
747752 sendAudio = this . pushToTalkActive ;
748753 } else if ( shouldGateAudio ) {
749- sendAudio = this . userIsSpeaking ;
754+ // Key fix: if VAD isn't available, don't gate — send audio.
755+ sendAudio = vadAvailable ? this . userIsSpeaking : true ;
750756 } else {
751757 // If gate_audio is false, always send audio
752758 sendAudio = true ;
753759 }
754760
761+ const base64 = arrayBufferToBase64 ( data . mono ) ;
762+
755763 if ( sendAudio ) {
756764 // If we have buffered audio and we're gating, send it first
757765 if ( shouldGateAudio && this . audioBuffer . length > 0 ) {
@@ -937,7 +945,7 @@ class LayercodeClient implements ILayercodeClient {
937945 this . _sendReadyIfNeeded ( ) ;
938946 }
939947
940- const reportedDeviceId = this . activeDeviceId ?? ( this . useSystemDefaultDevice ? 'default' : ( this . deviceId ?? 'default' ) ) ;
948+ const reportedDeviceId = this . activeDeviceId ?? ( this . useSystemDefaultDevice ? 'default' : this . deviceId ?? 'default' ) ;
941949 if ( reportedDeviceId !== this . lastReportedDeviceId ) {
942950 this . lastReportedDeviceId = reportedDeviceId ;
943951 if ( this . options . onDeviceSwitched ) {
@@ -1314,7 +1322,7 @@ class LayercodeClient implements ILayercodeClient {
13141322 const newStream = this . wavRecorder . getStream ( ) ;
13151323 await this . _reinitializeVAD ( newStream ) ;
13161324 }
1317- const reportedDeviceId = this . lastReportedDeviceId ?? this . activeDeviceId ?? ( this . useSystemDefaultDevice ? 'default' : ( normalizedDeviceId ?? 'default' ) ) ;
1325+ const reportedDeviceId = this . lastReportedDeviceId ?? this . activeDeviceId ?? ( this . useSystemDefaultDevice ? 'default' : normalizedDeviceId ?? 'default' ) ;
13181326 console . debug ( `Successfully switched to input device: ${ reportedDeviceId } ` ) ;
13191327 } catch ( error ) {
13201328 console . error ( `Failed to switch to input device ${ deviceId } :` , error ) ;
@@ -1373,7 +1381,7 @@ class LayercodeClient implements ILayercodeClient {
13731381 this . _sendReadyIfNeeded ( ) ;
13741382 }
13751383
1376- const reportedDeviceId = this . activeDeviceId ?? ( this . useSystemDefaultDevice ? 'default' : ( this . deviceId ?? 'default' ) ) ;
1384+ const reportedDeviceId = this . activeDeviceId ?? ( this . useSystemDefaultDevice ? 'default' : this . deviceId ?? 'default' ) ;
13771385 if ( reportedDeviceId !== previousReportedDeviceId ) {
13781386 this . lastReportedDeviceId = reportedDeviceId ;
13791387 if ( this . options . onDeviceSwitched ) {
@@ -1634,12 +1642,7 @@ class LayercodeClient implements ILayercodeClient {
16341642 private async _shouldWarnAudioDevicesRequireUserGesture ( error : unknown ) : Promise < boolean > {
16351643 const e : any = error as any ;
16361644 const name = typeof e ?. name === 'string' ? e . name : '' ;
1637- const msg =
1638- typeof e ?. message === 'string'
1639- ? e . message
1640- : typeof error === 'string'
1641- ? error
1642- : '' ;
1645+ const msg = typeof e ?. message === 'string' ? e . message : typeof error === 'string' ? error : '' ;
16431646
16441647 const isPermissionLike = name === 'NotAllowedError' || name === 'SecurityError' || name === 'PermissionDeniedError' ;
16451648 if ( ! isPermissionLike ) return false ;
0 commit comments