Uniaff commited on
Commit
6617422
·
verified ·
1 Parent(s): 7432451

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -153
app.py CHANGED
@@ -10,8 +10,6 @@ import numpy as np
10
  import torch
11
  import torchaudio
12
  from resemble_enhance.enhancer.inference import denoise
13
- from seedvc import voice_conversion
14
-
15
 
16
  # Установка переменных окружения для принятия лицензионных условий
17
  os.environ["COQUI_TOS_AGREED"] = "1"
@@ -19,17 +17,6 @@ os.environ["COQUI_TOS_AGREED"] = "1"
19
  # Определение устройства (CUDA или CPU)
20
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
21
 
22
- def normalize_audio(wave):
23
- """
24
- Нормализует аудиосигнал так, чтобы максимальное абсолютное значение было <= 1.0
25
- """
26
- max_val = np.max(np.abs(wave))
27
- if max_val > 1.0:
28
- wave = wave / max_val
29
- return wave
30
-
31
-
32
-
33
  # Глобальные переменные и настройки
34
  language_options = {
35
  "English (en)": "en",
@@ -76,52 +63,23 @@ def check_audio_length(audio_path, max_duration=120):
76
  print(f"Error while checking audio length: {e}")
77
  return False
78
 
79
-
80
- def synthesize_and_convert_voice(text, language_iso, voice_audio_path, speed, device='cpu'):
81
- """
82
- Синтезирует речь на основе текста, выполняет денойзинг для клонируемого аудио и преобразование голоса.
83
-
84
- Параметры:
85
- - text (str): Текст для синтеза речи.
86
- - language_iso (str): ISO-код языка для TTS.
87
- - voice_audio_path (str): Путь к аудио-файлу для клонирования голоса.
88
- - speed (float): Скорость синтеза речи.
89
- - device (str): Устройство для обработки (например, 'cpu' или 'cuda').
90
-
91
- Возвращает:
92
- - tuple: (частота дискретизации, numpy массив аудио данных)
93
- """
94
- # Загрузка аудио для клонирования
95
- voice_wav_tensor, voice_sample_rate = torchaudio.load(voice_audio_path)
96
-
97
- # Преобразование в моно, если аудио стерео
98
- if voice_wav_tensor.dim() > 1:
99
- voice_wav_tensor = voice_wav_tensor.mean(dim=0, keepdim=True)
100
-
101
- # Применение денойзинга к аудио для клонирования
102
- denoised_voice_wav_tensor, denoised_voice_sample_rate = denoise(
103
- voice_wav_tensor.squeeze(), voice_sample_rate, device=device
104
- )
105
-
106
- # Сохранение денойзенного аудио во временный файл
107
- with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_denoised_voice_file:
108
- temp_denoised_voice_path = temp_denoised_voice_file.name
109
- torchaudio.save(
110
- temp_denoised_voice_path,
111
- denoised_voice_wav_tensor.unsqueeze(0).cpu(),
112
- denoised_voice_sample_rate
113
- )
114
-
115
- # Синтез речи с использованием TTS
116
  tts_synthesis = TTS(model_name=f"tts_models/{language_iso}/fairseq/vits")
117
  wav_data = tts_synthesis.tts(text, speed=speed)
118
 
119
- # Преобразование в NumPy массив и нормализация
120
  wav_data_np = np.array(wav_data, dtype=np.float32)
121
- wav_data_np = wav_data_np / max(1.0, np.max(np.abs(wav_data_np)))
122
 
123
- # Масштабирование до int16 и временное сохранение
 
 
 
 
 
124
  wav_data_int16 = np.int16(wav_data_np * 32767)
 
 
125
  with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_tts_wav_file:
126
  temp_tts_wav_path = temp_tts_wav_file.name
127
  write(temp_tts_wav_path, 22050, wav_data_int16)
@@ -129,69 +87,41 @@ def synthesize_and_convert_voice(text, language_iso, voice_audio_path, speed, de
129
  # Загрузка синтезированного аудио
130
  wav_tensor, sample_rate = torchaudio.load(temp_tts_wav_path)
131
 
132
- # Преобразование в моно, если требуется
133
- if wav_tensor.dim() > 1:
134
  wav_tensor = wav_tensor.mean(dim=0, keepdim=True)
135
 
136
- # Применение денойзинга
137
- denoised_wav_tensor, denoised_sample_rate = denoise(wav_tensor.squeeze(), sample_rate, device=device)
138
-
139
- # Преобразование денойзенного тензора в NumPy массив
140
- denoised_wav_np = denoised_wav_tensor.cpu().numpy()
141
-
142
- # Масштабирование денойзенного аудио до int16
143
- denoised_wav_int16 = np.int16(denoised_wav_np * 32767)
144
 
145
  # Сохранение денойзенного аудио во временный файл
146
  with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_denoised_wav_file:
147
  temp_denoised_wav_path = temp_denoised_wav_file.name
148
- write(temp_denoised_wav_path, denoised_sample_rate, denoised_wav_int16)
149
-
150
- # Параметры для voice_conversion
151
- diffusion_steps = 30
152
- length_adjust = 1.0
153
- inference_cfg_rate = 0.6
154
- f0_condition = True
155
- auto_f0_adjust = True
156
- pitch_shift = 0
157
-
158
- # Вызов функции voice_conversion
159
- output_sample_rate, output_audio_data = voice_conversion(
160
- source=temp_denoised_wav_path,
161
- target=temp_denoised_voice_path,
162
- diffusion_steps=diffusion_steps,
163
- length_adjust=length_adjust,
164
- inference_cfg_rate=inference_cfg_rate,
165
- f0_condition=f0_condition,
166
- auto_f0_adjust=auto_f0_adjust,
167
- pitch_shift=pitch_shift
168
- )
169
 
170
- # Очистка временных файлов
171
- os.remove(temp_denoised_voice_path)
172
- os.remove(temp_tts_wav_path)
173
- os.remove(temp_denoised_wav_path)
174
 
175
- return output_sample_rate, output_audio_data
 
 
176
 
 
 
 
177
 
 
 
178
 
 
 
 
 
179
 
180
- def synthesize_speech(text, speaker_wav_path, language_iso, speed, device='cpu'):
181
- """
182
- Синтезирует речь на основе текста, предварительно очищая входящее аудио от шумов
183
- и выполняя преобразование голоса с помощью функции voice_conversion.
184
 
185
- Параметры:
186
- - text (str): Текст для синтеза речи.
187
- - speaker_wav_path (str): Путь к аудио говорящего для клонирования голоса.
188
- - language_iso (str): ISO-код языка для TTS.
189
- - speed (float): Скорость синтеза речи.
190
- - device (str): Устройство для обработки (например, 'cpu' или 'cuda').
191
 
192
- Возвращает:
193
- - tuple: (частота дискретизации, numpy массив аудио данных)
194
- """
195
  # Загрузка аудио говорящего
196
  speaker_wav_tensor, speaker_sample_rate = torchaudio.load(speaker_wav_path)
197
 
@@ -231,37 +161,38 @@ def synthesize_speech(text, speaker_wav_path, language_iso, speed, device='cpu')
231
  if wav_tensor.dim() > 1 and wav_tensor.size(0) > 1:
232
  wav_tensor = wav_tensor.mean(dim=0, keepdim=True)
233
 
234
- # Сохранение сгенерированного аудио во временный файл для voice_conversion
235
  with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_vc_input_file:
236
  temp_vc_input_path = temp_vc_input_file.name
237
  torchaudio.save(temp_vc_input_path, wav_tensor.cpu(), sample_rate)
238
 
239
- # Параметры для voice_conversion
240
- diffusion_steps = 30
241
- length_adjust = 1.0
242
- inference_cfg_rate = 0.6
243
- f0_condition = True
244
- auto_f0_adjust = True
245
- pitch_shift = 0
246
-
247
- # Вызов функции voice_conversion
248
- output_sample_rate, output_audio_data = voice_conversion(
249
- source=temp_vc_input_path,
250
- target=temp_denoised_speaker_path,
251
- diffusion_steps=diffusion_steps,
252
- length_adjust=length_adjust,
253
- inference_cfg_rate=inference_cfg_rate,
254
- f0_condition=f0_condition,
255
- auto_f0_adjust=auto_f0_adjust,
256
- pitch_shift=pitch_shift
257
  )
258
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  # Удаление временных файлов
260
  os.remove(temp_denoised_speaker_path)
261
  os.remove(temp_tts_output_path)
262
  os.remove(temp_vc_input_path)
 
263
 
264
- return output_sample_rate, output_audio_data
265
 
266
  def get_language_code(selected_language):
267
  if selected_language in language_options:
@@ -272,46 +203,30 @@ def get_language_code(selected_language):
272
  return None
273
 
274
  def process_speech(text, speaker_wav_path, selected_language, speed):
275
- """
276
- Обрабатывает текст, выполняет синтез речи и голосовое клонирование,
277
- а также возвращает путь к сгенерированному аудио-файлу.
278
- """
279
  language_code = get_language_code(selected_language)
280
 
281
  if language_code is None:
282
  raise ValueError("Выбранный язык не поддерживается.")
283
 
284
  if speaker_wav_path is None:
285
- raise ValueError("Пожалуйста, загрузите аудио файл говорящего.")
 
 
286
 
287
  # Проверка длины аудио
288
- try:
289
- audio = AudioSegment.from_file(speaker_wav_path)
290
- duration = audio.duration_seconds
291
- if duration > 120:
292
- raise ValueError("Длина аудио превышает допустимый лимит в 2 минуты.")
293
- except Exception as e:
294
- raise ValueError(f"Ошибка при проверке аудио: {e}")
295
-
296
- try:
297
- if selected_language in other_language:
298
- output_sample_rate, output_audio_data = synthesize_and_convert_voice(
299
- text, language_code, speaker_wav_path, speed
300
- )
301
- else:
302
- output_sample_rate, output_audio_data = synthesize_speech(
303
- text, speaker_wav_path, language_code, speed
304
- )
305
-
306
- # Сохранение результата в файл для вывода
307
- with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_output_file:
308
- temp_output_path = temp_output_file.name
309
- write(temp_output_path, output_sample_rate, output_audio_data)
310
-
311
- return temp_output_path # Возвращаем путь к сгенерированному аудио
312
 
313
- except Exception as e:
314
- raise ValueError(f"Ошибка при обработке речи: {e}")
315
 
316
  def restart_program():
317
  python = sys.executable
 
10
  import torch
11
  import torchaudio
12
  from resemble_enhance.enhancer.inference import denoise
 
 
13
 
14
  # Установка переменных окружения для принятия лицензионных условий
15
  os.environ["COQUI_TOS_AGREED"] = "1"
 
17
  # Определение устройства (CUDA или CPU)
18
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
19
 
 
 
 
 
 
 
 
 
 
 
 
20
  # Глобальные переменные и настройки
21
  language_options = {
22
  "English (en)": "en",
 
63
  print(f"Error while checking audio length: {e}")
64
  return False
65
 
66
+ def synthesize_and_convert_voice(text, language_iso, voice_audio_path, speed):
67
+ # Синтез речи с помощью TTS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  tts_synthesis = TTS(model_name=f"tts_models/{language_iso}/fairseq/vits")
69
  wav_data = tts_synthesis.tts(text, speed=speed)
70
 
71
+ # Преобразование wav_data из списка в NumPy массив с типом float32
72
  wav_data_np = np.array(wav_data, dtype=np.float32)
 
73
 
74
+ # Нормализация данных, если необходимо
75
+ max_val = np.max(np.abs(wav_data_np))
76
+ if max_val > 1.0:
77
+ wav_data_np = wav_data_np / max_val
78
+
79
+ # Масштабирование до int16 для записи в WAV файл
80
  wav_data_int16 = np.int16(wav_data_np * 32767)
81
+
82
+ # Сохранение синтезированного аудио во временный файл
83
  with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_tts_wav_file:
84
  temp_tts_wav_path = temp_tts_wav_file.name
85
  write(temp_tts_wav_path, 22050, wav_data_int16)
 
87
  # Загрузка синтезированного аудио
88
  wav_tensor, sample_rate = torchaudio.load(temp_tts_wav_path)
89
 
90
+ # Преобразование в моно, если аудио стерео
91
+ if wav_tensor.dim() > 1 and wav_tensor.size(0) > 1:
92
  wav_tensor = wav_tensor.mean(dim=0, keepdim=True)
93
 
94
+ # Применение денойзинга (не перемещаем wav_tensor на устройство)
95
+ denoised_wav_tensor, denoised_sample_rate = denoise(wav_tensor.squeeze(), sample_rate, device)
 
 
 
 
 
 
96
 
97
  # Сохранение денойзенного аудио во временный файл
98
  with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_denoised_wav_file:
99
  temp_denoised_wav_path = temp_denoised_wav_file.name
100
+ torchaudio.save(temp_denoised_wav_path, denoised_wav_tensor.unsqueeze(0).cpu(), denoised_sample_rate)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
+ # Преобразование голоса с использованием денойзенного аудио
103
+ tts_conversion = TTS(model_name="voice_conversion_models/multilingual/vctk/freevc24", progress_bar=False)
 
 
104
 
105
+ # Подготовка временного выходного файла
106
+ with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_output_wav_file:
107
+ temp_output_wav_path = temp_output_wav_file.name
108
 
109
+ # Преобразование голоса
110
+ tts_conversion.voice_conversion_to_file(temp_denoised_wav_path, target_wav=voice_audio_path,
111
+ file_path=temp_output_wav_path)
112
 
113
+ # Чтение преобразованного аудио
114
+ output_sample_rate, output_audio_data = read(temp_output_wav_path)
115
 
116
+ # Удаление временных файлов
117
+ os.remove(temp_tts_wav_path)
118
+ os.remove(temp_denoised_wav_path)
119
+ os.remove(temp_output_wav_path)
120
 
121
+ return (output_sample_rate, output_audio_data)
 
 
 
122
 
 
 
 
 
 
 
123
 
124
+ def synthesize_speech(text, speaker_wav_path, language_iso, speed):
 
 
125
  # Загрузка аудио говорящего
126
  speaker_wav_tensor, speaker_sample_rate = torchaudio.load(speaker_wav_path)
127
 
 
161
  if wav_tensor.dim() > 1 and wav_tensor.size(0) > 1:
162
  wav_tensor = wav_tensor.mean(dim=0, keepdim=True)
163
 
164
+ # Сохранение сгенерированного аудио во временный файл для voice cloning
165
  with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_vc_input_file:
166
  temp_vc_input_path = temp_vc_input_file.name
167
  torchaudio.save(temp_vc_input_path, wav_tensor.cpu(), sample_rate)
168
 
169
+ # Инициализация модели voice conversion
170
+ tts_conversion = TTS(
171
+ model_name="voice_conversion_models/multilingual/vctk/freevc24",
172
+ progress_bar=False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  )
174
 
175
+ # Подготовка временного выходного файла
176
+ with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_output_wav_file:
177
+ temp_output_wav_path = temp_output_wav_file.name
178
+
179
+ # Преобразование голоса
180
+ tts_conversion.voice_conversion_to_file(
181
+ temp_vc_input_path,
182
+ target_wav=temp_denoised_speaker_path,
183
+ file_path=temp_output_wav_path
184
+ )
185
+
186
+ # Чтение преобразованного аудио
187
+ output_sample_rate, output_audio_data = read(temp_output_wav_path)
188
+
189
  # Удаление временных файлов
190
  os.remove(temp_denoised_speaker_path)
191
  os.remove(temp_tts_output_path)
192
  os.remove(temp_vc_input_path)
193
+ os.remove(temp_output_wav_path)
194
 
195
+ return (output_sample_rate, output_audio_data)
196
 
197
  def get_language_code(selected_language):
198
  if selected_language in language_options:
 
203
  return None
204
 
205
  def process_speech(text, speaker_wav_path, selected_language, speed):
 
 
 
 
206
  language_code = get_language_code(selected_language)
207
 
208
  if language_code is None:
209
  raise ValueError("Выбранный язык не поддерживается.")
210
 
211
  if speaker_wav_path is None:
212
+ error_message = "Пожалуйста, загрузите аудио файл говорящего."
213
+ error = gr.Error(error_message, duration=5)
214
+ raise error
215
 
216
  # Проверка длины аудио
217
+ audio = AudioSegment.from_file(speaker_wav_path)
218
+ duration = audio.duration_seconds
219
+ if duration > 120:
220
+ error_message = "Длина аудио превышает допустимый лимит в 2 минуты."
221
+ error = gr.Error(error_message, duration=5)
222
+ raise error
223
+
224
+ if selected_language in other_language:
225
+ output_audio_data = synthesize_and_convert_voice(text, language_code, speaker_wav_path, speed)
226
+ else:
227
+ output_audio_data = synthesize_speech(text, speaker_wav_path, language_code, speed)
 
 
 
 
 
 
 
 
 
 
 
 
 
228
 
229
+ return output_audio_data
 
230
 
231
  def restart_program():
232
  python = sys.executable