import gradio as gr import requests import os from moviepy.editor import VideoFileClip, concatenate_videoclips import tempfile # ---------------- تنظیمات ---------------- PIXABAY_API_KEY = os.getenv("PIXABAY_API_KEY") # در Settings → Secrets در Hugging Face بگذار if not PIXABAY_API_KEY: raise ValueError("لطفاً PIXABAY_API_KEY را در Secrets فضای خود قرار دهید!") VIDEO_SEARCH_URL = "https://pixabay.com/api/videos/" CLIP_DURATION = 3.0 # ثانیه def download_video(url, temp_dir): """دانلود ویدیو و برگرداندن مسیر فایل""" response = requests.get(url, stream=True) if response.status_code != 200: return None temp_path = os.path.join(temp_dir, "clip.mp4") with open(temp_path, "wb") as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) return temp_path def search_pixabay_videos(query, per_page=10): params = { "key": PIXABAY_API_KEY, "q": query, "video_type": "all", # all / film / animation "per_page": per_page, "min_duration": 4, # حداقل ۴ ثانیه که بتوان ۳ ثانیه برداشت "safesearch": "true" } try: r = requests.get(VIDEO_SEARCH_URL, params=params, timeout=15) r.raise_for_status() data = r.json() videos = [] for hit in data.get("hits", []): # بهترین کیفیت ممکن (large یا medium) vid = hit.get("videos", {}) if "large" in vid and vid["large"]["url"]: videos.append(vid["large"]["url"]) elif "medium" in vid and vid["medium"]["url"]: videos.append(vid["medium"]["url"]) return videos[:8] # حداکثر ۸ تا ویدیو بگیریم که پردازش سنگین نشود except Exception as e: print(e) return [] def create_montage(keywords): if not keywords.strip(): return None, "لطفاً کلمات کلیدی وارد کنید" query = keywords.strip().replace(",", " ").replace(" ", " ") with tempfile.TemporaryDirectory() as tmpdirname: video_urls = search_pixabay_videos(query) if not video_urls: return None, f"هیچ ویدیویی برای '{query}' پیدا نشد." clips = [] count = 0 for url in video_urls: try: path = download_video(url, tmpdirname) if not path: continue clip = VideoFileClip(path) # اگر ویدیو کوتاه‌تر از ۳ ثانیه بود → skip if clip.duration < CLIP_DURATION: clip.close() continue # برش ۳ ثانیه (مثلاً از وسط یا اول) start = max(0, (clip.duration - CLIP_DURATION) / 2) # وسط ویدیو subclip = clip.subclip(start, start + CLIP_DURATION) clips.append(subclip) count += 1 clip.close() if count >= 5: # مثلاً حداکثر ۵ قطعه → حدود ۱۵ ثانیه break except Exception as e: print(f"خطا در پردازش ویدیو: {e}") continue if not clips: return None, "متأسفانه نتوانستیم ویدیوهای مناسب دانلود/برش دهیم." try: final_clip = concatenate_videoclips(clips, method="compose") # خروجی موقت output_path = os.path.join(tmpdirname, "montage.mp4") final_clip.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=24, preset="medium", threads=4, logger=None) return output_path, f"ویدیو با موفقیت ساخته شد ({len(clips)} قطعه × ۳ ثانیه)" except Exception as e: return None, f"خطا در ساخت ویدیو: {str(e)}" finally: # تمیز کردن حافظه for c in clips: c.close() if 'final_clip' in locals(): final_clip.close() # ---------------- رابط کاربری Gradio ---------------- with gr.Blocks(title="Pixabay Video Montage") as demo: gr.Markdown("# ساخت مونتاژ ویدیو از Pixabay\nکلمات کلیدی را وارد کنید (مثال: nature, sunset, drone)") textbox = gr.Textbox(label="کلمات کلیدی (با کاما یا فاصله جدا کنید)", placeholder="ocean waves, beach, sunset") btn = gr.Button("ساخت ویدیو (۳ ثانیه از هر کلیپ)") output_video = gr.Video(label="ویدیوی نهایی") status = gr.Textbox(label="وضعیت") btn.click( fn=create_montage, inputs=textbox, outputs=[output_video, status], api_name="make_montage" ) if __name__ == "__main__": demo.launch()