Akshayram1 commited on
Commit
b4a62b8
Β·
verified Β·
1 Parent(s): ae60bbf

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +297 -33
src/streamlit_app.py CHANGED
@@ -1,40 +1,304 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  """
7
- # Welcome to Streamlit!
8
 
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
 
 
 
 
 
12
 
13
- In the meantime, below is an example of what you can do with just a few lines of code:
 
 
 
14
  """
 
15
 
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
1
  import streamlit as st
2
+ import openai
3
+ import requests
4
+ from PIL import Image
5
+ from io import BytesIO
6
+ import re
7
+ import urllib.parse
8
 
9
+ # Set up the page
10
+ st.set_page_config(
11
+ page_title="AI Thumbnail Generator",
12
+ page_icon="🎬",
13
+ layout="wide"
14
+ )
15
+
16
+ st.title("🎬 AI Video Thumbnail Generator")
17
+ st.write("Generate engaging thumbnails for your videos using only OpenAI API")
18
+
19
+ # Sidebar for API key
20
+ with st.sidebar:
21
+ st.header("πŸ”‘ Configuration")
22
+ openai_api_key = st.text_input("OpenAI API Key", type="password")
23
+
24
+ if openai_api_key:
25
+ openai.api_key = openai_api_key
26
+ st.success("API Key loaded!")
27
+ else:
28
+ st.warning("Enter your OpenAI API key to continue")
29
+
30
+ def extract_video_info(url):
31
+ """Extract video information from URL using pattern matching"""
32
+ video_info = {"platform": "unknown", "title": "", "id": ""}
33
+
34
+ # YouTube patterns
35
+ youtube_patterns = [
36
+ r'(?:youtube\.com/watch\?v=|youtu\.be/)([a-zA-Z0-9_-]+)',
37
+ r'youtube\.com/embed/([a-zA-Z0-9_-]+)'
38
+ ]
39
+
40
+ for pattern in youtube_patterns:
41
+ match = re.search(pattern, url)
42
+ if match:
43
+ video_info["platform"] = "youtube"
44
+ video_info["id"] = match.group(1)
45
+ break
46
+
47
+ # Vimeo pattern
48
+ vimeo_match = re.search(r'vimeo\.com/(\d+)', url)
49
+ if vimeo_match:
50
+ video_info["platform"] = "vimeo"
51
+ video_info["id"] = vimeo_match.group(1)
52
+
53
+ # Extract filename from URL for other videos
54
+ if video_info["platform"] == "unknown":
55
+ parsed_url = urllib.parse.urlparse(url)
56
+ filename = parsed_url.path.split('/')[-1]
57
+ video_info["title"] = filename.replace('.mp4', '').replace('.avi', '').replace('.mov', '')
58
+
59
+ return video_info
60
+
61
+ def analyze_video_content(url, custom_description=""):
62
+ """Use GPT to analyze and create description for thumbnail generation"""
63
+
64
+ video_info = extract_video_info(url)
65
+
66
+ prompt = f"""
67
+ I need to create an engaging thumbnail for a video. Here's what I know:
68
+
69
+ Video URL: {url}
70
+ Platform: {video_info['platform']}
71
+ Video ID: {video_info['id']}
72
+
73
+ """
74
+
75
+ if custom_description:
76
+ prompt += f"User Description: {custom_description}\n"
77
+
78
+ prompt += """
79
+ Based on this information, create a detailed description for an engaging video thumbnail that would:
80
+ 1. Grab viewers' attention
81
+ 2. Represent the video content accurately
82
+ 3. Look professional and clickable
83
+ 4. Include visual elements, colors, and composition suggestions
84
+
85
+ Respond with a clear, detailed description in 2-3 sentences that I can use to generate the thumbnail image.
86
+ """
87
+
88
+ try:
89
+ response = openai.ChatCompletion.create(
90
+ model="gpt-4",
91
+ messages=[{"role": "user", "content": prompt}],
92
+ max_tokens=200,
93
+ temperature=0.7
94
+ )
95
+ return response.choices[0].message.content.strip()
96
+ except Exception as e:
97
+ st.error(f"Error analyzing video: {str(e)}")
98
+ return None
99
+
100
+ def generate_thumbnail(description, style="professional", size="1024x1024"):
101
+ """Generate thumbnail using DALL-E"""
102
+
103
+ style_prompts = {
104
+ "professional": "professional, clean, high-quality",
105
+ "creative": "creative, artistic, visually striking",
106
+ "minimalist": "minimalist, clean, simple design",
107
+ "colorful": "vibrant, colorful, eye-catching",
108
+ "dramatic": "dramatic lighting, cinematic, bold"
109
+ }
110
+
111
+ full_prompt = f"""
112
+ Create a {style_prompts[style]} YouTube-style thumbnail image: {description}
113
+
114
+ Requirements:
115
+ - 16:9 aspect ratio suitable for video thumbnails
116
+ - High contrast and bold visual elements
117
+ - Professional quality that would perform well on video platforms
118
+ - Engaging composition that draws the eye
119
+ """
120
+
121
+ try:
122
+ response = openai.Image.create(
123
+ prompt=full_prompt,
124
+ n=1,
125
+ size=size,
126
+ quality="hd" if size == "1024x1024" else "standard"
127
+ )
128
+
129
+ image_url = response.data[0].url
130
+ image_response = requests.get(image_url)
131
+ return Image.open(BytesIO(image_response.content))
132
+
133
+ except Exception as e:
134
+ st.error(f"Error generating thumbnail: {str(e)}")
135
+ return None
136
+
137
+ # Main interface
138
+ st.header("πŸ“₯ Input")
139
+
140
+ col1, col2 = st.columns([2, 1])
141
+
142
+ with col1:
143
+ video_url = st.text_input(
144
+ "Video URL:",
145
+ placeholder="https://youtube.com/watch?v=... or https://example.com/video.mp4",
146
+ help="Paste any video URL here"
147
+ )
148
+
149
+ with col2:
150
+ custom_description = st.text_area(
151
+ "Video Description (Optional):",
152
+ placeholder="Describe your video content...",
153
+ height=100,
154
+ help="Add details about your video for better thumbnails"
155
+ )
156
+
157
+ # Style and options
158
+ st.header("🎨 Customization")
159
+
160
+ col1, col2, col3 = st.columns(3)
161
+
162
+ with col1:
163
+ thumbnail_style = st.selectbox(
164
+ "Thumbnail Style:",
165
+ ["professional", "creative", "minimalist", "colorful", "dramatic"],
166
+ help="Choose the visual style for your thumbnail"
167
+ )
168
+
169
+ with col2:
170
+ image_size = st.selectbox(
171
+ "Image Size:",
172
+ ["1024x1024", "512x512"],
173
+ help="Higher resolution costs more but looks better"
174
+ )
175
+
176
+ with col3:
177
+ num_variations = st.slider(
178
+ "Number of Variations:",
179
+ min_value=1,
180
+ max_value=4,
181
+ value=1,
182
+ help="Generate multiple thumbnail options"
183
+ )
184
+
185
+ # Generate button
186
+ if st.button("πŸš€ Generate Thumbnail", type="primary", use_container_width=True):
187
+
188
+ if not video_url:
189
+ st.error("❌ Please enter a video URL")
190
+
191
+ elif not openai_api_key:
192
+ st.error("❌ Please enter your OpenAI API key in the sidebar")
193
+
194
+ else:
195
+ # Step 1: Analyze video content
196
+ with st.spinner("πŸ” Analyzing video content..."):
197
+ analysis = analyze_video_content(video_url, custom_description)
198
+
199
+ if analysis:
200
+ st.success("βœ… Video analysis complete!")
201
+
202
+ with st.expander("πŸ“ AI Analysis", expanded=True):
203
+ st.write(analysis)
204
+
205
+ # Step 2: Generate thumbnails
206
+ st.header("πŸ–ΌοΈ Generated Thumbnails")
207
+
208
+ for i in range(num_variations):
209
+ with st.spinner(f"🎨 Generating thumbnail {i+1}/{num_variations}..."):
210
+
211
+ # Add variation to prompt for multiple generations
212
+ varied_analysis = analysis
213
+ if num_variations > 1:
214
+ varied_analysis += f" (Style variation {i+1})"
215
+
216
+ thumbnail = generate_thumbnail(varied_analysis, thumbnail_style, image_size)
217
+
218
+ if thumbnail:
219
+ col1, col2 = st.columns([3, 1])
220
+
221
+ with col1:
222
+ st.image(
223
+ thumbnail,
224
+ caption=f"Thumbnail {i+1} - {thumbnail_style.title()} Style",
225
+ use_column_width=True
226
+ )
227
+
228
+ with col2:
229
+ # Download button
230
+ buffer = BytesIO()
231
+ thumbnail.save(buffer, format="PNG")
232
+ st.download_button(
233
+ label="πŸ“₯ Download",
234
+ data=buffer.getvalue(),
235
+ file_name=f"thumbnail_{i+1}_{thumbnail_style}.png",
236
+ mime="image/png",
237
+ key=f"download_{i}",
238
+ use_container_width=True
239
+ )
240
+
241
+ st.divider()
242
+ else:
243
+ st.error("❌ Failed to analyze video content. Please try again.")
244
+
245
+ # Information sections
246
+ st.header("ℹ️ How It Works")
247
+
248
+ col1, col2, col3 = st.columns(3)
249
+
250
+ with col1:
251
+ st.subheader("1️⃣ URL Analysis")
252
+ st.write("AI analyzes your video URL and description to understand the content")
253
+
254
+ with col2:
255
+ st.subheader("2️⃣ Content Description")
256
+ st.write("GPT-4 creates a detailed description optimized for thumbnail generation")
257
+
258
+ with col3:
259
+ st.subheader("3️⃣ Image Generation")
260
+ st.write("DALL-E creates professional thumbnails based on the analysis")
261
+
262
+ # Supported platforms
263
+ st.header("🌐 Supported Platforms")
264
+ st.info("""
265
+ βœ… **Fully Supported:** YouTube, Vimeo, direct video file URLs
266
+ βœ… **Partially Supported:** Any video URL (works with custom descriptions)
267
+ βœ… **Best Results:** Provide detailed video descriptions for better thumbnails
268
+ """)
269
+
270
+ # Pricing info
271
+ st.header("πŸ’° Cost Information")
272
+ cost_info = f"""
273
+ **OpenAI API Costs (approximate):**
274
+ - GPT-4 Analysis: ~$0.001 per video
275
+ - DALL-E Image Generation: ~$0.04 per {image_size} image
276
+ - **Total per thumbnail:** ~$0.041 USD
277
+
278
+ *Costs may vary based on current OpenAI pricing*
279
  """
280
+ st.info(cost_info)
281
 
282
+ # Tips
283
+ st.header("πŸ’‘ Tips for Best Results")
284
+ tips = """
285
+ 🎯 **For Better Thumbnails:**
286
+ - Provide detailed video descriptions
287
+ - Use keywords that describe the mood/style
288
+ - Try different style variations
289
+ - Include the target audience in your description
290
 
291
+ πŸš€ **Platform Optimization:**
292
+ - Use colorful/dramatic styles for YouTube
293
+ - Professional style works well for business content
294
+ - Minimalist style good for educational content
295
  """
296
+ st.info(tips)
297
 
298
+ # Footer
299
+ st.divider()
300
+ st.markdown("""
301
+ <div style='text-align: center; color: #666;'>
302
+ <p>Built with ❀️ using Streamlit and OpenAI API</p>
303
+ </div>
304
+ """, unsafe_allow_html=True)