Spaces:
Running
Running
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import torch
|
3 |
+
import torchaudio
|
4 |
+
from torchaudio.transforms import Resample
|
5 |
+
import numpy as np
|
6 |
+
import os
|
7 |
+
from datetime import datetime
|
8 |
+
import soundfile as sf
|
9 |
+
|
10 |
+
# بررسی وجود GPU
|
11 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
12 |
+
|
13 |
+
def load_audio(file_path, target_sr=16000):
|
14 |
+
"""بارگذاری فایل صوتی و تبدیل به تنسور"""
|
15 |
+
try:
|
16 |
+
waveform, sample_rate = torchaudio.load(file_path)
|
17 |
+
|
18 |
+
# تغییر نرخ نمونهبرداری در صورت نیاز
|
19 |
+
if sample_rate != target_sr:
|
20 |
+
resampler = Resample(sample_rate, target_sr)
|
21 |
+
waveform = resampler(waveform)
|
22 |
+
|
23 |
+
return waveform.to(device), target_sr
|
24 |
+
except Exception as e:
|
25 |
+
raise gr.Error(f"خطا در بارگذاری فایل صوتی: {str(e)}")
|
26 |
+
|
27 |
+
def preprocess_audio(waveform, sr):
|
28 |
+
"""پیشپردازش سیگنال صوتی"""
|
29 |
+
# نرمالایز کردن سیگنال
|
30 |
+
waveform = waveform / torch.max(torch.abs(waveform))
|
31 |
+
|
32 |
+
# تبدیل به مونو اگر استریو باشد
|
33 |
+
if waveform.shape[0] > 1:
|
34 |
+
waveform = torch.mean(waveform, dim=0, keepdim=True)
|
35 |
+
|
36 |
+
return waveform
|
37 |
+
|
38 |
+
def clone_voice(source_audio, target_audio, output_format="wav"):
|
39 |
+
"""عمل کلون کردن صدا"""
|
40 |
+
try:
|
41 |
+
# بارگذاری فایلهای صوتی
|
42 |
+
source_waveform, source_sr = load_audio(source_audio)
|
43 |
+
target_waveform, target_sr = load_audio(target_audio)
|
44 |
+
|
45 |
+
# پیشپردازش
|
46 |
+
source_waveform = preprocess_audio(source_waveform, source_sr)
|
47 |
+
target_waveform = preprocess_audio(target_waveform, target_sr)
|
48 |
+
|
49 |
+
# در اینجا باید مدل تبدیل صدا اعمال شود
|
50 |
+
# این قسمت سادهسازی شده و نیاز به پیادهسازی واقعی دارد
|
51 |
+
# برای نمونه، فقط طول موج هدف را با طول موج منبع هماهنگ میکنیم
|
52 |
+
min_len = min(source_waveform.shape[1], target_waveform.shape[1])
|
53 |
+
converted_waveform = target_waveform[:, :min_len]
|
54 |
+
|
55 |
+
# ذخیره فایل نتیجه
|
56 |
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
57 |
+
output_filename = f"output_{timestamp}.{output_format.lower()}"
|
58 |
+
|
59 |
+
# ذخیره با soundfile که با فرمتهای مختلف کار میکند
|
60 |
+
sf.write(output_filename, converted_waveform.cpu().numpy().T, target_sr)
|
61 |
+
|
62 |
+
return output_filename
|
63 |
+
except Exception as e:
|
64 |
+
raise gr.Error(f"خطا در پردازش صدا: {str(e)}")
|
65 |
+
|
66 |
+
# رابط Gradio
|
67 |
+
with gr.Blocks(title="Voice Cloner") as demo:
|
68 |
+
gr.Markdown("# 🎤 Voice Cloner")
|
69 |
+
gr.Markdown("بارگذاری فایل صوتی منبع و فایل صوتی هدف برای کلون کردن صدا")
|
70 |
+
|
71 |
+
with gr.Row():
|
72 |
+
with gr.Column():
|
73 |
+
source_audio = gr.Audio(label="فایل صوتی منبع (صدا برای کپی کردن)", type="filepath")
|
74 |
+
target_audio = gr.Audio(label="فایل صوتی هدف (محتوا برای تبدیل)", type="filepath")
|
75 |
+
output_format = gr.Dropdown(
|
76 |
+
choices=["wav", "mp3"],
|
77 |
+
value="wav",
|
78 |
+
label="فرمت فایل خروجی",
|
79 |
+
interactive=True
|
80 |
+
)
|
81 |
+
submit_btn = gr.Button("شروع تبدیل صدا")
|
82 |
+
|
83 |
+
with gr.Column():
|
84 |
+
output_audio = gr.Audio(label="فایل صوتی نتیجه", interactive=False)
|
85 |
+
download_link = gr.File(label="دانلود فایل نتیجه")
|
86 |
+
|
87 |
+
submit_btn.click(
|
88 |
+
fn=clone_voice,
|
89 |
+
inputs=[source_audio, target_audio, output_format],
|
90 |
+
outputs=[output_audio]
|
91 |
+
)
|
92 |
+
|
93 |
+
output_audio.change(
|
94 |
+
lambda x: gr.File(value=x),
|
95 |
+
inputs=[output_audio],
|
96 |
+
outputs=[download_link]
|
97 |
+
)
|
98 |
+
|
99 |
+
if __name__ == "__main__":
|
100 |
+
demo.launch()
|