Rezfars commited on
Commit
2e9c550
·
verified ·
1 Parent(s): 085dd67

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +139 -15
app.py CHANGED
@@ -1,23 +1,147 @@
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
- # ... (همون تابع make_video که قبلاً دادم، فقط ورودی/خروجی رو با st عوض کن)
 
9
 
10
- st.title("Pixabay ویدیو ۳ ثانیه‌ای")
 
11
 
12
- keywords = st.text_input("کلمات کلیدی (با فاصله یا کاما)", "باران جنگل شب")
 
13
 
14
- if st.button("ساخت ویدیو"):
15
- if keywords:
16
- video_path, status = make_video(keywords)
17
- if video_path:
18
- st.video(video_path)
19
- st.success(status)
20
- else:
21
- st.error(status)
22
- else:
23
- st.warning("کلمه کلیدی وارد کن")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
  import requests
3
  import os
4
  from moviepy.editor import VideoFileClip, concatenate_videoclips
5
  import tempfile
 
6
 
7
+ # ---------------- تنظیمات ----------------
8
+ PIXABAY_API_KEY = os.getenv("PIXABAY_API_KEY") # در Settings → Secrets در Hugging Face بگذار
9
 
10
+ if not PIXABAY_API_KEY:
11
+ raise ValueError("لطفاً PIXABAY_API_KEY را در Secrets فضای خود قرار دهید!")
12
 
13
+ VIDEO_SEARCH_URL = "https://pixabay.com/api/videos/"
14
+ CLIP_DURATION = 3.0 # ثانیه
15
 
16
+ def download_video(url, temp_dir):
17
+ """دانلود ویدیو و برگرداندن مسیر فایل"""
18
+ response = requests.get(url, stream=True)
19
+ if response.status_code != 200:
20
+ return None
21
+
22
+ temp_path = os.path.join(temp_dir, "clip.mp4")
23
+ with open(temp_path, "wb") as f:
24
+ for chunk in response.iter_content(chunk_size=8192):
25
+ f.write(chunk)
26
+ return temp_path
27
+
28
+ def search_pixabay_videos(query, per_page=10):
29
+ params = {
30
+ "key": PIXABAY_API_KEY,
31
+ "q": query,
32
+ "video_type": "all", # all / film / animation
33
+ "per_page": per_page,
34
+ "min_duration": 4, # حداقل ۴ ثانیه که بتوان ۳ ثانیه برداشت
35
+ "safesearch": "true"
36
+ }
37
+
38
+ try:
39
+ r = requests.get(VIDEO_SEARCH_URL, params=params, timeout=15)
40
+ r.raise_for_status()
41
+ data = r.json()
42
+
43
+ videos = []
44
+ for hit in data.get("hits", []):
45
+ # بهترین کیفیت ممکن (large یا medium)
46
+ vid = hit.get("videos", {})
47
+ if "large" in vid and vid["large"]["url"]:
48
+ videos.append(vid["large"]["url"])
49
+ elif "medium" in vid and vid["medium"]["url"]:
50
+ videos.append(vid["medium"]["url"])
51
+
52
+ return videos[:8] # حداکثر ۸ تا ویدیو بگیریم که پردازش سنگین نشود
53
+ except Exception as e:
54
+ print(e)
55
+ return []
56
+
57
+ def create_montage(keywords):
58
+ if not keywords.strip():
59
+ return None, "لطفاً کلمات کلیدی وارد کنید"
60
+
61
+ query = keywords.strip().replace(",", " ").replace(" ", " ")
62
+
63
+ with tempfile.TemporaryDirectory() as tmpdirname:
64
+ video_urls = search_pixabay_videos(query)
65
+
66
+ if not video_urls:
67
+ return None, f"هیچ ویدیویی برای '{query}' پیدا نشد."
68
+
69
+ clips = []
70
+ count = 0
71
+
72
+ for url in video_urls:
73
+ try:
74
+ path = download_video(url, tmpdirname)
75
+ if not path:
76
+ continue
77
+
78
+ clip = VideoFileClip(path)
79
+
80
+ # اگر ویدیو کوتاه‌تر از ۳ ثانیه بود → skip
81
+ if clip.duration < CLIP_DURATION:
82
+ clip.close()
83
+ continue
84
+
85
+ # برش ۳ ثانیه (مثلاً از وسط یا اول)
86
+ start = max(0, (clip.duration - CLIP_DURATION) / 2) # وسط ویدیو
87
+ subclip = clip.subclip(start, start + CLIP_DURATION)
88
+
89
+ clips.append(subclip)
90
+ count += 1
91
+
92
+ clip.close()
93
+ if count >= 5: # مثلاً حداکثر ۵ قطعه → حدود ۱۵ ثانیه
94
+ break
95
+
96
+ except Exception as e:
97
+ print(f"خطا در پردازش ویدیو: {e}")
98
+ continue
99
+
100
+ if not clips:
101
+ return None, "متأسفانه نتوانستیم ویدیوهای مناسب دانلود/برش دهیم."
102
+
103
+ try:
104
+ final_clip = concatenate_videoclips(clips, method="compose")
105
+
106
+ # خروجی موقت
107
+ output_path = os.path.join(tmpdirname, "montage.mp4")
108
+ final_clip.write_videofile(output_path,
109
+ codec="libx264",
110
+ audio_codec="aac",
111
+ fps=24,
112
+ preset="medium",
113
+ threads=4,
114
+ logger=None)
115
+
116
+ return output_path, f"و��دیو با موفقیت ساخته شد ({len(clips)} قطعه × ۳ ثانیه)"
117
+
118
+ except Exception as e:
119
+ return None, f"خطا در ساخت ویدیو: {str(e)}"
120
+
121
+ finally:
122
+ # تمیز کردن حافظه
123
+ for c in clips:
124
+ c.close()
125
+ if 'final_clip' in locals():
126
+ final_clip.close()
127
+
128
+ # ---------------- رابط کاربری Gradio ----------------
129
+ with gr.Blocks(title="Pixabay Video Montage") as demo:
130
+ gr.Markdown("# ساخت مونتاژ ویدیو از Pixabay\nکلمات کلیدی را وارد کنید (مثال: nature, sunset, drone)")
131
+
132
+ textbox = gr.Textbox(label="کلمات کلیدی (با کاما یا فاصله جدا کنید)", placeholder="ocean waves, beach, sunset")
133
+
134
+ btn = gr.Button("ساخت ویدیو (۳ ثانیه از هر کلیپ)")
135
+
136
+ output_video = gr.Video(label="ویدیوی نهایی")
137
+ status = gr.Textbox(label="وضعیت")
138
+
139
+ btn.click(
140
+ fn=create_montage,
141
+ inputs=textbox,
142
+ outputs=[output_video, status],
143
+ api_name="make_montage"
144
+ )
145
+
146
+ if __name__ == "__main__":
147
+ demo.launch()