Blame Raw
Cohee · e3f41666 · · 258 lines (10.0 KB)
1 contributor
1import { saveTtsProviderSettings } from './index.js';
2
3export { GSVITtsProvider };
4
5class GSVITtsProvider {
6 //########//
7 // Config //
8 //########//
9
10 settings;
11 ready = false;
12 separator = '. ';
13
14 characterList = {};
15 voices = [];
16 /**
17 * Perform any text processing before passing to TTS engine.
18 * @param {string} text Input text
19 * @returns {string} Processed text
20 */
21 processText(text) {
22 text = text.replace('<br>', '\n'); // Replace <br> with newline
23 return text;
24 }
25
26 languageLabels = {
27 'Multilingual': '多语种混合',
28 'Chinese': '中文',
29 'English': '英文',
30 'Japanese': '日文',
31 'Chinese-English': '中英混合',
32 'Japanese-English': '日英混合',
33 };
34 defaultSettings = {
35 provider_endpoint: 'http://127.0.0.1:5000',
36
37 language: '多语种混合',
38
39 cha_name: '',
40 character_emotion: 'default',
41
42 speed: 1,
43
44 top_k: 6,
45 top_p: 0.85,
46 temperature: 0.75,
47 batch_size: 10,
48
49 stream: false,
50 stream_chunk_size: 100,
51 };
52
53 // Added new methods to obtain characters and emotions
54 async fetchCharacterList() {
55 const response = await fetch(this.settings.provider_endpoint + '/character_list');
56 if (!response.ok) {
57 throw new Error(`HTTP ${response.status}: ${await response.text()}`);
58 }
59 const characterList = await response.json();
60 this.characterList = characterList;
61 this.voices = Object.keys(characterList);
62 }
63
64
65 get settingsHtml() {
66 let html = `
67 <label for="gsvi_api_language">Text Language</label>
68 <select id="gsvi_api_language">`;
69
70 for (let language in this.languageLabels) {
71 if (this.languageLabels[language] == this.settings?.language) {
72 html += `<option value="${this.languageLabels[language]}" selected="selected">${language}</option>`;
73 continue;
74 }
75
76 html += `<option value="${this.languageLabels[language]}">${language}</option>`;
77 }
78
79 html += `
80 </select>
81 <label>GSVI Settings:</label><br/>
82 <label for="gsvi_tts_endpoint">Provider Endpoint:</label>
83 <input id="gsvi_tts_endpoint" type="text" class="text_pole" maxlength="250" value="${this.defaultSettings.provider_endpoint}"/>
84
85
86 <label for="gsvi_speed">Speed: <span id="gsvi_tts_speed_output">${this.defaultSettings.speed}</span></label>
87 <input id="gsvi_speed" type="range" value="${this.defaultSettings.speed}" min="0.5" max="2" step="0.01" />
88
89 <label for="gsvi_top_k">Top K: <span id="gsvi_top_k_output">${this.defaultSettings.top_k}</span></label>
90 <input id="gsvi_top_k" type="range" value="${this.defaultSettings.top_k}" min="0" max="100" step="1" />
91
92 <label for="gsvi_top_p">Top P: <span id="gsvi_top_p_output">${this.defaultSettings.top_p}</span></label>
93 <input id="gsvi_top_p" type="range" value="${this.defaultSettings.top_p}" min="0" max="1" step="0.01" />
94
95 <label for="gsvi_temperature">Temperature: <span id="gsvi_tts_temperature_output">${this.defaultSettings.temperature}</span></label>
96 <input id="gsvi_temperature" type="range" value="${this.defaultSettings.temperature}" min="0.01" max="1" step="0.01" />
97
98 <label for="gsvi_batch_size">Batch Size: <span id="gsvi_batch_size_output">${this.defaultSettings.batch_size}</span></label>
99 <input id="gsvi_batch_size" type="range" value="${this.defaultSettings.batch_size}" min="1" max="35" step="1" />
100
101 <label for="gsvi_tts_streaming" class="checkbox_label">
102 <input id="gsvi_tts_streaming" type="checkbox" ${this.defaultSettings.stream ? 'checked' : ''}/>
103 <span>Streaming</span>
104 </label>
105
106 <label for="gsvi_stream_chunk_size">Stream Chunk Size: <span id="gsvi_stream_chunk_size_output">${this.defaultSettings.stream_chunk_size}</span></label>
107 <input id="gsvi_stream_chunk_size" type="range" value="${this.defaultSettings.stream_chunk_size}" min="100" max="400" step="1" />
108 <p>
109 For more information, visit the
110 <a href="https://github.com/X-T-E-R/GPT-SoVITS-Inference" target="_blank">GSVI project page</a>.
111 </p>
112 `;
113
114 return html;
115 }
116
117 onSettingsChange() {
118 // Update provider settings based on input fields
119 this.settings.provider_endpoint = $('#gsvi_tts_endpoint').val();
120 this.settings.language = $('#gsvi_api_language').val();
121
122
123 // Update the rest of TTS settings based on input fields
124 this.settings.speed = parseFloat($('#gsvi_speed').val());
125 this.settings.temperature = parseFloat($('#gsvi_temperature').val());
126 this.settings.top_k = parseInt($('#gsvi_top_k').val(), 10);
127 this.settings.top_p = parseFloat($('#gsvi_top_p').val());
128 this.settings.batch_size = parseInt($('#gsvi_batch_size').val(), 10);
129 this.settings.stream = $('#gsvi_tts_streaming').is(':checked');
130 this.settings.stream_chunk_size = parseInt($('#gsvi_stream_chunk_size').val(), 10);
131
132 // Update UI to reflect changes
133
134 $('#gsvi_tts_speed_output').text(this.settings.speed);
135 $('#gsvi_tts_temperature_output').text(this.settings.temperature);
136 $('#gsvi_top_k_output').text(this.settings.top_k);
137 $('#gsvi_top_p_output').text(this.settings.top_p);
138 $('#gsvi_stream_chunk_size_output').text(this.settings.stream_chunk_size);
139 $('#gsvi_batch_size_output').text(this.settings.batch_size);
140
141
142 // Persist settings changes
143 saveTtsProviderSettings();
144 }
145
146 async loadSettings(settings) {
147 // Populate Provider UI given input settings
148 if (Object.keys(settings).length === 0) {
149 console.info('Using default TTS Provider settings');
150 }
151
152 // Only accept keys defined in defaultSettings
153 this.settings = { ...this.defaultSettings, ...settings };
154
155 // Fetch character and emotion list
156 // Set initial values from the settings
157 $('#gsvi_tts_endpoint').val(this.settings.provider_endpoint);
158 $('#gsvi_api_language').val(this.settings.language);
159
160 $('#gsvi_speed').val(this.settings.speed);
161 $('#gsvi_temperature').val(this.settings.temperature);
162 $('#gsvi_top_k').val(this.settings.top_k);
163 $('#gsvi_top_p').val(this.settings.top_p);
164 $('#gsvi_batch_size').val(this.settings.batch_size);
165 $('#gsvi_tts_streaming').prop('checked', this.settings.stream);
166 $('#gsvi_stream_chunk_size').val(this.settings.stream_chunk_size);
167
168 // Update UI to reflect initial settings
169 $('#gsvi_tts_speed_output').text(this.settings.speed);
170 $('#gsvi_tts_temperature_output').text(this.settings.temperature);
171 $('#gsvi_top_k_output').text(this.settings.top_k);
172 $('#gsvi_top_p_output').text(this.settings.top_p);
173 $('#gsvi_stream_chunk_size_output').text(this.settings.stream_chunk_size);
174
175 // Register event listeners to update settings on user interaction
176 // (Similar to before, ensure event listeners for character and emotion selection are included)
177 // Register input/change event listeners to update settings on user interaction
178 $('#gsvi_tts_endpoint').on('input', () => { this.onSettingsChange(); });
179 $('#gsvi_api_language').on('change', () => { this.onSettingsChange(); });
180
181 $('#gsvi_speed').on('input', () => { this.onSettingsChange(); });
182 $('#gsvi_temperature').on('input', () => { this.onSettingsChange(); });
183 $('#gsvi_top_k').on('input', () => { this.onSettingsChange(); });
184 $('#gsvi_top_p').on('input', () => { this.onSettingsChange(); });
185 $('#gsvi_batch_size').on('input', () => { this.onSettingsChange(); });
186 $('#gsvi_tts_streaming').on('change', () => { this.onSettingsChange(); });
187 $('#gsvi_stream_chunk_size').on('input', () => { this.onSettingsChange(); });
188
189 await this.checkReady();
190 console.debug('GSVI: Settings loaded');
191 }
192
193
194 // Perform a simple readiness check by trying to fetch voiceIds
195 async checkReady() {
196 await Promise.allSettled([this.fetchCharacterList()]);
197 }
198
199 async onRefreshClick() {
200 return;
201 }
202
203 //#################//
204 // TTS Interfaces //
205 //#################//
206
207 async getVoice(voiceName) {
208 if (this.voices.length == 0) {
209 this.fetchCharacterList();
210 }
211 if (!this.voices.includes(voiceName)) {
212 throw `TTS Voice name ${voiceName} not found`;
213 }
214 return { name: voiceName, voice_id: voiceName, preview_url: false, lang: 'zh-CN' };
215 }
216
217 async generateTts(text, voiceId) {
218 const response = await this.fetchTtsGeneration(text, voiceId);
219 return response;
220 }
221
222 //###########//
223 // API CALLS //
224 //###########//
225 async fetchTtsVoiceObjects() {
226 if (this.voices.length == 0) {
227 await this.fetchCharacterList();
228 }
229 console.log(this.voices);
230 const voices = this.voices.map(x => ({ name: x, voice_id: x, preview_url: false, lang: 'zh-CN' }));
231 return voices;
232 }
233
234
235 async fetchTtsGeneration(inputText, voiceId) {
236 console.info(`Generating new TTS for voice_id ${voiceId}`);
237
238
239 const params = new URLSearchParams();
240 params.append('text', inputText);
241 params.append('cha_name', voiceId);
242 params.append('text_language', this.settings.language);
243 params.append('batch_size', this.settings.batch_size.toString());
244 params.append('speed', this.settings.speed.toString());
245 params.append('top_k', this.settings.top_k.toString());
246 params.append('top_p', this.settings.top_p.toString());
247 params.append('temperature', this.settings.temperature.toString());
248 params.append('stream', this.settings.stream.toString());
249
250
251 return `${this.settings.provider_endpoint}/tts?${params.toString()}`;
252 }
253
254 // Interface not used by GSVI TTS
255 async fetchTtsFromHistory(history_item_id) {
256 return Promise.resolve(history_item_id);
257 }
258}