talk-dial / app.py
suprimedev's picture
Update app.py
1d71064 verified
raw
history blame
9.73 kB
import gradio as gr
from pydub import AudioSegment
import requests
import os
import uuid
import re # برای پردازش لینک‌های ورودی
import mimetypes # برای استفاده از Content-Type برای تخمین پسوند فایل
# پوشه برای ذخیره فایل‌های موقت
TEMP_DIR = "temp_audio_files" # تغییر نام پوشه برای انعطاف‌پذیری بیشتر
os.makedirs(TEMP_DIR, exist_ok=True) # اطمینان از وجود پوشه
def download_audio(url: str, output_dir: str) -> tuple[str | None, str | None]:
"""
فایل صوتی را از URL دانلود می‌کند.
:param url: URL فایل صوتی.
:param output_dir: دایرکتوری برای ذخیره فایل دانلود شده.
:return: (مسیر کامل فایل دانلود شده, پسوند تخمین زده شده) یا (None, None) در صورت خطا.
"""
try:
response = requests.get(url, stream=True, timeout=30)
response.raise_for_status()
content_type = response.headers.get('Content-Type', '')
# تخمین پسوند فایل بر اساس Content-Type
# اگر نتوانستیم پسوند را از Content-Type حدس بزنیم، از 'mp3' به عنوان پیش‌فرض استفاده می‌کنیم
# این کار ریسک ایجاد می‌کند ولی pydub ممکن است بتواند آن را تشخیص دهد.
estimated_extension = mimetypes.guess_extension(content_type)
if not estimated_extension:
# سعی می‌کنیم پسوند را از URL بگیریم
path_parts = os.path.splitext(url.split('?')[0])
if len(path_parts) > 1 and path_parts[1]:
estimated_extension = path_parts[1].lower()
else:
# اگر هیچ کدام جواب نداد، mp3 را به عنوان پیش‌فرض قرار می‌دهیم
# pydub در زمان بارگذاری فایل واقعی، فرمت را بررسی می‌کند.
estimated_extension = ".mp3"
# اطمینان از پاک بودن پسوند (بدون نقطه اضافی)
if estimated_extension.startswith('.'):
estimated_extension = estimated_extension[1:]
# ساخت نام فایل موقت
temp_file_name = f"temp_download_{uuid.uuid4().hex}.{estimated_extension}"
output_path = os.path.join(output_dir, temp_file_name)
with open(output_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
print(f"Successfully downloaded {url} to {output_path} (estimated type: {estimated_extension})")
return output_path, estimated_extension
except requests.exceptions.Timeout:
print(f"Error downloading {url}: Request timed out.")
return None, None
except requests.exceptions.RequestException as e:
print(f"Error downloading {url}: {e}")
return None, None
except Exception as e:
print(f"An unexpected error occurred during download of {url}: {e}")
return None, None
def merge_audio_files_sequential(audio_file_paths: list[str], output_file_path: str) -> bool:
"""
چندین فایل صوتی را به ترتیب ادغام می‌کند. همه فایل‌ها به MP3 خروجی گرفته می‌شوند.
:param audio_file_paths: لیستی از مسیرهای فایل‌های صوتی (MP3, WAV, و غیره).
:param output_file_path: مسیر کامل برای ذخیره فایل ادغام شده (خروجی همیشه MP3 خواهد بود).
:return: True اگر ادغام موفق بود، False در غیر این صورت.
"""
if not audio_file_paths:
return False
combined_audio = None
try:
# بارگذاری اولین فایل
# pydub به طور خودکار فرمت را از پسوند فایل تشخیص می‌دهد.
combined_audio = AudioSegment.from_file(audio_file_paths[0])
# ادغام بقیه فایل‌ها
for i, file_path in enumerate(audio_file_paths[1:]):
audio = AudioSegment.from_file(file_path)
combined_audio += audio
print(f"Merged {file_path}")
# خروجی گرفتن نهایی به فرمت MP3
combined_audio.export(output_file_path, format="mp3")
print(f"Successfully merged all files to {output_file_path}")
return True
except Exception as e:
print(f"Error merging audio files: {e}")
return False
def process_audio_links_gradio(urls_input: str) -> tuple[str, str | None]:
"""
این تابع اصلی Gradio است که رشته‌ای از لینک‌های صوتی را دریافت کرده،
آن‌ها را دانلود و ادغام می‌کند.
:param urls_input: رشته‌ای شامل لینک‌های صوتی، جدا شده با خط جدید یا کاما.
:return: یک تاپل شامل پیام وضعیت و مسیر فایل خروجی (یا None).
"""
# پاکسازی و تقسیم لینک‌ها
urls = [url.strip() for url in re.split(r'[\n,]+', urls_input) if url.strip()]
if not urls:
return "لطفاً حداقل یک لینک فایل صوتی معتبر وارد کنید.", None
if len(urls) < 2:
return "لطفاً حداقل دو لینک فایل صوتی برای ادغام وارد کنید.", None
status_message = ""
output_audio_path = None
downloaded_files_paths = []
# برای تولید یک unique_id برای هر درخواست
request_unique_id = str(uuid.uuid4())
request_temp_dir = os.path.join(TEMP_DIR, request_unique_id)
os.makedirs(request_temp_dir, exist_ok=True)
try:
for i, url in enumerate(urls):
status_message += f"در حال دانلود فایل {i+1} از: {url}\n"
gr.Info(f"Downloading file {i+1}...")
# از تابع download_audio جدید استفاده می‌کنیم
downloaded_path, _ = download_audio(url, request_temp_dir)
if downloaded_path:
downloaded_files_paths.append(downloaded_path)
else:
return f"خطا در دانلود فایل {i+1} از '{url}'. لطفاً لینک را بررسی کنید. ممکن است فایل صوتی نباشد.", None
if not downloaded_files_paths:
return "هیچ فایلی با موفقیت دانلود نشد. لطفاً لینک‌ها را بررسی کنید.", None
status_message += "فایل‌ها با موفقیت دانلود شدند. در حال ادغام...\n"
gr.Info("Files downloaded. Merging...")
output_file_name = f"merged_output_{uuid.uuid4().hex}.mp3" # خروجی همیشه MP3 خواهد بود
output_file_path = os.path.join(request_temp_dir, output_file_name)
if merge_audio_files_sequential(downloaded_files_paths, output_file_path):
status_message += f"فایل‌ها با موفقیت ادغام شدند. فایل خروجی: {output_file_path}\n"
output_audio_path = output_file_path
else:
status_message += "خطا در ادغام فایل‌ها.\n"
except Exception as e:
status_message += f"خطای پیش‌بینی نشده: {e}\n"
finally:
# حذف فایل‌های موقت پس از اتمام کار
for f in os.listdir(request_temp_dir):
os.remove(os.path.join(request_temp_dir, f))
os.rmdir(request_temp_dir)
print(f"Removed temporary directory: {request_temp_dir}")
return status_message, output_audio_path
# تعریف رابط Gradio
# برای بهبود تجربه کاربری در فضای هاگینگ‌فیس، بهتر است از theme=gr.themes.Soft() استفاده کنید.
# و همچنین css را با دقت بیشتری برای RTL بنویسید.
iface = gr.Interface(
fn=process_audio_links_gradio,
inputs=[
gr.Textbox(
label="لینک‌های فایل صوتی (MP3, WAV و غیره) - هر لینک در یک خط یا با کاما جدا کنید",
placeholder="مثال:\nhttps://example.com/audio1.mp3\nhttps://example.com/audio2.wav\n...",
lines=5
),
],
outputs=[
gr.Textbox(label="وضعیت", interactive=False),
gr.Audio(label="فایل صوتی ادغام شده", type="filepath")
],
title="🎙️ ادغام کننده چندین فایل صوتی از طریق لینک (MP3, WAV و غیره) 🎵",
description="لینک فایل‌های صوتی خود را (هر لینک در یک خط جدید یا با کاما جدا شده) در کادر زیر وارد کنید تا به صورت یک فایل **MP3** ادغام شوند.",
allow_flagging="never",
theme=gr.themes.Soft(), # استفاده از تم جدید Gradio
css="""
body { font-family: 'Vazirmatn', sans-serif; direction: rtl; text-align: right; }
h1, h2, h3, h4, h5, h6 { text-align: center; }
.gr-textbox label, .gr-audio label { text-align: right; width: 100%; display: block; }
.gradio-container {
max-width: 800px;
margin: auto;
padding: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 8px;
}
.gr-button {
background-color: #4CAF50; /* Example button color */
color: white;
}
"""
)
# تابع راه اندازی:
if __name__ == "__main__":
iface.launch(share=True)