Support for AllTalk V1 and V2 Select the version in the interface. RVC is not supported on AllTalk V1

3138252928875c0aeeb5130188c62f49b6501c47

erew123 <35898566+erew123@users.noreply.github.com>

Signed
1 files changed, +418 -145Showing whitespace changes
public/scripts/extensions/tts/alltalk.js+418 -145
@@ -1,4 +1,4 @@
1import { doExtrasFetch } from '../../extensions.js';1import { doExtrasFetch, getApiUrl, modules } from '../../extensions.js';
2import { saveTtsProviderSettings } from './index.js'; 2import { saveTtsProviderSettings } from './index.js';
3 3
4export { AllTalkTtsProvider }; 4export { AllTalkTtsProvider };
@@ -13,22 +13,29 @@ class AllTalkTtsProvider {
13 // Initialize with default settings if they are not already set 13 // Initialize with default settings if they are not already set
14 this.settings = { 14 this.settings = {
15 provider_endpoint: this.settings.provider_endpoint || 'http://localhost:7851', 15 provider_endpoint: this.settings.provider_endpoint || 'http://localhost:7851',
16 server_version: this.settings.server_version || 'v2',
16 language: this.settings.language || 'en', 17 language: this.settings.language || 'en',
17 voiceMap: this.settings.voiceMap || {}, 18 voiceMap: this.settings.voiceMap || {},
18 at_generation_method: this.settings.at_generation_method || 'standard_generation', 19 at_generation_method: this.settings.at_generation_method || 'standard_generation',
19 narrator_enabled: this.settings.narrator_enabled || 'false', 20 narrator_enabled: this.settings.narrator_enabled || 'false',
20 at_narrator_text_not_inside: this.settings.at_narrator_text_not_inside || 'narrator', 21 at_narrator_text_not_inside: this.settings.at_narrator_text_not_inside || 'narrator',
21 narrator_voice_gen: this.settings.narrator_voice_gen || 'female_01.wav',22 narrator_voice_gen: this.settings.narrator_voice_gen || 'Please set a voice',
22 finetuned_model: this.settings.finetuned_model || 'false',23 rvc_character_voice: this.settings.rvc_character_voice || 'Disabled',
24 rvc_character_pitch: this.settings.rvc_character_pitch || '0',
25 rvc_narrator_voice: this.settings.rvc_narrator_voice || 'Disabled',
26 rvc_narrator_pitch: this.settings.rvc_narrator_pitch || '0',
27 finetuned_model: this.settings.finetuned_model || 'false'
23 }; 28 };
24 // Separate property for dynamically updated settings from the server 29 // Separate property for dynamically updated settings from the server
25 this.dynamicSettings = { 30 this.dynamicSettings = {
26 modelsAvailable: [], 31 modelsAvailable: [],
27 currentModel: '', 32 currentModel: '',
28 deepspeed_available: false, 33 deepspeed_available: false,
29 deepSpeedEnabled: false,34 deepspeed_enabled: false,
30 lowVramEnabled: false,35 lowvram_capable: false,
36 lowvram_enabled: false,
31 }; 37 };
38 this.rvcVoices = []; // Initialize rvcVoices as an empty array
32 } 39 }
33 ready = false; 40 ready = false;
34 voices = []; 41 voices = [];
@@ -56,7 +63,7 @@ class AllTalkTtsProvider {
56 }; 63 };
57 64
58 get settingsHtml() { 65 get settingsHtml() {
59 let html = '<div class="at-settings-separator">AllTalk Settings</div>';66 let html = `<div class="at-settings-separator">AllTalk V2 Settings</div>`;
60 67
61 html += `<div class="at-settings-row"> 68 html += `<div class="at-settings-row">
62 69
@@ -75,6 +82,7 @@ class AllTalkTtsProvider {
75 <label for="at_narrator_enabled">AT Narrator</label> 82 <label for="at_narrator_enabled">AT Narrator</label>
76 <select id="at_narrator_enabled"> 83 <select id="at_narrator_enabled">
77 <option value="true">Enabled</option> 84 <option value="true">Enabled</option>
85 <option value="silent">Enabled (Silenced)</option>
78 <option value="false">Disabled</option> 86 <option value="false">Disabled</option>
79 </select> 87 </select>
80 </div> 88 </div>
@@ -82,8 +90,9 @@ class AllTalkTtsProvider {
82 <div class="at-settings-option"> 90 <div class="at-settings-option">
83 <label for="at_narrator_text_not_inside">Text Not Inside * or " is</label> 91 <label for="at_narrator_text_not_inside">Text Not Inside * or " is</label>
84 <select id="at_narrator_text_not_inside"> 92 <select id="at_narrator_text_not_inside">
85 <option value="narrator">Narrator</option>
86 <option value="character">Character</option> 93 <option value="character">Character</option>
94 <option value="narrator">Narrator</option>
95 <option value="silent">Silent</option>
87 </select> 96 </select>
88 </div> 97 </div>
89 98
@@ -110,27 +119,74 @@ class AllTalkTtsProvider {
110 </div> 119 </div>
111 </div>`; 120 </div>`;
112 121
122 html += `<div class="at-settings-row">
123 <div class="at-settings-option">
124 <label for="rvc_character_voice">RVC Character</label>
125 <select id="rvc_character_voice">`;
126 if (this.rvcVoices) {
127 for (let rvccharvoice of this.rvcVoices) {
128 html += `<option value="${rvccharvoice.voice_id}">${rvccharvoice.name}</option>`;
129 }
130 }
131 html += `</select>
132 </div>
133 <div class="at-settings-option">
134 <label for="rvc_narrator_voice">RVC Narrator</label>
135 <select id="rvc_narrator_voice">`;
136 if (this.rvcVoices) {
137 for (let rvcnarrvoice of this.rvcVoices) {
138 html += `<option value="${rvcnarrvoice.voice_id}">${rvcnarrvoice.name}</option>`;
139 }
140 }
141 html += `</select>
142 </div>
143</div>`;
144
145 // Add the RVC pitch control row
146 html += `<div class="at-settings-row">
147 <div class="at-settings-option">
148 <label for="rvc_character_pitch">RVC Character Pitch</label>
149 <select id="rvc_character_pitch">`;
150 for (let i = -24; i <= 24; i++) {
151 const selected = i === 0 ? 'selected="selected"' : '';
152 html += `<option value="${i}" ${selected}>${i}</option>`;
153 }
154 html += `</select>
155 </div>
156 <div class="at-settings-option">
157 <label for="rvc_narrator_pitch">RVC Narrator Pitch</label>
158 <select id="rvc_narrator_pitch">`;
159 for (let i = -24; i <= 24; i++) {
160 const selected = i === 0 ? 'selected="selected"' : '';
161 html += `<option value="${i}" ${selected}>${i}</option>`;
162 }
163 html += `</select>
164 </div>
165 </div>`;
113 166
114 html += `<div class="at-model-endpoint-row"> 167 html += `<div class="at-model-endpoint-row">
115 <div class="at-model-option"> 168 <div class="at-model-option">
116 <label for="switch_model">Switch Model</label> 169 <label for="switch_model">Switch Model</label>
117 <select id="switch_model"> 170 <select id="switch_model">
118 <option value="api_tts">API TTS</option>171 <!-- Options will be dynamically populated -->
119 <option value="api_local">API Local</option>
120 <option value="xttsv2_local">XTTSv2 Local</option>
121 </select> 172 </select>
122 </div> 173 </div>
123 </div>
124
125 <div class="at-model-endpoint-row">
126 174
127 <div class="at-endpoint-option"> 175 <div class="at-endpoint-option">
128 <label for="at_server">AllTalk Endpoint:</label> 176 <label for="at_server">AllTalk Endpoint:</label>
129 <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}"/>
130 <i><b>Important:</b> Must match IP address & port in AllTalk settings.</i>
131 </div> 178 </div>
132 </div>`; 179 </div>`;
133 180
181 html += `<div class="at-settings-row">
182 <div class="at-settings-option">
183 <label for="server_version">AllTalk Server Version</label>
184 <select id="server_version">
185 <option value="v1">AllTalk V1</option>
186 <option value="v2">AllTalk V2</option>
187 </select>
188 </div>
189 </div>`;
134 190
135 html += `<div class="at-model-endpoint-row"> 191 html += `<div class="at-model-endpoint-row">
136 <div class="at-settings-option"> 192 <div class="at-settings-option">
@@ -152,7 +208,7 @@ class AllTalkTtsProvider {
152 208
153 html += `<div class="at-website-row"> 209 html += `<div class="at-website-row">
154 <div class="at-website-option"> 210 <div class="at-website-option">
155 <span>AllTalk <a target="_blank" href="${this.settings.provider_endpoint}">Config & Docs</a>.</span>211 <span>AllTalk V2<a target="_blank" href="${this.settings.provider_endpoint}">Config & Docs</a>.</span>
156 </div> 212 </div>
157 213
158 <div class="at-website-option"> 214 <div class="at-website-option">
@@ -162,7 +218,9 @@ class AllTalkTtsProvider {
162 218
163 html += `<div class="at-website-row"> 219 html += `<div class="at-website-row">
164<div class="at-website-option"> 220<div class="at-website-option">
165<span><strong>Text-generation-webui</strong> users - Uncheck <strong>Enable TTS</strong> in Text-generation-webui.</span>221<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>
222<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>
223<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>
166</div> 224</div>
167</div>`; 225</div>`;
168 226
@@ -193,35 +251,35 @@ class AllTalkTtsProvider {
193 // Update UI elements to reflect the loaded settings 251 // Update UI elements to reflect the loaded settings
194 $('#at_server').val(this.settings.provider_endpoint); 252 $('#at_server').val(this.settings.provider_endpoint);
195 $('#language_options').val(this.settings.language); 253 $('#language_options').val(this.settings.language);
196 //$('#voicemap').val(this.settings.voiceMap);
197 $('#at_generation_method').val(this.settings.at_generation_method); 254 $('#at_generation_method').val(this.settings.at_generation_method);
198 $('#at_narrator_enabled').val(this.settings.narrator_enabled); 255 $('#at_narrator_enabled').val(this.settings.narrator_enabled);
199 $('#at_narrator_text_not_inside').val(this.settings.at_narrator_text_not_inside); 256 $('#at_narrator_text_not_inside').val(this.settings.at_narrator_text_not_inside);
200 $('#narrator_voice').val(this.settings.narrator_voice_gen); 257 $('#narrator_voice').val(this.settings.narrator_voice_gen);
258 $('#rvc_character_voice').val(this.settings.rvc_character_voice);
259 $('#rvc_narrator_voice').val(this.settings.rvc_narrator_voice);
260 $('#rvc_character_pitch').val(this.settings.rvc_character_pitch);
261 $('#rvc_narrator_pitch').val(this.settings.rvc_narrator_pitch);
201 262
202 console.debug('AllTalkTTS: Settings loaded'); 263 console.debug('AllTalkTTS: Settings loaded');
203 await this.initEndpoint();
204 }
205
206 async initEndpoint() {
207 try { 264 try {
208 // Check if TTS provider is ready 265 // Check if TTS provider is ready
209 this.setupEventListeners();
210 this.updateLanguageDropdown();
211 await this.checkReady(); 266 await this.checkReady();
212 await this.updateSettingsFromServer(); // Fetch dynamic settings from the TTS server 267 await this.updateSettingsFromServer(); // Fetch dynamic settings from the TTS server
213 await this.fetchTtsVoiceObjects(); // Fetch voices only if service is ready 268 await this.fetchTtsVoiceObjects(); // Fetch voices only if service is ready
269 await this.fetchRvcVoiceObjects(); // Fetch RVC voices
214 this.updateNarratorVoicesDropdown(); 270 this.updateNarratorVoicesDropdown();
271 this.updateLanguageDropdown();
272 this.setupEventListeners();
215 this.applySettingsToHTML(); 273 this.applySettingsToHTML();
216 updateStatus('Ready'); 274 updateStatus('Ready');
217 } catch (error) { 275 } catch (error) {
218 console.error('Error loading settings:', error);276 console.error("Error loading settings:", error);
219 updateStatus('Offline'); 277 updateStatus('Offline');
220 } 278 }
221 } 279 }
222 280
281
223 applySettingsToHTML() { 282 applySettingsToHTML() {
224 // Apply loaded settings or use defaults
225 const narratorVoiceSelect = document.getElementById('narrator_voice'); 283 const narratorVoiceSelect = document.getElementById('narrator_voice');
226 const atNarratorSelect = document.getElementById('at_narrator_enabled'); 284 const atNarratorSelect = document.getElementById('at_narrator_enabled');
227 const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside'); 285 const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside');
@@ -229,30 +287,26 @@ class AllTalkTtsProvider {
229 this.settings.narrator_voice = this.settings.narrator_voice_gen; 287 this.settings.narrator_voice = this.settings.narrator_voice_gen;
230 // Apply settings to Narrator Voice dropdown 288 // Apply settings to Narrator Voice dropdown
231 if (narratorVoiceSelect && this.settings.narrator_voice) { 289 if (narratorVoiceSelect && this.settings.narrator_voice) {
232 narratorVoiceSelect.value = this.settings.narrator_voice.replace('.wav', '');290 narratorVoiceSelect.value = this.settings.narrator_voice; // Remove the parentheses
233 } 291 }
234 // Apply settings to AT Narrator Enabled dropdown 292 // Apply settings to AT Narrator Enabled dropdown
235 if (atNarratorSelect) { 293 if (atNarratorSelect) {
236 // Sync the state with the checkbox in index.js294 const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks');
237 const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks'); // Access the checkbox from index.js295 const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted');
238 const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted'); // Access the checkbox from index.js296 const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues');
239 const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues'); // Access the checkbox from index.js
240 // Sync the state with the checkbox in index.js
241 if (this.settings.narrator_enabled) { 297 if (this.settings.narrator_enabled) {
242 ttsPassAsterisksCheckbox.checked = false; 298 ttsPassAsterisksCheckbox.checked = false;
243 $('#tts_pass_asterisks').click(); // Simulate a click event299 $('#tts_pass_asterisks').click();
244 $('#tts_pass_asterisks').trigger('change'); 300 $('#tts_pass_asterisks').trigger('change');
245 } 301 }
246 if (!this.settings.narrator_enabled) { 302 if (!this.settings.narrator_enabled) {
247 ttsPassAsterisksCheckbox.checked = true; 303 ttsPassAsterisksCheckbox.checked = true;
248 $('#tts_pass_asterisks').click(); // Simulate a click event304 $('#tts_pass_asterisks').click();
249 $('#tts_pass_asterisks').trigger('change'); 305 $('#tts_pass_asterisks').trigger('change');
250 } 306 }
251 // Uncheck and set tts_narrate_quoted to false if narrator is enabled307 if (this.settings.narrator_enabled) {
252 if (this.settings.narrator_enabledd) {
253 ttsNarrateQuotedCheckbox.checked = true; 308 ttsNarrateQuotedCheckbox.checked = true;
254 ttsNarrateDialoguesCheckbox.checked = true; 309 ttsNarrateDialoguesCheckbox.checked = true;
255 // Trigger click events instead of change events
256 $('#tts_narrate_quoted').click(); 310 $('#tts_narrate_quoted').click();
257 $('#tts_narrate_quoted').trigger('change'); 311 $('#tts_narrate_quoted').trigger('change');
258 $('#tts_narrate_dialogues').click(); 312 $('#tts_narrate_dialogues').click();
@@ -261,42 +315,30 @@ class AllTalkTtsProvider {
261 atNarratorSelect.value = this.settings.narrator_enabled.toString(); 315 atNarratorSelect.value = this.settings.narrator_enabled.toString();
262 this.settings.narrator_enabled = this.settings.narrator_enabled.toString(); 316 this.settings.narrator_enabled = this.settings.narrator_enabled.toString();
263 } 317 }
264 // Apply settings to the Language dropdown
265 const languageSelect = document.getElementById('language_options'); 318 const languageSelect = document.getElementById('language_options');
266 if (languageSelect && this.settings.language) { 319 if (languageSelect && this.settings.language) {
267 languageSelect.value = this.settings.language; 320 languageSelect.value = this.settings.language;
268 } 321 }
269 // Apply settings to Text Not Inside dropdown
270 if (textNotInsideSelect && this.settings.text_not_inside) { 322 if (textNotInsideSelect && this.settings.text_not_inside) {
271 textNotInsideSelect.value = this.settings.text_not_inside; 323 textNotInsideSelect.value = this.settings.text_not_inside;
272 this.settings.at_narrator_text_not_inside = this.settings.text_not_inside; 324 this.settings.at_narrator_text_not_inside = this.settings.text_not_inside;
273 } 325 }
274 // Apply settings to Generation Method dropdown
275 if (generationMethodSelect && this.settings.at_generation_method) { 326 if (generationMethodSelect && this.settings.at_generation_method) {
276 generationMethodSelect.value = this.settings.at_generation_method; 327 generationMethodSelect.value = this.settings.at_generation_method;
277 } 328 }
278 // Additional logic to disable/enable dropdowns based on the selected generation method
279 const isStreamingEnabled = this.settings.at_generation_method === 'streaming_enabled'; 329 const isStreamingEnabled = this.settings.at_generation_method === 'streaming_enabled';
280 if (isStreamingEnabled) { 330 if (isStreamingEnabled) {
281 // Disable certain dropdowns when streaming is enabled
282 if (atNarratorSelect) atNarratorSelect.disabled = true; 331 if (atNarratorSelect) atNarratorSelect.disabled = true;
283 if (textNotInsideSelect) textNotInsideSelect.disabled = true; 332 if (textNotInsideSelect) textNotInsideSelect.disabled = true;
284 if (narratorVoiceSelect) narratorVoiceSelect.disabled = true; 333 if (narratorVoiceSelect) narratorVoiceSelect.disabled = true;
285 } else { 334 } else {
286 // Enable dropdowns for standard generation
287 if (atNarratorSelect) atNarratorSelect.disabled = false; 335 if (atNarratorSelect) atNarratorSelect.disabled = false;
288 if (textNotInsideSelect) textNotInsideSelect.disabled = !this.settings.narrator_enabled; 336 if (textNotInsideSelect) textNotInsideSelect.disabled = !this.settings.narrator_enabled;
289 if (narratorVoiceSelect) narratorVoiceSelect.disabled = !this.settings.narrator_enabled; 337 if (narratorVoiceSelect) narratorVoiceSelect.disabled = !this.settings.narrator_enabled;
290 } 338 }
291 const modelSelect = document.getElementById('switch_model');
292 if (this.settings.finetuned_model === 'true') {
293 const ftOption = document.createElement('option');
294 ftOption.value = 'XTTSv2 FT';
295 ftOption.textContent = 'XTTSv2 FT';
296 modelSelect.appendChild(ftOption);
297 }
298 } 339 }
299 340
341
300 //##############################// 342 //##############################//
301 // Check AT Server is Available // 343 // Check AT Server is Available //
302 //##############################// 344 //##############################//
@@ -320,7 +362,6 @@ class AllTalkTtsProvider {
320 } catch (error) { 362 } catch (error) {
321 console.error('Error checking TTS service readiness:', error); 363 console.error('Error checking TTS service readiness:', error);
322 this.ready = false; // Ensure ready flag is set to false in case of error 364 this.ready = false; // Ensure ready flag is set to false in case of error
323 throw error; // Rethrow the error for further handling
324 } 365 }
325 } 366 }
326 367
@@ -336,45 +377,149 @@ class AllTalkTtsProvider {
336 } 377 }
337 const data = await response.json(); 378 const data = await response.json();
338 const voices = data.voices.map(filename => { 379 const voices = data.voices.map(filename => {
339 const voiceName = filename.replace('.wav', '');
340 return { 380 return {
341 name: voiceName,381 name: filename,
342 voice_id: voiceName,382 voice_id: filename,
343 preview_url: null, // Preview URL will be dynamically generated 383 preview_url: null, // Preview URL will be dynamically generated
344 lang: 'en', // Default language384 lang: 'en' // Default language
345 }; 385 };
346 }); 386 });
347 this.voices = voices; // Assign to the class property 387 this.voices = voices; // Assign to the class property
348 return voices; // Also return this list 388 return voices; // Also return this list
349 } 389 }
350 390
391 async fetchRvcVoiceObjects() {
392 if (this.settings.server_version !== 'v2') {
393 console.log('Skipping RVC voices fetch for V1 server');
394 return [];
395 }
396
397 console.log('Fetching RVC Voices');
398 try {
399 const response = await fetch(`${this.settings.provider_endpoint}/api/rvcvoices`);
400 if (!response.ok) {
401 const errorText = await response.text();
402 console.error('Error text:', errorText);
403 throw new Error(`HTTP ${response.status}: ${errorText}`);
404 }
405
406 const data = await response.json();
407 if (!data || !data.rvcvoices) {
408 console.error('Invalid data format:', data);
409 throw new Error('Invalid data format received from /api/rvcvoices');
410 }
411
412 const voices = data.rvcvoices.map(filename => {
413 return {
414 name: filename,
415 voice_id: filename,
416 };
417 });
418
419 console.log('RVC voices:', voices);
420 this.rvcVoices = voices; // Assign to the class property
421 this.updateRvcVoiceDropdowns(); // Update UI after fetching voices
422 return voices; // Also return this list
423 } catch (error) {
424 console.error('Error fetching RVC voices:', error);
425 this.rvcVoices = [{ name: 'Disabled', voice_id: 'Disabled' }]; // Set default on error
426 throw error;
427 } finally {
428 // Ensure dropdowns are updated even if there was an error
429 this.updateRvcVoiceDropdowns();
430 }
431 }
432
351 //##########################################// 433 //##########################################//
352 // Get Current AT Server Config & Update ST // 434 // Get Current AT Server Config & Update ST //
353 //##########################################// 435 //##########################################//
354 436
355 async updateSettingsFromServer() { 437 async updateSettingsFromServer() {
356 try { 438 try {
357 // Fetch current settings
358 const response = await fetch(`${this.settings.provider_endpoint}/api/currentsettings`); 439 const response = await fetch(`${this.settings.provider_endpoint}/api/currentsettings`);
359 if (!response.ok) { 440 if (!response.ok) {
360 throw new Error(`Failed to fetch current settings: ${response.statusText}`); 441 throw new Error(`Failed to fetch current settings: ${response.statusText}`);
361 } 442 }
362 const currentSettings = await response.json(); 443 const currentSettings = await response.json();
363 // Update internal settings444 currentSettings.models_available.sort((a, b) => a.name.localeCompare(b.name));
445
446 this.settings.enginesAvailable = currentSettings.engines_available;
447 this.settings.currentEngineLoaded = currentSettings.current_engine_loaded;
364 this.settings.modelsAvailable = currentSettings.models_available; 448 this.settings.modelsAvailable = currentSettings.models_available;
365 this.settings.currentModel = currentSettings.current_model_loaded; 449 this.settings.currentModel = currentSettings.current_model_loaded;
450 this.settings.deepspeed_capable = currentSettings.deepspeed_capable;
366 this.settings.deepspeed_available = currentSettings.deepspeed_available; 451 this.settings.deepspeed_available = currentSettings.deepspeed_available;
367 this.settings.deepSpeedEnabled = currentSettings.deepspeed_status;452 this.settings.deepspeed_enabled = currentSettings.deepspeed_enabled;
368 this.settings.lowVramEnabled = currentSettings.low_vram_status;453 this.settings.lowvram_capable = currentSettings.lowvram_capable;
369 this.settings.finetuned_model = currentSettings.finetuned_model;454 this.settings.lowvram_enabled = currentSettings.lowvram_enabled;
370 // Update HTML elements455
456 await this.fetchRvcVoiceObjects(); // Fetch RVC voices
457
371 this.updateModelDropdown(); 458 this.updateModelDropdown();
372 this.updateCheckboxes(); 459 this.updateCheckboxes();
460 this.updateRvcVoiceDropdowns(); // Update the RVC voice dropdowns
373 } catch (error) { 461 } catch (error) {
374 console.error(`Error updating settings from server: ${error}`); 462 console.error(`Error updating settings from server: ${error}`);
375 } 463 }
376 } 464 }
377 465
466 updateRvcVoiceDropdowns() {
467 // Handle all RVC-related elements
468 const rvcElements = document.querySelectorAll('.rvc-setting');
469 const isV2 = this.settings.server_version === 'v2';
470
471 rvcElements.forEach(element => {
472 element.style.display = isV2 ? 'block' : 'none';
473 });
474
475 // Update and disable/enable character voice dropdown
476 const rvcCharacterVoiceSelect = document.getElementById('rvc_character_voice');
477 if (rvcCharacterVoiceSelect) {
478 rvcCharacterVoiceSelect.disabled = !isV2;
479 if (this.rvcVoices) {
480 rvcCharacterVoiceSelect.innerHTML = '';
481 for (let voice of this.rvcVoices) {
482 const option = document.createElement('option');
483 option.value = voice.voice_id;
484 option.textContent = voice.name;
485 if (voice.voice_id === this.settings.rvc_character_voice) {
486 option.selected = true;
487 }
488 rvcCharacterVoiceSelect.appendChild(option);
489 }
490 }
491 }
492
493 // Update and disable/enable narrator voice dropdown
494 const rvcNarratorVoiceSelect = document.getElementById('rvc_narrator_voice');
495 if (rvcNarratorVoiceSelect) {
496 rvcNarratorVoiceSelect.disabled = !isV2;
497 if (this.rvcVoices) {
498 rvcNarratorVoiceSelect.innerHTML = '';
499 for (let voice of this.rvcVoices) {
500 const option = document.createElement('option');
501 option.value = voice.voice_id;
502 option.textContent = voice.name;
503 if (voice.voice_id === this.settings.rvc_narrator_voice) {
504 option.selected = true;
505 }
506 rvcNarratorVoiceSelect.appendChild(option);
507 }
508 }
509 }
510
511 // Update pitch inputs
512 const characterPitch = document.getElementById('rvc_character_pitch');
513 if (characterPitch) {
514 characterPitch.disabled = !isV2;
515 }
516
517 const narratorPitch = document.getElementById('rvc_narrator_pitch');
518 if (narratorPitch) {
519 narratorPitch.disabled = !isV2;
520 }
521 }
522
378 //###################################################// 523 //###################################################//
379 // Get Current AT Server Config & Update ST (Models) // 524 // Get Current AT Server Config & Update ST (Models) //
380 //###################################################// 525 //###################################################//
@@ -385,9 +530,9 @@ class AllTalkTtsProvider {
385 modelSelect.innerHTML = ''; // Clear existing options 530 modelSelect.innerHTML = ''; // Clear existing options
386 this.settings.modelsAvailable.forEach(model => { 531 this.settings.modelsAvailable.forEach(model => {
387 const option = document.createElement('option'); 532 const option = document.createElement('option');
388 option.value = model.model_name;533 option.value = model.name;
389 option.textContent = model.model_name; // Use model_name instead of name534 option.textContent = model.name; // Use model name directly
390 option.selected = model.model_name === this.settings.currentModel;535 option.selected = model.name === this.settings.currentModel;
391 modelSelect.appendChild(option); 536 modelSelect.appendChild(option);
392 }); 537 });
393 } 538 }
@@ -400,13 +545,36 @@ class AllTalkTtsProvider {
400 updateCheckboxes() { 545 updateCheckboxes() {
401 const deepspeedCheckbox = document.getElementById('deepspeed'); 546 const deepspeedCheckbox = document.getElementById('deepspeed');
402 const lowVramCheckbox = document.getElementById('low_vram'); 547 const lowVramCheckbox = document.getElementById('low_vram');
403 if (lowVramCheckbox) lowVramCheckbox.checked = this.settings.lowVramEnabled;548
549 // Handle DeepSpeed checkbox
404 if (deepspeedCheckbox) { 550 if (deepspeedCheckbox) {
405 deepspeedCheckbox.checked = this.settings.deepSpeedEnabled;551 if (this.settings.deepspeed_capable) {
406 deepspeedCheckbox.disabled = !this.settings.deepspeed_available; // Disable checkbox if deepspeed is not available552 // If TTS engine is capable of using DeepSpeed
553 deepspeedCheckbox.disabled = !this.settings.deepspeed_available;
554 this.settings.deepspeed_enabled = this.settings.deepspeed_available && this.settings.deepspeed_enabled;
555 } else {
556 // If TTS engine is NOT capable of using DeepSpeed
557 deepspeedCheckbox.disabled = true;
558 this.settings.deepspeed_enabled = false;
407 } 559 }
560 deepspeedCheckbox.checked = this.settings.deepspeed_enabled;
408 } 561 }
409 562
563 // Handle Low VRAM checkbox
564 if (lowVramCheckbox) {
565 if (this.settings.lowvram_capable) {
566 // If TTS engine is capable of low VRAM
567 lowVramCheckbox.disabled = false;
568 } else {
569 // If TTS engine is NOT capable of low VRAM
570 lowVramCheckbox.disabled = true;
571 this.settings.lowvram_enabled = false;
572 }
573 lowVramCheckbox.checked = this.settings.lowvram_enabled;
574 }
575 }
576
577
410 //###############################################################// 578 //###############################################################//
411 // Get Current AT Server Config & Update ST (AT Narrator Voices) // 579 // Get Current AT Server Config & Update ST (AT Narrator Voices) //
412 //###############################################################// 580 //###############################################################//
@@ -433,8 +601,8 @@ class AllTalkTtsProvider {
433 updateLanguageDropdown() { 601 updateLanguageDropdown() {
434 const languageSelect = document.getElementById('language_options'); 602 const languageSelect = document.getElementById('language_options');
435 if (languageSelect) { 603 if (languageSelect) {
436 // Ensure default language is set (??? whatever that means)604 // Ensure default language is set
437 // this.settings.language = this.settings.language;605 this.settings.language = this.settings.language;
438 606
439 languageSelect.innerHTML = ''; 607 languageSelect.innerHTML = '';
440 for (let language in this.languageLabels) { 608 for (let language in this.languageLabels) {
@@ -456,28 +624,28 @@ class AllTalkTtsProvider {
456 setupEventListeners() { 624 setupEventListeners() {
457 625
458 let debounceTimeout; 626 let debounceTimeout;
459 const debounceDelay = 500; // Milliseconds627 const debounceDelay = 1400; // Milliseconds
460 628
461 // Define the event handler function 629 // Define the event handler function
462 const onModelSelectChange = async (event) => { 630 const onModelSelectChange = async (event) => {
463 console.log('Model select change event triggered'); // Debugging statement631 console.log("Model select change event triggered"); // Debugging statement
464 const selectedModel = event.target.value; 632 const selectedModel = event.target.value;
465 console.log(`Selected model: ${selectedModel}`); // Debugging statement 633 console.log(`Selected model: ${selectedModel}`); // Debugging statement
466 // Set status to Processing 634 // Set status to Processing
467 updateStatus('Processing'); 635 updateStatus('Processing');
468 try { 636 try {
469 const response = await fetch(`${this.settings.provider_endpoint}/api/reload?tts_method=${encodeURIComponent(selectedModel)}`, { 637 const response = await fetch(`${this.settings.provider_endpoint}/api/reload?tts_method=${encodeURIComponent(selectedModel)}`, {
470 method: 'POST',638 method: 'POST'
471 }); 639 });
472 if (!response.ok) { 640 if (!response.ok) {
473 throw new Error(`HTTP Error: ${response.status}`); 641 throw new Error(`HTTP Error: ${response.status}`);
474 } 642 }
475 const data = await response.json(); 643 const data = await response.json();
476 console.log('POST response data:', data); // Debugging statement644 console.log("POST response data:", data); // Debugging statement
477 // Set status to Ready if successful 645 // Set status to Ready if successful
478 updateStatus('Ready'); 646 updateStatus('Ready');
479 } catch (error) { 647 } catch (error) {
480 console.error('POST request error:', error); // Debugging statement648 console.error("POST request error:", error); // Debugging statement
481 // Set status to Error in case of failure 649 // Set status to Error in case of failure
482 updateStatus('Error'); 650 updateStatus('Error');
483 } 651 }
@@ -485,6 +653,52 @@ class AllTalkTtsProvider {
485 // Handle response or error 653 // Handle response or error
486 }; 654 };
487 655
656 // AllTalk Server version change listener
657 const serverVersionSelect = document.getElementById('server_version');
658 if (serverVersionSelect) {
659 serverVersionSelect.addEventListener('change', async (event) => {
660 this.settings.server_version = event.target.value;
661 // Clear and refetch voices if needed
662 if (event.target.value === 'v2') {
663 await this.fetchRvcVoiceObjects();
664 }
665 this.updateRvcVoiceDropdowns();
666 this.onSettingsChange();
667 });
668 }
669
670 const rvcCharacterVoiceSelect = document.getElementById('rvc_character_voice');
671 if (rvcCharacterVoiceSelect) {
672 rvcCharacterVoiceSelect.addEventListener('change', (event) => {
673 this.settings.rvccharacter_voice_gen = event.target.value;
674 this.onSettingsChange(); // Save the settings after change
675 });
676 }
677
678 const rvcNarratorVoiceSelect = document.getElementById('rvc_narrator_voice');
679 if (rvcNarratorVoiceSelect) {
680 rvcNarratorVoiceSelect.addEventListener('change', (event) => {
681 this.settings.rvcnarrator_voice_gen = event.target.value;
682 this.onSettingsChange(); // Save the settings after change
683 });
684 }
685
686 const rvcCharacterPitchSelect = document.getElementById('rvc_character_pitch');
687 if (rvcCharacterPitchSelect) {
688 rvcCharacterPitchSelect.addEventListener('change', (event) => {
689 this.settings.rvc_character_pitch = event.target.value;
690 this.onSettingsChange(); // Save the settings after change
691 });
692 }
693
694 const rvcNarratorPitchSelect = document.getElementById('rvc_narrator_pitch');
695 if (rvcNarratorPitchSelect) {
696 rvcNarratorPitchSelect.addEventListener('change', (event) => {
697 this.settings.rvc_narrator_pitch = event.target.value;
698 this.onSettingsChange(); // Save the settings after change
699 });
700 }
701
488 const debouncedModelSelectChange = (event) => { 702 const debouncedModelSelectChange = (event) => {
489 clearTimeout(debounceTimeout); 703 clearTimeout(debounceTimeout);
490 debounceTimeout = setTimeout(() => { 704 debounceTimeout = setTimeout(() => {
@@ -496,74 +710,89 @@ class AllTalkTtsProvider {
496 const modelSelect = document.getElementById('switch_model'); 710 const modelSelect = document.getElementById('switch_model');
497 if (modelSelect) { 711 if (modelSelect) {
498 // Remove the event listener if it was previously added 712 // Remove the event listener if it was previously added
713 modelSelect.removeEventListener('change', debouncedModelSelectChange);
499 // Add the debounced event listener 714 // Add the debounced event listener
500 $(modelSelect).off('change').on('change', debouncedModelSelectChange);715 modelSelect.addEventListener('change', debouncedModelSelectChange);
501 } 716 }
502 717
503 // DeepSpeed Listener 718 // DeepSpeed Listener
504 const deepspeedCheckbox = document.getElementById('deepspeed'); 719 const deepspeedCheckbox = document.getElementById('deepspeed');
505 if (deepspeedCheckbox) { 720 if (deepspeedCheckbox) {
506 $(deepspeedCheckbox).off('change').on('change', async (event) => {721 deepspeedCheckbox.addEventListener('change', async (event) => {
507 const deepSpeedValue = event.target.checked ? 'True' : 'False'; 722 const deepSpeedValue = event.target.checked ? 'True' : 'False';
508 // Set status to Processing 723 // Set status to Processing
509 updateStatus('Processing'); 724 updateStatus('Processing');
510 try { 725 try {
511 const response = await fetch(`${this.settings.provider_endpoint}/api/deepspeed?new_deepspeed_value=${deepSpeedValue}`, { 726 const response = await fetch(`${this.settings.provider_endpoint}/api/deepspeed?new_deepspeed_value=${deepSpeedValue}`, {
512 method: 'POST',727 method: 'POST'
513 }); 728 });
514 if (!response.ok) { 729 if (!response.ok) {
515 throw new Error(`HTTP Error: ${response.status}`); 730 throw new Error(`HTTP Error: ${response.status}`);
516 } 731 }
517 const data = await response.json(); 732 const data = await response.json();
518 console.log('POST response data:', data); // Debugging statement733 console.log("POST response data:", data); // Debugging statement
519 // Set status to Ready if successful 734 // Set status to Ready if successful
520 updateStatus('Ready'); 735 updateStatus('Ready');
521 } catch (error) { 736 } catch (error) {
522 console.error('POST request error:', error); // Debugging statement737 console.error("POST request error:", error); // Debugging statement
523 // Set status to Error in case of failure 738 // Set status to Error in case of failure
524 updateStatus('Error'); 739 updateStatus('Error');
525 } 740 }
526 }); 741 });
527 } 742 }
528 743
744 function lowvramdebounce(func, delay) {
745 let debounceTimer;
746 return function (...args) {
747 const context = this;
748 clearTimeout(debounceTimer);
749 debounceTimer = setTimeout(() => func.apply(context, args), delay);
750 };
751 }
752
529 // Low VRAM Listener 753 // Low VRAM Listener
530 const lowVramCheckbox = document.getElementById('low_vram'); 754 const lowVramCheckbox = document.getElementById('low_vram');
531 if (lowVramCheckbox) { 755 if (lowVramCheckbox) {
532 $(lowVramCheckbox).off('change').on('change', async (event) => {756 const handleLowVramChange = async (event) => {
533 const lowVramValue = event.target.checked ? 'True' : 'False'; 757 const lowVramValue = event.target.checked ? 'True' : 'False';
534 // Set status to Processing 758 // Set status to Processing
535 updateStatus('Processing'); 759 updateStatus('Processing');
536 try { 760 try {
537 const response = await fetch(`${this.settings.provider_endpoint}/api/lowvramsetting?new_low_vram_value=${lowVramValue}`, { 761 const response = await fetch(`${this.settings.provider_endpoint}/api/lowvramsetting?new_low_vram_value=${lowVramValue}`, {
538 method: 'POST',762 method: 'POST'
539 }); 763 });
540 if (!response.ok) { 764 if (!response.ok) {
541 throw new Error(`HTTP Error: ${response.status}`); 765 throw new Error(`HTTP Error: ${response.status}`);
542 } 766 }
543 const data = await response.json(); 767 const data = await response.json();
544 console.log('POST response data:', data); // Debugging statement768 console.log("POST response data:", data); // Debugging statement
545 // Set status to Ready if successful 769 // Set status to Ready if successful
546 updateStatus('Ready'); 770 updateStatus('Ready');
547 } catch (error) { 771 } catch (error) {
548 console.error('POST request error:', error); // Debugging statement772 console.error("POST request error:", error); // Debugging statement
549 // Set status to Error in case of failure 773 // Set status to Error in case of failure
550 updateStatus('Error'); 774 updateStatus('Error');
551 } 775 }
552 });776 };
777
778 const debouncedHandleLowVramChange = lowvramdebounce(handleLowVramChange, 300); // Adjust delay as needed
779
780 lowVramCheckbox.addEventListener('change', debouncedHandleLowVramChange);
553 } 781 }
554 782
783
555 // Narrator Voice Dropdown Listener 784 // Narrator Voice Dropdown Listener
556 const narratorVoiceSelect = document.getElementById('narrator_voice'); 785 const narratorVoiceSelect = document.getElementById('narrator_voice');
557 if (narratorVoiceSelect) { 786 if (narratorVoiceSelect) {
558 $(narratorVoiceSelect).off('change').on('change', (event) => {787 narratorVoiceSelect.addEventListener('change', (event) => {
559 this.settings.narrator_voice_gen = `${event.target.value}.wav`;788 this.settings.narrator_voice_gen = `${event.target.value}`;
560 this.onSettingsChange(); // Save the settings after change 789 this.onSettingsChange(); // Save the settings after change
561 }); 790 });
562 } 791 }
563 792
564 const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside'); 793 const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside');
565 if (textNotInsideSelect) { 794 if (textNotInsideSelect) {
566 $(textNotInsideSelect).off('change').on('change', (event) => {795 textNotInsideSelect.addEventListener('change', (event) => {
567 this.settings.text_not_inside = event.target.value; 796 this.settings.text_not_inside = event.target.value;
568 this.onSettingsChange(); // Save the settings after change 797 this.onSettingsChange(); // Save the settings after change
569 }); 798 });
@@ -571,39 +800,45 @@ class AllTalkTtsProvider {
571 800
572 // AT Narrator Dropdown Listener 801 // AT Narrator Dropdown Listener
573 const atNarratorSelect = document.getElementById('at_narrator_enabled'); 802 const atNarratorSelect = document.getElementById('at_narrator_enabled');
574 const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks'); // Access the checkbox from index.js803 const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks');
575 const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted'); // Access the checkbox from index.js804 const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted');
576 const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues'); // Access the checkbox from index.js805 const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues');
577 806
578 if (atNarratorSelect && textNotInsideSelect && narratorVoiceSelect) { 807 if (atNarratorSelect && textNotInsideSelect && narratorVoiceSelect) {
579 $(atNarratorSelect).off('change').on('change', (event) => {808 atNarratorSelect.addEventListener('change', (event) => {
580 const isNarratorEnabled = event.target.value === 'true';809 const narratorOption = event.target.value;
581 this.settings.narrator_enabled = isNarratorEnabled; // Update the setting here810 this.settings.narrator_enabled = narratorOption;
582 textNotInsideSelect.disabled = !isNarratorEnabled;811
583 narratorVoiceSelect.disabled = !isNarratorEnabled;812 // Check if narrator is disabled
584813 const isNarratorDisabled = narratorOption === 'false';
585 // Sync the state with the checkbox in index.js814 textNotInsideSelect.disabled = isNarratorDisabled;
586 if (isNarratorEnabled) {815 narratorVoiceSelect.disabled = isNarratorDisabled;
816
817 console.log(`Narrator option: ${narratorOption}`);
818 console.log(`textNotInsideSelect disabled: ${textNotInsideSelect.disabled}`);
819 console.log(`narratorVoiceSelect disabled: ${narratorVoiceSelect.disabled}`);
820
821 if (narratorOption === 'true') {
587 ttsPassAsterisksCheckbox.checked = false; 822 ttsPassAsterisksCheckbox.checked = false;
588 $('#tts_pass_asterisks').click(); // Simulate a click event823 $('#tts_pass_asterisks').click();
589 $('#tts_pass_asterisks').trigger('change'); 824 $('#tts_pass_asterisks').trigger('change');
590 }
591 if (!isNarratorEnabled) {
592 ttsPassAsterisksCheckbox.checked = true;
593 $('#tts_pass_asterisks').click(); // Simulate a click event
594 $('#tts_pass_asterisks').trigger('change');
595 }
596 // Uncheck and set tts_narrate_quoted to false if narrator is enabled
597 if (isNarratorEnabled) {
598 ttsNarrateQuotedCheckbox.checked = true; 825 ttsNarrateQuotedCheckbox.checked = true;
599 ttsNarrateDialoguesCheckbox.checked = true; 826 ttsNarrateDialoguesCheckbox.checked = true;
600 // Trigger click events instead of change events
601 $('#tts_narrate_quoted').click(); 827 $('#tts_narrate_quoted').click();
602 $('#tts_narrate_quoted').trigger('change'); 828 $('#tts_narrate_quoted').trigger('change');
603 $('#tts_narrate_dialogues').click(); 829 $('#tts_narrate_dialogues').click();
604 $('#tts_narrate_dialogues').trigger('change'); 830 $('#tts_narrate_dialogues').trigger('change');
831 } else if (narratorOption === 'silent') {
832 ttsPassAsterisksCheckbox.checked = false;
833 $('#tts_pass_asterisks').click();
834 $('#tts_pass_asterisks').trigger('change');
835 } else {
836 ttsPassAsterisksCheckbox.checked = true;
837 $('#tts_pass_asterisks').click();
838 $('#tts_pass_asterisks').trigger('change');
605 } 839 }
606 this.onSettingsChange(); // Save the settings after change840
841 this.onSettingsChange();
607 }); 842 });
608 } 843 }
609 844
@@ -612,7 +847,7 @@ class AllTalkTtsProvider {
612 const atGenerationMethodSelect = document.getElementById('at_generation_method'); 847 const atGenerationMethodSelect = document.getElementById('at_generation_method');
613 const atNarratorEnabledSelect = document.getElementById('at_narrator_enabled'); 848 const atNarratorEnabledSelect = document.getElementById('at_narrator_enabled');
614 if (atGenerationMethodSelect) { 849 if (atGenerationMethodSelect) {
615 $(atGenerationMethodSelect).off('change').on('change', (event) => {850 atGenerationMethodSelect.addEventListener('change', (event) => {
616 const selectedMethod = event.target.value; 851 const selectedMethod = event.target.value;
617 852
618 if (selectedMethod === 'streaming_enabled') { 853 if (selectedMethod === 'streaming_enabled') {
@@ -633,7 +868,7 @@ class AllTalkTtsProvider {
633 // Listener for Language Dropdown 868 // Listener for Language Dropdown
634 const languageSelect = document.getElementById('language_options'); 869 const languageSelect = document.getElementById('language_options');
635 if (languageSelect) { 870 if (languageSelect) {
636 $(languageSelect).off('change').on('change', (event) => {871 languageSelect.addEventListener('change', (event) => {
637 this.settings.language = event.target.value; 872 this.settings.language = event.target.value;
638 this.onSettingsChange(); // Save the settings after change 873 this.onSettingsChange(); // Save the settings after change
639 }); 874 });
@@ -642,7 +877,7 @@ class AllTalkTtsProvider {
642 // Listener for AllTalk Endpoint Input 877 // Listener for AllTalk Endpoint Input
643 const atServerInput = document.getElementById('at_server'); 878 const atServerInput = document.getElementById('at_server');
644 if (atServerInput) { 879 if (atServerInput) {
645 $(atServerInput).off('input').on('input', (event) => {880 atServerInput.addEventListener('input', (event) => {
646 this.settings.provider_endpoint = event.target.value; 881 this.settings.provider_endpoint = event.target.value;
647 this.onSettingsChange(); // Save the settings after change 882 this.onSettingsChange(); // Save the settings after change
648 }); 883 });
@@ -662,6 +897,10 @@ class AllTalkTtsProvider {
662 this.settings.at_generation_method = $('#at_generation_method').val(); 897 this.settings.at_generation_method = $('#at_generation_method').val();
663 this.settings.narrator_enabled = $('#at_narrator_enabled').val(); 898 this.settings.narrator_enabled = $('#at_narrator_enabled').val();
664 this.settings.at_narrator_text_not_inside = $('#at_narrator_text_not_inside').val(); 899 this.settings.at_narrator_text_not_inside = $('#at_narrator_text_not_inside').val();
900 this.settings.rvc_character_voice = $('#rvc_character_voice').val();
901 this.settings.rvc_narrator_voice = $('#rvc_narrator_voice').val();
902 this.settings.rvc_character_pitch = $('#rvc_character_pitch').val();
903 this.settings.rvc_narrator_pitch = $('#rvc_narrator_pitch').val();
665 this.settings.narrator_voice_gen = $('#narrator_voice').val(); 904 this.settings.narrator_voice_gen = $('#narrator_voice').val();
666 // Save the updated settings 905 // Save the updated settings
667 saveTtsProviderSettings(); 906 saveTtsProviderSettings();
@@ -672,8 +911,16 @@ class AllTalkTtsProvider {
672 //#########################// 911 //#########################//
673 912
674 async onRefreshClick() { 913 async onRefreshClick() {
675 await this.initEndpoint();914 try {
676 // Additional actions as needed915 updateStatus('Processing'); // Set status to Processing while refreshing
916 await this.checkReady(); // Check if the TTS provider is ready
917 await this.loadSettings(this.settings); // Reload the settings
918 await this.checkReady(); // Check if the TTS provider is ready
919 updateStatus(this.ready ? 'Ready' : 'Offline'); // Update the status based on readiness
920 } catch (error) {
921 console.error('Error during refresh:', error);
922 updateStatus('Error'); // Set status to Error in case of failure
923 }
677 } 924 }
678 925
679 //##################// 926 //##################//
@@ -684,33 +931,44 @@ class AllTalkTtsProvider {
684 try { 931 try {
685 // Prepare data for POST request 932 // Prepare data for POST request
686 const postData = new URLSearchParams(); 933 const postData = new URLSearchParams();
687 postData.append('voice', `${voiceName}.wav`);934 postData.append("voice", `${voiceName}`);
935
936 // Add RVC parameters for V2 if applicable
937 if (this.settings.server_version === 'v2' && this.settings.rvc_character_voice !== 'Disabled') {
938 postData.append("rvccharacter_voice_gen", this.settings.rvc_character_voice);
939 postData.append("rvccharacter_pitch", this.settings.rvc_character_pitch || "0");
940 }
941
688 // Making the POST request 942 // Making the POST request
689 const response = await fetch(`${this.settings.provider_endpoint}/api/previewvoice/`, { 943 const response = await fetch(`${this.settings.provider_endpoint}/api/previewvoice/`, {
690 method: 'POST',944 method: "POST",
691 headers: { 945 headers: {
692 'Content-Type': 'application/x-www-form-urlencoded',946 'Content-Type': 'application/x-www-form-urlencoded'
693 }, 947 },
694 body: postData, 948 body: postData,
695 }); 949 });
950
696 if (!response.ok) { 951 if (!response.ok) {
697 const errorText = await response.text(); 952 const errorText = await response.text();
698 console.error('[previewTtsVoice] Error Response Text:', errorText);953 console.error(`[previewTtsVoice] Error Response Text:`, errorText);
699 throw new Error(`HTTP ${response.status}: ${errorText}`); 954 throw new Error(`HTTP ${response.status}: ${errorText}`);
700 } 955 }
701 // Assuming the server returns a URL to the .wav file956
702 const data = await response.json(); 957 const data = await response.json();
703 if (data.output_file_url) { 958 if (data.output_file_url) {
704 // Use an audio element to play the .wav file959 // Handle V1/V2 URL differences
705 const audioElement = new Audio(data.output_file_url);960 const fullUrl = this.settings.server_version === 'v1'
706 audioElement.play().catch(e => console.error('Error playing audio:', e));961 ? data.output_file_url
962 : `${this.settings.provider_endpoint}${data.output_file_url}`;
963
964 const audioElement = new Audio(fullUrl);
965 audioElement.play().catch(e => console.error("Error playing audio:", e));
707 } else { 966 } else {
708 console.warn('[previewTtsVoice] No output file URL received in the response');967 console.warn("[previewTtsVoice] No output file URL received in the response");
709 throw new Error('No output file URL received in the response');968 throw new Error("No output file URL received in the response");
710 } 969 }
711
712 } catch (error) { 970 } catch (error) {
713 console.error('[previewTtsVoice] Exception caught during preview generation:', error);971 console.error("[previewTtsVoice] Exception caught during preview generation:", error);
714 throw error; 972 throw error;
715 } 973 }
716 } 974 }
@@ -744,8 +1002,8 @@ class AllTalkTtsProvider {
744 try { 1002 try {
745 if (this.settings.at_generation_method === 'streaming_enabled') { 1003 if (this.settings.at_generation_method === 'streaming_enabled') {
746 // Construct the streaming URL 1004 // Construct the streaming URL
747 const streamingUrl = `${this.settings.provider_endpoint}/api/tts-generate-streaming?text=${encodeURIComponent(inputText)}&voice=${encodeURIComponent(voiceId)}.wav&language=${encodeURIComponent(this.settings.language)}&output_file=stream_output.wav`;1005 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`;
748 console.log('Streaming URL:', streamingUrl);1006 console.log("Streaming URL:", streamingUrl);
749 1007
750 // Return the streaming URL directly 1008 // Return the streaming URL directly
751 return streamingUrl; 1009 return streamingUrl;
@@ -759,7 +1017,7 @@ class AllTalkTtsProvider {
759 return audioResponse; // Return the fetch response directly 1017 return audioResponse; // Return the fetch response directly
760 } 1018 }
761 } catch (error) { 1019 } catch (error) {
762 console.error('Error in generateTts:', error);1020 console.error("Error in generateTts:", error);
763 throw error; 1021 throw error;
764 } 1022 }
765 } 1023 }
@@ -770,20 +1028,31 @@ class AllTalkTtsProvider {
770 //####################// 1028 //####################//
771 1029
772 async fetchTtsGeneration(inputText, voiceId) { 1030 async fetchTtsGeneration(inputText, voiceId) {
773 // Prepare the request payload
774 const requestBody = new URLSearchParams({ 1031 const requestBody = new URLSearchParams({
775 'text_input': inputText, 1032 'text_input': inputText,
776 'text_filtering': 'standard',1033 'text_filtering': "standard",
777 'character_voice_gen': voiceId + '.wav',1034 'character_voice_gen': voiceId,
778 'narrator_enabled': this.settings.narrator_enabled, 1035 'narrator_enabled': this.settings.narrator_enabled,
779 'narrator_voice_gen': this.settings.narrator_voice_gen + '.wav',1036 'narrator_voice_gen': this.settings.narrator_voice_gen,
780 'text_not_inside': this.settings.at_narrator_text_not_inside, 1037 'text_not_inside': this.settings.at_narrator_text_not_inside,
781 'language': this.settings.language, 1038 'language': this.settings.language,
782 'output_file_name': 'st_output',1039 'output_file_name': "st_output",
783 'output_file_timestamp': 'true',1040 'output_file_timestamp': "true",
784 'autoplay': 'false',1041 'autoplay': "false",
785 'autoplay_volume': '0.8',1042 'autoplay_volume': "0.8"
786 }).toString();1043 });
1044
1045 // Add RVC parameters only for V2
1046 if (this.settings.server_version === 'v2') {
1047 if (this.settings.rvc_character_voice !== 'Disabled') {
1048 requestBody.append('rvccharacter_voice_gen', this.settings.rvc_character_voice);
1049 requestBody.append('rvccharacter_pitch', this.settings.rvc_character_pitch || "0");
1050 }
1051 if (this.settings.rvc_narrator_voice !== 'Disabled') {
1052 requestBody.append('rvcnarrator_voice_gen', this.settings.rvc_narrator_voice);
1053 requestBody.append('rvcnarrator_pitch', this.settings.rvc_narrator_pitch || "0");
1054 }
1055 }
787 1056
788 try { 1057 try {
789 const response = await doExtrasFetch( 1058 const response = await doExtrasFetch(
@@ -794,22 +1063,26 @@ class AllTalkTtsProvider {
794 'Content-Type': 'application/x-www-form-urlencoded', 1063 'Content-Type': 'application/x-www-form-urlencoded',
795 'Cache-Control': 'no-cache', 1064 'Cache-Control': 'no-cache',
796 }, 1065 },
797 body: requestBody,1066 body: requestBody
798 },1067 }
799 ); 1068 );
800 1069
801 if (!response.ok) { 1070 if (!response.ok) {
802 const errorText = await response.text(); 1071 const errorText = await response.text();
803 console.error('[fetchTtsGeneration] Error Response Text:', errorText);1072 console.error(`[fetchTtsGeneration] Error Response Text:`, errorText);
804 // toastr.error(response.statusText, 'TTS Generation Failed');
805 throw new Error(`HTTP ${response.status}: ${errorText}`); 1073 throw new Error(`HTTP ${response.status}: ${errorText}`);
806 } 1074 }
807 const data = await response.json(); 1075 const data = await response.json();
808 const outputUrl = data.output_file_url;1076
809 return outputUrl; // Return only the output_file_url1077 // Handle V1/V2 URL differences
1078 const outputUrl = this.settings.server_version === 'v1'
1079 ? data.output_file_url // V1 returns full URL
1080 : `${this.settings.provider_endpoint}${data.output_file_url}`; // V2 returns relative path
1081
1082 return outputUrl;
810 } catch (error) { 1083 } catch (error) {
811 console.error('[fetchTtsGeneration] Exception caught:', error);1084 console.error("[fetchTtsGeneration] Exception caught:", error);
812 throw error; // Rethrow the error for further handling1085 throw error;
813 } 1086 }
814 } 1087 }
815} 1088}