Rezfars commited on
Commit
856dcc0
·
verified ·
1 Parent(s): feccff5

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +150 -0
app.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+ import os
4
+ from moviepy.editor import VideoFileClip, concatenate_videoclips
5
+ import tempfile
6
+ import shutil
7
+
8
+ # ---------------- تنظیمات ----------------
9
+ PIXABAY_API_KEY = os.getenv("PIXABAY_API_KEY")
10
+
11
+ if not PIXABAY_API_KEY:
12
+ st.error("لطفاً PIXABAY_API_KEY را در Settings → Secrets فضای Hugging Face قرار دهید!")
13
+ st.stop()
14
+
15
+ VIDEO_SEARCH_URL = "https://pixabay.com/api/videos/"
16
+ CLIP_DURATION = 3.0 # ثانیه
17
+ MAX_CLIPS = 5 # حداکثر تعداد کلیپ برای جلوگیری از سنگین شدن
18
+
19
+ def search_pixabay_videos(query, per_page=12):
20
+ params = {
21
+ "key": PIXABAY_API_KEY,
22
+ "q": query,
23
+ "video_type": "all",
24
+ "per_page": per_page,
25
+ "min_duration": int(CLIP_DURATION + 1),
26
+ "safesearch": "true"
27
+ }
28
+ try:
29
+ response = requests.get(VIDEO_SEARCH_URL, params=params, timeout=20)
30
+ response.raise_for_status()
31
+ data = response.json()
32
+ videos = []
33
+ for hit in data.get("hits", []):
34
+ vid = hit.get("videos", {})
35
+ if "large" in vid and vid["large"].get("url"):
36
+ videos.append(vid["large"]["url"])
37
+ elif "medium" in vid and vid["medium"].get("url"):
38
+ videos.append(vid["medium"]["url"])
39
+ return videos
40
+ except Exception as e:
41
+ st.error(f"خطا در جستجو: {e}")
42
+ return []
43
+
44
+ @st.cache_data(show_spinner="در حال دانلود و پردازش ویدیوها...")
45
+ def create_montage(query):
46
+ if not query.strip():
47
+ return None, "کلمات کلیدی وارد کنید"
48
+
49
+ query_clean = " ".join(query.strip().split())
50
+
51
+ with tempfile.TemporaryDirectory() as tmp_dir:
52
+ video_urls = search_pixabay_videos(query_clean)
53
+
54
+ if not video_urls:
55
+ return None, f"هیچ ویدیویی برای '{query}' پیدا نشد 😔"
56
+
57
+ clips = []
58
+ downloaded = 0
59
+ progress_bar = st.progress(0)
60
+ status_text = st.empty()
61
+
62
+ for i, url in enumerate(video_urls):
63
+ if downloaded >= MAX_CLIPS:
64
+ break
65
+
66
+ status_text.text(f"در حال پردازش ویدیو {i+1}/{len(video_urls)} ...")
67
+
68
+ try:
69
+ # دانلود
70
+ resp = requests.get(url, stream=True, timeout=30)
71
+ if resp.status_code != 200:
72
+ continue
73
+
74
+ temp_path = os.path.join(tmp_dir, f"video_{downloaded}.mp4")
75
+ with open(temp_path, "wb") as f:
76
+ shutil.copyfileobj(resp.raw, f)
77
+
78
+ clip = VideoFileClip(temp_path)
79
+ if clip.duration < CLIP_DURATION:
80
+ clip.close()
81
+ continue
82
+
83
+ # برش از وسط (یا می‌تونی از اول بگیری: start=0)
84
+ start = max(0, (clip.duration - CLIP_DURATION) / 2)
85
+ subclip = clip.subclip(start, start + CLIP_DURATION)
86
+ clips.append(subclip)
87
+ downloaded += 1
88
+
89
+ clip.close()
90
+
91
+ except Exception as e:
92
+ st.warning(f"ویدیو {i+1} مشکل داشت: {e}")
93
+ continue
94
+
95
+ progress_bar.progress((i + 1) / len(video_urls))
96
+
97
+ progress_bar.empty()
98
+ status_text.empty()
99
+
100
+ if not clips:
101
+ return None, "متأسفانه نتوانستیم ویدیو مناسب پردازش کنیم."
102
+
103
+ try:
104
+ final_clip = concatenate_videoclips(clips, method="compose")
105
+ output_path = os.path.join(tmp_dir, "montage.mp4")
106
+
107
+ with st.spinner("در حال ذخیره نهایی ویدیو..."):
108
+ final_clip.write_videofile(
109
+ output_path,
110
+ codec="libx264",
111
+ audio_codec="aac",
112
+ fps=24,
113
+ preset="medium",
114
+ threads=2,
115
+ logger=None
116
+ )
117
+
118
+ for c in clips:
119
+ c.close()
120
+ final_clip.close()
121
+
122
+ return output_path, f"موفق! {len(clips)} کلیپ × {CLIP_DURATION} ثانیه"
123
+
124
+ except Exception as e:
125
+ return None, f"خطا در ساخت ویدیو: {str(e)}"
126
+
127
+ # ---------------- رابط کاربری Streamlit ----------------
128
+ st.set_page_config(page_title="مونتاژ ویدیو Pixabay", layout="wide")
129
+
130
+ st.title("ساخت مونتاژ ویدیو از Pixabay 🎥")
131
+ st.markdown("کلمات کلیدی را وارد کنید (مثال: sunset beach drone waves)")
132
+
133
+ query = st.text_input(
134
+ "کلمات کلیدی (با فاصله یا کاما جدا کنید)",
135
+ placeholder="nature, mountain, timelapse, 4k",
136
+ value="ocean sunset drone"
137
+ )
138
+
139
+ if st.button("ساخت مونتاژ (۳ ثانیه از هر کلیپ)", type="primary"):
140
+ with st.spinner("در حال جستجو و ساخت ویدیو... این ممکن است ۳۰–۹۰ ثانیه طول بکشد"):
141
+ video_path, message = create_montage(query)
142
+
143
+ if video_path:
144
+ st.success(message)
145
+ st.video(video_path)
146
+ else:
147
+ st.error(message)
148
+
149
+ st.markdown("---")
150
+ st.caption("نکته: API Key را در Secrets بگذارید | حداکثر ۵ کلیپ | هر کلیپ ۳ ثانیه")