Artrajz commited on
Commit
584e9b5
·
1 Parent(s): a108ccb

Update and Fix

Browse files

Change the frontend audio playback to use the POST method.
Disable CSRF protection for the voice_api blueprint.
Add an audio download button.
Fix cache clearing.
Resolve the npy loading issue in w2v2.

ModelManager.py CHANGED
@@ -174,7 +174,7 @@ class ModelManager(Subject):
174
 
175
  if model_type == ModelType.W2V2_VITS:
176
  if self.emotion_reference is None:
177
- self.emotion_reference = self.load_npy(config["model_config"]["dimensional_emotion_model"])
178
  model_args.update({"emotion_reference": self.emotion_reference,
179
  "dimensional_emotion_model": self.dimensional_emotion_model})
180
 
 
174
 
175
  if model_type == ModelType.W2V2_VITS:
176
  if self.emotion_reference is None:
177
+ self.emotion_reference = self.load_npy(config["model_config"]["dimensional_emotion_npy"])
178
  model_args.update({"emotion_reference": self.emotion_reference,
179
  "dimensional_emotion_model": self.dimensional_emotion_model})
180
 
TTSManager.py CHANGED
@@ -130,7 +130,7 @@ class TTSManager(Observer):
130
  length = float(element.attrib.get("length", root.attrib.get("length", config.LENGTH)))
131
  noise = float(element.attrib.get("noise", root.attrib.get("noise", config.NOISE)))
132
  noisew = float(element.attrib.get("noisew", root.attrib.get("noisew", config.NOISEW)))
133
- max = int(element.attrib.get("max", root.attrib.get("max", "0")))
134
  # 不填写默认就是vits
135
  model_type = element.attrib.get("model_type", root.attrib.get("model_type", "vits"))
136
  # w2v2-vits/emotion-vits才有emotion
@@ -170,7 +170,7 @@ class TTSManager(Observer):
170
  "length": length,
171
  "noise": noise,
172
  "noisew": noisew,
173
- "max": max,
174
  "model_type": model_type,
175
  "emotion": emotion,
176
  "sdp_ratio": sdp_ratio,
@@ -228,7 +228,7 @@ class TTSManager(Observer):
228
  state["text"] = re.sub(r'\s+', ' ', state["text"]).strip()
229
  sampling_rate = model.sampling_rate
230
 
231
- sentences_list = sentence_split_and_markup(state["text"], state["max"], state["lang"], state["speaker_lang"])
232
  # 停顿0.5s,避免语音分段合成再拼接后的连接突兀
233
  brk = np.zeros(int(0.5 * sampling_rate), dtype=np.int16)
234
 
@@ -265,7 +265,7 @@ class TTSManager(Observer):
265
  state["text"] = re.sub(r'\s+', ' ', state["text"]).strip()
266
  sampling_rate = model.sampling_rate
267
 
268
- sentences_list = sentence_split_and_markup(state["text"], state["max"], state["lang"], state["speaker_lang"])
269
  # 停顿0.5s,避免语音分段合成再拼接后的连接突兀
270
  brk = np.zeros(int(0.5 * sampling_rate), dtype=np.int16)
271
 
@@ -307,7 +307,7 @@ class TTSManager(Observer):
307
 
308
  sampling_rate = model.sampling_rate
309
 
310
- sentences_list = sentence_split_and_markup(state["text"], state["max"], state["lang"], state["speaker_lang"])
311
  # 停顿0.5s,避免语音分段合成再拼接后的连接突兀
312
  brk = np.zeros(int(0.5 * sampling_rate), dtype=np.int16)
313
 
@@ -361,7 +361,7 @@ class TTSManager(Observer):
361
  audios = []
362
 
363
  for (text, lang) in sentences_list:
364
- sentences = sentence_split(text, state["max"])
365
  for sentence in sentences:
366
  audio = model.infer(sentence, state["id"], lang, state["sdp_ratio"], state["noise"],
367
  state["noise"], state["length"])
@@ -384,7 +384,7 @@ class TTSManager(Observer):
384
  # audios = []
385
 
386
  for (text, lang) in sentences_list:
387
- sentences = sentence_split(text, state["max"])
388
  for sentence in sentences:
389
  audio = model.infer(sentence, state["id"], lang, state["sdp_ratio"], state["noise"],
390
  state["noise"], state["length"])
 
130
  length = float(element.attrib.get("length", root.attrib.get("length", config.LENGTH)))
131
  noise = float(element.attrib.get("noise", root.attrib.get("noise", config.NOISE)))
132
  noisew = float(element.attrib.get("noisew", root.attrib.get("noisew", config.NOISEW)))
133
+ segment_size = int(element.attrib.get("segment_size", root.attrib.get("segment_size", "0")))
134
  # 不填写默认就是vits
135
  model_type = element.attrib.get("model_type", root.attrib.get("model_type", "vits"))
136
  # w2v2-vits/emotion-vits才有emotion
 
170
  "length": length,
171
  "noise": noise,
172
  "noisew": noisew,
173
+ "segment_size": segment_size,
174
  "model_type": model_type,
175
  "emotion": emotion,
176
  "sdp_ratio": sdp_ratio,
 
228
  state["text"] = re.sub(r'\s+', ' ', state["text"]).strip()
229
  sampling_rate = model.sampling_rate
230
 
231
+ sentences_list = sentence_split_and_markup(state["text"], state["segment_size"], state["lang"], state["speaker_lang"])
232
  # 停顿0.5s,避免语音分段合成再拼接后的连接突兀
233
  brk = np.zeros(int(0.5 * sampling_rate), dtype=np.int16)
234
 
 
265
  state["text"] = re.sub(r'\s+', ' ', state["text"]).strip()
266
  sampling_rate = model.sampling_rate
267
 
268
+ sentences_list = sentence_split_and_markup(state["text"], state["segment_size"], state["lang"], state["speaker_lang"])
269
  # 停顿0.5s,避免语音分段合成再拼接后的连接突兀
270
  brk = np.zeros(int(0.5 * sampling_rate), dtype=np.int16)
271
 
 
307
 
308
  sampling_rate = model.sampling_rate
309
 
310
+ sentences_list = sentence_split_and_markup(state["text"], state["segment_size"], state["lang"], state["speaker_lang"])
311
  # 停顿0.5s,避免语音分段合成再拼接后的连接突兀
312
  brk = np.zeros(int(0.5 * sampling_rate), dtype=np.int16)
313
 
 
361
  audios = []
362
 
363
  for (text, lang) in sentences_list:
364
+ sentences = sentence_split(text, state["segment_size"])
365
  for sentence in sentences:
366
  audio = model.infer(sentence, state["id"], lang, state["sdp_ratio"], state["noise"],
367
  state["noise"], state["length"])
 
384
  # audios = []
385
 
386
  for (text, lang) in sentences_list:
387
+ sentences = sentence_split(text, state["segment_size"])
388
  for sentence in sentences:
389
  audio = model.infer(sentence, state["id"], lang, state["sdp_ratio"], state["noise"],
390
  state["noise"], state["length"])
app.py CHANGED
@@ -5,6 +5,7 @@ from flask_apscheduler import APScheduler
5
  from flask_login import LoginManager
6
  from flask_wtf import CSRFProtect
7
 
 
8
  from utils.phrases_dict import phrases_dict_init
9
  from tts_app import frontend, voice_api, auth, admin
10
  from utils.config_manager import global_config
@@ -17,13 +18,15 @@ app.config.update(global_config)
17
 
18
  phrases_dict_init()
19
 
 
 
 
 
20
  if app.config.get("IS_ADMIN_ENABLED", False):
21
  login_manager = LoginManager()
22
  login_manager.init_app(app)
23
  login_manager.login_view = 'auth.login'
24
 
25
- csrf = CSRFProtect(app)
26
-
27
 
28
  @login_manager.user_loader
29
  def load_user(user_id):
@@ -44,6 +47,13 @@ app.register_blueprint(voice_api, url_prefix='/voice')
44
  if app.config.get("IS_ADMIN_ENABLED", False):
45
  app.register_blueprint(auth, url_prefix=app.config.get("ADMIN_ROUTE", "/admin"))
46
  app.register_blueprint(admin, url_prefix=app.config.get("ADMIN_ROUTE", "/admin"))
 
 
 
 
 
 
 
47
 
48
  if __name__ == '__main__':
49
  app.run(host='0.0.0.0', port=app.config.get("PORT", 23456), debug=app.config.get("DEBUG", False))
 
5
  from flask_login import LoginManager
6
  from flask_wtf import CSRFProtect
7
 
8
+ from utils.data_utils import clean_folder
9
  from utils.phrases_dict import phrases_dict_init
10
  from tts_app import frontend, voice_api, auth, admin
11
  from utils.config_manager import global_config
 
18
 
19
  phrases_dict_init()
20
 
21
+ csrf = CSRFProtect(app)
22
+ # 禁用tts api请求的CSRF防护
23
+ csrf.exempt(voice_api)
24
+
25
  if app.config.get("IS_ADMIN_ENABLED", False):
26
  login_manager = LoginManager()
27
  login_manager.init_app(app)
28
  login_manager.login_view = 'auth.login'
29
 
 
 
30
 
31
  @login_manager.user_loader
32
  def load_user(user_id):
 
47
  if app.config.get("IS_ADMIN_ENABLED", False):
48
  app.register_blueprint(auth, url_prefix=app.config.get("ADMIN_ROUTE", "/admin"))
49
  app.register_blueprint(admin, url_prefix=app.config.get("ADMIN_ROUTE", "/admin"))
50
+
51
+ # regular cleaning
52
+ @scheduler.task('interval', id='clean_task', seconds=app.config.get("CLEAN_INTERVAL_SECONDS", 3600),
53
+ misfire_grace_time=900)
54
+ def clean_task():
55
+ clean_folder(app.config["UPLOAD_FOLDER"])
56
+ clean_folder(app.config["CACHE_PATH"])
57
 
58
  if __name__ == '__main__':
59
  app.run(host='0.0.0.0', port=app.config.get("PORT", 23456), debug=app.config.get("DEBUG", False))
config.py CHANGED
@@ -109,8 +109,8 @@ NOISE = 0.33
109
  NOISEW = 0.4
110
 
111
  # 长文本分段阈值,max<=0表示不分段.
112
- # Batch processing threshold. Text will not be processed in batches if max<=0
113
- MAX = 50
114
 
115
  # Bert_VITS2
116
  SDP_RATIO = 0.2
 
109
  NOISEW = 0.4
110
 
111
  # 长文本分段阈值,max<=0表示不分段.
112
+ # Batch processing threshold. Text will not be processed in batches if segment<=0
113
+ SEGMENT = 50
114
 
115
  # Bert_VITS2
116
  SDP_RATIO = 0.2
tts_app/static/css/pages/index.css CHANGED
@@ -67,3 +67,8 @@
67
  label {
68
  margin-bottom: 0.5rem;
69
  }
 
 
 
 
 
 
67
  label {
68
  margin-bottom: 0.5rem;
69
  }
70
+
71
+ button {
72
+ margin-left: 10px;
73
+ margin-right: 10px;
74
+ }
tts_app/static/js/index.js ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var baseUrl = getProtocol() + getUrl();
2
+ var currentModelPage = 1;
3
+ var vitsSpeakersCount = 0;
4
+ var w2v2SpeakersCount = 0;
5
+ var bertVits2SpeakersCount = 0;
6
+
7
+ function speakersInit() {
8
+ $.ajax({
9
+ url: '/voice/speakers',
10
+ type: 'GET',
11
+ dataType: 'json',
12
+ success: function (data) {
13
+ vitsSpeakersCount = data['VITS'].length;
14
+ w2v2SpeakersCount = data['W2V2-VITS'].length;
15
+ bertVits2SpeakersCount = data['BERT-VITS2'].length;
16
+ showModelContentBasedOnStatus();
17
+ },
18
+ error: function (xhr, status, error) {
19
+ console.error('Request failed with status', status, 'and error', error);
20
+ }
21
+ });
22
+ }
23
+
24
+ $(function () {
25
+ $('[data-toggle="tooltip"]').tooltip()
26
+ })
27
+
28
+ function getProtocol() {
29
+ return 'https:' == location.protocol ? "https://" : "http://";
30
+ }
31
+
32
+ function getUrl() {
33
+ let url = window.location.host;
34
+ return url;
35
+ }
36
+
37
+
38
+ function setBaseUrl() {
39
+ let text = document.getElementById("input_text" + currentModelPage).value;
40
+ let id = document.getElementById("input_id" + currentModelPage).value;
41
+
42
+ let vits_link = document.getElementById("vits_link");
43
+ let speakers_link = document.getElementById("speakers_link");
44
+
45
+ let vits_url = baseUrl + "/voice/vits?text=" + text + "&id=" + id;
46
+ let speakers_url = baseUrl + "/voice/speakers";
47
+
48
+ vits_link.href = vits_url;
49
+ vits_link.textContent = vits_url;
50
+
51
+ speakers_link.href = speakers_url;
52
+ speakers_link.textContent = speakers_url;
53
+ }
54
+
55
+ function getLink() {
56
+ let text = document.getElementById("input_text" + currentModelPage).value;
57
+ let id = document.getElementById("input_id" + currentModelPage).value;
58
+ let format = document.getElementById("input_format" + currentModelPage).value;
59
+ let lang = document.getElementById("input_lang" + currentModelPage).value;
60
+ let length = document.getElementById("input_length" + currentModelPage).value;
61
+ let noise = document.getElementById("input_noise" + currentModelPage).value;
62
+ let noisew = document.getElementById("input_noisew" + currentModelPage).value;
63
+ let max = document.getElementById("input_max" + currentModelPage).value;
64
+
65
+ let url = baseUrl
66
+ let streaming = null;
67
+ let sdp_ratio = null;
68
+ if (currentModelPage == 1) {
69
+ streaming = document.getElementById('streaming1');
70
+ url += "/voice/vits?text=" + text + "&id=" + id;
71
+ } else if (currentModelPage == 2) {
72
+ let emotion = document.getElementById('emotion').value;
73
+ url += "/voice/w2v2-vits?text=" + text + "&id=" + id + "&emotion=" + emotion;
74
+ } else if (currentModelPage == 3) {
75
+ sdp_ratio = document.getElementById("input_sdp_ratio").value;
76
+ streaming = document.getElementById('streaming3');
77
+ url += "/voice/bert-vits2?text=" + text + "&id=" + id;
78
+
79
+ } else {
80
+ console.error("Invalid model page: ", currentModelPage);
81
+ return null;
82
+ }
83
+ if (format != "") {
84
+ url += "&format=" + format;
85
+ }
86
+ if (lang != "") {
87
+ url += "&lang=" + lang;
88
+ }
89
+ if (length != "") {
90
+ url += "&length=" + length;
91
+ }
92
+ if (noise != "") {
93
+ url += "&noise=" + noise;
94
+ }
95
+ if (noisew != "") {
96
+ url += "&noisew=" + noisew;
97
+ }
98
+ if (max != "") {
99
+ url += "&max=" + max;
100
+ }
101
+
102
+ if (currentModelPage == 1) {
103
+ if (streaming.checked)
104
+ url += '&streaming=true';
105
+ } else if (currentModelPage == 3) {
106
+ if (streaming.checked)
107
+ url += '&streaming=true';
108
+ if (sdp_ratio != "")
109
+ url += "&sdp_ratio=" + sdp_ratio;
110
+ }
111
+
112
+ return url;
113
+ }
114
+
115
+ function updateLink() {
116
+ let url = getLink();
117
+ let link = document.getElementById("vits_link");
118
+ link.href = url;
119
+ link.textContent = url;
120
+ }
121
+
122
+ function setAudioSourceByGet() {
123
+ if (currentModelPage == 1 && vitsSpeakersCount <= 0) {
124
+ alert("未加载VITS模型");
125
+ return;
126
+ }
127
+ if (currentModelPage == 2 && w2v2SpeakersCount <= 0) {
128
+ alert("未加载W2V2-VITS模型");
129
+ return;
130
+ }
131
+ if (currentModelPage == 3 && bertVits2SpeakersCount <= 0) {
132
+ alert("未加载Bert-VITS2模型");
133
+ return;
134
+ }
135
+ let url = getLink();
136
+
137
+ // Add a timestamp parameter to prevent browser caching
138
+ let timestamp = new Date().getTime();
139
+ url += '&t=' + timestamp;
140
+
141
+ let audioPlayer = document.getElementById("audioPlayer" + currentModelPage);
142
+ audioPlayer.src = url;
143
+ audioPlayer.play();
144
+ }
145
+
146
+ function setAudioSourceByPost() {
147
+ if (currentModelPage == 1 && vitsSpeakersCount <= 0) {
148
+ alert("未加载VITS模型");
149
+ return;
150
+ }
151
+ if (currentModelPage == 2 && w2v2SpeakersCount <= 0) {
152
+ alert("未加载W2V2-VITS模型");
153
+ return;
154
+ }
155
+ if (currentModelPage == 3 && bertVits2SpeakersCount <= 0) {
156
+ alert("未加载Bert-VITS2模型");
157
+ return;
158
+ }
159
+ let text = $("#input_text" + currentModelPage).val();
160
+ let id = $("#input_id" + currentModelPage).val();
161
+ let format = $("#input_format" + currentModelPage).val();
162
+ let lang = $("#input_lang" + currentModelPage).val();
163
+ let length = $("#input_length" + currentModelPage).val();
164
+ let noise = $("#input_noise" + currentModelPage).val();
165
+ let noisew = $("#input_noisew" + currentModelPage).val();
166
+ let max = $("#input_max" + currentModelPage).val();
167
+
168
+ let url = "";
169
+ let streaming = null;
170
+ let sdp_ratio = null;
171
+
172
+ if (currentModelPage == 1) {
173
+ url = baseUrl + "/voice/vits";
174
+ streaming = $("#streaming1")[0];
175
+ } else if (currentModelPage == 2) {
176
+ let emotion = $("#emotion").val();
177
+ url = baseUrl + "/voice/w2v2-vits";
178
+ } else if (currentModelPage == 3) {
179
+ sdp_ratio = $("#input_sdp_ratio").val();
180
+ url = baseUrl + "/voice/bert-vits2";
181
+ streaming = $("#streaming3")[0];
182
+ }
183
+
184
+ let data = {
185
+ text: text,
186
+ id: id,
187
+ format: format,
188
+ lang: lang,
189
+ length: length,
190
+ noise: noise,
191
+ noisew: noisew,
192
+ max: max
193
+ };
194
+
195
+ if ((currentModelPage == 1 || currentModelPage == 3) && streaming.checked) {
196
+ data.streaming = true;
197
+ }
198
+ if (currentModelPage == 3 && sdp_ratio != "") {
199
+
200
+ data.sdp_ratio = sdp_ratio;
201
+ }
202
+
203
+ $.ajax({
204
+ url: url,
205
+ method: 'POST',
206
+ data: JSON.stringify(data),
207
+ contentType: 'application/json',
208
+ responseType: 'blob',
209
+ xhrFields: {
210
+ responseType: 'blob'
211
+ },
212
+ success: function (response, status, xhr) {
213
+
214
+ let blob = new Blob([response], {type: 'audio/wav'});
215
+ let audioPlayer = document.getElementById("audioPlayer" + currentModelPage);
216
+ let audioFileName = getFileNameFromResponseHeader(xhr);
217
+ audioPlayer.setAttribute('data-file-name', audioFileName);
218
+ audioPlayer.src = URL.createObjectURL(blob);
219
+ audioPlayer.load();
220
+ audioPlayer.play();
221
+ },
222
+ error: function (error) {
223
+ console.error('Error:', error);
224
+ alert("无法获取音频数据");
225
+ }
226
+ });
227
+
228
+ }
229
+
230
+ function getFileNameFromResponseHeader(xhr) {
231
+ var contentDispositionHeader = xhr.getResponseHeader('Content-Disposition');
232
+ var matches = contentDispositionHeader.match(/filename=(.+)$/);
233
+ return matches ? matches[1] : 'audio.wav'; // 如果无法从响应头获取文件名,则使用默认值
234
+ }
235
+
236
+ function downloadAudio() {
237
+ let audioPlayer = document.getElementById("audioPlayer" + currentModelPage);
238
+ let audioFileName = audioPlayer.getAttribute('data-file-name') || 'audio.wav';
239
+
240
+ let downloadLink = document.createElement('a');
241
+ downloadLink.href = audioPlayer.src;
242
+
243
+ downloadLink.download = audioFileName;
244
+
245
+ document.body.appendChild(downloadLink);
246
+ downloadLink.click();
247
+ document.body.removeChild(downloadLink);
248
+ }
249
+
250
+
251
+ function showContent(index) {
252
+ const panes = document.querySelectorAll(".content-pane");
253
+ const buttons = document.querySelectorAll(".tab-button");
254
+ currentModelPage = index + 1;
255
+
256
+ for (let i = 0; i < panes.length; i++) {
257
+ if (i === index) {
258
+ panes[i].classList.add("active");
259
+ buttons[i].classList.add("active");
260
+
261
+ } else {
262
+ panes[i].classList.remove("active");
263
+ buttons[i].classList.remove("active");
264
+ }
265
+ }
266
+ updateLink();
267
+ }
268
+
269
+ function showModelContentBasedOnStatus() {
270
+ if (vitsSpeakersCount > 0) {
271
+ showContent(0);
272
+ } else if (w2v2SpeakersCount > 0) {
273
+ showContent(1);
274
+ } else if (bertVits2SpeakersCount > 0) {
275
+ showContent(2);
276
+ } else {
277
+ showContent(0);
278
+ }
279
+ }
280
+
281
+ $(document).ready(function () {
282
+ speakersInit();
283
+
284
+ setBaseUrl();
285
+ });
tts_app/templates/pages/index.html CHANGED
@@ -98,7 +98,9 @@
98
 
99
  <div class="flex flex-wrap w-100"
100
  style="justify-content: center; align-items: center; height: 80px; margin-top: 20px; margin-bottom: 20px; border: 1px solid rgba(0,0,0,.125); border-radius: 0.25rem;">
101
- <button type="button" class="btn btn-outline-secondary" onclick="setAudioSource()"
 
 
102
  style="margin-right: 10px">
103
  播放器生成
104
  </button>
@@ -106,6 +108,10 @@
106
  <source src="" type="audio/mp3"/>
107
  Your browser does not support the audio element.
108
  </audio>
 
 
 
 
109
  <div class="mb-3 form-check">
110
  <input type="checkbox" id="streaming1" onchange="updateLink()">
111
  <label class="form-check-label" data-toggle="tooltip" data-placement="top"
@@ -196,14 +202,19 @@
196
 
197
  <div class="flex flex-wrap w-100"
198
  style="justify-content: center; align-items: center; height: 80px; margin-top: 20px; margin-bottom: 20px; border: 1px solid rgba(0,0,0,.125); border-radius: 0.25rem;">
199
- <button type="button" class="btn btn-outline-secondary" onclick="setAudioSource()"
200
- style="margin-right: 10px">
201
- 播放器生成
202
- </button>
203
  <audio id="audioPlayer2" controls>
204
  <source src="" type="audio/mp3"/>
205
  Your browser does not support the audio element.
206
  </audio>
 
 
 
 
 
 
 
 
207
  </div>
208
  </div>
209
  <div class="content-pane w-100 flex-wrap" id="bert-vits2-page">
@@ -288,7 +299,7 @@
288
 
289
  <div class="flex flex-wrap w-100"
290
  style="justify-content: center; align-items: center; height: 80px; margin-top: 20px; margin-bottom: 20px; border: 1px solid rgba(0,0,0,.125); border-radius: 0.25rem;">
291
- <button type="button" class="btn btn-outline-secondary" onclick="setAudioSource()"
292
  style="margin-right: 10px">
293
  播放器生成
294
  </button>
@@ -296,6 +307,10 @@
296
  <source src="" type="audio/mp3"/>
297
  Your browser does not support the audio element.
298
  </audio>
 
 
 
 
299
  <div class="mb-3 form-check">
300
  <input type="checkbox" id="streaming3" onchange="updateLink()">
301
  <label class="form-check-label" data-toggle="tooltip" data-placement="top"
@@ -331,185 +346,6 @@
331
 
332
  {% include 'includes/scripts.html' %}
333
 
334
- <script>
335
- $(function () {
336
- $('[data-toggle="tooltip"]').tooltip()
337
- })
338
-
339
- function getProtocol() {
340
- return 'https:' == location.protocol ? "https://" : "http://";
341
- }
342
-
343
- function getUrl() {
344
- var url = window.location.host;
345
- return url;
346
- }
347
-
348
- var baseUrl = getProtocol() + getUrl();
349
- var model_type = 1;
350
- var vits_status = false;
351
- var w2v2_status = false;
352
- var bert_vits2_status = false;
353
- {% if vits_speakers_count > 0 %}
354
- vits_status = true;
355
- {% endif %}
356
- {% if w2v2_speakers_count > 0 %}
357
- w2v2_status = true;
358
- {% endif %}
359
- {% if bert_vits2_speakers_count > 0 %}
360
- bert_vits2_status = true;
361
- {% endif %}
362
-
363
- $(document).ready(function () {
364
- if (vits_status) {
365
- $('#vits-button').addClass("active");
366
- $('#vits-page').addClass("active");
367
- model_type = 1;
368
- } else if (w2v2_status) {
369
- $('#w2v2-vits-button').addClass("active");
370
- $('#w2v2-vits-page').addClass("active");
371
- model_type = 2;
372
- } else if (bert_vits2_status) {
373
- $('#bert-vits2-button').addClass("active");
374
- $('#bert-vits2-page').addClass("active");
375
- model_type = 3;
376
- } else {
377
- $('#vits-button').addClass("active");
378
- $('#vits-page').addClass("active");
379
- model_type = 1;
380
- }
381
- setBaseUrl();
382
- });
383
-
384
-
385
- function setBaseUrl() {
386
- var text = document.getElementById("input_text" + model_type).value;
387
- var id = document.getElementById("input_id" + model_type).value;
388
-
389
- var vits_link = document.getElementById("vits_link");
390
- var speakers_link = document.getElementById("speakers_link");
391
-
392
- var vits_url = baseUrl + "/voice/vits?text=" + text + "&id=" + id;
393
- var speakers_url = baseUrl + "/voice/speakers";
394
-
395
- vits_link.href = vits_url;
396
- vits_link.textContent = vits_url;
397
-
398
- speakers_link.href = speakers_url;
399
- speakers_link.textContent = speakers_url;
400
- }
401
-
402
- function getLink() {
403
- var text = document.getElementById("input_text" + model_type).value;
404
- var id = document.getElementById("input_id" + model_type).value;
405
- var format = document.getElementById("input_format" + model_type).value;
406
- var lang = document.getElementById("input_lang" + model_type).value;
407
- var length = document.getElementById("input_length" + model_type).value;
408
- var noise = document.getElementById("input_noise" + model_type).value;
409
- var noisew = document.getElementById("input_noisew" + model_type).value;
410
- var max = document.getElementById("input_max" + model_type).value;
411
-
412
- if (model_type == 1) {
413
- var url = baseUrl + "/voice/vits?text=" + text + "&id=" + id;
414
- var streaming = document.getElementById('streaming' + model_type);
415
- } else if (model_type == 2) {
416
- var emotion = document.getElementById('emotion').value;
417
- var url = baseUrl + "/voice/w2v2-vits?text=" + text + "&id=" + id + "&emotion=" + emotion;
418
- } else if (model_type == 3) {
419
- var sdp_ratio = document.getElementById("input_sdp_ratio").value;
420
- var url = baseUrl + "/voice/bert-vits2?text=" + text + "&id=" + id;
421
- var streaming = document.getElementById('streaming3');
422
- }
423
- if (format != "") {
424
- url += "&format=" + format;
425
- }
426
- if (lang != "") {
427
- url += "&lang=" + lang;
428
- }
429
- if (length != "") {
430
- url += "&length=" + length;
431
- }
432
- if (noise != "") {
433
- url += "&noise=" + noise;
434
- }
435
- if (noisew != "") {
436
- url += "&noisew=" + noisew;
437
- }
438
- if (max != "") {
439
- url += "&max=" + max;
440
- }
441
- if ((model_type == 1 || model_type == 3) && streaming.checked) {
442
- url += '&streaming=true';
443
- }
444
- if (model_type == 3 && sdp_ratio != "") {
445
- url += "&sdp_ratio=" + sdp_ratio;
446
- }
447
-
448
- return url;
449
- }
450
-
451
- function updateLink() {
452
- var url = getLink();
453
- var link = document.getElementById("vits_link");
454
- link.href = url;
455
- link.textContent = url;
456
- }
457
-
458
- function setAudioSource() {
459
- if (model_type == 1 && !vits_status) {
460
- alert("未加载VITS模型");
461
- return;
462
- }
463
- if (model_type == 2 && !w2v2_status) {
464
- alert("未加载W2V2-VITS模型");
465
- return;
466
- }
467
- if (model_type == 3 && !bert_vits2_status) {
468
- alert("未加载Bert-VITS2模型");
469
- return;
470
- }
471
- var url = getLink();
472
-
473
- // Add a timestamp parameter to prevent browser caching
474
- var timestamp = new Date().getTime();
475
- url += '&t=' + timestamp;
476
-
477
- var audioPlayer = document.getElementById("audioPlayer" + model_type);
478
- audioPlayer.src = url;
479
- audioPlayer.play();
480
- }
481
-
482
- function showContent(index) {
483
- const panes = document.querySelectorAll(".content-pane");
484
- const buttons = document.querySelectorAll(".tab-button");
485
- model_type = index + 1;
486
-
487
- for (let i = 0; i < panes.length; i++) {
488
- if (i === index) {
489
- panes[i].classList.add("active");
490
- buttons[i].classList.add("active");
491
-
492
- } else {
493
- panes[i].classList.remove("active");
494
- buttons[i].classList.remove("active");
495
- }
496
- }
497
- updateLink();
498
- }
499
-
500
- document.querySelectorAll('.slider-group').forEach(function (group) {
501
- group.addEventListener("input", function (event) {
502
- if (event.target.matches('.slider')) {
503
- let value = event.target.value;
504
- group.querySelector('.slider-input').value = value;
505
- group.querySelector('.slider-value').textContent = value;
506
- } else if (event.target.matches('.slider-input')) {
507
- let value = event.target.value;
508
- group.querySelector('.slider').value = value;
509
- group.querySelector('.slider-value').textContent = value;
510
- }
511
- });
512
- });
513
- </script>
514
  </body>
515
  </html>
 
98
 
99
  <div class="flex flex-wrap w-100"
100
  style="justify-content: center; align-items: center; height: 80px; margin-top: 20px; margin-bottom: 20px; border: 1px solid rgba(0,0,0,.125); border-radius: 0.25rem;">
101
+
102
+
103
+ <button type="button" class="btn btn-outline-secondary" onclick="setAudioSourceByPost()"
104
  style="margin-right: 10px">
105
  播放器生成
106
  </button>
 
108
  <source src="" type="audio/mp3"/>
109
  Your browser does not support the audio element.
110
  </audio>
111
+ <button type="button" class="btn btn-outline-secondary" onclick="downloadAudio()"
112
+ style="margin-right: 10px">
113
+ 下载音频
114
+ </button>
115
  <div class="mb-3 form-check">
116
  <input type="checkbox" id="streaming1" onchange="updateLink()">
117
  <label class="form-check-label" data-toggle="tooltip" data-placement="top"
 
202
 
203
  <div class="flex flex-wrap w-100"
204
  style="justify-content: center; align-items: center; height: 80px; margin-top: 20px; margin-bottom: 20px; border: 1px solid rgba(0,0,0,.125); border-radius: 0.25rem;">
205
+
 
 
 
206
  <audio id="audioPlayer2" controls>
207
  <source src="" type="audio/mp3"/>
208
  Your browser does not support the audio element.
209
  </audio>
210
+ <button type="button" class="btn btn-outline-secondary" onclick="setAudioSourceByPost()"
211
+ style="margin-right: 10px">
212
+ 播放器生成
213
+ </button>
214
+ <button type="button" class="btn btn-outline-secondary" onclick="downloadAudio()"
215
+ style="margin-right: 10px">
216
+ 下载音频
217
+ </button>
218
  </div>
219
  </div>
220
  <div class="content-pane w-100 flex-wrap" id="bert-vits2-page">
 
299
 
300
  <div class="flex flex-wrap w-100"
301
  style="justify-content: center; align-items: center; height: 80px; margin-top: 20px; margin-bottom: 20px; border: 1px solid rgba(0,0,0,.125); border-radius: 0.25rem;">
302
+ <button type="button" class="btn btn-outline-secondary" onclick="setAudioSourceByPost()"
303
  style="margin-right: 10px">
304
  播放器生成
305
  </button>
 
307
  <source src="" type="audio/mp3"/>
308
  Your browser does not support the audio element.
309
  </audio>
310
+ <button type="button" class="btn btn-outline-secondary" onclick="downloadAudio()"
311
+ style="margin-right: 10px">
312
+ 下载音频
313
+ </button>
314
  <div class="mb-3 form-check">
315
  <input type="checkbox" id="streaming3" onchange="updateLink()">
316
  <label class="form-check-label" data-toggle="tooltip" data-placement="top"
 
346
 
347
  {% include 'includes/scripts.html' %}
348
 
349
+ <script src="{{ url_for('static', filename='js/index.js') }}"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  </body>
351
  </html>
tts_app/voice_api/utils/__init__.py CHANGED
@@ -1,14 +1,3 @@
1
- import os
2
-
3
-
4
- def clean_folder(folder_path):
5
- for filename in os.listdir(folder_path):
6
- file_path = os.path.join(folder_path, filename)
7
- # 如果是文件,则删除文件。如果是文件夹则跳过。
8
- if os.path.isfile(file_path):
9
- os.remove(file_path)
10
-
11
-
12
  def check_is_none(item) -> bool:
13
  # none -> True, not none -> False
14
  return item is None or (isinstance(item, str) and str(item).isspace()) or str(item) == ""
@@ -16,4 +5,4 @@ def check_is_none(item) -> bool:
16
 
17
  def save_audio(audio, path):
18
  with open(path, "wb") as f:
19
- f.write(audio)
 
 
 
 
 
 
 
 
 
 
 
 
1
  def check_is_none(item) -> bool:
2
  # none -> True, not none -> False
3
  return item is None or (isinstance(item, str) and str(item).isspace()) or str(item) == ""
 
5
 
6
  def save_audio(audio, path):
7
  with open(path, "wb") as f:
8
+ f.write(audio)
tts_app/voice_api/views.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import time
2
  import uuid
3
  from io import BytesIO
@@ -15,6 +16,26 @@ from utils.data_utils import check_is_none
15
  voice_api = Blueprint("voice_api", __name__)
16
 
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  @voice_api.route('/speakers', methods=["GET", "POST"])
19
  def voice_speakers_api():
20
  return jsonify(model_manager.voice_speakers)
@@ -34,15 +55,15 @@ def voice_vits_api():
34
  else:
35
  request_data = request.form
36
 
37
- text = request_data.get("text", "")
38
- id = int(request_data.get("id", current_app.config.get("ID", 0)))
39
- format = request_data.get("format", current_app.config.get("FORMAT", "wav"))
40
- lang = request_data.get("lang", current_app.config.get("LANG", "auto")).lower()
41
- length = float(request_data.get("length", current_app.config.get("LENGTH", 1)))
42
- noise = float(request_data.get("noise", current_app.config.get("NOISE", 0.667)))
43
- noisew = float(request_data.get("noisew", current_app.config.get("NOISEW", 0.8)))
44
- max = int(request_data.get("max", current_app.config.get("MAX", 50)))
45
- use_streaming = request_data.get('streaming', False, type=bool)
46
  except Exception as e:
47
  logger.error(f"[{ModelType.VITS.value}] {e}")
48
  return make_response("parameter error", 400)
@@ -86,7 +107,7 @@ def voice_vits_api():
86
  "length": length,
87
  "noise": noise,
88
  "noisew": noisew,
89
- "max": max,
90
  "lang": lang,
91
  "speaker_lang": speaker_lang}
92
 
@@ -116,12 +137,12 @@ def voice_hubert_api():
116
  if request.method == "POST":
117
  try:
118
  voice = request.files['upload']
119
- id = int(request.form.get("id"))
120
- format = request.form.get("format", current_app.config.get("LANG", "auto"))
121
- length = float(request.form.get("length", current_app.config.get("LENGTH", 1)))
122
- noise = float(request.form.get("noise", current_app.config.get("NOISE", 0.667)))
123
- noisew = float(request.form.get("noisew", current_app.config.get("NOISEW", 0.8)))
124
- use_streaming = request.form.get('streaming', False, type=bool)
125
  except Exception as e:
126
  logger.error(f"[{ModelType.HUBERT_VITS.value}] {e}")
127
  return make_response("parameter error", 400)
@@ -181,17 +202,17 @@ def voice_w2v2_api():
181
  else:
182
  request_data = request.form
183
 
184
- text = request_data.get("text", "")
185
- id = int(request_data.get("id", current_app.config.get("ID", 0)))
186
- format = request_data.get("format", current_app.config.get("FORMAT", "wav"))
187
- lang = request_data.get("lang", current_app.config.get("LANG", "auto")).lower()
188
- length = float(request_data.get("length", current_app.config.get("LENGTH", 1)))
189
- noise = float(request_data.get("noise", current_app.config.get("NOISE", 0.667)))
190
- noisew = float(request_data.get("noisew", current_app.config.get("NOISEW", 0.8)))
191
- max = int(request_data.get("max", current_app.config.get("MAX", 50)))
192
- emotion = int(request_data.get("emotion", current_app.config.get("EMOTION", 0)))
193
- emotion_reference = request_data.get("emotion_reference", None)
194
- use_streaming = request_data.get('streaming', False, type=bool)
195
  except Exception as e:
196
  logger.error(f"[{ModelType.W2V2_VITS.value}] {e}")
197
  return make_response(f"parameter error", 400)
@@ -235,7 +256,7 @@ def voice_w2v2_api():
235
  "length": length,
236
  "noise": noise,
237
  "noisew": noisew,
238
- "max": max,
239
  "lang": lang,
240
  "emotion": emotion,
241
  "emotion_reference": emotion_reference,
@@ -268,10 +289,10 @@ def vits_voice_conversion_api():
268
  if request.method == "POST":
269
  try:
270
  voice = request.files['upload']
271
- original_id = int(request.form["original_id"])
272
- target_id = int(request.form["target_id"])
273
- format = request.form.get("format", voice.filename.split(".")[1])
274
- use_streaming = request.form.get('streaming', False, type=bool)
275
  except Exception as e:
276
  logger.error(f"[vits_voice_convertsion] {e}")
277
  return make_response("parameter error", 400)
@@ -345,7 +366,6 @@ def dimensional_emotion_api():
345
  if request.method == "POST":
346
  try:
347
  audio = request.files['upload']
348
- use_streaming = request.form.get('streaming', False, type=bool)
349
  except Exception as e:
350
  logger.error(f"[dimensional_emotion] {e}")
351
  return make_response("parameter error", 400)
@@ -355,14 +375,7 @@ def dimensional_emotion_api():
355
  file_type = "application/octet-stream; charset=ascii"
356
  fname = os.path.splitext(audio.filename)[0] + ".npy"
357
  emotion_npy = tts_manager.get_dimensional_emotion_npy(content)
358
- if use_streaming:
359
- emotion_npy = tts_manager.generate_audio_chunks(emotion_npy)
360
- response = make_response(emotion_npy)
361
- response.headers['Content-Disposition'] = f'attachment; filename={fname}'
362
- response.headers['Content-Type'] = file_type
363
- return response
364
- else:
365
- return send_file(path_or_file=emotion_npy, mimetype=file_type, download_name=fname)
366
 
367
 
368
  @voice_api.route('/bert-vits2', methods=["GET", "POST"])
@@ -378,16 +391,16 @@ def voice_bert_vits2_api():
378
  else:
379
  request_data = request.form
380
 
381
- text = request_data.get("text", "")
382
- id = int(request_data.get("id", current_app.config.get("ID", 0)))
383
- format = request_data.get("format", current_app.config.get("FORMAT", "wav"))
384
- lang = request_data.get("lang", "auto").lower()
385
- length = float(request_data.get("length", current_app.config.get("LENGTH", 1)))
386
- noise = float(request_data.get("noise", current_app.config.get("NOISE", 0.667)))
387
- noisew = float(request_data.get("noisew", current_app.config.get("NOISEW", 0.8)))
388
- sdp_ratio = float(request_data.get("sdp_ratio", current_app.config.get("SDP_RATIO", 0.2)))
389
- max = int(request_data.get("max", current_app.config.get("MAX", 50)))
390
- use_streaming = request_data.get('streaming', False, type=bool)
391
  except Exception as e:
392
  logger.error(f"[{ModelType.BERT_VITS2.value}] {e}")
393
  return make_response("parameter error", 400)
@@ -426,16 +439,16 @@ def voice_bert_vits2_api():
426
  fname = f"{str(uuid.uuid1())}.{format}"
427
  file_type = f"audio/{format}"
428
  state = {"text": text,
429
- "id": id,
430
- "format": format,
431
- "length": length,
432
- "noise": noise,
433
- "noisew": noisew,
434
- "sdp_ratio": sdp_ratio,
435
- "max": max,
436
- "lang": lang,
437
- "speaker_lang": speaker_lang}
438
-
439
  if use_streaming:
440
  audio = tts_manager.stream_bert_vits2_infer(state)
441
  response = make_response(audio)
@@ -448,8 +461,6 @@ def voice_bert_vits2_api():
448
  t2 = time.time()
449
  logger.info(f"[{ModelType.BERT_VITS2.value}] finish in {(t2 - t1):.2f}s")
450
 
451
-
452
-
453
  if current_app.config.get("SAVE_AUDIO", False):
454
  logger.debug(f"[{ModelType.BERT_VITS2.value}] {fname}")
455
  path = os.path.join(current_app.config.get('CACHE_PATH'), fname)
@@ -505,10 +516,3 @@ def check():
505
  logger.info(f"[check] check id:{id} name:{name} lang:{lang}")
506
 
507
  return make_response(jsonify({"status": "success", "id": id, "name": name, "lang": lang}), 200)
508
-
509
- # regular cleaning
510
- @scheduler.task('interval', id='clean_task', seconds=current_app.config.get("CLEAN_INTERVAL_SECONDS", 3600),
511
- misfire_grace_time=900)
512
- def clean_task():
513
- clean_folder(current_app.config["UPLOAD_FOLDER"])
514
- clean_folder(current_app.config["CACHE_PATH"])
 
1
+ import os
2
  import time
3
  import uuid
4
  from io import BytesIO
 
16
  voice_api = Blueprint("voice_api", __name__)
17
 
18
 
19
+ def get_param(request_data, key, default, data_type=None):
20
+ if key == "segment_size" and "max" in request_data:
21
+ logger.warning(
22
+ "The 'max' parameter is deprecated and will be phased out in the future. Please use 'segment_size' instead.")
23
+ return get_param(request_data, "max", default, data_type)
24
+
25
+ value = request_data.get(key, "")
26
+
27
+ if data_type:
28
+ try:
29
+ value = data_type(value)
30
+ except:
31
+ value = default
32
+
33
+ if value == "":
34
+ value = default
35
+
36
+ return value
37
+
38
+
39
  @voice_api.route('/speakers', methods=["GET", "POST"])
40
  def voice_speakers_api():
41
  return jsonify(model_manager.voice_speakers)
 
55
  else:
56
  request_data = request.form
57
 
58
+ text = get_param(request_data, "text", "", str)
59
+ id = get_param(request_data, "id", current_app.config.get("ID", 0), int)
60
+ format = get_param(request_data, "format", current_app.config.get("FORMAT", "wav"), str)
61
+ lang = get_param(request_data, "lang", current_app.config.get("LANG", "auto"), str).lower()
62
+ length = get_param(request_data, "length", current_app.config.get("LENGTH", 1), float)
63
+ noise = get_param(request_data, "noise", current_app.config.get("NOISE", 0.667), float)
64
+ noisew = get_param(request_data, "noisew", current_app.config.get("NOISEW", 0.8), float)
65
+ segment_size = get_param(request_data, "segment_size", current_app.config.get("SEGMENT_SIZE", 50), int)
66
+ use_streaming = get_param(request_data, 'streaming', False, bool)
67
  except Exception as e:
68
  logger.error(f"[{ModelType.VITS.value}] {e}")
69
  return make_response("parameter error", 400)
 
107
  "length": length,
108
  "noise": noise,
109
  "noisew": noisew,
110
+ "segment_size": segment_size,
111
  "lang": lang,
112
  "speaker_lang": speaker_lang}
113
 
 
137
  if request.method == "POST":
138
  try:
139
  voice = request.files['upload']
140
+ id = get_param(request.form, "id", 0, int)
141
+ format = get_param(request.form, "format", current_app.config.get("LANG", "auto"))
142
+ length = get_param(request.form, "length", current_app.config.get("LENGTH", 1), float)
143
+ noise = get_param(request.form, "noise", current_app.config.get("NOISE", 0.667), float)
144
+ noisew = get_param(request.form, "noisew", current_app.config.get("NOISEW", 0.8), float)
145
+ use_streaming = get_param(request.form, 'streaming', False, bool)
146
  except Exception as e:
147
  logger.error(f"[{ModelType.HUBERT_VITS.value}] {e}")
148
  return make_response("parameter error", 400)
 
202
  else:
203
  request_data = request.form
204
 
205
+ text = get_param(request_data, "text", "", str)
206
+ id = get_param(request_data, "id", current_app.config.get("ID", 0), int)
207
+ format = get_param(request_data, "format", current_app.config.get("FORMAT", "wav"), str)
208
+ lang = get_param(request_data, "lang", current_app.config.get("LANG", "auto"), str).lower()
209
+ length = get_param(request_data, "length", current_app.config.get("LENGTH", 1), float)
210
+ noise = get_param(request_data, "noise", current_app.config.get("NOISE", 0.667), float)
211
+ noisew = get_param(request_data, "noisew", current_app.config.get("NOISEW", 0.8), float)
212
+ segment_size = get_param(request_data, "segment_size", current_app.config.get("SEGMENT_SIZE", 50), int)
213
+ emotion = get_param(request_data, "emotion", current_app.config.get("EMOTION", 0), int)
214
+ emotion_reference = get_param(request_data, "emotion_reference", None, str)
215
+ use_streaming = get_param(request_data, 'streaming', False, bool)
216
  except Exception as e:
217
  logger.error(f"[{ModelType.W2V2_VITS.value}] {e}")
218
  return make_response(f"parameter error", 400)
 
256
  "length": length,
257
  "noise": noise,
258
  "noisew": noisew,
259
+ "segment_size": segment_size,
260
  "lang": lang,
261
  "emotion": emotion,
262
  "emotion_reference": emotion_reference,
 
289
  if request.method == "POST":
290
  try:
291
  voice = request.files['upload']
292
+ original_id = get_param(request.form, "original_id", 0, int)
293
+ target_id = get_param(request.form, "target_id", 0, int)
294
+ format = get_param(request.form, "format", voice.filename.split(".")[1], str)
295
+ use_streaming = get_param(request.form, 'streaming', False, bool)
296
  except Exception as e:
297
  logger.error(f"[vits_voice_convertsion] {e}")
298
  return make_response("parameter error", 400)
 
366
  if request.method == "POST":
367
  try:
368
  audio = request.files['upload']
 
369
  except Exception as e:
370
  logger.error(f"[dimensional_emotion] {e}")
371
  return make_response("parameter error", 400)
 
375
  file_type = "application/octet-stream; charset=ascii"
376
  fname = os.path.splitext(audio.filename)[0] + ".npy"
377
  emotion_npy = tts_manager.get_dimensional_emotion_npy(content)
378
+ return send_file(path_or_file=emotion_npy, mimetype=file_type, download_name=fname)
 
 
 
 
 
 
 
379
 
380
 
381
  @voice_api.route('/bert-vits2', methods=["GET", "POST"])
 
391
  else:
392
  request_data = request.form
393
 
394
+ text = get_param(request_data, "text", "", str)
395
+ id = get_param(request_data, "id", current_app.config.get("ID", 0), int)
396
+ format = get_param(request_data, "format", current_app.config.get("FORMAT", "wav"), str)
397
+ lang = get_param(request_data, "lang", current_app.config.get("LANG", "auto"), str).lower()
398
+ length = get_param(request_data, "length", current_app.config.get("LENGTH", 1), float)
399
+ noise = get_param(request_data, "noise", current_app.config.get("NOISE", 0.667), float)
400
+ noisew = get_param(request_data, "noisew", current_app.config.get("NOISEW", 0.8), float)
401
+ sdp_ratio = get_param(request_data, "sdp_ratio", current_app.config.get("SDP_RATIO", 0.2), float)
402
+ segment_size = get_param(request_data, "segment_size", current_app.config.get("SEGMENT_SIZE", 50), int)
403
+ use_streaming = get_param(request_data, 'streaming', False, bool)
404
  except Exception as e:
405
  logger.error(f"[{ModelType.BERT_VITS2.value}] {e}")
406
  return make_response("parameter error", 400)
 
439
  fname = f"{str(uuid.uuid1())}.{format}"
440
  file_type = f"audio/{format}"
441
  state = {"text": text,
442
+ "id": id,
443
+ "format": format,
444
+ "length": length,
445
+ "noise": noise,
446
+ "noisew": noisew,
447
+ "sdp_ratio": sdp_ratio,
448
+ "segment_size": segment_size,
449
+ "lang": lang,
450
+ "speaker_lang": speaker_lang}
451
+
452
  if use_streaming:
453
  audio = tts_manager.stream_bert_vits2_infer(state)
454
  response = make_response(audio)
 
461
  t2 = time.time()
462
  logger.info(f"[{ModelType.BERT_VITS2.value}] finish in {(t2 - t1):.2f}s")
463
 
 
 
464
  if current_app.config.get("SAVE_AUDIO", False):
465
  logger.debug(f"[{ModelType.BERT_VITS2.value}] {fname}")
466
  path = os.path.join(current_app.config.get('CACHE_PATH'), fname)
 
516
  logger.info(f"[check] check id:{id} name:{name} lang:{lang}")
517
 
518
  return make_response(jsonify({"status": "success", "id": id, "name": name, "lang": lang}), 200)
 
 
 
 
 
 
 
utils/data_utils.py CHANGED
@@ -82,3 +82,11 @@ def load_audio_to_torch(full_path, target_sampling_rate):
82
  def check_is_none(item) -> bool:
83
  # none -> True, not none -> False
84
  return item is None or (isinstance(item, str) and str(item).isspace()) or str(item) == ""
 
 
 
 
 
 
 
 
 
82
  def check_is_none(item) -> bool:
83
  # none -> True, not none -> False
84
  return item is None or (isinstance(item, str) and str(item).isspace()) or str(item) == ""
85
+
86
+
87
+ def clean_folder(folder_path):
88
+ for filename in os.listdir(folder_path):
89
+ file_path = os.path.join(folder_path, filename)
90
+ # 如果是文件,则删除文件。如果是文件夹则跳过。
91
+ if os.path.isfile(file_path):
92
+ os.remove(file_path)