Vgjkmhf commited on
Commit
3c44ab0
·
verified ·
1 Parent(s): 4b76478

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -81
app.py CHANGED
@@ -10,11 +10,11 @@ import numpy as np
10
  import soundfile as sf
11
  import librosa
12
  import gradio as gr
13
- import scipy.signal as signal # اضافه شده برای پردازش سیگنال حرفه‌ای
14
  from datetime import datetime
15
 
16
  # ==========================================
17
- # 1. تنظیمات اولیه و کتابخانه‌ها
18
  # ==========================================
19
  print(">>> در حال راه‌اندازی سیستم RVC Pro Max...")
20
 
@@ -25,7 +25,6 @@ try:
25
  print("✅ کتابخانه‌های RVC با موفقیت بارگذاری شدند.")
26
  except ImportError as e:
27
  print(f"❌ خطای بحرانی در ایمپورت: {e}")
28
- print("لطفاً requirements.txt را بررسی کنید.")
29
  sys.exit(1)
30
 
31
  # تنظیم مسیر FFmpeg
@@ -33,7 +32,6 @@ try:
33
  static_ffmpeg.add_paths()
34
  ffmpeg_exe = imageio_ffmpeg.get_ffmpeg_exe()
35
  os.environ["PATH"] += os.pathsep + os.path.dirname(ffmpeg_exe)
36
- print(f"✅ FFmpeg یافت شد: {ffmpeg_exe}")
37
  except Exception as e:
38
  print(f"⚠️ هشدار FFmpeg: {e}")
39
 
@@ -43,7 +41,7 @@ os.environ["TEMP"] = TEMP_DIR
43
  os.environ["TMPDIR"] = TEMP_DIR
44
 
45
  # ==========================================
46
- # 2. توابع پردازش صدا (Audio DSP)
47
  # ==========================================
48
 
49
  def log_message(message):
@@ -51,33 +49,23 @@ def log_message(message):
51
  return f"[{timestamp}] {message}"
52
 
53
  def apply_clarity_eq(y, sr):
54
- """
55
- اعمال EQ برای رفع تودماغی و شفاف‌سازی صدا
56
- 1. Low-Cut: حذف هام (Hum) زیر 60Hz
57
- 2. Mid-Cut: کاهش فرکانس‌های تودماغی (800Hz - 1.2kHz)
58
- 3. High-Boost: افزایش فرکانس‌های شفاف (Air) بالای 6kHz
59
- """
60
  try:
61
- # 1. High-pass filter (حذف نویز خیلی بم)
62
  sos_hp = signal.butter(4, 60, 'hp', fs=sr, output='sos')
63
  y = signal.sosfilt(sos_hp, y)
64
 
65
- # 2. Notch/Bell filter برای کاهش تودماغی (حدود 1000Hz)
66
- # استفاده از فیلتر Peaking EQ معکوس
67
- b, a = signal.iirpeak(1000, 1.0, fs=sr)
68
- # اعمال معکوس (کاهش دامنه در این فرکانس) - پیاده‌سازی ساده‌تر با فیلتر باترورث بند-استاپ نرم
69
- # اما اینجا یک ترفند ساده‌تر می‌زنیم: کاهش ملایم میدرنج
70
- # یک فیلتر ساده برای کاهش ناحیه 1k
71
  sos_mid = signal.butter(2, [800, 1200], 'bandstop', fs=sr, output='sos')
72
- # میکس کردن سیگنال فیلتر شده با اصلی (Dry/Wet) برای اینکه صدا توخالی نشود
73
  y_filtered = signal.sosfilt(sos_mid, y)
74
- y = (y * 0.7) + (y_filtered * 0.3) # تاثیر ملایم
 
75
 
76
- # 3. High Shelf Boost (شفافیت)
77
- # بوست کردن فرکانس‌های بالای 5000 هرتز
78
  sos_high = signal.butter(2, 5000, 'hp', fs=sr, output='sos')
79
  y_high = signal.sosfilt(sos_high, y)
80
- y = y + (y_high * 0.15) # افزودن 15% فرکانس بالا به سیگنال اصلی
81
 
82
  return y
83
  except Exception as e:
@@ -89,27 +77,19 @@ def preprocess_audio(input_path):
89
  y, sr = librosa.load(input_path, sr=None)
90
  if y.ndim > 1:
91
  y = librosa.to_mono(y)
92
-
93
- # نرمال‌سازی استاندارد
94
  y = librosa.util.normalize(y)
95
-
96
  processed_path = os.path.join(TEMP_DIR, "preprocessed.wav")
97
  sf.write(processed_path, y, sr)
98
  return processed_path, f"✅ صدا پیش‌پردازش شد (SR: {sr}Hz)"
99
  except Exception as e:
100
- return input_path, f"⚠️ پیش‌پردازش ناموفق: {e}"
101
 
102
  def post_process_audio(input_path, clarity_boost=True):
103
- """پردازش نهایی برای کیفیت استودیویی"""
104
  try:
105
  y, sr = librosa.load(input_path, sr=None)
106
-
107
  if clarity_boost:
108
  y = apply_clarity_eq(y, sr)
109
-
110
- # نرمال‌سازی نهایی (جلوگیری از Clipping)
111
  y = librosa.util.normalize(y) * 0.95
112
-
113
  output_path = input_path.replace(".wav", "_final.wav")
114
  sf.write(output_path, y, sr)
115
  return output_path
@@ -118,14 +98,13 @@ def post_process_audio(input_path, clarity_boost=True):
118
 
119
  def cleanup_temp():
120
  try:
121
- if os.path.exists(TEMP_DIR):
122
- shutil.rmtree(TEMP_DIR)
123
- os.makedirs(TEMP_DIR)
124
  except Exception:
125
  pass
126
 
127
  # ==========================================
128
- # 3. موتور تبدیل صدا (RVC Engine)
129
  # ==========================================
130
 
131
  def rvc_process_pipeline(
@@ -138,26 +117,28 @@ def rvc_process_pipeline(
138
  logs = []
139
  logs.append(log_message("🚀 شروع عملیات تبدیل..."))
140
 
141
- if not audio_path: return None, "❌ فایل صوتی انتخاب نشده است."
142
- if not model_file: return None, "❌ فایل مدل انتخاب نشده است."
 
 
143
 
144
  try:
145
  cleanup_temp()
146
  model_path = model_file.name
147
  index_path = index_file.name if index_file else None
148
 
149
- # 1. پیش‌پردازش
150
  clean_audio, msg = preprocess_audio(audio_path)
151
  logs.append(log_message(msg))
152
 
153
- # 2. لود مدل
154
  logs.append(log_message(f"📂 مدل: {os.path.basename(model_path)}"))
155
- rvc = RVCInference(device="cpu") # اگر GPU دارید "cuda" بگذارید
156
  rvc.load_model(model_path)
157
 
158
  output_temp = os.path.join(TEMP_DIR, f"rvc_out_{int(time.time())}.wav")
159
 
160
- # 3. تنظیم پارامترها (بهینه‌سازی شده برای کیفیت)
161
  kwargs = {
162
  "input_path": clean_audio,
163
  "output_path": output_temp,
@@ -172,49 +153,54 @@ def rvc_process_pipeline(
172
  "hop_length": int(hop_length)
173
  }
174
 
175
- # بررسی پارامترهای معتبر تابع (برای جلوگیری از ارور نسخه‌های قدیمی)
176
  sig = inspect.signature(rvc.infer_file)
177
  valid_keys = sig.parameters.keys()
178
- filtered_kwargs = {k: v for k, v in kwargs.items() if k in valid_keys or k == "pitch" or k == "method"}
179
 
180
- # هندل کردن تغییر نام پارامترها در نسخه‌های مختلف
181
- if "f0_up_key" in valid_keys and "pitch" in filtered_kwargs:
182
- filtered_kwargs["f0_up_key"] = filtered_kwargs.pop("pitch")
183
- if "f0_method" in valid_keys and "method" in filtered_kwargs:
184
- filtered_kwargs["f0_method"] = filtered_kwargs.pop("method")
185
-
186
- logs.append(log_message(f"⚙️ متد: {f0_method} | شفاف‌سازی: {'فعال' if enable_clarity else 'غیرفعال'}"))
 
 
 
 
187
 
188
- # 4. اجرای تبدیل
189
  start_time = time.time()
190
- rvc.infer_file(**filtered_kwargs)
191
 
192
- # 5. پس‌پردازش (شفاف‌سازی)
193
  final_output = output_temp
194
- if enable_clarity:
195
- logs.append(log_message("✨ در حال اعمال فیلتر شفاف‌سازی و رفع تودماغی..."))
196
  final_output = post_process_audio(output_temp, clarity_boost=True)
197
 
198
  duration = time.time() - start_time
199
  logs.append(log_message(f"✅ تمام شد! ({duration:.2f}s)"))
200
 
201
- return final_output, "
 
202
  ".join(logs)
 
203
 
204
  except Exception as e:
205
- return None, f"❌ خطا: {traceback.format_exc()}"
 
 
206
 
207
  # ==========================================
208
- # 4. رابط کاربری (Gradio)
209
  # ==========================================
210
 
211
  custom_css = """
212
  #run_btn {background: linear-gradient(90deg, #FF5722 0%, #FF8A65 100%); color: white; border: none;}
213
- .gradio-container {font-family: 'Tahoma', sans-serif;}
214
  """
215
 
216
  with gr.Blocks(title="RVC Pro Persian", theme=gr.themes.Soft(), css=custom_css) as demo:
217
- gr.Markdown("## 🎙️ RVC Pro: مبدل صدای حرفه‌ای (رفع گنگی و تودماغی)")
218
 
219
  with gr.Row():
220
  with gr.Column():
@@ -223,33 +209,23 @@ with gr.Blocks(title="RVC Pro Persian", theme=gr.themes.Soft(), css=custom_css)
223
  model_input = gr.File(label="مدل (.pth)", file_types=[".pth"])
224
  index_input = gr.File(label="ایندکس (.index)", file_types=[".index"])
225
 
226
- # تمام الگوریتم‌ها
227
  algo_dropdown = gr.Dropdown(
228
  choices=["rmvpe", "fcpe", "crepe", "harvest", "pm"],
229
  value="rmvpe",
230
- label="الگوریتم (RMVPE پیشنهاد می‌شود)",
231
- info="RMVPE: بهترین کیفیت | PM: سریع | Harvest: برای نت‌های پایین"
232
  )
233
-
234
- pitch_slider = gr.Slider(-24, 24, value=0, step=1, label="تغییر گام (Pitch)")
235
-
236
  btn_run = gr.Button("🚀 تبدیل صدا", elem_id="run_btn", variant="primary")
237
 
238
  with gr.Column():
239
- with gr.Accordion("تنظیمات کیفیت (رفع نویز و خش)", open=True):
240
- enable_clarity = gr.Checkbox(value=True, label="✨ فعال‌سازی شفاف‌کننده صدا (رفع تودماغی)")
241
-
242
- with gr.Row():
243
- index_rate = gr.Slider(0, 1, value=0.4, step=0.05, label="تاثیر ایندکس", info="بیشتر = شبیه‌تر به مدل (اما شاید نویزی)")
244
- envelope_mix = gr.Slider(0, 1, value=0.25, step=0.05, label="میکس حجم (Volume Mix)", info="کمتر = شفاف‌تر (حجم مدل)")
245
-
246
- with gr.Row():
247
- protect_val = gr.Slider(0, 0.5, value=0.33, step=0.01, label="محافظت (Protect)", info="0.33 استاندارد است")
248
- filter_radius = gr.Slider(0, 7, value=3, step=1, label="فیلتر نرم‌کننده", info="3 = متعادل")
249
-
250
- with gr.Row():
251
- resample_sr = gr.Slider(0, 48000, value=0, step=1000, label="ری‌سمپل", info="0 = بدون تغییر (پیشنهادی)")
252
- hop_len = gr.Slider(1, 512, value=128, step=1, label="Hop Length", info="128 استاندارد")
253
 
254
  output_audio = gr.Audio(label="خروجی نهایی", type="filepath")
255
  logs = gr.Textbox(label="گزارش", lines=5)
 
10
  import soundfile as sf
11
  import librosa
12
  import gradio as gr
13
+ import scipy.signal as signal
14
  from datetime import datetime
15
 
16
  # ==========================================
17
+ # 1. تنظیمات اولیه
18
  # ==========================================
19
  print(">>> در حال راه‌اندازی سیستم RVC Pro Max...")
20
 
 
25
  print("✅ کتابخانه‌های RVC با موفقیت بارگذاری شدند.")
26
  except ImportError as e:
27
  print(f"❌ خطای بحرانی در ایمپورت: {e}")
 
28
  sys.exit(1)
29
 
30
  # تنظیم مسیر FFmpeg
 
32
  static_ffmpeg.add_paths()
33
  ffmpeg_exe = imageio_ffmpeg.get_ffmpeg_exe()
34
  os.environ["PATH"] += os.pathsep + os.path.dirname(ffmpeg_exe)
 
35
  except Exception as e:
36
  print(f"⚠️ هشدار FFmpeg: {e}")
37
 
 
41
  os.environ["TMPDIR"] = TEMP_DIR
42
 
43
  # ==========================================
44
+ # 2. توابع پردازش صدا (DSP)
45
  # ==========================================
46
 
47
  def log_message(message):
 
49
  return f"[{timestamp}] {message}"
50
 
51
  def apply_clarity_eq(y, sr):
52
+ """اعمال EQ برای شفاف‌سازی و رفع تودماغی"""
 
 
 
 
 
53
  try:
54
+ # 1. Low-Cut (حذف نویز زیر 60 هرتز)
55
  sos_hp = signal.butter(4, 60, 'hp', fs=sr, output='sos')
56
  y = signal.sosfilt(sos_hp, y)
57
 
58
+ # 2. کاهش فرکانس‌های تودماغی (حدود 1000 هرتز)
59
+ # فیلتر Band-stop ملایم
 
 
 
 
60
  sos_mid = signal.butter(2, [800, 1200], 'bandstop', fs=sr, output='sos')
 
61
  y_filtered = signal.sosfilt(sos_mid, y)
62
+ # ترکیب 30 درصد فیلتر شده با 70 درصد اصلی
63
+ y = (y * 0.7) + (y_filtered * 0.3)
64
 
65
+ # 3. High Boost (شفافیت)
 
66
  sos_high = signal.butter(2, 5000, 'hp', fs=sr, output='sos')
67
  y_high = signal.sosfilt(sos_high, y)
68
+ y = y + (y_high * 0.15)
69
 
70
  return y
71
  except Exception as e:
 
77
  y, sr = librosa.load(input_path, sr=None)
78
  if y.ndim > 1:
79
  y = librosa.to_mono(y)
 
 
80
  y = librosa.util.normalize(y)
 
81
  processed_path = os.path.join(TEMP_DIR, "preprocessed.wav")
82
  sf.write(processed_path, y, sr)
83
  return processed_path, f"✅ صدا پیش‌پردازش شد (SR: {sr}Hz)"
84
  except Exception as e:
85
+ return input_path, f"⚠️ خطا در پیش‌پردازش: {e}"
86
 
87
  def post_process_audio(input_path, clarity_boost=True):
 
88
  try:
89
  y, sr = librosa.load(input_path, sr=None)
 
90
  if clarity_boost:
91
  y = apply_clarity_eq(y, sr)
 
 
92
  y = librosa.util.normalize(y) * 0.95
 
93
  output_path = input_path.replace(".wav", "_final.wav")
94
  sf.write(output_path, y, sr)
95
  return output_path
 
98
 
99
  def cleanup_temp():
100
  try:
101
+ for f in os.listdir(TEMP_DIR):
102
+ os.remove(os.path.join(TEMP_DIR, f))
 
103
  except Exception:
104
  pass
105
 
106
  # ==========================================
107
+ # 3. موتور تبدیل صلاح شده)
108
  # ==========================================
109
 
110
  def rvc_process_pipeline(
 
117
  logs = []
118
  logs.append(log_message("🚀 شروع عملیات تبدیل..."))
119
 
120
+ if not audio_path:
121
+ return None, "❌ فایل صوتی انتخاب نشده است."
122
+ if not model_file:
123
+ return None, "❌ فایل مدل انتخاب نشده است."
124
 
125
  try:
126
  cleanup_temp()
127
  model_path = model_file.name
128
  index_path = index_file.name if index_file else None
129
 
130
+ # پیش‌پردازش
131
  clean_audio, msg = preprocess_audio(audio_path)
132
  logs.append(log_message(msg))
133
 
134
+ # بارگذاری مدل
135
  logs.append(log_message(f"📂 مدل: {os.path.basename(model_path)}"))
136
+ rvc = RVCInference(device="cpu")
137
  rvc.load_model(model_path)
138
 
139
  output_temp = os.path.join(TEMP_DIR, f"rvc_out_{int(time.time())}.wav")
140
 
141
+ # پارامترها
142
  kwargs = {
143
  "input_path": clean_audio,
144
  "output_path": output_temp,
 
153
  "hop_length": int(hop_length)
154
  }
155
 
156
+ # فیلتر کردن پارامترهای نامعتبر برای جلوگیری از خطای نسخه
157
  sig = inspect.signature(rvc.infer_file)
158
  valid_keys = sig.parameters.keys()
 
159
 
160
+ final_kwargs = {}
161
+ for k, v in kwargs.items():
162
+ if k in valid_keys:
163
+ final_kwargs[k] = v
164
+ # نگاشت نام‌های قدیمی به جدید
165
+ elif k == "pitch" and "f0_up_key" in valid_keys:
166
+ final_kwargs["f0_up_key"] = v
167
+ elif k == "method" and "f0_method" in valid_keys:
168
+ final_kwargs["f0_method"] = v
169
+
170
+ logs.append(log_message(f"⚙️ متد: {f0_method}"))
171
 
 
172
  start_time = time.time()
173
+ rvc.infer_file(**final_kwargs)
174
 
175
+ # پس‌پردازش
176
  final_output = output_temp
177
+ if enable_clarity and os.path.exists(output_temp):
178
+ logs.append(log_message("✨ اعمال فیلتر شفاف‌سازی..."))
179
  final_output = post_process_audio(output_temp, clarity_boost=True)
180
 
181
  duration = time.time() - start_time
182
  logs.append(log_message(f"✅ تمام شد! ({duration:.2f}s)"))
183
 
184
+ # اینجا خطایی که داشتید رفع شده است:
185
+ log_text = "
186
  ".join(logs)
187
+ return final_output, log_text
188
 
189
  except Exception as e:
190
+ err_msg = f"❌ خطا: {traceback.format_exc()}"
191
+ print(err_msg)
192
+ return None, err_msg
193
 
194
  # ==========================================
195
+ # 4. رابط کاربری
196
  # ==========================================
197
 
198
  custom_css = """
199
  #run_btn {background: linear-gradient(90deg, #FF5722 0%, #FF8A65 100%); color: white; border: none;}
 
200
  """
201
 
202
  with gr.Blocks(title="RVC Pro Persian", theme=gr.themes.Soft(), css=custom_css) as demo:
203
+ gr.Markdown("## 🎙️ RVC Pro: مبدل صدای حرفه‌ای (اصلاح شده)")
204
 
205
  with gr.Row():
206
  with gr.Column():
 
209
  model_input = gr.File(label="مدل (.pth)", file_types=[".pth"])
210
  index_input = gr.File(label="ایندکس (.index)", file_types=[".index"])
211
 
 
212
  algo_dropdown = gr.Dropdown(
213
  choices=["rmvpe", "fcpe", "crepe", "harvest", "pm"],
214
  value="rmvpe",
215
+ label="الگوریتم"
 
216
  )
217
+ pitch_slider = gr.Slider(-24, 24, value=0, step=1, label="تغییر گام")
 
 
218
  btn_run = gr.Button("🚀 تبدیل صدا", elem_id="run_btn", variant="primary")
219
 
220
  with gr.Column():
221
+ with gr.Accordion("تنظیمات کیفیت", open=True):
222
+ enable_clarity = gr.Checkbox(value=True, label="رفع تودماغی (Clarity)")
223
+ index_rate = gr.Slider(0, 1, value=0.4, step=0.05, label="تاثیر ایندکس")
224
+ envelope_mix = gr.Slider(0, 1, value=0.25, step=0.05, label="Volume Mix")
225
+ protect_val = gr.Slider(0, 0.5, value=0.33, step=0.01, label="Protect")
226
+ filter_radius = gr.Slider(0, 7, value=3, step=1, label="Filter Radius")
227
+ resample_sr = gr.Slider(0, 48000, value=0, step=1000, label="Resample SR")
228
+ hop_len = gr.Slider(1, 512, value=128, step=1, label="Hop Length")
 
 
 
 
 
 
229
 
230
  output_audio = gr.Audio(label="خروجی نهایی", type="filepath")
231
  logs = gr.Textbox(label="گزارش", lines=5)