import streamlit as st import requests import os from moviepy.editor import VideoFileClip, concatenate_videoclips import tempfile import shutil # ---------------- تنظیمات ---------------- PIXABAY_API_KEY = os.getenv("PIXABAY_API_KEY") if not PIXABAY_API_KEY: st.error("لطفاً PIXABAY_API_KEY را در Settings → Secrets فضای Hugging Face قرار دهید!") st.stop() VIDEO_SEARCH_URL = "https://pixabay.com/api/videos/" CLIP_DURATION = 3.0 # ثانیه MAX_CLIPS = 5 # حداکثر تعداد کلیپ برای جلوگیری از سنگین شدن def search_pixabay_videos(query, per_page=12): params = { "key": PIXABAY_API_KEY, "q": query, "video_type": "all", "per_page": per_page, "min_duration": int(CLIP_DURATION + 1), "safesearch": "true" } try: response = requests.get(VIDEO_SEARCH_URL, params=params, timeout=20) response.raise_for_status() data = response.json() videos = [] for hit in data.get("hits", []): vid = hit.get("videos", {}) if "large" in vid and vid["large"].get("url"): videos.append(vid["large"]["url"]) elif "medium" in vid and vid["medium"].get("url"): videos.append(vid["medium"]["url"]) return videos except Exception as e: st.error(f"خطا در جستجو: {e}") return [] @st.cache_data(show_spinner="در حال دانلود و پردازش ویدیوها...") def create_montage(query): if not query.strip(): return None, "کلمات کلیدی وارد کنید" query_clean = " ".join(query.strip().split()) with tempfile.TemporaryDirectory() as tmp_dir: video_urls = search_pixabay_videos(query_clean) if not video_urls: return None, f"هیچ ویدیویی برای '{query}' پیدا نشد 😔" clips = [] downloaded = 0 progress_bar = st.progress(0) status_text = st.empty() for i, url in enumerate(video_urls): if downloaded >= MAX_CLIPS: break status_text.text(f"در حال پردازش ویدیو {i+1}/{len(video_urls)} ...") try: # دانلود resp = requests.get(url, stream=True, timeout=30) if resp.status_code != 200: continue temp_path = os.path.join(tmp_dir, f"video_{downloaded}.mp4") with open(temp_path, "wb") as f: shutil.copyfileobj(resp.raw, f) clip = VideoFileClip(temp_path) if clip.duration < CLIP_DURATION: clip.close() continue # برش از وسط (یا می‌تونی از اول بگیری: start=0) start = max(0, (clip.duration - CLIP_DURATION) / 2) subclip = clip.subclip(start, start + CLIP_DURATION) clips.append(subclip) downloaded += 1 clip.close() except Exception as e: st.warning(f"ویدیو {i+1} مشکل داشت: {e}") continue progress_bar.progress((i + 1) / len(video_urls)) progress_bar.empty() status_text.empty() if not clips: return None, "متأسفانه نتوانستیم ویدیو مناسب پردازش کنیم." try: final_clip = concatenate_videoclips(clips, method="compose") output_path = os.path.join(tmp_dir, "montage.mp4") with st.spinner("در حال ذخیره نهایی ویدیو..."): final_clip.write_videofile( output_path, codec="libx264", audio_codec="aac", fps=24, preset="medium", threads=2, logger=None ) for c in clips: c.close() final_clip.close() return output_path, f"موفق! {len(clips)} کلیپ × {CLIP_DURATION} ثانیه" except Exception as e: return None, f"خطا در ساخت ویدیو: {str(e)}" # ---------------- رابط کاربری Streamlit ---------------- st.set_page_config(page_title="مونتاژ ویدیو Pixabay", layout="wide") st.title("ساخت مونتاژ ویدیو از Pixabay 🎥") st.markdown("کلمات کلیدی را وارد کنید (مثال: sunset beach drone waves)") query = st.text_input( "کلمات کلیدی (با فاصله یا کاما جدا کنید)", placeholder="nature, mountain, timelapse, 4k", value="ocean sunset drone" ) if st.button("ساخت مونتاژ (۳ ثانیه از هر کلیپ)", type="primary"): with st.spinner("در حال جستجو و ساخت ویدیو... این ممکن است ۳۰–۹۰ ثانیه طول بکشد"): video_path, message = create_montage(query) if video_path: st.success(message) st.video(video_path) else: st.error(message) st.markdown("---") st.caption("نکته: API Key را در Secrets بگذارید | حداکثر ۵ کلیپ | هر کلیپ ۳ ثانیه")