Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| from openai import OpenAI | |
| import requests | |
| from PIL import Image | |
| from io import BytesIO | |
| import re | |
| import urllib.parse | |
| # Set up the page | |
| st.set_page_config( | |
| page_title="AI Thumbnail Generator", | |
| page_icon="π¬", | |
| layout="wide" | |
| ) | |
| st.title("π¬ AI Video Thumbnail Generator") | |
| st.write("Generate engaging thumbnails for your videos using OpenAI's DALL-E 3") | |
| # Sidebar for API key | |
| with st.sidebar: | |
| st.header("π Configuration") | |
| openai_api_key = st.text_input("OpenAI API Key", type="password") | |
| if openai_api_key: | |
| client = OpenAI(api_key=openai_api_key) | |
| st.success("API Key loaded!") | |
| else: | |
| st.warning("Enter your OpenAI API key to continue") | |
| client = None | |
| def extract_video_info(url): | |
| """Extract video information from URL using web scraping""" | |
| video_info = {"platform": "unknown", "title": "", "id": "", "description": "", "extraction_success": False} | |
| try: | |
| # Identify platform first | |
| if 'facebook.com' in url or 'fb.watch' in url: | |
| video_info["platform"] = "facebook" | |
| # Extract video ID from Facebook URL patterns | |
| fb_patterns = [ | |
| r'facebook\.com/.*?/videos/(\d+)', | |
| r'facebook\.com/watch/?\?v=(\d+)', | |
| r'facebook\.com/share/v/([a-zA-Z0-9]+)', | |
| r'fb\.watch/([a-zA-Z0-9_-]+)' | |
| ] | |
| for pattern in fb_patterns: | |
| match = re.search(pattern, url) | |
| if match: | |
| video_info["id"] = match.group(1) | |
| break | |
| st.warning("π Facebook videos require special handling. Please use **Manual Description mode** for best results.") | |
| return video_info | |
| elif 'instagram.com' in url: | |
| video_info["platform"] = "instagram" | |
| # Extract Instagram post/reel ID | |
| ig_patterns = [ | |
| r'instagram\.com/p/([a-zA-Z0-9_-]+)', | |
| r'instagram\.com/reel/([a-zA-Z0-9_-]+)', | |
| r'instagram\.com/tv/([a-zA-Z0-9_-]+)' | |
| ] | |
| for pattern in ig_patterns: | |
| match = re.search(pattern, url) | |
| if match: | |
| video_info["id"] = match.group(1) | |
| break | |
| st.warning("π Instagram videos require login access. Please use **Manual Description mode** for best results.") | |
| return video_info | |
| elif 'tiktok.com' in url: | |
| video_info["platform"] = "tiktok" | |
| # Extract TikTok video ID | |
| tiktok_match = re.search(r'tiktok\.com/.*?/video/(\d+)', url) | |
| if tiktok_match: | |
| video_info["id"] = tiktok_match.group(1) | |
| st.warning("π TikTok videos have access restrictions. Please use **Manual Description mode** for best results.") | |
| return video_info | |
| elif 'twitter.com' in url or 'x.com' in url: | |
| video_info["platform"] = "twitter" | |
| # Extract tweet ID | |
| twitter_patterns = [ | |
| r'twitter\.com/.*?/status/(\d+)', | |
| r'x\.com/.*?/status/(\d+)' | |
| ] | |
| for pattern in twitter_patterns: | |
| match = re.search(pattern, url) | |
| if match: | |
| video_info["id"] = match.group(1) | |
| break | |
| st.warning("π Twitter/X videos have access restrictions. Please use **Manual Description mode** for best results.") | |
| return video_info | |
| # For supported platforms, continue with web scraping | |
| headers = { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' | |
| } | |
| response = requests.get(url, headers=headers, timeout=10) | |
| html_content = response.text | |
| # YouTube patterns | |
| youtube_patterns = [ | |
| r'(?:youtube\.com/watch\?v=|youtu\.be/)([a-zA-Z0-9_-]+)', | |
| r'youtube\.com/embed/([a-zA-Z0-9_-]+)' | |
| ] | |
| for pattern in youtube_patterns: | |
| match = re.search(pattern, url) | |
| if match: | |
| video_info["platform"] = "youtube" | |
| video_info["id"] = match.group(1) | |
| # Extract title from YouTube | |
| title_patterns = [ | |
| r'<title>([^<]+)</title>', | |
| r'"title":"([^"]+)"', | |
| r'<meta property="og:title" content="([^"]+)"' | |
| ] | |
| for title_pattern in title_patterns: | |
| title_match = re.search(title_pattern, html_content) | |
| if title_match: | |
| video_info["title"] = title_match.group(1).replace(' - YouTube', '').replace('\\u0026', '&') | |
| break | |
| # Extract description from meta tags | |
| desc_patterns = [ | |
| r'<meta name="description" content="([^"]+)"', | |
| r'<meta property="og:description" content="([^"]+)"', | |
| r'"description":"([^"]+)"' | |
| ] | |
| for desc_pattern in desc_patterns: | |
| desc_match = re.search(desc_pattern, html_content) | |
| if desc_match: | |
| video_info["description"] = desc_match.group(1).replace('\\n', ' ').replace('\\u0026', '&') | |
| break | |
| video_info["extraction_success"] = True | |
| break | |
| # Vimeo pattern | |
| vimeo_match = re.search(r'vimeo\.com/(\d+)', url) | |
| if vimeo_match: | |
| video_info["platform"] = "vimeo" | |
| video_info["id"] = vimeo_match.group(1) | |
| # Extract title from Vimeo | |
| title_patterns = [ | |
| r'<title>([^<]+)</title>', | |
| r'<meta property="og:title" content="([^"]+)"' | |
| ] | |
| for title_pattern in title_patterns: | |
| title_match = re.search(title_pattern, html_content) | |
| if title_match: | |
| video_info["title"] = title_match.group(1).replace(' on Vimeo', '') | |
| break | |
| # Extract description | |
| desc_patterns = [ | |
| r'<meta name="description" content="([^"]+)"', | |
| r'<meta property="og:description" content="([^"]+)"' | |
| ] | |
| for desc_pattern in desc_patterns: | |
| desc_match = re.search(desc_pattern, html_content) | |
| if desc_match: | |
| video_info["description"] = desc_match.group(1) | |
| break | |
| video_info["extraction_success"] = True | |
| # For other platforms, try to extract general info | |
| if video_info["platform"] == "unknown": | |
| # Try to get title from any webpage | |
| title_patterns = [ | |
| r'<title>([^<]+)</title>', | |
| r'<meta property="og:title" content="([^"]+)"' | |
| ] | |
| for title_pattern in title_patterns: | |
| title_match = re.search(title_pattern, html_content) | |
| if title_match: | |
| video_info["title"] = title_match.group(1) | |
| break | |
| # Try to get description from meta tags | |
| desc_patterns = [ | |
| r'<meta name="description" content="([^"]+)"', | |
| r'<meta property="og:description" content="([^"]+)"' | |
| ] | |
| for desc_pattern in desc_patterns: | |
| desc_match = re.search(desc_pattern, html_content) | |
| if desc_match: | |
| video_info["description"] = desc_match.group(1) | |
| video_info["extraction_success"] = True | |
| break | |
| # Extract filename as fallback | |
| from urllib.parse import urlparse | |
| parsed_url = urlparse(url) | |
| filename = parsed_url.path.split('/')[-1] | |
| if not video_info["title"] and filename: | |
| video_info["title"] = filename.replace('.mp4', '').replace('.avi', '').replace('.mov', '') | |
| except Exception as e: | |
| st.warning(f"β οΈ Could not automatically extract video information: {str(e)}") | |
| st.info("π‘ **Tip:** Use **Manual Description mode** for better results with this URL.") | |
| # Try to at least identify the platform for better guidance | |
| if 'facebook.com' in url or 'fb.watch' in url: | |
| video_info["platform"] = "facebook" | |
| elif 'instagram.com' in url: | |
| video_info["platform"] = "instagram" | |
| elif 'tiktok.com' in url: | |
| video_info["platform"] = "tiktok" | |
| elif 'twitter.com' in url or 'x.com' in url: | |
| video_info["platform"] = "twitter" | |
| elif 'youtube.com' in url or 'youtu.be' in url: | |
| video_info["platform"] = "youtube" | |
| elif 'vimeo.com' in url: | |
| video_info["platform"] = "vimeo" | |
| # Fallback to basic URL parsing | |
| from urllib.parse import urlparse | |
| parsed_url = urlparse(url) | |
| filename = parsed_url.path.split('/')[-1] | |
| if filename: | |
| video_info["title"] = filename.replace('.mp4', '').replace('.avi', '').replace('.mov', '') | |
| return video_info | |
| def analyze_video_content(url, custom_description=""): | |
| """Use GPT to analyze and create description for thumbnail generation""" | |
| if not client: | |
| return None | |
| video_info = extract_video_info(url) | |
| prompt = f""" | |
| I need to create an engaging video thumbnail. Here's the video information I gathered: | |
| URL: {url} | |
| Platform: {video_info['platform']} | |
| Video ID: {video_info['id']} | |
| Title: {video_info['title']} | |
| Description: {video_info['description']} | |
| """ | |
| if custom_description: | |
| prompt += f"Additional User Description: {custom_description}\n" | |
| prompt += """ | |
| Based on this video information, analyze the content and create a detailed description for generating an engaging thumbnail that would: | |
| 1. Grab viewers' attention and make them want to click | |
| 2. Accurately represent the video content based on the title and description | |
| 3. Look professional and suitable for the platform | |
| 4. Include specific visual elements, colors, mood, and composition suggestions | |
| 5. Consider what type of content this appears to be (educational, entertainment, tutorial, etc.) | |
| Please provide: | |
| - A clear, detailed description for the thumbnail image (2-3 sentences) | |
| - Suggested visual style and mood | |
| - Key elements that should be prominently featured | |
| Focus on creating a thumbnail that would perform well and attract the target audience for this type of content. | |
| """ | |
| try: | |
| response = client.chat.completions.create( | |
| model="gpt-4", | |
| messages=[{"role": "user", "content": prompt}], | |
| max_tokens=300, | |
| temperature=0.7 | |
| ) | |
| return response.choices[0].message.content.strip() | |
| except Exception as e: | |
| st.error(f"Error analyzing video: {str(e)}") | |
| return None | |
| def generate_thumbnail(description, style="professional", size="1024x1024"): | |
| """Generate thumbnail using DALL-E 3""" | |
| if not client: | |
| return None | |
| style_prompts = { | |
| "professional": "professional, clean, high-quality", | |
| "creative": "creative, artistic, visually striking", | |
| "minimalist": "minimalist, clean, simple design", | |
| "colorful": "vibrant, colorful, eye-catching", | |
| "dramatic": "dramatic lighting, cinematic, bold" | |
| } | |
| full_prompt = f""" | |
| Create a {style_prompts[style]} YouTube-style thumbnail image: {description} | |
| Requirements: | |
| - 16:9 aspect ratio suitable for video thumbnails | |
| - High contrast and bold visual elements | |
| - Professional quality that would perform well on video platforms | |
| - Engaging composition that draws the eye | |
| """ | |
| try: | |
| response = client.images.generate( | |
| model="dall-e-3", | |
| prompt=full_prompt, | |
| size=size, | |
| quality="hd", | |
| n=1 | |
| ) | |
| image_url = response.data[0].url | |
| image_response = requests.get(image_url) | |
| return Image.open(BytesIO(image_response.content)) | |
| except Exception as e: | |
| st.error(f"Error generating thumbnail: {str(e)}") | |
| return None | |
| # Main interface | |
| st.header("π₯ Input") | |
| # Add mode selection | |
| analysis_mode = st.radio( | |
| "Choose input mode:", | |
| ["π URL Analysis (Automatic)", "βοΈ Manual Description (Custom)"], | |
| help="Choose whether to analyze a video URL or create thumbnails from your own description" | |
| ) | |
| if analysis_mode == "π URL Analysis (Automatic)": | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| video_url = st.text_input( | |
| "Video URL:", | |
| placeholder="https://youtube.com/watch?v=... or https://example.com/video.mp4", | |
| help="Paste any video URL here" | |
| ) | |
| with col2: | |
| custom_description = st.text_area( | |
| "Additional Description (Optional):", | |
| placeholder="Add extra details about your video...", | |
| height=100, | |
| help="Supplement the automatic analysis with your own details" | |
| ) | |
| else: | |
| video_url = "" | |
| custom_description = st.text_area( | |
| "Describe your video content:", | |
| placeholder="Describe what your video is about, the mood, target audience, key topics, etc. Be as detailed as possible for better thumbnails...", | |
| height=150, | |
| help="Provide a detailed description of your video content for AI thumbnail generation" | |
| ) | |
| # Style and options | |
| st.header("π¨ Customization") | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| thumbnail_style = st.selectbox( | |
| "Thumbnail Style:", | |
| ["professional", "creative", "minimalist", "colorful", "dramatic"], | |
| help="Choose the visual style for your thumbnail" | |
| ) | |
| with col2: | |
| image_size = st.selectbox( | |
| "Image Size:", | |
| ["1024x1024", "512x512"], | |
| help="Higher resolution costs more but looks better" | |
| ) | |
| with col3: | |
| num_variations = st.slider( | |
| "Number of Variations:", | |
| min_value=1, | |
| max_value=3, | |
| value=1, | |
| help="Generate multiple thumbnail options (DALL-E 3 generates one at a time)" | |
| ) | |
| # Generate button | |
| if st.button("π Generate Thumbnail", type="primary", use_container_width=True): | |
| if analysis_mode == "π URL Analysis (Automatic)" and not video_url: | |
| st.error("β Please enter a video URL or switch to Manual Description mode") | |
| elif analysis_mode == "βοΈ Manual Description (Custom)" and not custom_description: | |
| st.error("β Please provide a description of your video content") | |
| elif not client: | |
| st.error("β Please enter your OpenAI API key in the sidebar") | |
| else: | |
| if analysis_mode == "π URL Analysis (Automatic)": | |
| # Step 1: Extract video information | |
| with st.spinner("π Extracting video information..."): | |
| video_info = extract_video_info(video_url) | |
| # Display extracted information | |
| if video_info['title'] or video_info['description'] or video_info['platform'] != 'unknown': | |
| st.success("β Video platform identified!") | |
| with st.expander("π Extracted Video Information", expanded=True): | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.write("**Platform:**", video_info['platform'].title()) | |
| if video_info['id']: | |
| st.write("**Video ID:**", video_info['id']) | |
| if video_info['title']: | |
| st.write("**Title:**", video_info['title']) | |
| with col2: | |
| if video_info['description']: | |
| st.write("**Description:**") | |
| st.write(video_info['description'][:200] + "..." if len(video_info['description']) > 200 else video_info['description']) | |
| elif video_info['platform'] in ['facebook', 'instagram', 'tiktok', 'twitter']: | |
| st.info(f"βΉοΈ {video_info['platform'].title()} content detected. For best results, switch to **Manual Description mode** and describe your video content.") | |
| # Check if we should continue with AI analysis or recommend manual mode | |
| if video_info['platform'] in ['facebook', 'instagram', 'tiktok', 'twitter'] and not custom_description: | |
| st.warning("π **Recommendation:** For social media videos, please either:") | |
| st.write("1. Switch to **Manual Description mode** and describe your video content") | |
| st.write("2. Or add a detailed description in the 'Additional Description' field above") | |
| if st.button("π Switch to Manual Mode", key="switch_mode"): | |
| st.rerun() | |
| analysis = None | |
| else: | |
| # Step 2: Analyze video content with AI | |
| with st.spinner("π€ Analyzing video content with AI..."): | |
| analysis = analyze_video_content(video_url, custom_description) | |
| else: | |
| # Manual mode - use custom description directly | |
| st.success("β Using your custom description!") | |
| analysis_prompt = f""" | |
| Create a detailed description for generating an engaging video thumbnail based on this video content: | |
| {custom_description} | |
| Please analyze this content and provide: | |
| 1. A clear, detailed description for the thumbnail image (2-3 sentences) | |
| 2. Suggested visual style and mood that matches the content | |
| 3. Key elements that should be prominently featured | |
| 4. Color palette and composition suggestions | |
| Focus on creating a thumbnail that would grab attention and accurately represent this content. | |
| """ | |
| with st.spinner("π€ Analyzing your description with AI..."): | |
| try: | |
| response = client.chat.completions.create( | |
| model="gpt-4", | |
| messages=[{"role": "user", "content": analysis_prompt}], | |
| max_tokens=300, | |
| temperature=0.7 | |
| ) | |
| analysis = response.choices[0].message.content.strip() | |
| except Exception as e: | |
| st.error(f"Error analyzing description: {str(e)}") | |
| analysis = None | |
| if analysis: | |
| st.success("β AI analysis complete!") | |
| with st.expander("π§ AI Content Analysis", expanded=True): | |
| st.write(analysis) | |
| # Step 3: Generate thumbnails | |
| st.header("πΌοΈ Generated Thumbnails") | |
| for i in range(num_variations): | |
| with st.spinner(f"π¨ Generating thumbnail {i+1}/{num_variations}..."): | |
| # Add variation to prompt for multiple generations | |
| varied_analysis = analysis | |
| if num_variations > 1: | |
| varied_analysis += f" (Create a unique visual variation #{i+1} with different composition, colors, or focus while maintaining the core message)" | |
| thumbnail = generate_thumbnail(varied_analysis, thumbnail_style, image_size) | |
| if thumbnail: | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| st.image( | |
| thumbnail, | |
| caption=f"Thumbnail {i+1} - {thumbnail_style.title()} Style", | |
| use_column_width=True | |
| ) | |
| with col2: | |
| # Download button | |
| buffer = BytesIO() | |
| thumbnail.save(buffer, format="PNG") | |
| st.download_button( | |
| label="π₯ Download", | |
| data=buffer.getvalue(), | |
| file_name=f"thumbnail_{i+1}_{thumbnail_style}.png", | |
| mime="image/png", | |
| key=f"download_{i}", | |
| use_container_width=True | |
| ) | |
| st.divider() | |
| elif analysis_mode == "π URL Analysis (Automatic)": | |
| # Only show this error for URL mode, not when we're recommending manual mode | |
| if not (video_info.get('platform') in ['facebook', 'instagram', 'tiktok', 'twitter'] and not custom_description): | |
| st.error("β Failed to analyze content. Please try again or provide more details.") | |
| # Information sections | |
| st.header("βΉοΈ How It Works") | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.subheader("1οΈβ£ URL Analysis") | |
| st.write("AI analyzes your video URL and description to understand the content") | |
| with col2: | |
| st.subheader("2οΈβ£ Content Description") | |
| st.write("GPT-4 creates a detailed description optimized for thumbnail generation") | |
| with col3: | |
| st.subheader("3οΈβ£ Image Generation") | |
| st.write("DALL-E 3 creates high-quality thumbnails with better prompt following") | |
| # Supported platforms | |
| st.header("π Platform Support & Recommendations") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.subheader("β Automatic Analysis Works Well") | |
| st.success(""" | |
| **YouTube** - Full title & description extraction | |
| **Vimeo** - Complete metadata support | |
| **Direct Video URLs** - Basic information extraction | |
| **General Websites** - Title and meta description | |
| """) | |
| with col2: | |
| st.subheader("π Use Manual Mode For") | |
| st.info(""" | |
| **Facebook** - Requires login/blocked by anti-scraping | |
| **Instagram** - Login required for video access | |
| **TikTok** - Access restrictions and complex structure | |
| **Twitter/X** - Limited public API access | |
| **Private/Protected Videos** - Authentication required | |
| """) | |
| st.header("π οΈ Quick Fix for Facebook/Social Media Videos") | |
| # Quick helper for social media users | |
| if st.button("π I have a Facebook/Instagram/TikTok video - Help me!", type="secondary"): | |
| st.balloons() | |
| st.success("π― **Quick Solution for Social Media Videos:**") | |
| st.write("1. Select **βοΈ Manual Description (Custom)** mode above") | |
| st.write("2. In the description box, tell us about your video:") | |
| st.code("""Example template: | |
| "[Video topic] - [what happens in video] | |
| Target audience: [who watches this] | |
| Mood: [fun/serious/educational/promotional] | |
| Visual style: [colors you want/aesthetic] | |
| Key elements: [people/objects/scenes]" | |
| """) | |
| st.write("3. Choose your preferred style and generate!") | |
| st.info("π‘ This method often works **better** than automatic analysis because you know your content best!") | |
| st.header("π οΈ How to Handle Facebook Videos") | |
| with st.expander("π Step-by-step guide for Facebook videos", expanded=True): | |
| st.write(""" | |
| **For your Facebook video:** `https://www.facebook.com/share/v/16HtujeeH2/` | |
| 1. **Switch to Manual Description mode** (select the βοΈ option above) | |
| 2. **Describe your Facebook video content, for example:** | |
| - What is the video about? | |
| - What's the main topic or message? | |
| - Who is the target audience? | |
| - What's the mood/tone (educational, funny, serious, promotional)? | |
| - Any key visual elements or people in the video? | |
| 3. **Example description:** | |
| > "Educational video about sustainable farming techniques for small-scale farmers. Shows practical tips for organic gardening, water conservation, and crop rotation. Target audience is beginner gardeners and environmentally conscious people. Should have a clean, educational feel with earth tones." | |
| 4. **Generate thumbnail** - The AI will create perfect thumbnails based on your description! | |
| """) | |
| st.header("π‘ Pro Tips for Social Media Videos") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.subheader("π― Better Descriptions") | |
| st.info(""" | |
| **Include:** | |
| - Video topic and main message | |
| - Target audience (age, interests) | |
| - Mood/tone (fun, serious, educational) | |
| - Key visual elements or people | |
| - Desired colors or style | |
| """) | |
| with col2: | |
| st.subheader("π Platform-Specific Styles") | |
| st.info(""" | |
| **Facebook**: Professional or colorful styles work well | |
| **Instagram**: Creative and colorful for better engagement | |
| **TikTok**: Dramatic and colorful for younger audience | |
| **Twitter**: Clean, minimalist for news/discussion content | |
| """) | |
| # DALL-E 3 Benefits section | |
| st.header("π¨ DALL-E 3 Advantages") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.info(""" | |
| β **Higher Quality:** Superior image generation | |
| β **Better Prompt Following:** More accurate to descriptions | |
| β **Enhanced Details:** Sharper, more professional results | |
| """) | |
| with col2: | |
| st.info(""" | |
| β **HD Quality:** Crystal clear thumbnails | |
| β **Better Composition:** Superior layout and visual balance | |
| β **Text Integration:** Can include readable text elements | |
| """) | |
| # Pricing info | |
| st.header("π° Cost Information") | |
| cost_info = f""" | |
| **OpenAI API Costs (approximate):** | |
| - GPT-4 Analysis: ~$0.001 per video | |
| - DALL-E 3 Image Generation: ~$0.08 per {image_size} HD image | |
| - **Total per thumbnail:** ~$0.081 USD | |
| *Costs may vary based on current OpenAI pricing* | |
| """ | |
| st.info(cost_info) | |
| # Tips | |
| st.header("π‘ Tips for Best Results") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.subheader("π― For Better Analysis") | |
| st.info(""" | |
| **URL Tips:** | |
| - Use direct YouTube/Vimeo links for best results | |
| - Make sure the video is publicly accessible | |
| - For private videos, provide detailed descriptions | |
| **Description Tips:** | |
| - Include the video topic and target audience | |
| - Mention the mood/tone (serious, fun, educational) | |
| - Specify any key visual elements or themes | |
| """) | |
| with col2: | |
| st.subheader("π For Better Thumbnails") | |
| st.info(""" | |
| **Style Selection:** | |
| - **Professional**: Business, tutorials, serious content | |
| - **Creative**: Art, design, entertainment content | |
| - **Colorful**: Kids content, fun videos, gaming | |
| - **Dramatic**: Action, movie trailers, intense content | |
| - **Minimalist**: Tech, educational, clean aesthetic | |
| """) | |
| # Troubleshooting section | |
| st.header("π§ Troubleshooting Common Issues") | |
| with st.expander("β Why doesn't automatic analysis work for my video?"): | |
| st.write(""" | |
| **Social Media Platforms (Facebook, Instagram, TikTok, Twitter):** | |
| - These platforms block automated content extraction | |
| - They require login/authentication for video access | |
| - **Solution:** Use **Manual Description mode** instead | |
| **YouTube/Vimeo Issues:** | |
| - Video might be private or region-locked | |
| - Some videos have restricted metadata | |
| - **Solution:** Add custom description for better context | |
| **General Website Videos:** | |
| - Some sites block automated requests | |
| - Limited metadata available | |
| - **Solution:** Describe the video content manually | |
| """) | |
| with st.expander("π How to get the best thumbnails?"): | |
| st.write(""" | |
| **For Manual Descriptions:** | |
| 1. **Be Specific:** Instead of "cooking video" β "Italian pasta making tutorial showing step-by-step homemade fettuccine preparation" | |
| 2. **Include Visual Details:** "Close-up shots of hands kneading dough, flour dust, kitchen setting with warm lighting" | |
| 3. **Mention Target Audience:** "For beginner home cooks and food enthusiasts" | |
| 4. **Specify Mood/Style:** "Cozy, warm atmosphere with rustic kitchen aesthetic" | |
| 5. **Color Preferences:** "Earth tones, warm yellows and browns, natural lighting" | |
| """) | |
| with st.expander("π° Cost concerns?"): | |
| st.write(""" | |
| **Cost Breakdown:** | |
| - GPT-4 Analysis: ~$0.001 per video | |
| - DALL-E 3 Generation: ~$0.08 per HD thumbnail | |
| - **Total:** ~$0.081 per thumbnail | |
| **Tips to Save:** | |
| - Generate fewer variations (1-2 instead of 3) | |
| - Use 512x512 size if budget is tight | |
| - Perfect your description before generating to avoid re-dos | |
| """) | |
| with st.expander("π Privacy and social media videos"): | |
| st.write(""" | |
| **Why Manual Mode is Better for Social Media:** | |
| - **Privacy:** No need to access private content | |
| - **Accuracy:** You know your video better than any algorithm | |
| - **Control:** Full control over thumbnail style and messaging | |
| - **Speed:** No need to wait for extraction attempts | |
| **Security:** Your video content stays private - only your description is sent to OpenAI. | |
| """) | |
| # Footer | |
| st.divider() | |
| st.markdown(""" | |
| <div style='text-align: center; color: #666;'> | |
| <p>Built with β€οΈ using Streamlit and OpenAI API (GPT-4 + DALL-E 3)</p> | |
| </div> | |
| """, unsafe_allow_html=True) |