suprimedev commited on
Commit
cd88e5f
·
verified ·
1 Parent(s): 39ac26a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -45
app.py CHANGED
@@ -1,52 +1,180 @@
1
  import gradio as gr
2
  from pydub import AudioSegment
 
3
  import os
4
- from datetime import datetime
 
5
 
6
- def merge_mp3_files(file1, file2):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  try:
8
- # خواندن فایل‌های صوتی
9
- audio1 = AudioSegment.from_mp3(file1.name)
10
- audio2 = AudioSegment.from_mp3(file2.name)
11
-
12
- # ادغام فایل‌ها
13
- combined = audio1 + audio2
14
-
15
- # ایجاد نام فایل خروجی منحصر به فرد
16
- output_filename = f"merged_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp3"
17
-
18
- # ذخیره فایل ادغام شده
19
- combined.export(output_filename, format="mp3")
20
-
21
- return output_filename, f"فایل‌ها با موفقیت ادغام شدند. حجم فایل خروجی: {len(combined)} میلی‌ثانیه"
22
  except Exception as e:
23
- return None, f"خطا در پردازش فایل‌ها: {str(e)}"
24
-
25
- # رابط Gradio
26
- with gr.Blocks(title="ادغام کننده فایل‌های MP3") as demo:
27
- with gr.Row():
28
- gr.Markdown("""
29
- ## برنامه ادغام فایل‌های MP3
30
- لطفاً دو فایل MP3 را برای ادغام انتخاب کنید.
31
- """)
32
-
33
- with gr.Row():
34
- file1 = gr.File(label="فایل MP3 اول")
35
- file2 = gr.File(label="فایل MP3 دوم")
36
-
37
- with gr.Row():
38
- merge_btn = gr.Button("ادغام فایل‌ها")
39
-
40
- with gr.Row():
41
- output_file = gr.File(label="فایل ادغام شده", interactive=False)
42
- output_message = gr.Textbox(label="پیام سیستم", interactive=False)
43
-
44
- merge_btn.click(
45
- fn=merge_mp3_files,
46
- inputs=[file1, file2],
47
- outputs=[output_file, output_message]
48
- )
49
-
50
- # اجرای برنامه
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  if __name__ == "__main__":
52
- demo.launch()
 
1
  import gradio as gr
2
  from pydub import AudioSegment
3
+ import requests
4
  import os
5
+ import uuid
6
+ import re # برای پردازش لینک‌های ورودی
7
 
8
+ # پوشه برای ذخیره فایل‌های موقت
9
+ TEMP_DIR = "temp_mp3_files"
10
+ os.makedirs(TEMP_DIR, exist_ok=True) # اطمینان از وجود پوشه
11
+
12
+ def download_mp3(url: str, output_path: str) -> bool:
13
+ """
14
+ فایل MP3 را از URL دانلود می‌کند.
15
+ :param url: URL فایل MP3.
16
+ :param output_path: مسیر کامل برای ذخیره فایل دانلود شده.
17
+ :return: True اگر دانلود موفق بود، False در غیر این صورت.
18
+ """
19
+ try:
20
+ response = requests.get(url, stream=True, timeout=30) # افزودن timeout
21
+ response.raise_for_status() # برای HTTP errors (4xx or 5xx)
22
+
23
+ content_type = response.headers.get('Content-Type', '')
24
+ if 'audio' not in content_type and 'mpeg' not in content_type:
25
+ print(f"URL: {url} does not seem to point to an audio file. Content-Type: {content_type}")
26
+ return False
27
+
28
+ with open(output_path, 'wb') as f:
29
+ for chunk in response.iter_content(chunk_size=8192):
30
+ if chunk: # filter out keep-alive new chunks
31
+ f.write(chunk)
32
+ print(f"Successfully downloaded {url} to {output_path}")
33
+ return True
34
+ except requests.exceptions.Timeout:
35
+ print(f"Error downloading {url}: Request timed out.")
36
+ return False
37
+ except requests.exceptions.RequestException as e:
38
+ print(f"Error downloading {url}: {e}")
39
+ return False
40
+ except Exception as e:
41
+ print(f"An unexpected error occurred during download of {url}: {e}")
42
+ return False
43
+
44
+ def merge_mp3_files_sequential(mp3_file_paths: list[str], output_file_path: str) -> bool:
45
+ """
46
+ چندین فایل MP3 را به ترتیب ادغام می‌کند.
47
+ :param mp3_file_paths: لیستی از مسیرهای فایل‌های MP3.
48
+ :param output_file_path: مسیر کامل برای ذخیره فایل ادغام شده.
49
+ :return: True اگر ادغام موفق بود، False در غیر این صورت.
50
+ """
51
+ if not mp3_file_paths:
52
+ return False
53
+
54
+ combined_audio = None
55
  try:
56
+ # بارگذاری اولین فایل
57
+ combined_audio = AudioSegment.from_file(mp3_file_paths[0], format="mp3")
58
+
59
+ # ادغام بقیه فایل‌ها
60
+ for i, file_path in enumerate(mp3_file_paths[1:]):
61
+ audio = AudioSegment.from_file(file_path, format="mp3")
62
+ combined_audio += audio
63
+ print(f"Merged {file_path}")
64
+
65
+ combined_audio.export(output_file_path, format="mp3")
66
+ print(f"Successfully merged all files to {output_file_path}")
67
+ return True
 
 
68
  except Exception as e:
69
+ print(f"Error merging MP3 files: {e}")
70
+ return False
71
+
72
+ def process_mp3_links_gradio(urls_input: str) -> tuple[str, str | None]:
73
+ """
74
+ این تابع اصلی Gradio است که رشته‌ای از لینک‌های MP3 را دریافت کرده،
75
+ آن‌ها را دانلود و ادغام می‌کند.
76
+ :param urls_input: رشته‌ای شامل لینک‌های MP3، جدا شده با خط جدید یا کاما.
77
+ :return: یک تاپل شامل پیام وضعیت و مسیر فایل خروجی (یا None).
78
+ """
79
+ # پاکسازی و تقسیم لینک‌ها
80
+ # حذف فضای خالی اطراف لینک‌ها و فیلتر کردن لینک‌های خالی
81
+ urls = [url.strip() for url in re.split(r'[\n,]+', urls_input) if url.strip()]
82
+
83
+ if not urls:
84
+ return "لطفاً حداقل یک لینک MP3 معتبر وارد کنید.", None
85
+
86
+ if len(urls) < 2:
87
+ return "لطفاً حداقل دو لینک MP3 برای ادغام وارد کنید.", None
88
+
89
+ status_message = ""
90
+ output_audio_path = None
91
+ downloaded_files_paths = [] # برای نگهداری مسیر فایل‌های دانلود شده
92
+ temp_file_mapping = {} # URL -> temp_path
93
+
94
+ # برای تولید یک unique_id برای هر درخواست
95
+ request_unique_id = str(uuid.uuid4())
96
+ request_temp_dir = os.path.join(TEMP_DIR, request_unique_id)
97
+ os.makedirs(request_temp_dir, exist_ok=True)
98
+
99
+
100
+ try:
101
+ for i, url in enumerate(urls):
102
+ temp_file_name = f"temp_{i+1}_{uuid.uuid4().hex}.mp3"
103
+ temp_file_path = os.path.join(request_temp_dir, temp_file_name)
104
+ temp_file_mapping[url] = temp_file_path # ذخیره mapping برای حذف آسان
105
+
106
+ status_message += f"در حال دانلود فایل {i+1} از: {url}\n"
107
+ gr.Info(f"Downloading file {i+1}...") # نمایش پیام در UI Gradio
108
+ if download_mp3(url, temp_file_path):
109
+ downloaded_files_paths.append(temp_file_path)
110
+ else:
111
+ return f"خطا در دانلود فایل {i+1} از '{url}'. لطفاً لینک را بررسی کنید.", None
112
+
113
+ if not downloaded_files_paths:
114
+ return "هیچ فایلی با موفقیت دانلود نشد. لطفاً لینک‌ها را بررسی کنید.", None
115
+
116
+ status_message += "فایل‌ها با موفقیت دانلود شدند. در حال ادغام...\n"
117
+ gr.Info("Files downloaded. Merging...")
118
+
119
+ output_file_name = f"merged_output_{uuid.uuid4().hex}.mp3"
120
+ output_file_path = os.path.join(request_temp_dir, output_file_name)
121
+
122
+ if merge_mp3_files_sequential(downloaded_files_paths, output_file_path):
123
+ status_message += f"فایل‌ها با موفقیت ادغام شدند. فایل خروجی: {output_file_path}\n"
124
+ output_audio_path = output_file_path # مسیر فایل برای Gradio
125
+ else:
126
+ status_message += "خطا در ادغام فایل‌ها.\n"
127
+
128
+ except Exception as e:
129
+ status_message += f"خطای پیش‌بینی نشده: {e}\n"
130
+ finally:
131
+ # حذف فایل‌های موقت پس از اتمام کار
132
+ # حذف تنها فایل‌هایی که در این درخواست ایجاد شده‌اند
133
+ for f in os.listdir(request_temp_dir):
134
+ os.remove(os.path.join(request_temp_dir, f))
135
+ os.rmdir(request_temp_dir)
136
+ print(f"Removed temporary directory: {request_temp_dir}")
137
+
138
+ return status_message, output_audio_path
139
+
140
+ # تعریف رابط Gradio
141
+ # برای بهبود تجربه کاربری در فضای هاگینگ‌فیس، بهتر است از theme=gr.themes.Soft() استفاده کنید.
142
+ # و همچنین css را با دقت بیشتری برای RTL بنویسید.
143
+ iface = gr.Interface(
144
+ fn=process_mp3_links_gradio,
145
+ inputs=[
146
+ gr.Textbox(
147
+ label="لینک‌های MP3 (هر لینک در یک خط یا با کاما جدا کنید)",
148
+ placeholder="مثال:\nhttps://example.com/audio1.mp3\nhttps://example.com/audio2.mp3\n...",
149
+ lines=5 # امکان ورود چند خط
150
+ ),
151
+ ],
152
+ outputs=[
153
+ gr.Textbox(label="وضعیت", interactive=False),
154
+ gr.Audio(label="فایل MP3 ادغام شده", type="filepath")
155
+ ],
156
+ title="🎙️ ادغام کننده چندین فایل MP3 از طریق لینک 🎵",
157
+ description="لینک‌های فایل‌های MP3 خود را (هر لینک در یک خط جدید یا با کاما جدا شده) در کادر زیر وارد کنید تا به صورت یک فایل ادغام شوند.",
158
+ allow_flagging="never",
159
+ theme=gr.themes.Soft(), # استفاده از تم جدید Gradio
160
+ css="""
161
+ body { font-family: 'Vazirmatn', sans-serif; direction: rtl; text-align: right; }
162
+ h1, h2, h3, h4, h5, h6 { text-align: center; }
163
+ .gr-textbox label, .gr-audio label { text-align: right; width: 100%; display: block; }
164
+ .gradio-container {
165
+ max-width: 800px;
166
+ margin: auto;
167
+ padding: 20px;
168
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
169
+ border-radius: 8px;
170
+ }
171
+ .gr-button {
172
+ background-color: #4CAF50; /* Example button color */
173
+ color: white;
174
+ }
175
+ """
176
+ )
177
+
178
+ # تابع راه اندازی:
179
  if __name__ == "__main__":
180
+ iface.launch(share=True) # share=True برای دسترسی عمومی در هاگینگ‌فیس یا از طریق لینک موقت