@@ -62,54 +62,7 @@ const KokoroTTS = {
6262 settings : {
6363 enabled : true ,
6464 volume : 0.8 ,
65- speed : 1.0 ,
66- useFastMode : false // If true, use browser TTS for instant response
67- } ,
68-
69- // ═══════════════════════════════════════════════════════════
70- // FAST MODE - Browser's built-in TTS for instant response
71- // ═══════════════════════════════════════════════════════════
72-
73- _webSpeechAvailable : null ,
74-
75- checkWebSpeech ( ) {
76- if ( this . _webSpeechAvailable !== null ) return this . _webSpeechAvailable ;
77- this . _webSpeechAvailable = 'speechSynthesis' in window ;
78- return this . _webSpeechAvailable ;
79- } ,
80-
81- // Use browser TTS - instant but robotic
82- speakFast ( text , npcType , npcData = { } ) {
83- if ( ! this . checkWebSpeech ( ) ) return false ;
84- const clean = this . _clean ( text ) ;
85- if ( ! clean ) return false ;
86-
87- // Stop any current speech
88- speechSynthesis . cancel ( ) ;
89-
90- const utterance = new SpeechSynthesisUtterance ( clean ) ;
91- utterance . rate = this . settings . speed ;
92- utterance . volume = this . settings . volume ;
93-
94- // Try to pick appropriate voice
95- const voices = speechSynthesis . getVoices ( ) ;
96- const isFemale = this . _isFemaleNPC ( npcType , npcData ) ;
97- const preferredVoice = voices . find ( v =>
98- ( isFemale ? v . name . toLowerCase ( ) . includes ( 'female' ) || v . name . includes ( 'Zira' ) || v . name . includes ( 'Samantha' ) :
99- v . name . toLowerCase ( ) . includes ( 'male' ) || v . name . includes ( 'David' ) || v . name . includes ( 'Daniel' ) )
100- ) || voices [ 0 ] ;
101-
102- if ( preferredVoice ) utterance . voice = preferredVoice ;
103- speechSynthesis . speak ( utterance ) ;
104- return true ;
105- } ,
106-
107- _isFemaleNPC ( npcType , npcData ) {
108- if ( npcData . gender === 'female' || npcData . isFemale ) return true ;
109- if ( ! npcType ) return false ;
110- const n = npcType . toLowerCase ( ) ;
111- return [ 'woman' , 'lady' , 'girl' , 'maiden' , 'wife' , 'mother' , 'queen' , 'princess' , 'witch' ,
112- 'healer' , 'barmaid' , 'priestess' , 'sorceress' , 'herbalist' , 'seamstress' , 'fortune_teller' ] . some ( k => n . includes ( k ) ) ;
65+ speed : 1.0
11366 } ,
11467
11568 // ═══════════════════════════════════════════════════════════
@@ -345,57 +298,38 @@ const KokoroTTS = {
345298 // SPEECH - NON-BLOCKING via Worker
346299 // ═══════════════════════════════════════════════════════════
347300
348- // Maximum characters for fast response - longer text gets chunked
349- MAX_CHUNK_LENGTH : 150 ,
350-
351- // Generation timeout - fall back to browser TTS if Kokoro takes too long
352- GENERATION_TIMEOUT : 8000 , // 8 seconds max per chunk
301+ // Maximum characters per chunk - smaller = faster first response
302+ MAX_CHUNK_LENGTH : 100 ,
353303
354304 async speak ( text , npcType , npcData = { } ) {
355305 if ( ! this . settings . enabled || ! text ?. trim ( ) ) return false ;
356-
357- const clean = this . _clean ( text ) ;
358- if ( ! clean ) return false ;
359-
360- // FAST MODE: Use browser TTS for instant response
361- if ( this . settings . useFastMode ) {
362- console . log ( '🎙️ TTS Fast Mode: Using browser speech' ) ;
363- return this . speakFast ( text , npcType , npcData ) ;
364- }
365-
366- // If Kokoro not ready, use browser TTS as fallback
367306 if ( ! this . _initialized || ! this . _worker ) {
368- console . log ( '🎙️ KokoroTTS: Not initialized, using browser TTS ' ) ;
369- return this . speakFast ( text , npcType , npcData ) ;
307+ console . log ( '🎙️ KokoroTTS: Not initialized' ) ;
308+ return false ;
370309 }
371310
311+ const clean = this . _clean ( text ) ;
312+ if ( ! clean ) return false ;
372313 const voice = npcData . voice || this . getVoiceForNPC ( npcType , npcData ) ;
373314
374315 try {
375- // Split into sentences for faster first response
316+ // Split into small chunks for faster first response
376317 const chunks = this . _splitIntoChunks ( clean ) ;
377- console . log ( `🎙️ KokoroTTS: "${ voice } ": ${ chunks . length } chunk(s), first: " ${ chunks [ 0 ] ?. substring ( 0 , 40 ) } ..." ` ) ;
318+ console . log ( `🎙️ KokoroTTS: "${ voice } ": ${ chunks . length } chunk(s)` ) ;
378319
379320 this . _showIndicator ( true ) ;
380321
381- // Generate and play each chunk with timeout
322+ // Generate and play each chunk
382323 for ( let i = 0 ; i < chunks . length ; i ++ ) {
383324 const chunk = chunks [ i ] ;
384325 if ( ! chunk . trim ( ) ) continue ;
385326
386- // Check if we were told to stop
387327 if ( this . _stopRequested ) {
388328 this . _stopRequested = false ;
389329 break ;
390330 }
391331
392- // Race between generation and timeout
393- const result = await Promise . race ( [
394- this . _send ( 'generate' , { text : chunk , voice, speed : this . settings . speed } ) ,
395- new Promise ( ( _ , reject ) =>
396- setTimeout ( ( ) => reject ( new Error ( 'Generation timeout' ) ) , this . GENERATION_TIMEOUT )
397- )
398- ] ) ;
332+ const result = await this . _send ( 'generate' , { text : chunk , voice, speed : this . settings . speed } ) ;
399333
400334 if ( result ?. audio ) {
401335 await this . _play ( result . audio , result . rate ) ;
@@ -406,10 +340,9 @@ const KokoroTTS = {
406340 return true ;
407341
408342 } catch ( error ) {
409- console . warn ( '🎙️ KokoroTTS slow/ failed, falling back to browser TTS :' , error . message ) ;
343+ console . error ( '🎙️ KokoroTTS failed:' , error ) ;
410344 this . _showIndicator ( false ) ;
411- // Fall back to browser TTS
412- return this . speakFast ( text , npcType , npcData ) ;
345+ return false ;
413346 }
414347 } ,
415348
@@ -503,25 +436,12 @@ const KokoroTTS = {
503436 } ,
504437
505438 stop ( ) {
506- this . _stopRequested = true ; // Stop any chunked playback in progress
439+ this . _stopRequested = true ;
507440 if ( this . _currentAudio ) { try { this . _currentAudio . stop ( ) ; } catch { } this . _currentAudio = null ; }
508- // Also stop browser TTS if it's speaking
509- if ( this . checkWebSpeech ( ) ) { try { speechSynthesis . cancel ( ) ; } catch { } }
510441 this . _showIndicator ( false ) ;
511442 } ,
512443
513- isPlaying ( ) {
514- // Check both Kokoro and browser TTS
515- if ( this . _currentAudio ) return true ;
516- if ( this . checkWebSpeech ( ) && speechSynthesis . speaking ) return true ;
517- return false ;
518- } ,
519-
520- // Toggle between fast (browser) and quality (Kokoro) mode
521- setFastMode ( enabled ) {
522- this . settings . useFastMode = enabled ;
523- console . log ( `🎙️ TTS Mode: ${ enabled ? 'Fast (Browser)' : 'Quality (Kokoro AI)' } ` ) ;
524- } ,
444+ isPlaying ( ) { return this . _currentAudio !== null ; } ,
525445 isInitialized ( ) { return this . _initialized ; } ,
526446 isLoading ( ) { return this . _loading ; } ,
527447
0 commit comments