Mahmoudmody777 commited on
Commit
cc8814e
·
verified ·
1 Parent(s): b3eed00

Upload 14 files

Browse files
background.png ADDED
export_button.png ADDED
export_button_hover.png ADDED
icons/facebook_icon.png ADDED
icons/facebook_icon_hover.png ADDED
icons/instagram_icon.png ADDED
icons/instagram_icon_hover.png ADDED
icons/twitter_icon.png ADDED
icons/twitter_icon_hover.png ADDED
icons/youtube_icon.png ADDED
icons/youtube_icon_hover.png ADDED
main.py ADDED
@@ -0,0 +1,353 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import tkinter as tk
3
+ from tkinter import ttk, messagebox
4
+ from PIL import Image, ImageTk
5
+ import requests
6
+ from bs4 import BeautifulSoup
7
+ import google.generativeai as genai
8
+ import json
9
+ from io import BytesIO
10
+ from moviepy.editor import ImageSequenceClip, AudioFileClip, concatenate_videoclips
11
+ import sys
12
+ import re
13
+ # إعدادات FFmpeg
14
+ root = tk.Tk()
15
+ root.title("أداة عمل المحتوى من قناة مدرسة الذكاء الاصطناعي")
16
+ root.geometry("930x820")
17
+ root.resizable(False, False)
18
+
19
+ if getattr(sys, 'frozen', False):
20
+ base_path = sys._MEIPASS # عند تشغيل ملف EXE
21
+ ffmpeg_exe = os.path.join(base_path, 'ffmpeg', 'ffmpeg.exe')
22
+ else:
23
+ base_path = os.path.dirname(os.path.abspath(__file__)) # عند تشغيل PyCharm
24
+ ffmpeg_exe = os.path.join(base_path, 'ffmpeg', 'ffmpeg.exe')
25
+
26
+
27
+ background_image_path = os.path.join(base_path, "background.png")
28
+ background_image = Image.open(background_image_path)
29
+ background_photo = ImageTk.PhotoImage(background_image)
30
+
31
+ canvas = tk.Canvas(root, width=930, height=820)
32
+ canvas.pack(fill="both", expand=True)
33
+ canvas.create_image(0, 0, image=background_photo, anchor="nw")
34
+
35
+ # إعدادات الأيقونات
36
+ icons = {
37
+ "YouTube": ("icons/youtube_icon.png", "icons/youtube_icon_hover.png", "https://youtube.com/@arabianAiSchool/"),
38
+ "Instagram": ("icons/instagram_icon.png", "icons/instagram_icon_hover.png", "https://www.instagram.com/arabianaischool"),
39
+ "Twitter": ("icons/twitter_icon.png", "icons/twitter_icon_hover.png", "https://twitter.com/arabianaischool"),
40
+ "Facebook": ("icons/facebook_icon.png", "icons/facebook_icon_hover.png", "https://www.facebook.com/arabianaischool")
41
+ }
42
+
43
+ icon_positions = [(300, 170), (370, 170), (440, 170), (510, 170)]
44
+ icon_labels = []
45
+
46
+ def on_enter_icon(event, icon_label, hover_photo):
47
+ icon_label.config(image=hover_photo)
48
+
49
+ def on_leave_icon(event, icon_label, photo):
50
+ icon_label.config(image=photo)
51
+
52
+ def open_link(url):
53
+ import webbrowser
54
+ webbrowser.open(url)
55
+
56
+ for (name, (icon_path, hover_icon_path, url)), (x, y) in zip(icons.items(), icon_positions):
57
+ icon_image = Image.open(os.path.join(base_path, icon_path))
58
+ icon_hover_image = Image.open(os.path.join(base_path, hover_icon_path))
59
+
60
+ icon_image = icon_image.resize((50, 50), Image.LANCZOS)
61
+ icon_hover_image = icon_hover_image.resize((50, 50), Image.LANCZOS)
62
+
63
+ icon_photo = ImageTk.PhotoImage(icon_image)
64
+ icon_hover_photo = ImageTk.PhotoImage(icon_hover_image)
65
+
66
+ icon_label = tk.Label(root, image=icon_photo, cursor="hand2", bg="#000000")
67
+ icon_label.image = icon_photo
68
+ icon_label.place(x=x, y=y)
69
+ icon_label.bind("<Button-1>", lambda e, url=url: open_link(url))
70
+ icon_label.bind("<Enter>", lambda e, icon_label=icon_label, hover_photo=icon_hover_photo: on_enter_icon(e, icon_label, hover_photo))
71
+ icon_label.bind("<Leave>", lambda e, icon_label=icon_label, photo=icon_photo: on_leave_icon(e, icon_label, photo))
72
+ icon_labels.append(icon_label)
73
+
74
+ # الحقول المدخلة
75
+ gemini_label = tk.Label(root, text="أدخل مفتاح جيميناي:", font=("Arial", 14, "bold"), bg="#000000", fg="#FFFFFF")
76
+ gemini_label.place(x=660, y=240)
77
+ gemini_entry = ttk.Entry(root, width=40, font=("Arial", 14))
78
+ gemini_entry.place(x=200, y=240)
79
+
80
+ eleven_label = tk.Label(root, text="أدخل مفتاح الفن لابس", font=("Arial", 14, "bold"), bg="#000000", fg="#FFFFFF")
81
+ eleven_label.place(x=660, y=280)
82
+ eleven_entry = ttk.Entry(root, width=40, font=("Arial", 14))
83
+ eleven_entry.place(x=200, y=280)
84
+
85
+ # تمكين النسخ واللصق في حقول الإدخال
86
+ def paste_into_entry(event, entry):
87
+ try:
88
+ entry.insert(tk.INSERT, root.clipboard_get())
89
+ except tk.TclError:
90
+ pass
91
+
92
+ def create_entry_context_menu(entry):
93
+ menu = tk.Menu(entry, tearoff=0)
94
+ menu.add_command(label="قص", command=lambda: entry.event_generate('<<Cut>>'))
95
+ menu.add_command(label="نسخ", command=lambda: entry.event_generate('<<Copy>>'))
96
+ menu.add_command(label="لصق", command=lambda: entry.event_generate('<<Paste>>'))
97
+
98
+ def show_context_menu(event):
99
+ menu.tk_popup(event.x_root, event.y_root)
100
+ return "break"
101
+
102
+ entry.bind("<Button-3>", show_context_menu) # للويندوز
103
+ entry.bind("<Button-2>", show_context_menu) # للماك
104
+
105
+ # ربط Ctrl+V بحقول الإدخال
106
+ gemini_entry.bind('<Control-v>', lambda event: paste_into_entry(event, gemini_entry))
107
+ eleven_entry.bind('<Control-v>', lambda event: paste_into_entry(event, eleven_entry))
108
+
109
+ # إنشاء قوائم منبثقة لحقول الإدخال
110
+ create_entry_context_menu(gemini_entry)
111
+ create_entry_context_menu(eleven_entry)
112
+
113
+ # قائمة نوع المحتوى مع الأنواع الجديدة
114
+ content_types = ["رياضي", "ترفيهي", "اخباري", "معلومات عامة", "تحفيزي"]
115
+ content_type_label = tk.Label(root, text="اختر نوع المحتوى", font=("Arial", 14, "bold"), bg="#000000", fg="#FFFFFF")
116
+ content_type_label.place(x=660, y=330)
117
+ content_type_combo = ttk.Combobox(root, values=content_types, font=("Arial", 14))
118
+ content_type_combo.place(x=400, y=330)
119
+ content_type_combo.current(0)
120
+
121
+ # قسم الجدولة
122
+ schedule_label = tk.Label(root, text="حدد وقت عمل الفيديو", font=("Arial", 14, "bold"), bg="#000000", fg="#FFFFFF")
123
+ schedule_label.place(x=660, y=380)
124
+ hour_label = tk.Label(root, text="ساعة", font=("Arial", 12, "bold"), bg="#000000", fg="#FFFFFF")
125
+ hour_label.place(x=600, y=380)
126
+ minute_label = tk.Label(root, text="دقيقة:", font=("Arial", 12, "bold"), bg="#000000", fg="#FFFFFF")
127
+ minute_label.place(x=400, y=380)
128
+ hour_entry = ttk.Combobox(root, values=[f"{i:02}" for i in range(24)], width=5, font=("Arial", 12))
129
+ hour_entry.place(x=490, y=380)
130
+ minute_entry = ttk.Combobox(root, values=[f"{i:02}" for i in range(60)], width=5, font=("Arial", 12))
131
+ minute_entry.place(x=280, y=380)
132
+
133
+ # تأثيرات الأزرار عند المرور عليها
134
+ def on_enter_save_button(event):
135
+ save_button.config(image=save_button_hover_photo)
136
+
137
+ def on_leave_save_button(event):
138
+ save_button.config(image=save_button_photo)
139
+
140
+ save_button_image_path = os.path.join(base_path, "save_button.png")
141
+ save_button_hover_image_path = os.path.join(base_path, "save_button_hover.png")
142
+ save_button_image = Image.open(save_button_image_path).resize((300, 70), Image.LANCZOS)
143
+ save_button_hover_image = Image.open(save_button_hover_image_path).resize((300, 70), Image.LANCZOS)
144
+ save_button_photo = ImageTk.PhotoImage(save_button_image)
145
+ save_button_hover_photo = ImageTk.PhotoImage(save_button_hover_image)
146
+
147
+ save_button = tk.Button(root, image=save_button_photo, command=lambda: print("Settings Saved"), borderwidth=0, bg="#000000")
148
+ save_button.place(x=340, y=450)
149
+ save_button.bind("<Enter>", on_enter_save_button)
150
+ save_button.bind("<Leave>", on_leave_save_button)
151
+
152
+ def on_enter_export_button(event):
153
+ export_button.config(image=export_button_hover_photo)
154
+
155
+ def on_leave_export_button(event):
156
+ export_button.config(image=export_button_photo)
157
+
158
+ export_button_image_path = os.path.join(base_path, "export_button.png")
159
+ export_button_hover_image_path = os.path.join(base_path, "export_button_hover.png")
160
+ export_button_image = Image.open(export_button_image_path).resize((300, 70), Image.LANCZOS)
161
+ export_button_hover_image = Image.open(export_button_hover_image_path).resize((300, 70), Image.LANCZOS)
162
+ export_button_photo = ImageTk.PhotoImage(export_button_image)
163
+ export_button_hover_photo = ImageTk.PhotoImage(export_button_hover_image)
164
+
165
+ export_button = tk.Button(root, image=export_button_photo, command=lambda: create_content(), borderwidth=0, bg="#000000")
166
+ export_button.place(x=340, y=570)
167
+ export_button.bind("<Enter>", on_enter_export_button)
168
+ export_button.bind("<Leave>", on_leave_export_button)
169
+
170
+ # وظيفة إنشاء النص بناءً على نوع المحتوى
171
+ def generate_script_based_on_content_type(api_key, content_type):
172
+ genai.configure(api_key=api_key)
173
+ if content_type == "رياضي":
174
+ prompt = "ااكتب نصًا باللغة العربية لفيديو مدته 60 ثانية لقناة يوتيوب متخصصة في حقائق كرة القدم. يجب أن يكون النص جذابًا ومثيرًا، يركز على قصة أو حقيقة عن لاعب كرة قدم أو مدرب أو حدث مهم في عالم كرة القدم. امزج بين الإثارة والواقعية. اذكر كيف غير هذا الشخص أو الحدث مسار مباراة أو بطولة مهمة بطريقة غير متوقعة. قم بتضمين دعوة للمشاهدين للإعجاب بالفيديو والتعليق والاشتراك في القناة لمزيد من الفيديوهات. اجعل الأسلوب حيويًا وشيقًا، مع التركيز على جذب الانتباه بسرعة. لا تذكر توجيهات مشهدية أو إشارات بصرية محددة في النص"
175
+ elif content_type == "ترفيهي":
176
+ prompt = "اكتب نصًا باللغة العربية لفيديو مدته 60 ثانية لقناة يوتيوب ترفيهية..."
177
+ elif content_type == "اخباري":
178
+ prompt = "اكتب نصًا باللغة العربية لفيديو مدته 60 ثانية لقناة يوتيوب إخبارية. يجب أن يكون النص دقيقًا ومثيرًا، يركز على خبر حديث أو حدث مهم يجري الآن في العالم أو المنطقة. امزج بين المعلومات والموضوعية. اذكر التفاصيل الأساسية وكيف يؤثر هذا الخبر على الجمهور أو المجتمع بشكل عام. قم بتضمين دعوة للمشاهدين للإعجاب بالفيديو والتعليق والاشتراك في القناة لمزيد من التحديثات الإخبارية. ��جعل الأسلوب واضحًا وجذابًا، مع التركيز على نقل المعلومة بسرعة وفعالية. لا تذكر توجيهات مشهدية أو إشارات بصرية محددة في النص."
179
+ elif content_type == "معلومات عامة":
180
+ prompt = "اكتب نصًا باللغة العربية لفيديو مدته 60 ثانية لقناة يوتيوب تقدم معلومات عامة مفيدة. يجب أن يكون النص مفيدًا ومثيرًا للاهتمام، يركز على معلومة أو حقيقة غير معروفة عن موضوع مثل العلوم، التاريخ، الثقافة، أو الطبيعة. امزج بين المعرفة والتشويق. اذكر كيف يمكن لهذه المعلومة أن توسع آفاق المشاهدين أو تغير فهمهم لموضوع معين. قم بتضمين دعوة للمشاهدين للإعجاب بالفيديو والتعليق والاشتراك في القناة لمزيد من المحتوى المثير للاهتمام. اجعل الأسلوب حيويًا وجاذبًا، مع التركيز على تقديم المعلومة بطريقة سهلة الفهم. لا تذكر توجيهات مشهدية أو إشارات بصرية محددة في النص"
181
+ elif content_type == "تحفيزي":
182
+ prompt = "اكتب نصًا باللغة العربية لفيديو مدته 60 ثانية لقناة يوتيوب تحفيزية. يجب أن يكون النص ملهمًا ومحفزًا، يركز على قصة نجاح، اقتباس مؤثر، أو رسالة تشجيعية تدفع المشاهدين لتحقيق أهدافهم. امزج بين الإلهام والواقعية. اذكر كيف يمكن للتفاني والإصرار أن يغير حياة الشخص بشكل إيجابي. قم بتضمين دعوة للمشاهدين للإعجاب بالفيديو والتعليق والاشتراك في القناة لمزيد من المحتوى التحفيزي. اجعل الأسلوب مؤثرًا وجاذبًا، مع التركيز على تحفيز المشاهدين لاتخاذ خطوات إيجابية. لا تذكر توجيهات مشهدية أو إشارات بصرية محددة في النص"
183
+
184
+ else:
185
+ prompt = ""
186
+
187
+ if not prompt:
188
+ return ""
189
+
190
+ model = genai.GenerativeModel('gemini-pro')
191
+ chat = model.start_chat(history=[])
192
+ response = chat.send_message(prompt)
193
+ return response.text
194
+
195
+ # تنظيف النص
196
+ def clean_script(script):
197
+ lines = script.split('\n')
198
+ cleaned_lines = [line for line in lines if not any(word in line.lower() for word in ['مشهد', 'صورة', 'لقطة'])]
199
+ return '\n'.join(cleaned_lines)
200
+
201
+ # إنشاء التعليق الصوتي باستخدام Eleven Labs API
202
+ def generate_voiceover(script, api_key):
203
+ try:
204
+ url = "https://api.elevenlabs.io/v1/text-to-speech/pNInz6obpgDQGcFmaJgB"
205
+ headers = {
206
+ "Accept": "audio/mpeg",
207
+ "Content-Type": "application/json",
208
+ "xi-api-key": api_key
209
+ }
210
+ data = {
211
+ "text": script,
212
+ "model_id": "eleven_multilingual_v2",
213
+ "voice_settings": {
214
+ "stability": 0.5,
215
+ "similarity_boost": 0.5
216
+ }
217
+ }
218
+ response = requests.post(url, json=data, headers=headers)
219
+ response.raise_for_status()
220
+ output_audio_filename = 'arabic_voiceover.mp3'
221
+ with open(output_audio_filename, 'wb') as f:
222
+ for chunk in response.iter_content(chunk_size=1024):
223
+ if chunk:
224
+ f.write(chunk)
225
+ print(f"تم إنشاء الصوت وحفظه كـ {output_audio_filename}")
226
+ return output_audio_filename
227
+ except Exception as e:
228
+ print(f"Error generating voiceover: {e}")
229
+ return None
230
+
231
+ # استخراج المصطلحات الأساسية للصور
232
+ def extract_arabic_key_terms(script):
233
+ words = re.findall(r'\b\w+\b', script)
234
+ return list(set(words))
235
+
236
+ # تنزيل صور عالية الجودة من Bing وتعديل حجمها
237
+ def download_images_from_bing(query, num_images, folder):
238
+ headers = {
239
+ "User-Agent": "Mozilla/5.0"
240
+ }
241
+ search_url = f"https://www.bing.com/images/search?q={query}&FORM=HDRSC2"
242
+ response = requests.get(search_url, headers=headers)
243
+ soup = BeautifulSoup(response.text, 'html.parser')
244
+ image_elements = soup.find_all('a', {'class': 'iusc'})
245
+
246
+ os.makedirs(folder, exist_ok=True)
247
+ image_count = 0
248
+
249
+ for i, img_element in enumerate(image_elements):
250
+ if image_count >= num_images:
251
+ break
252
+ m = img_element.get('m')
253
+ if m:
254
+ m = json.loads(m)
255
+ img_url = m['murl']
256
+
257
+ if img_url:
258
+ try:
259
+ img_data = requests.get(img_url, headers=headers, timeout=10).content
260
+ img = Image.open(BytesIO(img_data))
261
+ img = resize_and_crop_image(img)
262
+ img_filename = os.path.join(folder, f'image_{image_count + 1}.jpg')
263
+ img.save(img_filename, format='JPEG', quality=95)
264
+ image_count += 1
265
+ print(f"Downloaded {img_filename}")
266
+ except Exception as e:
267
+ print(f"Failed to download image {i + 1}: {e}")
268
+
269
+ # تعديل حجم الصورة إلى 1080x1920
270
+ def resize_and_crop_image(img):
271
+ target_size = (1080, 1920)
272
+ img_ratio = img.width / img.height
273
+ target_ratio = target_size[0] / target_size[1]
274
+
275
+ if img_ratio > target_ratio:
276
+ # قص العرض
277
+ new_width = int(img.height * target_ratio)
278
+ left = (img.width - new_width) // 2
279
+ img = img.crop((left, 0, left + new_width, img.height))
280
+ else:
281
+ # قص الارتفاع
282
+ new_height = int(img.width / target_ratio)
283
+ top = (img.height - new_height) // 2
284
+ img = img.crop((0, top, img.width, top + new_height))
285
+
286
+ img = img.resize(target_size, Image.LANCZOS)
287
+ return img
288
+
289
+ # إنشاء الفيديو مع الترجمة
290
+ def create_video_from_images_and_audio(image_folder, audio_filename):
291
+ image_files = sorted([os.path.join(image_folder, img) for img in os.listdir(image_folder) if img.endswith(".jpg")])
292
+ if not image_files:
293
+ messagebox.showwarning("تحذير", "لا توجد صور لإنشاء الفيديو.")
294
+ return
295
+
296
+ clips = []
297
+ duration_per_image = None
298
+
299
+ if audio_filename and os.path.exists(audio_filename):
300
+ audio_clip = AudioFileClip(audio_filename)
301
+ total_duration = audio_clip.duration
302
+ duration_per_image = total_duration / len(image_files)
303
+ else:
304
+ total_duration = len(image_files) * 3 # نفترض 3 ثواني لكل صورة
305
+ duration_per_image = 3
306
+
307
+ # إنشاء مقاطع الصور
308
+ for img_path in image_files:
309
+ img_clip = ImageSequenceClip([img_path], durations=[duration_per_image])
310
+ clips.append(img_clip)
311
+
312
+ video_clip = concatenate_videoclips(clips)
313
+
314
+ if audio_filename and os.path.exists(audio_filename):
315
+ video_clip = video_clip.set_audio(audio_clip)
316
+
317
+ # تحديد مسار سطح المكتب
318
+ desktop_path = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop')
319
+ output_video_path = os.path.join(desktop_path, "final_video.mp4")
320
+
321
+ video_clip.write_videofile(output_video_path, fps=24, codec="libx264", audio_codec="aac")
322
+
323
+ def create_content():
324
+ gemini_api_key = gemini_entry.get()
325
+ eleven_labs_api_key = eleven_entry.get()
326
+ content_type = content_type_combo.get()
327
+
328
+ script = generate_script_based_on_content_type(gemini_api_key, content_type)
329
+ if not script:
330
+ messagebox.showwarning("تحذير", "لا يوجد نص لتوليد المحتوى.")
331
+ return
332
+
333
+ cleaned_script = clean_script(script)
334
+
335
+ # إنشاء التعليق الصوتي
336
+ voiceover_filename = generate_voiceover(cleaned_script, eleven_labs_api_key)
337
+
338
+ # استخراج المصطلحات الأساسية
339
+ key_terms = extract_arabic_key_terms(cleaned_script)
340
+
341
+ # تنزيل الصور
342
+ total_images = 0
343
+ for term in key_terms:
344
+ download_images_from_bing(term, num_images=2, folder="visual")
345
+ total_images += 2 # نفترض صورتين لكل مصطلح
346
+
347
+ # إنشاء الفيديو
348
+ try:
349
+ create_video_from_images_and_audio("visual", voiceover_filename)
350
+ messagebox.showinfo("نجاح", "تم إنشاء المحتوى بنجاح!")
351
+ except Exception as e:
352
+ messagebox.showerror("خطأ", f"حدث خطأ أثناء إنشاء الفيديو: {e}")
353
+ root.mainloop()
save_button.png ADDED
save_button_hover.png ADDED