@@ -459,52 +459,67 @@ export class SpeechStream<TModel extends STTModels> extends BaseSpeechStream {
459459 }
460460
461461 private processTranscript ( data : Record < string , any > , isFinal : boolean ) {
462+ // Check if queue is closed to avoid race condition during disconnect
463+ if ( this . queue . closed ) return ;
464+
462465 const requestId = data . request_id ?? this . requestId ;
463466 const text = data . transcript ?? '' ;
464467 const language = data . language ?? this . opts . language ?? 'en' ;
465468
466469 if ( ! text && ! isFinal ) return ;
467470
468- // We'll have a more accurate way of detecting when speech started when we have VAD
469- if ( ! this . speaking ) {
470- this . speaking = true ;
471- this . queue . put ( { type : SpeechEventType . START_OF_SPEECH } ) ;
472- }
471+ try {
472+ // We'll have a more accurate way of detecting when speech started when we have VAD
473+ if ( ! this . speaking ) {
474+ this . speaking = true ;
475+ this . queue . put ( { type : SpeechEventType . START_OF_SPEECH } ) ;
476+ }
473477
474- const speechData : SpeechData = {
475- language,
476- startTime : data . start ?? 0 ,
477- endTime : data . duration ?? 0 ,
478- confidence : data . confidence ?? 1.0 ,
479- text,
480- } ;
478+ const speechData : SpeechData = {
479+ language,
480+ startTime : data . start ?? 0 ,
481+ endTime : data . duration ?? 0 ,
482+ confidence : data . confidence ?? 1.0 ,
483+ text,
484+ } ;
485+
486+ if ( isFinal ) {
487+ if ( this . speechDuration > 0 ) {
488+ this . queue . put ( {
489+ type : SpeechEventType . RECOGNITION_USAGE ,
490+ requestId,
491+ recognitionUsage : { audioDuration : this . speechDuration } ,
492+ } ) ;
493+ this . speechDuration = 0 ;
494+ }
481495
482- if ( isFinal ) {
483- if ( this . speechDuration > 0 ) {
484496 this . queue . put ( {
485- type : SpeechEventType . RECOGNITION_USAGE ,
497+ type : SpeechEventType . FINAL_TRANSCRIPT ,
486498 requestId,
487- recognitionUsage : { audioDuration : this . speechDuration } ,
499+ alternatives : [ speechData ] ,
488500 } ) ;
489- this . speechDuration = 0 ;
490- }
491-
492- this . queue . put ( {
493- type : SpeechEventType . FINAL_TRANSCRIPT ,
494- requestId,
495- alternatives : [ speechData ] ,
496- } ) ;
497501
498- if ( this . speaking ) {
499- this . speaking = false ;
500- this . queue . put ( { type : SpeechEventType . END_OF_SPEECH } ) ;
502+ if ( this . speaking ) {
503+ this . speaking = false ;
504+ this . queue . put ( { type : SpeechEventType . END_OF_SPEECH } ) ;
505+ }
506+ } else {
507+ this . queue . put ( {
508+ type : SpeechEventType . INTERIM_TRANSCRIPT ,
509+ requestId,
510+ alternatives : [ speechData ] ,
511+ } ) ;
512+ }
513+ } catch ( e ) {
514+ if ( e instanceof Error && e . message . includes ( 'Queue is closed' ) ) {
515+ // Expected behavior on disconnect, log as warning
516+ this . #logger. warn (
517+ { err : e } ,
518+ 'Queue closed during transcript processing (expected during disconnect)' ,
519+ ) ;
520+ } else {
521+ this . #logger. error ( { err : e } , 'Error putting transcript to queue' ) ;
501522 }
502- } else {
503- this . queue . put ( {
504- type : SpeechEventType . INTERIM_TRANSCRIPT ,
505- requestId,
506- alternatives : [ speechData ] ,
507- } ) ;
508523 }
509524 }
510525}
0 commit comments