Opera8 commited on
Commit
428894f
·
verified ·
1 Parent(s): 885b401

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -44
app.py CHANGED
@@ -86,33 +86,14 @@ os.makedirs("ckpts/Vevo", exist_ok=True)
86
 
87
  from models.vc.vevo.vevo_utils import VevoInferencePipeline
88
 
89
- # --- تابع ذخیره سازی پیشرفته (حذف نویز + فرمت استاندارد) ---
90
- def save_audio_final(waveform, output_path, sample_rate=24000, target_length=None):
91
  try:
92
  if isinstance(waveform, torch.Tensor):
93
  waveform = waveform.detach().cpu()
94
  if waveform.dim() == 2 and waveform.shape[0] == 1:
95
  waveform = waveform.squeeze(0)
96
  waveform = waveform.numpy()
97
-
98
- # 1. همگام‌سازی طول (حذف نویز اضافه آخر فایل)
99
- if target_length is not None:
100
- if len(waveform) > target_length:
101
- waveform = waveform[:target_length]
102
- elif len(waveform) < target_length:
103
- # اگر کوتاه‌تر بود، با سکوت پر کن (معمولاً پیش نمیاد)
104
- padding = np.zeros(target_length - len(waveform))
105
- waveform = np.concatenate([waveform, padding])
106
-
107
- # 2. اعمال Fade Out (جلوگیری از صدای کلیک در لحظه قطع شدن)
108
- fade_len = int(sample_rate * 0.05) # 50 میلی ثانیه
109
- if len(waveform) > fade_len:
110
- fade_curve = np.linspace(1, 0, fade_len)
111
- waveform[-fade_len:] *= fade_curve
112
-
113
- # 3. ذخیره با فرمت 16 بیتی
114
  sf.write(output_path, waveform, sample_rate, subtype='PCM_16')
115
-
116
  except Exception as e:
117
  print(f"Save error: {e}")
118
  raise e
@@ -142,10 +123,7 @@ inference_pipelines = {}
142
  def preload_all_resources():
143
  print("Preloading resources...")
144
  setup_configs()
145
-
146
- global downloaded_content_style_tokenizer_path
147
- global downloaded_fmt_path
148
- global downloaded_vocoder_path
149
 
150
  if not downloaded_resources["tokenizer_vq8192"]:
151
  local_dir = snapshot_download(repo_id="amphion/Vevo", repo_type="model", cache_dir="./ckpts/Vevo", allow_patterns=["tokenizer/vq8192/*"])
@@ -196,7 +174,7 @@ def vevo_timbre(content_wav, reference_wav):
196
  raise ValueError("Please upload audio files")
197
 
198
  try:
199
- # --- پردازش صدای اصلی ---
200
  if isinstance(content_wav, tuple):
201
  content_sr, content_data = content_wav if isinstance(content_wav[0], int) else (content_wav[1], content_wav[0])
202
  else:
@@ -210,12 +188,10 @@ def vevo_timbre(content_wav, reference_wav):
210
  content_tensor = torchaudio.functional.resample(content_tensor, content_sr, 24000)
211
  content_sr = 24000
212
 
 
213
  content_tensor = content_tensor / (torch.max(torch.abs(content_tensor)) + 1e-6) * 0.95
214
-
215
- # ذخیره طول دقیق فایل ورودی برای برش نهایی
216
- target_length_samples = content_tensor.shape[-1]
217
 
218
- # --- پردازش صدای رفرنس ---
219
  if isinstance(reference_wav, tuple):
220
  ref_sr, ref_data = reference_wav if isinstance(reference_wav[0], int) else (reference_wav[1], reference_wav[0])
221
  else:
@@ -231,34 +207,70 @@ def vevo_timbre(content_wav, reference_wav):
231
 
232
  ref_tensor = ref_tensor / (torch.max(torch.abs(ref_tensor)) + 1e-6) * 0.95
233
 
234
- save_audio_final(content_tensor, temp_content_path, content_sr)
235
- save_audio_final(ref_tensor, temp_reference_path, ref_sr)
236
-
237
- print(f"[{session_id}] Processing...")
 
 
238
 
 
239
  pipeline = get_pipeline()
240
 
241
- gen_audio = pipeline.inference_fm(
242
- src_wav_path=temp_content_path,
243
- timbre_ref_wav_path=temp_reference_path,
244
- flow_matching_steps=32,
245
- )
246
 
247
- if torch.isnan(gen_audio).any() or torch.isinf(gen_audio).any():
248
- gen_audio = torch.nan_to_num(gen_audio, nan=0.0, posinf=0.95, neginf=-0.95)
249
 
250
- # اینجا فایل را دقیقاً به اندازه ورودی برش می‌ز��یم
251
- # این کار باعث می‌شود نویز اضافه‌ای که مدل در پایان تولید کرده حذف شود
252
- save_audio_final(gen_audio, output_path, 24000, target_length=target_length_samples)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
 
 
 
254
  return output_path
255
 
256
  finally:
257
  if os.path.exists(temp_content_path): os.remove(temp_content_path)
258
  if os.path.exists(temp_reference_path): os.remove(temp_reference_path)
259
 
260
- with gr.Blocks(title="Vevo-Timbre (Clean)") as demo:
261
  gr.Markdown("## Vevo-Timbre: Zero-Shot Voice Conversion")
 
262
 
263
  with gr.Row():
264
  with gr.Column():
 
86
 
87
  from models.vc.vevo.vevo_utils import VevoInferencePipeline
88
 
89
+ def save_audio_pcm16(waveform, output_path, sample_rate=24000):
 
90
  try:
91
  if isinstance(waveform, torch.Tensor):
92
  waveform = waveform.detach().cpu()
93
  if waveform.dim() == 2 and waveform.shape[0] == 1:
94
  waveform = waveform.squeeze(0)
95
  waveform = waveform.numpy()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  sf.write(output_path, waveform, sample_rate, subtype='PCM_16')
 
97
  except Exception as e:
98
  print(f"Save error: {e}")
99
  raise e
 
123
  def preload_all_resources():
124
  print("Preloading resources...")
125
  setup_configs()
126
+ global downloaded_content_style_tokenizer_path, downloaded_fmt_path, downloaded_vocoder_path
 
 
 
127
 
128
  if not downloaded_resources["tokenizer_vq8192"]:
129
  local_dir = snapshot_download(repo_id="amphion/Vevo", repo_type="model", cache_dir="./ckpts/Vevo", allow_patterns=["tokenizer/vq8192/*"])
 
174
  raise ValueError("Please upload audio files")
175
 
176
  try:
177
+ # --- آماده سازی Content ---
178
  if isinstance(content_wav, tuple):
179
  content_sr, content_data = content_wav if isinstance(content_wav[0], int) else (content_wav[1], content_wav[0])
180
  else:
 
188
  content_tensor = torchaudio.functional.resample(content_tensor, content_sr, 24000)
189
  content_sr = 24000
190
 
191
+ # نرمال سازی
192
  content_tensor = content_tensor / (torch.max(torch.abs(content_tensor)) + 1e-6) * 0.95
 
 
 
193
 
194
+ # --- آماده سازی Reference ---
195
  if isinstance(reference_wav, tuple):
196
  ref_sr, ref_data = reference_wav if isinstance(reference_wav[0], int) else (reference_wav[1], reference_wav[0])
197
  else:
 
207
 
208
  ref_tensor = ref_tensor / (torch.max(torch.abs(ref_tensor)) + 1e-6) * 0.95
209
 
210
+ # اگر رفرنس خیلی طولانی باشد، فقط 20 ثانیه اول کافی است (برای استخراج Timbre)
211
+ # این کار سرعت را بالا می‌برد و تاثیری در کیفیت ندارد
212
+ if ref_tensor.shape[1] > 24000 * 20:
213
+ ref_tensor = ref_tensor[:, :24000 * 20]
214
+
215
+ save_audio_pcm16(ref_tensor, temp_reference_path, ref_sr)
216
 
217
+ # --- منطق Chunking (حل مشکل فایل طولانی) ---
218
  pipeline = get_pipeline()
219
 
220
+ # هر تکه 15 ثانیه (360000 سمپل)
221
+ CHUNK_SIZE = 15 * 24000
222
+ total_samples = content_tensor.shape[1]
223
+
224
+ print(f"[{session_id}] Audio Duration: {total_samples/24000:.2f}s. Starting Chunking...")
225
 
226
+ generated_chunks = []
 
227
 
228
+ for start in range(0, total_samples, CHUNK_SIZE):
229
+ end = min(start + CHUNK_SIZE, total_samples)
230
+ current_chunk = content_tensor[:, start:end]
231
+
232
+ # ذخیره تکه جاری
233
+ save_audio_pcm16(current_chunk, temp_content_path, 24000)
234
+
235
+ print(f"[{session_id}] Processing chunk {start/24000:.1f}s to {end/24000:.1f}s")
236
+
237
+ try:
238
+ gen_chunk = pipeline.inference_fm(
239
+ src_wav_path=temp_content_path,
240
+ timbre_ref_wav_path=temp_reference_path,
241
+ flow_matching_steps=32,
242
+ )
243
+
244
+ # رفع NaN
245
+ if torch.isnan(gen_chunk).any() or torch.isinf(gen_chunk).any():
246
+ gen_chunk = torch.nan_to_num(gen_chunk, nan=0.0, posinf=0.95, neginf=-0.95)
247
+
248
+ # مطمئن شویم تنسور دو بعدی است [1, T]
249
+ if gen_chunk.dim() == 1:
250
+ gen_chunk = gen_chunk.unsqueeze(0)
251
+
252
+ generated_chunks.append(gen_chunk.cpu())
253
+
254
+ except Exception as e:
255
+ print(f"Error in chunk: {e}")
256
+ # اگر خطایی رخ داد، سکوت اضافه کن تا فایل قطع نشود
257
+ silence = torch.zeros((1, end - start))
258
+ generated_chunks.append(silence)
259
+
260
+ # چسباندن تکه‌ها
261
+ final_audio = torch.cat(generated_chunks, dim=1)
262
 
263
+ # ذخیره نهایی
264
+ save_audio_pcm16(final_audio, output_path, 24000)
265
  return output_path
266
 
267
  finally:
268
  if os.path.exists(temp_content_path): os.remove(temp_content_path)
269
  if os.path.exists(temp_reference_path): os.remove(temp_reference_path)
270
 
271
+ with gr.Blocks(title="Vevo-Timbre (Long Audio)") as demo:
272
  gr.Markdown("## Vevo-Timbre: Zero-Shot Voice Conversion")
273
+ gr.Markdown("پشتیبانی کامل از فایل‌های طولانی (بدون نویز و قطعی)")
274
 
275
  with gr.Row():
276
  with gr.Column():