Dhruv-Ty commited on
Commit
45857ba
·
verified ·
1 Parent(s): b7ccc33

Create main.py

Browse files
Files changed (1) hide show
  1. main.py +275 -0
main.py ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import tempfile
3
+ import os
4
+ import yt_dlp
5
+ import re
6
+ from pathlib import Path
7
+ import google.generativeai as genai
8
+ from google.generativeai import upload_file, get_file
9
+ import time
10
+
11
+ # Configure Google AI
12
+ GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
13
+ if GOOGLE_API_KEY:
14
+ genai.configure(api_key=GOOGLE_API_KEY)
15
+ else:
16
+ raise ValueError("GOOGLE_API_KEY environment variable not set")
17
+
18
+ def is_valid_url(url):
19
+ """Check if URL is from supported platforms"""
20
+ patterns = [
21
+ r'(https?://)?(www\.)?(youtube\.com|youtu\.be)',
22
+ r'(https?://)?(www\.)?(instagram\.com|instagr\.am)',
23
+ r'(https?://)?(www\.)?(tiktok\.com)',
24
+ r'(https?://)?(www\.)?(twitter\.com|x\.com)',
25
+ ]
26
+
27
+ for pattern in patterns:
28
+ if re.search(pattern, url, re.IGNORECASE):
29
+ return True
30
+ return False
31
+
32
+ def download_video(url, progress=gr.Progress()):
33
+ """Download video from URL using yt-dlp"""
34
+ if not is_valid_url(url):
35
+ raise gr.Error("Please enter a valid YouTube, Instagram, TikTok, or X video URL")
36
+
37
+ progress(0.1, desc="Starting download...")
38
+
39
+ # Create temp file
40
+ temp_video = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
41
+ temp_video.close()
42
+
43
+ # yt-dlp options optimized for HF Spaces
44
+ ydl_opts = {
45
+ 'outtmpl': temp_video.name,
46
+ 'format': 'best[filesize<100M]/worst[filesize<100M]/best',
47
+ 'quiet': True,
48
+ 'no_warnings': True,
49
+ 'nooverwrites': False,
50
+ 'user_agent': 'Mozilla/5.0 (compatible; GradioApp/1.0)',
51
+ 'retries': 2,
52
+ 'fragment_retries': 2,
53
+ 'extractor_retries': 2,
54
+ 'socket_timeout': 30,
55
+ 'nocheckcertificate': True,
56
+ }
57
+
58
+ progress(0.3, desc="Downloading video...")
59
+
60
+ try:
61
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
62
+ ydl.download([url])
63
+
64
+ # Verify download
65
+ if os.path.exists(temp_video.name) and os.path.getsize(temp_video.name) > 0:
66
+ file_size_mb = os.path.getsize(temp_video.name) / (1024 * 1024)
67
+
68
+ if file_size_mb > 100:
69
+ os.unlink(temp_video.name)
70
+ raise gr.Error(f"Video too large ({file_size_mb:.1f}MB). Please use a smaller video.")
71
+
72
+ progress(0.7, desc="Processing video...")
73
+ return temp_video.name
74
+ else:
75
+ raise gr.Error("Downloaded file is empty or doesn't exist")
76
+
77
+ except Exception as e:
78
+ # Clean up on error
79
+ if os.path.exists(temp_video.name):
80
+ try:
81
+ os.unlink(temp_video.name)
82
+ except:
83
+ pass
84
+
85
+ error_msg = str(e)
86
+ if "403" in error_msg or "Forbidden" in error_msg:
87
+ raise gr.Error("Video download was blocked. Try a different video or use a shorter one.")
88
+ elif "404" in error_msg:
89
+ raise gr.Error("Video not found. Please check the URL.")
90
+ else:
91
+ raise gr.Error(f"Download failed: {error_msg}")
92
+
93
+ def analyze_video_with_ai(video_path, query, progress=gr.Progress()):
94
+ """Analyze video using Google Gemini AI"""
95
+ if not video_path or not os.path.exists(video_path):
96
+ raise gr.Error("No video file found")
97
+
98
+ progress(0.1, desc="Uploading video to AI...")
99
+
100
+ try:
101
+ # Upload video to Google AI
102
+ processed_video = upload_file(video_path)
103
+
104
+ progress(0.5, desc="Processing video...")
105
+
106
+ # Wait for processing
107
+ while processed_video.state.name == "PROCESSING":
108
+ time.sleep(2)
109
+ processed_video = get_file(processed_video.name)
110
+
111
+ if processed_video.state.name == "FAILED":
112
+ raise gr.Error("Video processing failed")
113
+
114
+ progress(0.8, desc="Generating response...")
115
+
116
+ # Generate AI response
117
+ model = genai.GenerativeModel('gemini-2.0-flash-exp')
118
+
119
+ prompt = f"""
120
+ Analyze this video and respond to the user's question: {query}
121
+
122
+ Provide a comprehensive, insightful response that includes:
123
+ 1. Direct analysis of the video content
124
+ 2. Key insights and observations
125
+ 3. Specific details from what you can see/hear
126
+ 4. Actionable takeaways if relevant
127
+
128
+ Be conversational and engaging while being thorough and accurate.
129
+ """
130
+
131
+ response = model.generate_content([processed_video, prompt])
132
+
133
+ progress(1.0, desc="Complete!")
134
+
135
+ return response.text
136
+
137
+ except Exception as e:
138
+ raise gr.Error(f"AI analysis failed: {str(e)}")
139
+
140
+ finally:
141
+ # Clean up video file
142
+ try:
143
+ if video_path and os.path.exists(video_path):
144
+ os.unlink(video_path)
145
+ except:
146
+ pass
147
+
148
+ def process_video_and_chat(url, query):
149
+ """Main function to download video and get AI response"""
150
+ if not url.strip():
151
+ raise gr.Error("Please enter a video URL")
152
+
153
+ if not query.strip():
154
+ raise gr.Error("Please enter a question about the video")
155
+
156
+ # Download video
157
+ progress = gr.Progress()
158
+ progress(0.0, desc="Starting...")
159
+
160
+ video_path = download_video(url, progress)
161
+
162
+ # Analyze with AI
163
+ response = analyze_video_with_ai(video_path, query, progress)
164
+
165
+ return response
166
+
167
+ # Create Gradio interface
168
+ def create_interface():
169
+ with gr.Blocks(
170
+ title="The Plug - AI Video Analyzer",
171
+ theme=gr.themes.Soft(),
172
+ css="""
173
+ .gradio-container {
174
+ max-width: 800px !important;
175
+ margin: auto !important;
176
+ }
177
+ .header {
178
+ text-align: center;
179
+ margin-bottom: 2rem;
180
+ }
181
+ .footer {
182
+ text-align: center;
183
+ margin-top: 2rem;
184
+ color: #666;
185
+ }
186
+ """
187
+ ) as demo:
188
+
189
+ # Header
190
+ gr.HTML("""
191
+ <div class="header">
192
+ <h1>🎥 The Plug - AI Video Analyzer</h1>
193
+ <p>Analyze videos from YouTube, Instagram, TikTok, and X with AI</p>
194
+ </div>
195
+ """)
196
+
197
+ with gr.Row():
198
+ with gr.Column():
199
+ # Video URL input
200
+ video_url = gr.Textbox(
201
+ label="Video URL",
202
+ placeholder="https://youtube.com/watch?v=... or Instagram/TikTok/X link",
203
+ lines=1,
204
+ info="Paste a video URL from YouTube, Instagram, TikTok, or X"
205
+ )
206
+
207
+ # Query input
208
+ query = gr.Textbox(
209
+ label="Your Question",
210
+ placeholder="What is the main topic? Summarize the key points...",
211
+ lines=3,
212
+ info="Ask anything about the video content"
213
+ )
214
+
215
+ # Submit button
216
+ submit_btn = gr.Button("🚀 Analyze Video", variant="primary", size="lg")
217
+
218
+ with gr.Row():
219
+ with gr.Column():
220
+ # Response output
221
+ response = gr.Textbox(
222
+ label="AI Analysis",
223
+ lines=15,
224
+ max_lines=25,
225
+ interactive=False,
226
+ show_copy_button=True
227
+ )
228
+
229
+ # Example queries
230
+ gr.Examples(
231
+ examples=[
232
+ ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "What is this video about?"],
233
+ ["", "Summarize the key points mentioned"],
234
+ ["", "What are the main takeaways?"],
235
+ ["", "Who is the target audience?"],
236
+ ],
237
+ inputs=[video_url, query],
238
+ label="Example Questions"
239
+ )
240
+
241
+ # Footer
242
+ gr.HTML("""
243
+ <div class="footer">
244
+ <p>Built with ❤️ using Gradio and Google Gemini AI</p>
245
+ <p>Supports YouTube, Instagram, TikTok, and X video URLs</p>
246
+ </div>
247
+ """)
248
+
249
+ # Connect the function
250
+ submit_btn.click(
251
+ fn=process_video_and_chat,
252
+ inputs=[video_url, query],
253
+ outputs=response,
254
+ show_progress=True
255
+ )
256
+
257
+ # Also allow Enter key to submit
258
+ query.submit(
259
+ fn=process_video_and_chat,
260
+ inputs=[video_url, query],
261
+ outputs=response,
262
+ show_progress=True
263
+ )
264
+
265
+ return demo
266
+
267
+ # Launch the app
268
+ if __name__ == "__main__":
269
+ demo = create_interface()
270
+ demo.launch(
271
+ share=True,
272
+ server_name="0.0.0.0",
273
+ server_port=7860,
274
+ show_error=True
275
+ )