Merge pull request #3868 from YunZLu/staging Fix Edge Browser TTS Compatibility

586ce36167f4faee2620d7fac209494c75e11ae1

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
1 files changed, +66 -17Ignore whitespace
public/scripts/extensions/tts/system.js+66 -17
@@ -79,6 +79,10 @@ class SystemTtsProvider {
7979 // Config //
8080 //########//
8181
82+ // Static constants for the simulated default voice
83+ static BROWSER_DEFAULT_VOICE_ID = '__browser_default__';
84+ static BROWSER_DEFAULT_VOICE_NAME = 'System Default Voice';
85+
8286 settings;
8387 ready = false;
8488 voices = [];
@@ -168,51 +172,97 @@ class SystemTtsProvider {
168172 //#################//
169173 fetchTtsVoiceObjects() {
170174 if (!('speechSynthesis' in window)) {
171175 return Promise.resolve([]);
172176 }
173177
174178 return new Promise((resolve) => {
175179 setTimeout(() => {
176180 constlet voices = speechSynthesis.getVoices();
177- .getVoices()
181+
178- .sort((a, b) => a.lang.localeCompare(b.lang) || a.name.localeCompare(b.name))
182+ if (voices.length === 0) {
179- .map(x => ({ name: x.name, voice_id: x.voiceURI, preview_url: false, lang: x.lang }));
183+ // Edge compat: Provide default when voices empty
180-
184+ console.warn('SystemTTS: getVoices() returned empty list. Providing browser default option.');
181- resolve(voices);
185+ const defaultVoice = {
182- }, 1);
186+ name: SystemTtsProvider.BROWSER_DEFAULT_VOICE_NAME,
187+ voice_id: SystemTtsProvider.BROWSER_DEFAULT_VOICE_ID,
188+ preview_url: false,
189+ lang: navigator.language || 'en-US',
190+ };
191+ resolve([defaultVoice]);
192+ } else {
193+ const mappedVoices = voices
194+ .sort((a, b) => a.lang.localeCompare(b.lang) || a.name.localeCompare(b.name))
195+ .map(x => ({ name: x.name, voice_id: x.voiceURI, preview_url: false, lang: x.lang }));
196+ resolve(mappedVoices);
197+ }
198+ }, 50);
183199 });
184200 }
185201
186202 previewTtsVoice(voiceId) {
187203 if (!('speechSynthesis' in window)) {
188204 throw new Error('Speech synthesis API is not supported');
189205 }
190206
191- const voice = speechSynthesis.getVoices().find(x => x.voiceURI === voiceId);
207+ let voice = null;
208+ if (voiceId !== SystemTtsProvider.BROWSER_DEFAULT_VOICE_ID) {
209+ const voices = speechSynthesis.getVoices();
210+ voice = voices.find(x => x.voiceURI === voiceId);
192211
193212 if (!voice && voices.length > 0) {
194- throw `TTS Voice id ${voiceId} not found`;
213+ console.warn(`SystemTTS Preview: Voice ID "${voiceId}" not found among available voices. Using browser default.`);
214+ } else if (!voice && voices.length === 0) {
215+ console.warn('SystemTTS Preview: Voice list is empty. Using browser default.');
216+ }
217+ } else {
218+ console.log('SystemTTS Preview: Using browser default voice as requested.');
195219 }
196220
197221 speechSynthesis.cancel();
198- const text = getPreviewString(voice.lang);
222+ const langForPreview = voice ? voice.lang : (navigator.language || 'en-US');
223+ const text = getPreviewString(langForPreview);
199224 const utterance = new SpeechSynthesisUtterance(text);
200- utterance.voice = voice;
225+
226+ if (voice) {
227+ utterance.voice = voice;
228+ }
229+
201230 utterance.rate = this.settings.rate || 1;
202231 utterance.pitch = this.settings.pitch || 1;
232+
233+ utterance.onerror = (event) => {
234+ console.error(`SystemTTS Preview Error: ${event.error}`, event);
235+ };
236+
203237 speechSynthesis.speak(utterance);
204238 }
205239
206240 async getVoice(voiceName) {
207241 if (!('speechSynthesis' in window)) {
208242 return { voice_id: null, name: 'API Not Supported' };
243+ }
244+
245+ if (voiceName === SystemTtsProvider.BROWSER_DEFAULT_VOICE_NAME) {
246+ return {
247+ voice_id: SystemTtsProvider.BROWSER_DEFAULT_VOICE_ID,
248+ name: SystemTtsProvider.BROWSER_DEFAULT_VOICE_NAME,
249+ };
209250 }
210251
211252 const voices = speechSynthesis.getVoices();
253+
254+ if (voices.length === 0) {
255+ console.warn('SystemTTS: Empty voice list, using default fallback');
256+ return {
257+ voice_id: SystemTtsProvider.BROWSER_DEFAULT_VOICE_ID,
258+ name: SystemTtsProvider.BROWSER_DEFAULT_VOICE_NAME,
259+ };
260+ }
261+
212262 const match = voices.find(x => x.name == voiceName);
213263
214264 if (!match) {
215265 throw new Error(`SystemTTS getVoice: TTS Voice name "${voiceName}" not found`);
216266 }
217267
218268 return { voice_id: match.voiceURI, name: match.name };
@@ -237,7 +287,6 @@ class SystemTtsProvider {
237287 speechUtteranceChunker(utterance, {
238288 chunkLength: 200,
239289 }, function () {
240- //some code to execute when done
241290 resolve(silence);
242291 console.log('System TTS done');
243292 });