Add files via upload

a2b4f03d9d73685fea1b412f587b60398c318e9b

刘悦 <zcxey2911@hotmail.com>

Signed
1 files changed, +204 -0Showing whitespace changes
public/scripts/extensions/tts/cosyvoice.js+204 -0
@@ -0,0 +1,204 @@
1import { getPreviewString, saveTtsProviderSettings } from './index.js';
2
3export { CosyVoiceProvider };
4
5class CosyVoiceProvider {
6 //########//
7 // Config //
8 //########//
9
10 settings;
11 ready = false;
12 voices = [];
13 separator = '. ';
14 audioElement = document.createElement('audio');
15
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 return text;
23 }
24
25 audioFormats = ['wav', 'ogg', 'silk', 'mp3', 'flac'];
26
27 languageLabels = {
28 'Auto': 'auto',
29 };
30
31 langKey2LangCode = {
32 'zh': 'zh-CN',
33 'en': 'en-US',
34 'ja': 'ja-JP',
35 'ko': 'ko-KR',
36 };
37
38 modelTypes = {
39 CosyVoice: 'CosyVoice',
40 };
41
42 defaultSettings = {
43 provider_endpoint: 'http://localhost:9880',
44 format: 'wav',
45 lang: 'auto',
46 streaming: false,
47
48 };
49
50 get settingsHtml() {
51 let html = `
52
53 <label for="tts_endpoint">Provider Endpoint:</label>
54 <input id="tts_endpoint" type="text" class="text_pole" maxlength="250" height="300" value="${this.defaultSettings.provider_endpoint}"/>
55 <br/>
56
57 `;
58
59 return html;
60 }
61
62 onSettingsChange() {
63 // Used when provider settings are updated from UI
64 this.settings.provider_endpoint = $('#tts_endpoint').val();
65
66
67 saveTtsProviderSettings();
68 this.changeTTSSettings();
69 }
70
71 async loadSettings(settings) {
72 // Pupulate Provider UI given input settings
73 if (Object.keys(settings).length == 0) {
74 console.info('Using default TTS Provider settings');
75 }
76
77 // Only accept keys defined in defaultSettings
78 this.settings = this.defaultSettings;
79
80 for (const key in settings) {
81 if (key in this.settings) {
82 this.settings[key] = settings[key];
83 } else {
84 console.debug(`Ignoring non-user-configurable setting: ${key}`);
85 }
86 }
87
88 // Set initial values from the settings
89 $('#tts_endpoint').val(this.settings.provider_endpoint);
90
91
92 await this.checkReady();
93
94 console.info('ITS: Settings loaded');
95 }
96
97 // Perform a simple readiness check by trying to fetch voiceIds
98 async checkReady() {
99 await Promise.allSettled([this.fetchTtsVoiceObjects(), this.changeTTSSettings()]);
100 }
101
102 async onRefreshClick() {
103 return;
104 }
105
106 //#################//
107 // TTS Interfaces //
108 //#################//
109
110 async getVoice(voiceName) {
111
112
113
114 if (this.voices.length == 0) {
115 this.voices = await this.fetchTtsVoiceObjects();
116 }
117
118
119
120 const match = this.voices.filter(
121 v => v.name == voiceName,
122 )[0];
123 console.log(match);
124 if (!match) {
125 throw `TTS Voice name ${voiceName} not found`;
126 }
127 return match;
128 }
129
130
131
132 async generateTts(text, voiceId) {
133 const response = await this.fetchTtsGeneration(text, voiceId);
134 return response;
135 }
136
137 //###########//
138 // API CALLS //
139 //###########//
140 async fetchTtsVoiceObjects() {
141 const response = await fetch(`${this.settings.provider_endpoint}/speakers`);
142 console.info(response);
143
144 if (!response.ok) {
145 throw new Error(`HTTP ${response.status}: ${await response.json()}`);
146 }
147 const responseJson = await response.json();
148
149
150 this.voices = responseJson;
151
152 return responseJson;
153 }
154
155 // Each time a parameter is changed, we change the configuration
156 async changeTTSSettings() {
157 }
158
159 /**
160 * Fetch TTS generation from the API.
161 * @param {string} inputText Text to generate TTS for
162 * @param {string} voiceId Voice ID to use (model_type&speaker_id))
163 * @returns {Promise<Response|string>} Fetch response
164 */
165 async fetchTtsGeneration(inputText, voiceId, lang = null, forceNoStreaming = false) {
166 console.info(`Generating new TTS for voice_id ${voiceId}`);
167
168 const streaming = this.settings.streaming;
169
170 const params = {
171 text: inputText,
172 speaker: voiceId,
173 };
174
175 if (streaming) {
176 params['streaming'] = 1;
177 }
178
179 const url = `${this.settings.provider_endpoint}/`;
180
181 const response = await fetch(
182 url,
183 {
184 method: 'POST',
185 headers: {
186 'Content-Type': 'application/json',
187 },
188 body: JSON.stringify(params), // 将参数对象转换为 JSON 字符串
189 },
190 );
191 if (!response.ok) {
192 toastr.error(response.statusText, 'TTS Generation Failed');
193 throw new Error(`HTTP ${response.status}: ${await response.text()}`);
194 }
195 return response;
196 }
197
198
199
200 // Interface not used
201 async fetchTtsFromHistory(history_item_id) {
202 return Promise.resolve(history_item_id);
203 }
204}