Merge branch 'release' into staging

12db782a308e0177218106c065f38875d797270b

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

1 files changed, +1072 -1072Ignore whitespace
public/scripts/extensions/tts/alltalk.js+1072 -1072
@@ -1,1072 +1,1072 @@
1import { doExtrasFetch } from '../../extensions.js'; 1import { doExtrasFetch } from '../../extensions.js';
2import { debounce } from '../../utils.js'; 2import { debounce } from '../../utils.js';
3import { saveTtsProviderSettings } from './index.js'; 3import { saveTtsProviderSettings } from './index.js';
4 4
5export { AllTalkTtsProvider }; 5export { AllTalkTtsProvider };
6 6
7class AllTalkTtsProvider { 7class AllTalkTtsProvider {
8 //########// 8 //########//
9 // Config // 9 // Config //
10 //########// 10 //########//
11 11
12 settings = {}; 12 settings = {};
13 constructor() { 13 constructor() {
14 // Initialize with default settings if they are not already set 14 // Initialize with default settings if they are not already set
15 this.settings = { 15 this.settings = {
16 provider_endpoint: this.settings.provider_endpoint || 'http://localhost:7851', 16 provider_endpoint: this.settings.provider_endpoint || 'http://localhost:7851',
17 server_version: this.settings.server_version || 'v2', 17 server_version: this.settings.server_version || 'v2',
18 language: this.settings.language || 'en', 18 language: this.settings.language || 'en',
19 voiceMap: this.settings.voiceMap || {}, 19 voiceMap: this.settings.voiceMap || {},
20 at_generation_method: this.settings.at_generation_method || 'standard_generation', 20 at_generation_method: this.settings.at_generation_method || 'standard_generation',
21 narrator_enabled: this.settings.narrator_enabled || 'false', 21 narrator_enabled: this.settings.narrator_enabled || 'false',
22 at_narrator_text_not_inside: this.settings.at_narrator_text_not_inside || 'narrator', 22 at_narrator_text_not_inside: this.settings.at_narrator_text_not_inside || 'narrator',
23 narrator_voice_gen: this.settings.narrator_voice_gen || 'Please set a voice', 23 narrator_voice_gen: this.settings.narrator_voice_gen || 'Please set a voice',
24 rvc_character_voice: this.settings.rvc_character_voice || 'Disabled', 24 rvc_character_voice: this.settings.rvc_character_voice || 'Disabled',
25 rvc_character_pitch: this.settings.rvc_character_pitch || '0', 25 rvc_character_pitch: this.settings.rvc_character_pitch || '0',
26 rvc_narrator_voice: this.settings.rvc_narrator_voice || 'Disabled', 26 rvc_narrator_voice: this.settings.rvc_narrator_voice || 'Disabled',
27 rvc_narrator_pitch: this.settings.rvc_narrator_pitch || '0', 27 rvc_narrator_pitch: this.settings.rvc_narrator_pitch || '0',
28 finetuned_model: this.settings.finetuned_model || 'false', 28 finetuned_model: this.settings.finetuned_model || 'false',
29 }; 29 };
30 // Separate property for dynamically updated settings from the server 30 // Separate property for dynamically updated settings from the server
31 this.dynamicSettings = { 31 this.dynamicSettings = {
32 modelsAvailable: [], 32 modelsAvailable: [],
33 currentModel: '', 33 currentModel: '',
34 deepspeed_available: false, 34 deepspeed_available: false,
35 deepspeed_enabled: false, 35 deepspeed_enabled: false,
36 lowvram_capable: false, 36 lowvram_capable: false,
37 lowvram_enabled: false, 37 lowvram_enabled: false,
38 }; 38 };
39 this.rvcVoices = []; // Initialize rvcVoices as an empty array 39 this.rvcVoices = []; // Initialize rvcVoices as an empty array
40 } 40 }
41 ready = false; 41 ready = false;
42 voices = []; 42 voices = [];
43 separator = '. '; 43 separator = '. ';
44 audioElement = document.createElement('audio'); 44 audioElement = document.createElement('audio');
45 45
46 languageLabels = { 46 languageLabels = {
47 'Arabic': 'ar', 47 'Arabic': 'ar',
48 'Brazilian Portuguese': 'pt', 48 'Brazilian Portuguese': 'pt',
49 'Chinese': 'zh-cn', 49 'Chinese': 'zh-cn',
50 'Czech': 'cs', 50 'Czech': 'cs',
51 'Dutch': 'nl', 51 'Dutch': 'nl',
52 'English': 'en', 52 'English': 'en',
53 'French': 'fr', 53 'French': 'fr',
54 'German': 'de', 54 'German': 'de',
55 'Italian': 'it', 55 'Italian': 'it',
56 'Polish': 'pl', 56 'Polish': 'pl',
57 'Russian': 'ru', 57 'Russian': 'ru',
58 'Spanish': 'es', 58 'Spanish': 'es',
59 'Turkish': 'tr', 59 'Turkish': 'tr',
60 'Japanese': 'ja', 60 'Japanese': 'ja',
61 'Korean': 'ko', 61 'Korean': 'ko',
62 'Hungarian': 'hu', 62 'Hungarian': 'hu',
63 'Hindi': 'hi', 63 'Hindi': 'hi',
64 }; 64 };
65 65
66 get settingsHtml() { 66 get settingsHtml() {
67 // HTML template literals can trigger ESLint quotes warnings when quotes are used in HTML attributes. 67 // HTML template literals can trigger ESLint quotes warnings when quotes are used in HTML attributes.
68 // Disabling quotes rule for this one line as it's a false positive with HTML template literals. 68 // Disabling quotes rule for this one line as it's a false positive with HTML template literals.
69 // eslint-disable-next-line quotes 69 // eslint-disable-next-line quotes
70 let html = `<div class="at-settings-separator">AllTalk V2 Settings</div>`; 70 let html = `<div class="at-settings-separator">AllTalk V2 Settings</div>`;
71 71
72 html += `<div class='at-settings-row'> 72 html += `<div class='at-settings-row'>
73 <div class='at-settings-option'> 73 <div class='at-settings-option'>
74 <label for='at_generation_method'>AllTalk TTS Generation Method</label> 74 <label for='at_generation_method'>AllTalk TTS Generation Method</label>
75 <select id='at_generation_method'> 75 <select id='at_generation_method'>
76 <option value='standard_generation'>Standard Audio Generation (AT Narrator - Optional)</option> 76 <option value='standard_generation'>Standard Audio Generation (AT Narrator - Optional)</option>
77 <option value='streaming_enabled'>Streaming Audio Generation (AT Narrator - Disabled)</option> 77 <option value='streaming_enabled'>Streaming Audio Generation (AT Narrator - Disabled)</option>
78 </select> 78 </select>
79 </div> 79 </div>
80 </div>`; 80 </div>`;
81 81
82 html += `<div class='at-settings-row'> 82 html += `<div class='at-settings-row'>
83 <div class='at-settings-option'> 83 <div class='at-settings-option'>
84 <label for='at_narrator_enabled'>AT Narrator</label> 84 <label for='at_narrator_enabled'>AT Narrator</label>
85 <select id='at_narrator_enabled'> 85 <select id='at_narrator_enabled'>
86 <option value='true'>Enabled</option> 86 <option value='true'>Enabled</option>
87 <option value='silent'>Enabled (Silenced)</option> 87 <option value='silent'>Enabled (Silenced)</option>
88 <option value='false'>Disabled</option> 88 <option value='false'>Disabled</option>
89 </select> 89 </select>
90 </div> 90 </div>
91 91
92 <div class='at-settings-option'> 92 <div class='at-settings-option'>
93 <label for='at_narrator_text_not_inside'>Text Not Inside * or " is</label> 93 <label for='at_narrator_text_not_inside'>Text Not Inside * or " is</label>
94 <select id='at_narrator_text_not_inside'> 94 <select id='at_narrator_text_not_inside'>
95 <option value='character'>Character</option> 95 <option value='character'>Character</option>
96 <option value='narrator'>Narrator</option> 96 <option value='narrator'>Narrator</option>
97 <option value='silent'>Silent</option> 97 <option value='silent'>Silent</option>
98 </select> 98 </select>
99 </div> 99 </div>
100 </div>`; 100 </div>`;
101 101
102 html += `<div class='at-settings-row'> 102 html += `<div class='at-settings-row'>
103 <div class='at-settings-option'> 103 <div class='at-settings-option'>
104 <label for='narrator_voice'>Narrator Voice</label> 104 <label for='narrator_voice'>Narrator Voice</label>
105 <select id='narrator_voice'>`; 105 <select id='narrator_voice'>`;
106 if (this.voices) { 106 if (this.voices) {
107 for (let voice of this.voices) { 107 for (let voice of this.voices) {
108 html += `<option value='${voice.voice_id}'>${voice.name}</option>`; 108 html += `<option value='${voice.voice_id}'>${voice.name}</option>`;
109 } 109 }
110 } 110 }
111 html += `</select> 111 html += `</select>
112 </div> 112 </div>
113 <div class='at-settings-option'> 113 <div class='at-settings-option'>
114 <label for='language_options'>Language</label> 114 <label for='language_options'>Language</label>
115 <select id='language_options'>`; 115 <select id='language_options'>`;
116 for (let language in this.languageLabels) { 116 for (let language in this.languageLabels) {
117 html += `<option value='${this.languageLabels[language]}' ${this.languageLabels[language] === this.settings?.language ? 'selected="selected"' : ''}>${language}</option>`; 117 html += `<option value='${this.languageLabels[language]}' ${this.languageLabels[language] === this.settings?.language ? 'selected="selected"' : ''}>${language}</option>`;
118 } 118 }
119 html += `</select> 119 html += `</select>
120 </div> 120 </div>
121 </div>`; 121 </div>`;
122 122
123 html += `<div class='at-settings-row'> 123 html += `<div class='at-settings-row'>
124 <div class='at-settings-option'> 124 <div class='at-settings-option'>
125 <label for='rvc_character_voice'>RVC Character</label> 125 <label for='rvc_character_voice'>RVC Character</label>
126 <select id='rvc_character_voice'>`; 126 <select id='rvc_character_voice'>`;
127 if (this.rvcVoices) { 127 if (this.rvcVoices) {
128 for (let rvccharvoice of this.rvcVoices) { 128 for (let rvccharvoice of this.rvcVoices) {
129 html += `<option value='${rvccharvoice.voice_id}'>${rvccharvoice.name}</option>`; 129 html += `<option value='${rvccharvoice.voice_id}'>${rvccharvoice.name}</option>`;
130 } 130 }
131 } 131 }
132 html += `</select> 132 html += `</select>
133 </div> 133 </div>
134 <div class='at-settings-option'> 134 <div class='at-settings-option'>
135 <label for='rvc_narrator_voice'>RVC Narrator</label> 135 <label for='rvc_narrator_voice'>RVC Narrator</label>
136 <select id='rvc_narrator_voice'>`; 136 <select id='rvc_narrator_voice'>`;
137 if (this.rvcVoices) { 137 if (this.rvcVoices) {
138 for (let rvcnarrvoice of this.rvcVoices) { 138 for (let rvcnarrvoice of this.rvcVoices) {
139 html += `<option value='${rvcnarrvoice.voice_id}'>${rvcnarrvoice.name}</option>`; 139 html += `<option value='${rvcnarrvoice.voice_id}'>${rvcnarrvoice.name}</option>`;
140 } 140 }
141 } 141 }
142 html += `</select> 142 html += `</select>
143 </div> 143 </div>
144</div>`; 144</div>`;
145 145
146 html += `<div class='at-settings-row'> 146 html += `<div class='at-settings-row'>
147 <div class='at-settings-option'> 147 <div class='at-settings-option'>
148 <label for='rvc_character_pitch'>RVC Character Pitch</label> 148 <label for='rvc_character_pitch'>RVC Character Pitch</label>
149 <select id='rvc_character_pitch'>`; 149 <select id='rvc_character_pitch'>`;
150 for (let i = -24; i <= 24; i++) { 150 for (let i = -24; i <= 24; i++) {
151 const selected = i === 0 ? 'selected="selected"' : ''; 151 const selected = i === 0 ? 'selected="selected"' : '';
152 html += `<option value='${i}' ${selected}>${i}</option>`; 152 html += `<option value='${i}' ${selected}>${i}</option>`;
153 } 153 }
154 html += `</select> 154 html += `</select>
155 </div> 155 </div>
156 <div class='at-settings-option'> 156 <div class='at-settings-option'>
157 <label for='rvc_narrator_pitch'>RVC Narrator Pitch</label> 157 <label for='rvc_narrator_pitch'>RVC Narrator Pitch</label>
158 <select id='rvc_narrator_pitch'>`; 158 <select id='rvc_narrator_pitch'>`;
159 for (let i = -24; i <= 24; i++) { 159 for (let i = -24; i <= 24; i++) {
160 const selected = i === 0 ? 'selected="selected"' : ''; 160 const selected = i === 0 ? 'selected="selected"' : '';
161 html += `<option value='${i}' ${selected}>${i}</option>`; 161 html += `<option value='${i}' ${selected}>${i}</option>`;
162 } 162 }
163 html += `</select> 163 html += `</select>
164 </div> 164 </div>
165 </div>`; 165 </div>`;
166 166
167 html += `<div class='at-model-endpoint-row'> 167 html += `<div class='at-model-endpoint-row'>
168 <div class='at-model-option'> 168 <div class='at-model-option'>
169 <label for='switch_model'>Switch Model</label> 169 <label for='switch_model'>Switch Model</label>
170 <select id='switch_model'> 170 <select id='switch_model'>
171 <!-- Options will be dynamically populated --> 171 <!-- Options will be dynamically populated -->
172 </select> 172 </select>
173 </div> 173 </div>
174 174
175 <div class='at-endpoint-option'> 175 <div class='at-endpoint-option'>
176 <label for='at_server'>AllTalk Endpoint:</label> 176 <label for='at_server'>AllTalk Endpoint:</label>
177 <input id='at_server' type='text' class='text_pole' maxlength='80' value='${this.settings.provider_endpoint}'/> 177 <input id='at_server' type='text' class='text_pole' maxlength='80' value='${this.settings.provider_endpoint}'/>
178 </div> 178 </div>
179 </div>`; 179 </div>`;
180 180
181 html += `<div class='at-settings-row'> 181 html += `<div class='at-settings-row'>
182 <div class='at-settings-option'> 182 <div class='at-settings-option'>
183 <label for='server_version'>AllTalk Server Version</label> 183 <label for='server_version'>AllTalk Server Version</label>
184 <select id='server_version'> 184 <select id='server_version'>
185 <option value='v1'>AllTalk V1</option> 185 <option value='v1'>AllTalk V1</option>
186 <option value='v2'>AllTalk V2</option> 186 <option value='v2'>AllTalk V2</option>
187 </select> 187 </select>
188 </div> 188 </div>
189 </div>`; 189 </div>`;
190 190
191 html += `<div class='at-model-endpoint-row'> 191 html += `<div class='at-model-endpoint-row'>
192 <div class='at-settings-option'> 192 <div class='at-settings-option'>
193 <label for='low_vram'>Low VRAM</label> 193 <label for='low_vram'>Low VRAM</label>
194 <input id='low_vram' type='checkbox'/> 194 <input id='low_vram' type='checkbox'/>
195 </div> 195 </div>
196 <div class='at-settings-option'> 196 <div class='at-settings-option'>
197 <label for='deepspeed'>DeepSpeed</label> 197 <label for='deepspeed'>DeepSpeed</label>
198 <input id='deepspeed' type='checkbox'/> 198 <input id='deepspeed' type='checkbox'/>
199 </div> 199 </div>
200 <div class='at-settings-option status-option'> 200 <div class='at-settings-option status-option'>
201 <span>Status: <span id='status_info'>Ready</span></span> 201 <span>Status: <span id='status_info'>Ready</span></span>
202 </div> 202 </div>
203 <div class='at-settings-option empty-option'> 203 <div class='at-settings-option empty-option'>
204 <!-- This div remains empty for spacing --> 204 <!-- This div remains empty for spacing -->
205 </div> 205 </div>
206</div>`; 206</div>`;
207 207
208 html += `<div class='at-website-row'> 208 html += `<div class='at-website-row'>
209 <div class='at-website-option'> 209 <div class='at-website-option'>
210 <span>AllTalk V2<a target='_blank' href='${this.settings.provider_endpoint}'>Config & Docs</a>.</span> 210 <span>AllTalk V2<a target='_blank' href='${this.settings.provider_endpoint}'>Config & Docs</a>.</span>
211 </div> 211 </div>
212 212
213 <div class='at-website-option'> 213 <div class='at-website-option'>
214 <span>AllTalk <a target='_blank' href='https://github.com/erew123/alltalk_tts/'>Website</a>.</span> 214 <span>AllTalk <a target='_blank' href='https://github.com/erew123/alltalk_tts/'>Website</a>.</span>
215 </div> 215 </div>
216</div>`; 216</div>`;
217 217
218 html += `<div class='at-website-row'> 218 html += `<div class='at-website-row'>
219<div class='at-website-option'> 219<div class='at-website-option'>
220<span>- If you <strong>change your TTS engine</strong> in AllTalk, you will need to <strong>Reload</strong> (button above) and re-select your voices.</span><br><br> 220<span>- If you <strong>change your TTS engine</strong> in AllTalk, you will need to <strong>Reload</strong> (button above) and re-select your voices.</span><br><br>
221<span>- Assuming the server is <strong>Status: Ready</strong>, most problems will be resolved by hitting Reload and selecting voices that match the loaded TTS engine.</span><br><br> 221<span>- Assuming the server is <strong>Status: Ready</strong>, most problems will be resolved by hitting Reload and selecting voices that match the loaded TTS engine.</span><br><br>
222<span>- <strong>Text-generation-webui</strong> users - Uncheck <strong>Enable TTS</strong> in the TGWUI interface, or you will hear 2x voices and file names being generated.</span> 222<span>- <strong>Text-generation-webui</strong> users - Uncheck <strong>Enable TTS</strong> in the TGWUI interface, or you will hear 2x voices and file names being generated.</span>
223</div> 223</div>
224</div>`; 224</div>`;
225 225
226 return html; 226 return html;
227 } 227 }
228 228
229 229
230 //#################// 230 //#################//
231 // Startup ST & AT // 231 // Startup ST & AT //
232 //#################// 232 //#################//
233 233
234 async loadSettings(settings) { 234 async loadSettings(settings) {
235 updateStatus('Offline'); 235 updateStatus('Offline');
236 236
237 if (Object.keys(settings).length === 0) { 237 if (Object.keys(settings).length === 0) {
238 console.info('Using default AllTalk TTS Provider settings'); 238 console.info('Using default AllTalk TTS Provider settings');
239 } else { 239 } else {
240 // Populate settings with provided values, ignoring server-provided settings 240 // Populate settings with provided values, ignoring server-provided settings
241 for (const key in settings) { 241 for (const key in settings) {
242 if (key in this.settings) { 242 if (key in this.settings) {
243 this.settings[key] = settings[key]; 243 this.settings[key] = settings[key];
244 } else { 244 } else {
245 console.debug(`Ignoring non-user-configurable setting: ${key}`); 245 console.debug(`Ignoring non-user-configurable setting: ${key}`);
246 } 246 }
247 } 247 }
248 } 248 }
249 249
250 // Update UI elements to reflect the loaded settings 250 // Update UI elements to reflect the loaded settings
251 $('#at_server').val(this.settings.provider_endpoint); 251 $('#at_server').val(this.settings.provider_endpoint);
252 $('#language_options').val(this.settings.language); 252 $('#language_options').val(this.settings.language);
253 $('#at_generation_method').val(this.settings.at_generation_method); 253 $('#at_generation_method').val(this.settings.at_generation_method);
254 $('#at_narrator_enabled').val(this.settings.narrator_enabled); 254 $('#at_narrator_enabled').val(this.settings.narrator_enabled);
255 $('#at_narrator_text_not_inside').val(this.settings.at_narrator_text_not_inside); 255 $('#at_narrator_text_not_inside').val(this.settings.at_narrator_text_not_inside);
256 $('#narrator_voice').val(this.settings.narrator_voice_gen); 256 $('#narrator_voice').val(this.settings.narrator_voice_gen);
257 $('#rvc_character_voice').val(this.settings.rvc_character_voice); 257 $('#rvc_character_voice').val(this.settings.rvc_character_voice);
258 $('#rvc_narrator_voice').val(this.settings.rvc_narrator_voice); 258 $('#rvc_narrator_voice').val(this.settings.rvc_narrator_voice);
259 $('#rvc_character_pitch').val(this.settings.rvc_character_pitch); 259 $('#rvc_character_pitch').val(this.settings.rvc_character_pitch);
260 $('#rvc_narrator_pitch').val(this.settings.rvc_narrator_pitch); 260 $('#rvc_narrator_pitch').val(this.settings.rvc_narrator_pitch);
261 261
262 console.debug('AllTalkTTS: Settings loaded'); 262 console.debug('AllTalkTTS: Settings loaded');
263 try { 263 try {
264 // Check if TTS provider is ready 264 // Check if TTS provider is ready
265 await this.checkReady(); 265 this.setupEventListeners();
266 await this.updateSettingsFromServer(); // Fetch dynamic settings from the TTS server 266 this.updateLanguageDropdown();
267 await this.fetchTtsVoiceObjects(); // Fetch voices only if service is ready 267 await this.checkReady();
268 await this.fetchRvcVoiceObjects(); // Fetch RVC voices 268 await this.updateSettingsFromServer(); // Fetch dynamic settings from the TTS server
269 this.updateNarratorVoicesDropdown(); 269 await this.fetchTtsVoiceObjects(); // Fetch voices only if service is ready
270 this.updateLanguageDropdown(); 270 await this.fetchRvcVoiceObjects(); // Fetch RVC voices
271 this.setupEventListeners(); 271 this.updateNarratorVoicesDropdown();
272 this.applySettingsToHTML(); 272 this.applySettingsToHTML();
273 updateStatus('Ready'); 273 updateStatus('Ready');
274 } catch (error) { 274 } catch (error) {
275 console.error('Error loading settings:', error); 275 console.error('Error loading settings:', error);
276 updateStatus('Offline'); 276 updateStatus('Offline');
277 } 277 }
278 } 278 }
279 279
280 280
281 applySettingsToHTML() { 281 applySettingsToHTML() {
282 const narratorVoiceSelect = document.getElementById('narrator_voice'); 282 const narratorVoiceSelect = document.getElementById('narrator_voice');
283 const atNarratorSelect = document.getElementById('at_narrator_enabled'); 283 const atNarratorSelect = document.getElementById('at_narrator_enabled');
284 const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside'); 284 const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside');
285 const generationMethodSelect = document.getElementById('at_generation_method'); 285 const generationMethodSelect = document.getElementById('at_generation_method');
286 this.settings.narrator_voice = this.settings.narrator_voice_gen; 286 this.settings.narrator_voice = this.settings.narrator_voice_gen;
287 // Apply settings to Narrator Voice dropdown 287 // Apply settings to Narrator Voice dropdown
288 if (narratorVoiceSelect && this.settings.narrator_voice) { 288 if (narratorVoiceSelect && this.settings.narrator_voice) {
289 narratorVoiceSelect.value = this.settings.narrator_voice; // Remove the parentheses 289 narratorVoiceSelect.value = this.settings.narrator_voice; // Remove the parentheses
290 } 290 }
291 // Apply settings to AT Narrator Enabled dropdown 291 // Apply settings to AT Narrator Enabled dropdown
292 if (atNarratorSelect) { 292 if (atNarratorSelect) {
293 const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks'); 293 const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks');
294 const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted'); 294 const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted');
295 const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues'); 295 const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues');
296 if (this.settings.narrator_enabled) { 296 if (this.settings.narrator_enabled) {
297 ttsPassAsterisksCheckbox.checked = false; 297 ttsPassAsterisksCheckbox.checked = false;
298 $('#tts_pass_asterisks').click(); 298 $('#tts_pass_asterisks').click();
299 $('#tts_pass_asterisks').trigger('change'); 299 $('#tts_pass_asterisks').trigger('change');
300 } 300 }
301 if (!this.settings.narrator_enabled) { 301 if (!this.settings.narrator_enabled) {
302 ttsPassAsterisksCheckbox.checked = true; 302 ttsPassAsterisksCheckbox.checked = true;
303 $('#tts_pass_asterisks').click(); 303 $('#tts_pass_asterisks').click();
304 $('#tts_pass_asterisks').trigger('change'); 304 $('#tts_pass_asterisks').trigger('change');
305 } 305 }
306 if (this.settings.narrator_enabled) { 306 if (this.settings.narrator_enabled) {
307 ttsNarrateQuotedCheckbox.checked = true; 307 ttsNarrateQuotedCheckbox.checked = true;
308 ttsNarrateDialoguesCheckbox.checked = true; 308 ttsNarrateDialoguesCheckbox.checked = true;
309 $('#tts_narrate_quoted').click(); 309 $('#tts_narrate_quoted').click();
310 $('#tts_narrate_quoted').trigger('change'); 310 $('#tts_narrate_quoted').trigger('change');
311 $('#tts_narrate_dialogues').click(); 311 $('#tts_narrate_dialogues').click();
312 $('#tts_narrate_dialogues').trigger('change'); 312 $('#tts_narrate_dialogues').trigger('change');
313 } 313 }
314 atNarratorSelect.value = this.settings.narrator_enabled.toString(); 314 atNarratorSelect.value = this.settings.narrator_enabled.toString();
315 this.settings.narrator_enabled = this.settings.narrator_enabled.toString(); 315 this.settings.narrator_enabled = this.settings.narrator_enabled.toString();
316 } 316 }
317 const languageSelect = document.getElementById('language_options'); 317 const languageSelect = document.getElementById('language_options');
318 if (languageSelect && this.settings.language) { 318 if (languageSelect && this.settings.language) {
319 languageSelect.value = this.settings.language; 319 languageSelect.value = this.settings.language;
320 } 320 }
321 if (textNotInsideSelect && this.settings.text_not_inside) { 321 if (textNotInsideSelect && this.settings.text_not_inside) {
322 textNotInsideSelect.value = this.settings.text_not_inside; 322 textNotInsideSelect.value = this.settings.text_not_inside;
323 this.settings.at_narrator_text_not_inside = this.settings.text_not_inside; 323 this.settings.at_narrator_text_not_inside = this.settings.text_not_inside;
324 } 324 }
325 if (generationMethodSelect && this.settings.at_generation_method) { 325 if (generationMethodSelect && this.settings.at_generation_method) {
326 generationMethodSelect.value = this.settings.at_generation_method; 326 generationMethodSelect.value = this.settings.at_generation_method;
327 } 327 }
328 const isStreamingEnabled = this.settings.at_generation_method === 'streaming_enabled'; 328 const isStreamingEnabled = this.settings.at_generation_method === 'streaming_enabled';
329 if (isStreamingEnabled) { 329 if (isStreamingEnabled) {
330 if (atNarratorSelect) atNarratorSelect.disabled = true; 330 if (atNarratorSelect) atNarratorSelect.disabled = true;
331 if (textNotInsideSelect) textNotInsideSelect.disabled = true; 331 if (textNotInsideSelect) textNotInsideSelect.disabled = true;
332 if (narratorVoiceSelect) narratorVoiceSelect.disabled = true; 332 if (narratorVoiceSelect) narratorVoiceSelect.disabled = true;
333 } else { 333 } else {
334 if (atNarratorSelect) atNarratorSelect.disabled = false; 334 if (atNarratorSelect) atNarratorSelect.disabled = false;
335 if (textNotInsideSelect) textNotInsideSelect.disabled = !this.settings.narrator_enabled; 335 if (textNotInsideSelect) textNotInsideSelect.disabled = !this.settings.narrator_enabled;
336 if (narratorVoiceSelect) narratorVoiceSelect.disabled = !this.settings.narrator_enabled; 336 if (narratorVoiceSelect) narratorVoiceSelect.disabled = !this.settings.narrator_enabled;
337 } 337 }
338 } 338 }
339 339
340 340
341 //##############################// 341 //##############################//
342 // Check AT Server is Available // 342 // Check AT Server is Available //
343 //##############################// 343 //##############################//
344 344
345 async checkReady() { 345 async checkReady() {
346 try { 346 try {
347 const response = await fetch(`${this.settings.provider_endpoint}/api/ready`); 347 const response = await fetch(`${this.settings.provider_endpoint}/api/ready`);
348 // Check if the HTTP request was successful 348 // Check if the HTTP request was successful
349 if (!response.ok) { 349 if (!response.ok) {
350 throw new Error(`HTTP Error Response: ${response.status} ${response.statusText}`); 350 throw new Error(`HTTP Error Response: ${response.status} ${response.statusText}`);
351 } 351 }
352 const statusText = await response.text(); 352 const statusText = await response.text();
353 // Check if the response is 'Ready' 353 // Check if the response is 'Ready'
354 if (statusText === 'Ready') { 354 if (statusText === 'Ready') {
355 this.ready = true; // Set the ready flag to true 355 this.ready = true; // Set the ready flag to true
356 console.log('TTS service is ready.'); 356 console.log('TTS service is ready.');
357 } else { 357 } else {
358 this.ready = false; 358 this.ready = false;
359 console.log('TTS service is not ready.'); 359 console.log('TTS service is not ready.');
360 } 360 }
361 } catch (error) { 361 } catch (error) {
362 console.error('Error checking TTS service readiness:', error); 362 console.error('Error checking TTS service readiness:', error);
363 this.ready = false; // Ensure ready flag is set to false in case of error 363 this.ready = false; // Ensure ready flag is set to false in case of error
364 } 364 }
365 } 365 }
366 366
367 //######################// 367 //######################//
368 // Get Available Voices // 368 // Get Available Voices //
369 //######################// 369 //######################//
370 370
371 async fetchTtsVoiceObjects() { 371 async fetchTtsVoiceObjects() {
372 const response = await fetch(`${this.settings.provider_endpoint}/api/voices`); 372 const response = await fetch(`${this.settings.provider_endpoint}/api/voices`);
373 if (!response.ok) { 373 if (!response.ok) {
374 const errorText = await response.text(); 374 const errorText = await response.text();
375 throw new Error(`HTTP ${response.status}: ${errorText}`); 375 throw new Error(`HTTP ${response.status}: ${errorText}`);
376 } 376 }
377 const data = await response.json(); 377 const data = await response.json();
378 const voices = data.voices.map(filename => { 378 const voices = data.voices.map(filename => {
379 return { 379 return {
380 name: filename, 380 name: filename,
381 voice_id: filename, 381 voice_id: filename,
382 preview_url: null, // Preview URL will be dynamically generated 382 preview_url: null, // Preview URL will be dynamically generated
383 lang: 'en', // Default language 383 lang: 'en', // Default language
384 }; 384 };
385 }); 385 });
386 this.voices = voices; // Assign to the class property 386 this.voices = voices; // Assign to the class property
387 return voices; // Also return this list 387 return voices; // Also return this list
388 } 388 }
389 389
390 async fetchRvcVoiceObjects() { 390 async fetchRvcVoiceObjects() {
391 if (this.settings.server_version !== 'v2') { 391 if (this.settings.server_version !== 'v2') {
392 console.log('Skipping RVC voices fetch for V1 server'); 392 console.log('Skipping RVC voices fetch for V1 server');
393 return []; 393 return [];
394 } 394 }
395 395
396 console.log('Fetching RVC Voices'); 396 console.log('Fetching RVC Voices');
397 try { 397 try {
398 const response = await fetch(`${this.settings.provider_endpoint}/api/rvcvoices`); 398 const response = await fetch(`${this.settings.provider_endpoint}/api/rvcvoices`);
399 if (!response.ok) { 399 if (!response.ok) {
400 const errorText = await response.text(); 400 const errorText = await response.text();
401 console.error('Error text:', errorText); 401 console.error('Error text:', errorText);
402 throw new Error(`HTTP ${response.status}: ${errorText}`); 402 throw new Error(`HTTP ${response.status}: ${errorText}`);
403 } 403 }
404 404
405 const data = await response.json(); 405 const data = await response.json();
406 if (!data || !data.rvcvoices) { 406 if (!data || !data.rvcvoices) {
407 console.error('Invalid data format:', data); 407 console.error('Invalid data format:', data);
408 throw new Error('Invalid data format received from /api/rvcvoices'); 408 throw new Error('Invalid data format received from /api/rvcvoices');
409 } 409 }
410 410
411 const voices = data.rvcvoices.map(filename => { 411 const voices = data.rvcvoices.map(filename => {
412 return { 412 return {
413 name: filename, 413 name: filename,
414 voice_id: filename, 414 voice_id: filename,
415 }; 415 };
416 }); 416 });
417 417
418 console.log('RVC voices:', voices); 418 console.log('RVC voices:', voices);
419 this.rvcVoices = voices; // Assign to the class property 419 this.rvcVoices = voices; // Assign to the class property
420 this.updateRvcVoiceDropdowns(); // Update UI after fetching voices 420 this.updateRvcVoiceDropdowns(); // Update UI after fetching voices
421 return voices; // Also return this list 421 return voices; // Also return this list
422 } catch (error) { 422 } catch (error) {
423 console.error('Error fetching RVC voices:', error); 423 console.error('Error fetching RVC voices:', error);
424 this.rvcVoices = [{ name: 'Disabled', voice_id: 'Disabled' }]; // Set default on error 424 this.rvcVoices = [{ name: 'Disabled', voice_id: 'Disabled' }]; // Set default on error
425 throw error; 425 throw error;
426 } finally { 426 } finally {
427 // Ensure dropdowns are updated even if there was an error 427 // Ensure dropdowns are updated even if there was an error
428 this.updateRvcVoiceDropdowns(); 428 this.updateRvcVoiceDropdowns();
429 } 429 }
430 } 430 }
431 431
432 //##########################################// 432 //##########################################//
433 // Get Current AT Server Config & Update ST // 433 // Get Current AT Server Config & Update ST //
434 //##########################################// 434 //##########################################//
435 435
436 async updateSettingsFromServer() { 436 async updateSettingsFromServer() {
437 try { 437 try {
438 const response = await fetch(`${this.settings.provider_endpoint}/api/currentsettings`); 438 const response = await fetch(`${this.settings.provider_endpoint}/api/currentsettings`);
439 if (!response.ok) { 439 if (!response.ok) {
440 throw new Error(`Failed to fetch current settings: ${response.statusText}`); 440 throw new Error(`Failed to fetch current settings: ${response.statusText}`);
441 } 441 }
442 const currentSettings = await response.json(); 442 const currentSettings = await response.json();
443 currentSettings.models_available.sort((a, b) => a.name.localeCompare(b.name)); 443 currentSettings.models_available.sort((a, b) => a.name.localeCompare(b.name));
444 444
445 this.settings.enginesAvailable = currentSettings.engines_available; 445 this.settings.enginesAvailable = currentSettings.engines_available;
446 this.settings.currentEngineLoaded = currentSettings.current_engine_loaded; 446 this.settings.currentEngineLoaded = currentSettings.current_engine_loaded;
447 this.settings.modelsAvailable = currentSettings.models_available; 447 this.settings.modelsAvailable = currentSettings.models_available;
448 this.settings.currentModel = currentSettings.current_model_loaded; 448 this.settings.currentModel = currentSettings.current_model_loaded;
449 this.settings.deepspeed_capable = currentSettings.deepspeed_capable; 449 this.settings.deepspeed_capable = currentSettings.deepspeed_capable;
450 this.settings.deepspeed_available = currentSettings.deepspeed_available; 450 this.settings.deepspeed_available = currentSettings.deepspeed_available;
451 this.settings.deepspeed_enabled = currentSettings.deepspeed_enabled; 451 this.settings.deepspeed_enabled = currentSettings.deepspeed_enabled;
452 this.settings.lowvram_capable = currentSettings.lowvram_capable; 452 this.settings.lowvram_capable = currentSettings.lowvram_capable;
453 this.settings.lowvram_enabled = currentSettings.lowvram_enabled; 453 this.settings.lowvram_enabled = currentSettings.lowvram_enabled;
454 454
455 await this.fetchRvcVoiceObjects(); // Fetch RVC voices 455 await this.fetchRvcVoiceObjects(); // Fetch RVC voices
456 456
457 this.updateModelDropdown(); 457 this.updateModelDropdown();
458 this.updateCheckboxes(); 458 this.updateCheckboxes();
459 this.updateRvcVoiceDropdowns(); // Update the RVC voice dropdowns 459 this.updateRvcVoiceDropdowns(); // Update the RVC voice dropdowns
460 } catch (error) { 460 } catch (error) {
461 console.error(`Error updating settings from server: ${error}`); 461 console.error(`Error updating settings from server: ${error}`);
462 } 462 }
463 } 463 }
464 464
465 updateRvcVoiceDropdowns() { 465 updateRvcVoiceDropdowns() {
466 // Handle all RVC-related elements 466 // Handle all RVC-related elements
467 const rvcElements = document.querySelectorAll('.rvc-setting'); 467 const rvcElements = document.querySelectorAll('.rvc-setting');
468 const isV2 = this.settings.server_version === 'v2'; 468 const isV2 = this.settings.server_version === 'v2';
469 469
470 rvcElements.forEach(element => { 470 rvcElements.forEach(element => {
471 element.style.display = isV2 ? 'block' : 'none'; 471 element.style.display = isV2 ? 'block' : 'none';
472 }); 472 });
473 473
474 // Update and disable/enable character voice dropdown 474 // Update and disable/enable character voice dropdown
475 const rvcCharacterVoiceSelect = document.getElementById('rvc_character_voice'); 475 const rvcCharacterVoiceSelect = document.getElementById('rvc_character_voice');
476 if (rvcCharacterVoiceSelect) { 476 if (rvcCharacterVoiceSelect) {
477 rvcCharacterVoiceSelect.disabled = !isV2; 477 rvcCharacterVoiceSelect.disabled = !isV2;
478 if (this.rvcVoices) { 478 if (this.rvcVoices) {
479 rvcCharacterVoiceSelect.innerHTML = ''; 479 rvcCharacterVoiceSelect.innerHTML = '';
480 for (let voice of this.rvcVoices) { 480 for (let voice of this.rvcVoices) {
481 const option = document.createElement('option'); 481 const option = document.createElement('option');
482 option.value = voice.voice_id; 482 option.value = voice.voice_id;
483 option.textContent = voice.name; 483 option.textContent = voice.name;
484 if (voice.voice_id === this.settings.rvc_character_voice) { 484 if (voice.voice_id === this.settings.rvc_character_voice) {
485 option.selected = true; 485 option.selected = true;
486 } 486 }
487 rvcCharacterVoiceSelect.appendChild(option); 487 rvcCharacterVoiceSelect.appendChild(option);
488 } 488 }
489 } 489 }
490 } 490 }
491 491
492 // Update and disable/enable narrator voice dropdown 492 // Update and disable/enable narrator voice dropdown
493 const rvcNarratorVoiceSelect = document.getElementById('rvc_narrator_voice'); 493 const rvcNarratorVoiceSelect = document.getElementById('rvc_narrator_voice');
494 if (rvcNarratorVoiceSelect) { 494 if (rvcNarratorVoiceSelect) {
495 rvcNarratorVoiceSelect.disabled = !isV2; 495 rvcNarratorVoiceSelect.disabled = !isV2;
496 if (this.rvcVoices) { 496 if (this.rvcVoices) {
497 rvcNarratorVoiceSelect.innerHTML = ''; 497 rvcNarratorVoiceSelect.innerHTML = '';
498 for (let voice of this.rvcVoices) { 498 for (let voice of this.rvcVoices) {
499 const option = document.createElement('option'); 499 const option = document.createElement('option');
500 option.value = voice.voice_id; 500 option.value = voice.voice_id;
501 option.textContent = voice.name; 501 option.textContent = voice.name;
502 if (voice.voice_id === this.settings.rvc_narrator_voice) { 502 if (voice.voice_id === this.settings.rvc_narrator_voice) {
503 option.selected = true; 503 option.selected = true;
504 } 504 }
505 rvcNarratorVoiceSelect.appendChild(option); 505 rvcNarratorVoiceSelect.appendChild(option);
506 } 506 }
507 } 507 }
508 } 508 }
509 509
510 // Update pitch inputs 510 // Update pitch inputs
511 const characterPitch = document.getElementById('rvc_character_pitch'); 511 const characterPitch = document.getElementById('rvc_character_pitch');
512 if (characterPitch) { 512 if (characterPitch) {
513 characterPitch.disabled = !isV2; 513 characterPitch.disabled = !isV2;
514 } 514 }
515 515
516 const narratorPitch = document.getElementById('rvc_narrator_pitch'); 516 const narratorPitch = document.getElementById('rvc_narrator_pitch');
517 if (narratorPitch) { 517 if (narratorPitch) {
518 narratorPitch.disabled = !isV2; 518 narratorPitch.disabled = !isV2;
519 } 519 }
520 } 520 }
521 521
522 //###################################################// 522 //###################################################//
523 // Get Current AT Server Config & Update ST (Models) // 523 // Get Current AT Server Config & Update ST (Models) //
524 //###################################################// 524 //###################################################//
525 525
526 updateModelDropdown() { 526 updateModelDropdown() {
527 const modelSelect = document.getElementById('switch_model'); 527 const modelSelect = document.getElementById('switch_model');
528 if (modelSelect) { 528 if (modelSelect) {
529 modelSelect.innerHTML = ''; // Clear existing options 529 modelSelect.innerHTML = ''; // Clear existing options
530 this.settings.modelsAvailable.forEach(model => { 530 this.settings.modelsAvailable.forEach(model => {
531 const option = document.createElement('option'); 531 const option = document.createElement('option');
532 option.value = model.name; 532 option.value = model.name;
533 option.textContent = model.name; // Use model name directly 533 option.textContent = model.name; // Use model name directly
534 option.selected = model.name === this.settings.currentModel; 534 option.selected = model.name === this.settings.currentModel;
535 modelSelect.appendChild(option); 535 modelSelect.appendChild(option);
536 }); 536 });
537 } 537 }
538 } 538 }
539 539
540 //#######################################################// 540 //#######################################################//
541 // Get Current AT Server Config & Update ST (DS and LVR) // 541 // Get Current AT Server Config & Update ST (DS and LVR) //
542 //#######################################################// 542 //#######################################################//
543 543
544 updateCheckboxes() { 544 updateCheckboxes() {
545 const deepspeedCheckbox = document.getElementById('deepspeed'); 545 const deepspeedCheckbox = document.getElementById('deepspeed');
546 const lowVramCheckbox = document.getElementById('low_vram'); 546 const lowVramCheckbox = document.getElementById('low_vram');
547 547
548 // Handle DeepSpeed checkbox 548 // Handle DeepSpeed checkbox
549 if (deepspeedCheckbox) { 549 if (deepspeedCheckbox) {
550 if (this.settings.deepspeed_capable) { 550 if (this.settings.deepspeed_capable) {
551 // If TTS engine is capable of using DeepSpeed 551 // If TTS engine is capable of using DeepSpeed
552 deepspeedCheckbox.disabled = !this.settings.deepspeed_available; 552 deepspeedCheckbox.disabled = !this.settings.deepspeed_available;
553 this.settings.deepspeed_enabled = this.settings.deepspeed_available && this.settings.deepspeed_enabled; 553 this.settings.deepspeed_enabled = this.settings.deepspeed_available && this.settings.deepspeed_enabled;
554 } else { 554 } else {
555 // If TTS engine is NOT capable of using DeepSpeed 555 // If TTS engine is NOT capable of using DeepSpeed
556 deepspeedCheckbox.disabled = true; 556 deepspeedCheckbox.disabled = true;
557 this.settings.deepspeed_enabled = false; 557 this.settings.deepspeed_enabled = false;
558 } 558 }
559 deepspeedCheckbox.checked = this.settings.deepspeed_enabled; 559 deepspeedCheckbox.checked = this.settings.deepspeed_enabled;
560 } 560 }
561 561
562 // Handle Low VRAM checkbox 562 // Handle Low VRAM checkbox
563 if (lowVramCheckbox) { 563 if (lowVramCheckbox) {
564 if (this.settings.lowvram_capable) { 564 if (this.settings.lowvram_capable) {
565 // If TTS engine is capable of low VRAM 565 // If TTS engine is capable of low VRAM
566 lowVramCheckbox.disabled = false; 566 lowVramCheckbox.disabled = false;
567 } else { 567 } else {
568 // If TTS engine is NOT capable of low VRAM 568 // If TTS engine is NOT capable of low VRAM
569 lowVramCheckbox.disabled = true; 569 lowVramCheckbox.disabled = true;
570 this.settings.lowvram_enabled = false; 570 this.settings.lowvram_enabled = false;
571 } 571 }
572 lowVramCheckbox.checked = this.settings.lowvram_enabled; 572 lowVramCheckbox.checked = this.settings.lowvram_enabled;
573 } 573 }
574 } 574 }
575 575
576 576
577 //###############################################################// 577 //###############################################################//
578 // Get Current AT Server Config & Update ST (AT Narrator Voices) // 578 // Get Current AT Server Config & Update ST (AT Narrator Voices) //
579 //###############################################################// 579 //###############################################################//
580 580
581 updateNarratorVoicesDropdown() { 581 updateNarratorVoicesDropdown() {
582 const narratorVoiceSelect = document.getElementById('narrator_voice'); 582 const narratorVoiceSelect = document.getElementById('narrator_voice');
583 if (narratorVoiceSelect && this.voices) { 583 if (narratorVoiceSelect && this.voices) {
584 // Clear existing options 584 // Clear existing options
585 narratorVoiceSelect.innerHTML = ''; 585 narratorVoiceSelect.innerHTML = '';
586 // Add new options 586 // Add new options
587 for (let voice of this.voices) { 587 for (let voice of this.voices) {
588 const option = document.createElement('option'); 588 const option = document.createElement('option');
589 option.value = voice.voice_id; 589 option.value = voice.voice_id;
590 option.textContent = voice.name; 590 option.textContent = voice.name;
591 narratorVoiceSelect.appendChild(option); 591 narratorVoiceSelect.appendChild(option);
592 } 592 }
593 } 593 }
594 } 594 }
595 595
596 //######################################################// 596 //######################################################//
597 // Get Current AT Server Config & Update ST (Languages) // 597 // Get Current AT Server Config & Update ST (Languages) //
598 //######################################################// 598 //######################################################//
599 599
600 updateLanguageDropdown() { 600 updateLanguageDropdown() {
601 const languageSelect = document.getElementById('language_options'); 601 const languageSelect = document.getElementById('language_options');
602 if (languageSelect) { 602 if (languageSelect) {
603 // Ensure default language is set 603 // Ensure default language is set
604 this.settings.language = this.settings.language || 'en'; 604 this.settings.language = this.settings.language || 'en';
605 605
606 languageSelect.innerHTML = ''; 606 languageSelect.innerHTML = '';
607 for (let language in this.languageLabels) { 607 for (let language in this.languageLabels) {
608 const option = document.createElement('option'); 608 const option = document.createElement('option');
609 option.value = this.languageLabels[language]; 609 option.value = this.languageLabels[language];
610 option.textContent = language; 610 option.textContent = language;
611 if (this.languageLabels[language] === this.settings.language) { 611 if (this.languageLabels[language] === this.settings.language) {
612 option.selected = true; 612 option.selected = true;
613 } 613 }
614 languageSelect.appendChild(option); 614 languageSelect.appendChild(option);
615 } 615 }
616 } 616 }
617 } 617 }
618 618
619 //########################################// 619 //########################################//
620 // Start AT TTS extenstion page listeners // 620 // Start AT TTS extenstion page listeners //
621 //########################################// 621 //########################################//
622 622
623 setupEventListeners() { 623 setupEventListeners() {
624 // Define the event handler function 624 // Define the event handler function
625 const onModelSelectChange = async (event) => { 625 const onModelSelectChange = async (event) => {
626 console.log('Model select change event triggered'); 626 console.log('Model select change event triggered');
627 const selectedModel = event.target.value; 627 const selectedModel = event.target.value;
628 console.log(`Selected model: ${selectedModel}`); 628 console.log(`Selected model: ${selectedModel}`);
629 updateStatus('Processing'); 629 updateStatus('Processing');
630 try { 630 try {
631 const response = await fetch(`${this.settings.provider_endpoint}/api/reload?tts_method=${encodeURIComponent(selectedModel)}`, { 631 const response = await fetch(`${this.settings.provider_endpoint}/api/reload?tts_method=${encodeURIComponent(selectedModel)}`, {
632 method: 'POST', 632 method: 'POST',
633 }); 633 });
634 if (!response.ok) { 634 if (!response.ok) {
635 throw new Error(`HTTP Error: ${response.status}`); 635 throw new Error(`HTTP Error: ${response.status}`);
636 } 636 }
637 const data = await response.json(); 637 const data = await response.json();
638 console.log('POST response data:', data); 638 console.log('POST response data:', data);
639 updateStatus('Ready'); 639 updateStatus('Ready');
640 } catch (error) { 640 } catch (error) {
641 console.error('POST request error:', error); 641 console.error('POST request error:', error);
642 updateStatus('Error'); 642 updateStatus('Error');
643 } 643 }
644 }; 644 };
645 645
646 // Switch Model Listener with debounce 646 // Switch Model Listener with debounce
647 const modelSelect = document.getElementById('switch_model'); 647 const modelSelect = document.getElementById('switch_model');
648 if (modelSelect) { 648 if (modelSelect) {
649 const debouncedModelSelectChange = debounce(onModelSelectChange, 1400); 649 const debouncedModelSelectChange = debounce(onModelSelectChange, 1400);
650 modelSelect.addEventListener('change', debouncedModelSelectChange); 650 modelSelect.addEventListener('change', debouncedModelSelectChange);
651 } 651 }
652 652
653 // AllTalk Server version change listener 653 // AllTalk Server version change listener
654 const serverVersionSelect = document.getElementById('server_version'); 654 const serverVersionSelect = document.getElementById('server_version');
655 if (serverVersionSelect) { 655 if (serverVersionSelect) {
656 serverVersionSelect.addEventListener('change', async (event) => { 656 serverVersionSelect.addEventListener('change', async (event) => {
657 this.settings.server_version = event.target.value; 657 this.settings.server_version = event.target.value;
658 if (event.target.value === 'v2') { 658 if (event.target.value === 'v2') {
659 await this.fetchRvcVoiceObjects(); 659 await this.fetchRvcVoiceObjects();
660 } 660 }
661 this.updateRvcVoiceDropdowns(); 661 this.updateRvcVoiceDropdowns();
662 this.onSettingsChange(); 662 this.onSettingsChange();
663 }); 663 });
664 } 664 }
665 665
666 // RVC Voice and Pitch listeners 666 // RVC Voice and Pitch listeners
667 const rvcCharacterVoiceSelect = document.getElementById('rvc_character_voice'); 667 const rvcCharacterVoiceSelect = document.getElementById('rvc_character_voice');
668 if (rvcCharacterVoiceSelect) { 668 if (rvcCharacterVoiceSelect) {
669 rvcCharacterVoiceSelect.addEventListener('change', (event) => { 669 rvcCharacterVoiceSelect.addEventListener('change', (event) => {
670 this.settings.rvccharacter_voice_gen = event.target.value; 670 this.settings.rvccharacter_voice_gen = event.target.value;
671 this.onSettingsChange(); 671 this.onSettingsChange();
672 }); 672 });
673 } 673 }
674 674
675 const rvcNarratorVoiceSelect = document.getElementById('rvc_narrator_voice'); 675 const rvcNarratorVoiceSelect = document.getElementById('rvc_narrator_voice');
676 if (rvcNarratorVoiceSelect) { 676 if (rvcNarratorVoiceSelect) {
677 rvcNarratorVoiceSelect.addEventListener('change', (event) => { 677 rvcNarratorVoiceSelect.addEventListener('change', (event) => {
678 this.settings.rvcnarrator_voice_gen = event.target.value; 678 this.settings.rvcnarrator_voice_gen = event.target.value;
679 this.onSettingsChange(); 679 this.onSettingsChange();
680 }); 680 });
681 } 681 }
682 682
683 const rvcCharacterPitchSelect = document.getElementById('rvc_character_pitch'); 683 const rvcCharacterPitchSelect = document.getElementById('rvc_character_pitch');
684 if (rvcCharacterPitchSelect) { 684 if (rvcCharacterPitchSelect) {
685 rvcCharacterPitchSelect.addEventListener('change', (event) => { 685 rvcCharacterPitchSelect.addEventListener('change', (event) => {
686 this.settings.rvc_character_pitch = event.target.value; 686 this.settings.rvc_character_pitch = event.target.value;
687 this.onSettingsChange(); 687 this.onSettingsChange();
688 }); 688 });
689 } 689 }
690 690
691 const rvcNarratorPitchSelect = document.getElementById('rvc_narrator_pitch'); 691 const rvcNarratorPitchSelect = document.getElementById('rvc_narrator_pitch');
692 if (rvcNarratorPitchSelect) { 692 if (rvcNarratorPitchSelect) {
693 rvcNarratorPitchSelect.addEventListener('change', (event) => { 693 rvcNarratorPitchSelect.addEventListener('change', (event) => {
694 this.settings.rvc_narrator_pitch = event.target.value; 694 this.settings.rvc_narrator_pitch = event.target.value;
695 this.onSettingsChange(); 695 this.onSettingsChange();
696 }); 696 });
697 } 697 }
698 698
699 // DeepSpeed Listener 699 // DeepSpeed Listener
700 const deepspeedCheckbox = document.getElementById('deepspeed'); 700 const deepspeedCheckbox = document.getElementById('deepspeed');
701 if (deepspeedCheckbox) { 701 if (deepspeedCheckbox) {
702 const handleDeepSpeedChange = async (event) => { 702 const handleDeepSpeedChange = async (event) => {
703 const deepSpeedValue = event.target.checked ? 'True' : 'False'; 703 const deepSpeedValue = event.target.checked ? 'True' : 'False';
704 updateStatus('Processing'); 704 updateStatus('Processing');
705 try { 705 try {
706 const response = await fetch(`${this.settings.provider_endpoint}/api/deepspeed?new_deepspeed_value=${deepSpeedValue}`, { 706 const response = await fetch(`${this.settings.provider_endpoint}/api/deepspeed?new_deepspeed_value=${deepSpeedValue}`, {
707 method: 'POST', 707 method: 'POST',
708 }); 708 });
709 if (!response.ok) { 709 if (!response.ok) {
710 throw new Error(`HTTP Error: ${response.status}`); 710 throw new Error(`HTTP Error: ${response.status}`);
711 } 711 }
712 const data = await response.json(); 712 const data = await response.json();
713 console.log('POST response data:', data); 713 console.log('POST response data:', data);
714 updateStatus('Ready'); 714 updateStatus('Ready');
715 } catch (error) { 715 } catch (error) {
716 console.error('POST request error:', error); 716 console.error('POST request error:', error);
717 updateStatus('Error'); 717 updateStatus('Error');
718 } 718 }
719 }; 719 };
720 720
721 const debouncedHandleDeepSpeedChange = debounce(handleDeepSpeedChange, 300); 721 const debouncedHandleDeepSpeedChange = debounce(handleDeepSpeedChange, 300);
722 deepspeedCheckbox.addEventListener('change', debouncedHandleDeepSpeedChange); 722 deepspeedCheckbox.addEventListener('change', debouncedHandleDeepSpeedChange);
723 } 723 }
724 724
725 // Low VRAM Listener 725 // Low VRAM Listener
726 const lowVramCheckbox = document.getElementById('low_vram'); 726 const lowVramCheckbox = document.getElementById('low_vram');
727 if (lowVramCheckbox) { 727 if (lowVramCheckbox) {
728 const handleLowVramChange = async (event) => { 728 const handleLowVramChange = async (event) => {
729 const lowVramValue = event.target.checked ? 'True' : 'False'; 729 const lowVramValue = event.target.checked ? 'True' : 'False';
730 updateStatus('Processing'); 730 updateStatus('Processing');
731 try { 731 try {
732 const response = await fetch(`${this.settings.provider_endpoint}/api/lowvramsetting?new_low_vram_value=${lowVramValue}`, { 732 const response = await fetch(`${this.settings.provider_endpoint}/api/lowvramsetting?new_low_vram_value=${lowVramValue}`, {
733 method: 'POST', 733 method: 'POST',
734 }); 734 });
735 if (!response.ok) { 735 if (!response.ok) {
736 throw new Error(`HTTP Error: ${response.status}`); 736 throw new Error(`HTTP Error: ${response.status}`);
737 } 737 }
738 const data = await response.json(); 738 const data = await response.json();
739 console.log('POST response data:', data); 739 console.log('POST response data:', data);
740 updateStatus('Ready'); 740 updateStatus('Ready');
741 } catch (error) { 741 } catch (error) {
742 console.error('POST request error:', error); 742 console.error('POST request error:', error);
743 updateStatus('Error'); 743 updateStatus('Error');
744 } 744 }
745 }; 745 };
746 746
747 const debouncedHandleLowVramChange = debounce(handleLowVramChange, 300); 747 const debouncedHandleLowVramChange = debounce(handleLowVramChange, 300);
748 lowVramCheckbox.addEventListener('change', debouncedHandleLowVramChange); 748 lowVramCheckbox.addEventListener('change', debouncedHandleLowVramChange);
749 } 749 }
750 750
751 // Other listeners without debounce since they don't need it 751 // Other listeners without debounce since they don't need it
752 const narratorVoiceSelect = document.getElementById('narrator_voice'); 752 const narratorVoiceSelect = document.getElementById('narrator_voice');
753 if (narratorVoiceSelect) { 753 if (narratorVoiceSelect) {
754 narratorVoiceSelect.addEventListener('change', (event) => { 754 narratorVoiceSelect.addEventListener('change', (event) => {
755 this.settings.narrator_voice_gen = `${event.target.value}`; 755 this.settings.narrator_voice_gen = `${event.target.value}`;
756 this.onSettingsChange(); 756 this.onSettingsChange();
757 }); 757 });
758 } 758 }
759 759
760 const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside'); 760 const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside');
761 if (textNotInsideSelect) { 761 if (textNotInsideSelect) {
762 textNotInsideSelect.addEventListener('change', (event) => { 762 textNotInsideSelect.addEventListener('change', (event) => {
763 this.settings.text_not_inside = event.target.value; 763 this.settings.text_not_inside = event.target.value;
764 this.onSettingsChange(); 764 this.onSettingsChange();
765 }); 765 });
766 } 766 }
767 767
768 // AT Narrator Dropdown Listener 768 // AT Narrator Dropdown Listener
769 const atNarratorSelect = document.getElementById('at_narrator_enabled'); 769 const atNarratorSelect = document.getElementById('at_narrator_enabled');
770 const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks'); 770 const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks');
771 const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted'); 771 const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted');
772 const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues'); 772 const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues');
773 773
774 if (atNarratorSelect && textNotInsideSelect && narratorVoiceSelect) { 774 if (atNarratorSelect && textNotInsideSelect && narratorVoiceSelect) {
775 atNarratorSelect.addEventListener('change', (event) => { 775 atNarratorSelect.addEventListener('change', (event) => {
776 const narratorOption = event.target.value; 776 const narratorOption = event.target.value;
777 this.settings.narrator_enabled = narratorOption; 777 this.settings.narrator_enabled = narratorOption;
778 778
779 const isNarratorDisabled = narratorOption === 'false'; 779 const isNarratorDisabled = narratorOption === 'false';
780 textNotInsideSelect.disabled = isNarratorDisabled; 780 textNotInsideSelect.disabled = isNarratorDisabled;
781 narratorVoiceSelect.disabled = isNarratorDisabled; 781 narratorVoiceSelect.disabled = isNarratorDisabled;
782 782
783 if (narratorOption === 'true') { 783 if (narratorOption === 'true') {
784 ttsPassAsterisksCheckbox.checked = false; 784 ttsPassAsterisksCheckbox.checked = false;
785 $('#tts_pass_asterisks').click(); 785 $('#tts_pass_asterisks').click();
786 $('#tts_pass_asterisks').trigger('change'); 786 $('#tts_pass_asterisks').trigger('change');
787 ttsNarrateQuotedCheckbox.checked = true; 787 ttsNarrateQuotedCheckbox.checked = true;
788 ttsNarrateDialoguesCheckbox.checked = true; 788 ttsNarrateDialoguesCheckbox.checked = true;
789 $('#tts_narrate_quoted').click(); 789 $('#tts_narrate_quoted').click();
790 $('#tts_narrate_quoted').trigger('change'); 790 $('#tts_narrate_quoted').trigger('change');
791 $('#tts_narrate_dialogues').click(); 791 $('#tts_narrate_dialogues').click();
792 $('#tts_narrate_dialogues').trigger('change'); 792 $('#tts_narrate_dialogues').trigger('change');
793 } else if (narratorOption === 'silent') { 793 } else if (narratorOption === 'silent') {
794 ttsPassAsterisksCheckbox.checked = false; 794 ttsPassAsterisksCheckbox.checked = false;
795 $('#tts_pass_asterisks').click(); 795 $('#tts_pass_asterisks').click();
796 $('#tts_pass_asterisks').trigger('change'); 796 $('#tts_pass_asterisks').trigger('change');
797 } else { 797 } else {
798 ttsPassAsterisksCheckbox.checked = true; 798 ttsPassAsterisksCheckbox.checked = true;
799 $('#tts_pass_asterisks').click(); 799 $('#tts_pass_asterisks').click();
800 $('#tts_pass_asterisks').trigger('change'); 800 $('#tts_pass_asterisks').trigger('change');
801 } 801 }
802 802
803 this.onSettingsChange(); 803 this.onSettingsChange();
804 }); 804 });
805 } 805 }
806 806
807 // Event Listener for AT Generation Method Dropdown 807 // Event Listener for AT Generation Method Dropdown
808 const atGenerationMethodSelect = document.getElementById('at_generation_method'); 808 const atGenerationMethodSelect = document.getElementById('at_generation_method');
809 if (atGenerationMethodSelect) { 809 if (atGenerationMethodSelect) {
810 atGenerationMethodSelect.addEventListener('change', (event) => { 810 atGenerationMethodSelect.addEventListener('change', (event) => {
811 const selectedMethod = event.target.value; 811 const selectedMethod = event.target.value;
812 812
813 if (selectedMethod === 'streaming_enabled') { 813 if (selectedMethod === 'streaming_enabled') {
814 // Disable and unselect AT Narrator 814 // Disable and unselect AT Narrator
815 atNarratorSelect.disabled = true; 815 atNarratorSelect.disabled = true;
816 atNarratorSelect.value = 'false'; 816 atNarratorSelect.value = 'false';
817 textNotInsideSelect.disabled = true; 817 textNotInsideSelect.disabled = true;
818 narratorVoiceSelect.disabled = true; 818 narratorVoiceSelect.disabled = true;
819 } else if (selectedMethod === 'standard_generation') { 819 } else if (selectedMethod === 'standard_generation') {
820 // Enable AT Narrator 820 // Enable AT Narrator
821 atNarratorSelect.disabled = false; 821 atNarratorSelect.disabled = false;
822 } 822 }
823 this.settings.at_generation_method = selectedMethod; 823 this.settings.at_generation_method = selectedMethod;
824 this.onSettingsChange(); 824 this.onSettingsChange();
825 }); 825 });
826 } 826 }
827 827
828 // Language Dropdown Listener 828 // Language Dropdown Listener
829 const languageSelect = document.getElementById('language_options'); 829 const languageSelect = document.getElementById('language_options');
830 if (languageSelect) { 830 if (languageSelect) {
831 languageSelect.addEventListener('change', (event) => { 831 languageSelect.addEventListener('change', (event) => {
832 this.settings.language = event.target.value; 832 this.settings.language = event.target.value;
833 this.onSettingsChange(); 833 this.onSettingsChange();
834 }); 834 });
835 } 835 }
836 836
837 // AllTalk Endpoint Input Listener 837 // AllTalk Endpoint Input Listener
838 const atServerInput = document.getElementById('at_server'); 838 const atServerInput = document.getElementById('at_server');
839 if (atServerInput) { 839 if (atServerInput) {
840 atServerInput.addEventListener('input', (event) => { 840 atServerInput.addEventListener('input', (event) => {
841 this.settings.provider_endpoint = event.target.value; 841 this.settings.provider_endpoint = event.target.value;
842 this.onSettingsChange(); 842 this.onSettingsChange();
843 }); 843 });
844 } 844 }
845 } 845 }
846 846
847 //#############################// 847 //#############################//
848 // Store ST interface settings // 848 // Store ST interface settings //
849 //#############################// 849 //#############################//
850 850
851 onSettingsChange() { 851 onSettingsChange() {
852 // Update settings based on the UI elements 852 // Update settings based on the UI elements
853 //this.settings.provider_endpoint = $('#at_server').val(); 853 //this.settings.provider_endpoint = $('#at_server').val();
854 this.settings.language = $('#language_options').val(); 854 this.settings.language = $('#language_options').val();
855 //this.settings.voiceMap = $('#voicemap').val(); 855 //this.settings.voiceMap = $('#voicemap').val();
856 this.settings.at_generation_method = $('#at_generation_method').val(); 856 this.settings.at_generation_method = $('#at_generation_method').val();
857 this.settings.narrator_enabled = $('#at_narrator_enabled').val(); 857 this.settings.narrator_enabled = $('#at_narrator_enabled').val();
858 this.settings.at_narrator_text_not_inside = $('#at_narrator_text_not_inside').val(); 858 this.settings.at_narrator_text_not_inside = $('#at_narrator_text_not_inside').val();
859 this.settings.rvc_character_voice = $('#rvc_character_voice').val(); 859 this.settings.rvc_character_voice = $('#rvc_character_voice').val();
860 this.settings.rvc_narrator_voice = $('#rvc_narrator_voice').val(); 860 this.settings.rvc_narrator_voice = $('#rvc_narrator_voice').val();
861 this.settings.rvc_character_pitch = $('#rvc_character_pitch').val(); 861 this.settings.rvc_character_pitch = $('#rvc_character_pitch').val();
862 this.settings.rvc_narrator_pitch = $('#rvc_narrator_pitch').val(); 862 this.settings.rvc_narrator_pitch = $('#rvc_narrator_pitch').val();
863 this.settings.narrator_voice_gen = $('#narrator_voice').val(); 863 this.settings.narrator_voice_gen = $('#narrator_voice').val();
864 // Save the updated settings 864 // Save the updated settings
865 saveTtsProviderSettings(); 865 saveTtsProviderSettings();
866 } 866 }
867 867
868 //#########################// 868 //#########################//
869 // ST Handle Reload button // 869 // ST Handle Reload button //
870 //#########################// 870 //#########################//
871 871
872 async onRefreshClick() { 872 async onRefreshClick() {
873 try { 873 try {
874 updateStatus('Processing'); // Set status to Processing while refreshing 874 updateStatus('Processing'); // Set status to Processing while refreshing
875 await this.checkReady(); // Check if the TTS provider is ready 875 await this.checkReady(); // Check if the TTS provider is ready
876 await this.loadSettings(this.settings); // Reload the settings 876 await this.loadSettings(this.settings); // Reload the settings
877 await this.checkReady(); // Check if the TTS provider is ready 877 await this.checkReady(); // Check if the TTS provider is ready
878 updateStatus(this.ready ? 'Ready' : 'Offline'); // Update the status based on readiness 878 updateStatus(this.ready ? 'Ready' : 'Offline'); // Update the status based on readiness
879 } catch (error) { 879 } catch (error) {
880 console.error('Error during refresh:', error); 880 console.error('Error during refresh:', error);
881 updateStatus('Error'); // Set status to Error in case of failure 881 updateStatus('Error'); // Set status to Error in case of failure
882 } 882 }
883 } 883 }
884 884
885 //##################// 885 //##################//
886 // Preview AT Voice // 886 // Preview AT Voice //
887 //##################// 887 //##################//
888 888
889 async previewTtsVoice(voiceName) { 889 async previewTtsVoice(voiceName) {
890 try { 890 try {
891 // Prepare data for POST request 891 // Prepare data for POST request
892 const postData = new URLSearchParams(); 892 const postData = new URLSearchParams();
893 postData.append('voice', `${voiceName}`); 893 postData.append('voice', `${voiceName}`);
894 894
895 // Add RVC parameters for V2 if applicable 895 // Add RVC parameters for V2 if applicable
896 if (this.settings.server_version === 'v2' && this.settings.rvc_character_voice !== 'Disabled') { 896 if (this.settings.server_version === 'v2' && this.settings.rvc_character_voice !== 'Disabled') {
897 postData.append('rvccharacter_voice_gen', this.settings.rvc_character_voice); 897 postData.append('rvccharacter_voice_gen', this.settings.rvc_character_voice);
898 postData.append('rvccharacter_pitch', this.settings.rvc_character_pitch || '0'); 898 postData.append('rvccharacter_pitch', this.settings.rvc_character_pitch || '0');
899 } 899 }
900 900
901 // Making the POST request 901 // Making the POST request
902 const response = await fetch(`${this.settings.provider_endpoint}/api/previewvoice/`, { 902 const response = await fetch(`${this.settings.provider_endpoint}/api/previewvoice/`, {
903 method: 'POST', 903 method: 'POST',
904 headers: { 904 headers: {
905 'Content-Type': 'application/x-www-form-urlencoded', 905 'Content-Type': 'application/x-www-form-urlencoded',
906 }, 906 },
907 body: postData, 907 body: postData,
908 }); 908 });
909 909
910 if (!response.ok) { 910 if (!response.ok) {
911 const errorText = await response.text(); 911 const errorText = await response.text();
912 console.error('previewTtsVoice Error Response Text:', errorText); 912 console.error('previewTtsVoice Error Response Text:', errorText);
913 throw new Error(`HTTP ${response.status}: ${errorText}`); 913 throw new Error(`HTTP ${response.status}: ${errorText}`);
914 } 914 }
915 915
916 const data = await response.json(); 916 const data = await response.json();
917 if (data.output_file_url) { 917 if (data.output_file_url) {
918 // Handle V1/V2 URL differences 918 // Handle V1/V2 URL differences
919 const fullUrl = this.settings.server_version === 'v1' 919 const fullUrl = this.settings.server_version === 'v1'
920 ? data.output_file_url 920 ? data.output_file_url
921 : `${this.settings.provider_endpoint}${data.output_file_url}`; 921 : `${this.settings.provider_endpoint}${data.output_file_url}`;
922 922
923 const audioElement = new Audio(fullUrl); 923 const audioElement = new Audio(fullUrl);
924 audioElement.play().catch(e => console.error('Error playing audio:', e)); 924 audioElement.play().catch(e => console.error('Error playing audio:', e));
925 } else { 925 } else {
926 console.warn('previewTtsVoice No output file URL received in the response'); 926 console.warn('previewTtsVoice No output file URL received in the response');
927 throw new Error('No output file URL received in the response'); 927 throw new Error('No output file URL received in the response');
928 } 928 }
929 } catch (error) { 929 } catch (error) {
930 console.error('previewTtsVoice Exception caught during preview generation:', error); 930 console.error('previewTtsVoice Exception caught during preview generation:', error);
931 throw error; 931 throw error;
932 } 932 }
933 } 933 }
934 934
935 //#####################// 935 //#####################//
936 // Populate ST voices // 936 // Populate ST voices //
937 //#####################// 937 //#####################//
938 938
939 async getVoice(voiceName, generatePreview = false) { 939 async getVoice(voiceName, generatePreview = false) {
940 // Ensure this.voices is populated 940 // Ensure this.voices is populated
941 if (this.voices.length === 0) { 941 if (this.voices.length === 0) {
942 // Fetch voice objects logic 942 // Fetch voice objects logic
943 } 943 }
944 // Find the object where the name matches voiceName 944 // Find the object where the name matches voiceName
945 const match = this.voices.find(voice => voice.name === voiceName); 945 const match = this.voices.find(voice => voice.name === voiceName);
946 if (!match) { 946 if (!match) {
947 // Error handling 947 // Error handling
948 } 948 }
949 // Generate preview URL only if requested 949 // Generate preview URL only if requested
950 if (!match.preview_url && generatePreview) { 950 if (!match.preview_url && generatePreview) {
951 // Generate preview logic 951 // Generate preview logic
952 } 952 }
953 return match; // Return the found voice object 953 return match; // Return the found voice object
954 } 954 }
955 955
956 //##########################################// 956 //##########################################//
957 // Generate TTS Streaming or call Standard // 957 // Generate TTS Streaming or call Standard //
958 //##########################################// 958 //##########################################//
959 959
960 async generateTts(inputText, voiceId) { 960 async generateTts(inputText, voiceId) {
961 try { 961 try {
962 if (this.settings.at_generation_method === 'streaming_enabled') { 962 if (this.settings.at_generation_method === 'streaming_enabled') {
963 // Construct the streaming URL 963 // Construct the streaming URL
964 const streamingUrl = `${this.settings.provider_endpoint}/api/tts-generate-streaming?text=${encodeURIComponent(inputText)}&voice=${encodeURIComponent(voiceId)}&language=${encodeURIComponent(this.settings.language)}&output_file=stream_output.wav`; 964 const streamingUrl = `${this.settings.provider_endpoint}/api/tts-generate-streaming?text=${encodeURIComponent(inputText)}&voice=${encodeURIComponent(voiceId)}&language=${encodeURIComponent(this.settings.language)}&output_file=stream_output.wav`;
965 console.log('Streaming URL:', streamingUrl); 965 console.log('Streaming URL:', streamingUrl);
966 966
967 // Return the streaming URL directly 967 // Return the streaming URL directly
968 return streamingUrl; 968 return streamingUrl;
969 } else { 969 } else {
970 // For standard method 970 // For standard method
971 const outputUrl = await this.fetchTtsGeneration(inputText, voiceId); 971 const outputUrl = await this.fetchTtsGeneration(inputText, voiceId);
972 const audioResponse = await fetch(outputUrl); 972 const audioResponse = await fetch(outputUrl);
973 if (!audioResponse.ok) { 973 if (!audioResponse.ok) {
974 throw new Error(`HTTP ${audioResponse.status}: Failed to fetch audio data`); 974 throw new Error(`HTTP ${audioResponse.status}: Failed to fetch audio data`);
975 } 975 }
976 return audioResponse; // Return the fetch response directly 976 return audioResponse; // Return the fetch response directly
977 } 977 }
978 } catch (error) { 978 } catch (error) {
979 console.error('Error in generateTts:', error); 979 console.error('Error in generateTts:', error);
980 throw error; 980 throw error;
981 } 981 }
982 } 982 }
983 983
984 984
985 //####################// 985 //####################//
986 // Generate Standard // 986 // Generate Standard //
987 //####################// 987 //####################//
988 988
989 async fetchTtsGeneration(inputText, voiceId) { 989 async fetchTtsGeneration(inputText, voiceId) {
990 const requestBody = new URLSearchParams({ 990 const requestBody = new URLSearchParams({
991 'text_input': inputText, 991 'text_input': inputText,
992 'text_filtering': 'standard', 992 'text_filtering': 'standard',
993 'character_voice_gen': voiceId, 993 'character_voice_gen': voiceId,
994 'narrator_enabled': this.settings.narrator_enabled, 994 'narrator_enabled': this.settings.narrator_enabled,
995 'narrator_voice_gen': this.settings.narrator_voice_gen, 995 'narrator_voice_gen': this.settings.narrator_voice_gen,
996 'text_not_inside': this.settings.at_narrator_text_not_inside, 996 'text_not_inside': this.settings.at_narrator_text_not_inside,
997 'language': this.settings.language, 997 'language': this.settings.language,
998 'output_file_name': 'st_output', 998 'output_file_name': 'st_output',
999 'output_file_timestamp': 'true', 999 'output_file_timestamp': 'true',
1000 'autoplay': 'false', 1000 'autoplay': 'false',
1001 'autoplay_volume': '0.8', 1001 'autoplay_volume': '0.8',
1002 }); 1002 });
1003 1003
1004 // Add RVC parameters only for V2 1004 // Add RVC parameters only for V2
1005 if (this.settings.server_version === 'v2') { 1005 if (this.settings.server_version === 'v2') {
1006 if (this.settings.rvc_character_voice !== 'Disabled') { 1006 if (this.settings.rvc_character_voice !== 'Disabled') {
1007 requestBody.append('rvccharacter_voice_gen', this.settings.rvc_character_voice); 1007 requestBody.append('rvccharacter_voice_gen', this.settings.rvc_character_voice);
1008 requestBody.append('rvccharacter_pitch', this.settings.rvc_character_pitch || '0'); 1008 requestBody.append('rvccharacter_pitch', this.settings.rvc_character_pitch || '0');
1009 } 1009 }
1010 if (this.settings.rvc_narrator_voice !== 'Disabled') { 1010 if (this.settings.rvc_narrator_voice !== 'Disabled') {
1011 requestBody.append('rvcnarrator_voice_gen', this.settings.rvc_narrator_voice); 1011 requestBody.append('rvcnarrator_voice_gen', this.settings.rvc_narrator_voice);
1012 requestBody.append('rvcnarrator_pitch', this.settings.rvc_narrator_pitch || '0'); 1012 requestBody.append('rvcnarrator_pitch', this.settings.rvc_narrator_pitch || '0');
1013 } 1013 }
1014 } 1014 }
1015 1015
1016 try { 1016 try {
1017 const response = await doExtrasFetch( 1017 const response = await doExtrasFetch(
1018 `${this.settings.provider_endpoint}/api/tts-generate`, 1018 `${this.settings.provider_endpoint}/api/tts-generate`,
1019 { 1019 {
1020 method: 'POST', 1020 method: 'POST',
1021 headers: { 1021 headers: {
1022 'Content-Type': 'application/x-www-form-urlencoded', 1022 'Content-Type': 'application/x-www-form-urlencoded',
1023 'Cache-Control': 'no-cache', 1023 'Cache-Control': 'no-cache',
1024 }, 1024 },
1025 body: requestBody, 1025 body: requestBody,
1026 }, 1026 },
1027 ); 1027 );
1028 1028
1029 if (!response.ok) { 1029 if (!response.ok) {
1030 const errorText = await response.text(); 1030 const errorText = await response.text();
1031 console.error('fetchTtsGeneration Error Response Text:', errorText); 1031 console.error('fetchTtsGeneration Error Response Text:', errorText);
1032 throw new Error(`HTTP ${response.status}: ${errorText}`); 1032 throw new Error(`HTTP ${response.status}: ${errorText}`);
1033 } 1033 }
1034 const data = await response.json(); 1034 const data = await response.json();
1035 1035
1036 // Handle V1/V2 URL differences 1036 // Handle V1/V2 URL differences
1037 const outputUrl = this.settings.server_version === 'v1' 1037 const outputUrl = this.settings.server_version === 'v1'
1038 ? data.output_file_url // V1 returns full URL 1038 ? data.output_file_url // V1 returns full URL
1039 : `${this.settings.provider_endpoint}${data.output_file_url}`; // V2 returns relative path 1039 : `${this.settings.provider_endpoint}${data.output_file_url}`; // V2 returns relative path
1040 1040
1041 return outputUrl; 1041 return outputUrl;
1042 } catch (error) { 1042 } catch (error) {
1043 console.error('[fetchTtsGeneration] Exception caught:', error); 1043 console.error('[fetchTtsGeneration] Exception caught:', error);
1044 throw error; 1044 throw error;
1045 } 1045 }
1046 } 1046 }
1047} 1047}
1048 1048
1049//#########################// 1049//#########################//
1050// Update Status Messages // 1050// Update Status Messages //
1051//#########################// 1051//#########################//
1052 1052
1053function updateStatus(message) { 1053function updateStatus(message) {
1054 const statusElement = document.getElementById('status_info'); 1054 const statusElement = document.getElementById('status_info');
1055 if (statusElement) { 1055 if (statusElement) {
1056 statusElement.textContent = message; 1056 statusElement.textContent = message;
1057 switch (message) { 1057 switch (message) {
1058 case 'Offline': 1058 case 'Offline':
1059 statusElement.style.color = 'red'; 1059 statusElement.style.color = 'red';
1060 break; 1060 break;
1061 case 'Ready': 1061 case 'Ready':
1062 statusElement.style.color = 'lightgreen'; 1062 statusElement.style.color = 'lightgreen';
1063 break; 1063 break;
1064 case 'Processing': 1064 case 'Processing':
1065 statusElement.style.color = 'blue'; 1065 statusElement.style.color = 'blue';
1066 break; 1066 break;
1067 case 'Error': 1067 case 'Error':
1068 statusElement.style.color = 'red'; 1068 statusElement.style.color = 'red';
1069 break; 1069 break;
1070 } 1070 }
1071 } 1071 }
1072} 1072}