talk-dial / app.py
suprimedev's picture
Update app.py
cd88e5f verified
raw
history blame
8.41 kB
import gradio as gr
from pydub import AudioSegment
import requests
import os
import uuid
import re # برای پردازش لینک‌های ورودی
# پوشه برای ذخیره فایل‌های موقت
TEMP_DIR = "temp_mp3_files"
os.makedirs(TEMP_DIR, exist_ok=True) # اطمینان از وجود پوشه
def download_mp3(url: str, output_path: str) -> bool:
"""
فایل MP3 را از URL دانلود می‌کند.
:param url: URL فایل MP3.
:param output_path: مسیر کامل برای ذخیره فایل دانلود شده.
:return: True اگر دانلود موفق بود، False در غیر این صورت.
"""
try:
response = requests.get(url, stream=True, timeout=30) # افزودن timeout
response.raise_for_status() # برای HTTP errors (4xx or 5xx)
content_type = response.headers.get('Content-Type', '')
if 'audio' not in content_type and 'mpeg' not in content_type:
print(f"URL: {url} does not seem to point to an audio file. Content-Type: {content_type}")
return False
with open(output_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
print(f"Successfully downloaded {url} to {output_path}")
return True
except requests.exceptions.Timeout:
print(f"Error downloading {url}: Request timed out.")
return False
except requests.exceptions.RequestException as e:
print(f"Error downloading {url}: {e}")
return False
except Exception as e:
print(f"An unexpected error occurred during download of {url}: {e}")
return False
def merge_mp3_files_sequential(mp3_file_paths: list[str], output_file_path: str) -> bool:
"""
چندین فایل MP3 را به ترتیب ادغام می‌کند.
:param mp3_file_paths: لیستی از مسیرهای فایل‌های MP3.
:param output_file_path: مسیر کامل برای ذخیره فایل ادغام شده.
:return: True اگر ادغام موفق بود، False در غیر این صورت.
"""
if not mp3_file_paths:
return False
combined_audio = None
try:
# بارگذاری اولین فایل
combined_audio = AudioSegment.from_file(mp3_file_paths[0], format="mp3")
# ادغام بقیه فایل‌ها
for i, file_path in enumerate(mp3_file_paths[1:]):
audio = AudioSegment.from_file(file_path, format="mp3")
combined_audio += audio
print(f"Merged {file_path}")
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 MP3 files: {e}")
return False
def process_mp3_links_gradio(urls_input: str) -> tuple[str, str | None]:
"""
این تابع اصلی Gradio است که رشته‌ای از لینک‌های MP3 را دریافت کرده،
آن‌ها را دانلود و ادغام می‌کند.
:param urls_input: رشته‌ای شامل لینک‌های MP3، جدا شده با خط جدید یا کاما.
:return: یک تاپل شامل پیام وضعیت و مسیر فایل خروجی (یا None).
"""
# پاکسازی و تقسیم لینک‌ها
# حذف فضای خالی اطراف لینک‌ها و فیلتر کردن لینک‌های خالی
urls = [url.strip() for url in re.split(r'[\n,]+', urls_input) if url.strip()]
if not urls:
return "لطفاً حداقل یک لینک MP3 معتبر وارد کنید.", None
if len(urls) < 2:
return "لطفاً حداقل دو لینک MP3 برای ادغام وارد کنید.", None
status_message = ""
output_audio_path = None
downloaded_files_paths = [] # برای نگهداری مسیر فایل‌های دانلود شده
temp_file_mapping = {} # URL -> temp_path
# برای تولید یک 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):
temp_file_name = f"temp_{i+1}_{uuid.uuid4().hex}.mp3"
temp_file_path = os.path.join(request_temp_dir, temp_file_name)
temp_file_mapping[url] = temp_file_path # ذخیره mapping برای حذف آسان
status_message += f"در حال دانلود فایل {i+1} از: {url}\n"
gr.Info(f"Downloading file {i+1}...") # نمایش پیام در UI Gradio
if download_mp3(url, temp_file_path):
downloaded_files_paths.append(temp_file_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"
output_file_path = os.path.join(request_temp_dir, output_file_name)
if merge_mp3_files_sequential(downloaded_files_paths, output_file_path):
status_message += f"فایل‌ها با موفقیت ادغام شدند. فایل خروجی: {output_file_path}\n"
output_audio_path = output_file_path # مسیر فایل برای Gradio
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_mp3_links_gradio,
inputs=[
gr.Textbox(
label="لینک‌های MP3 (هر لینک در یک خط یا با کاما جدا کنید)",
placeholder="مثال:\nhttps://example.com/audio1.mp3\nhttps://example.com/audio2.mp3\n...",
lines=5 # امکان ورود چند خط
),
],
outputs=[
gr.Textbox(label="وضعیت", interactive=False),
gr.Audio(label="فایل MP3 ادغام شده", type="filepath")
],
title="🎙️ ادغام کننده چندین فایل MP3 از طریق لینک 🎵",
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) # share=True برای دسترسی عمومی در هاگینگ‌فیس یا از طریق لینک موقت