nniehaus commited on
Commit
6198ee8
·
verified ·
1 Parent(s): ae6dbfe

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +396 -186
app.py CHANGED
@@ -1,6 +1,10 @@
1
  import streamlit as st
2
- from openai import OpenAI
3
  import os
 
 
 
 
4
  from reportlab.lib.pagesizes import letter
5
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
6
  from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
@@ -87,16 +91,184 @@ st.markdown("""
87
  </style>
88
  """, unsafe_allow_html=True)
89
 
90
- # Initialize OpenAI client
91
  @st.cache_resource
92
- def get_openai_client():
93
  api_key = os.getenv("OPENAI_API_KEY")
94
  if not api_key:
95
  st.error("Please set your OPENAI_API_KEY environment variable")
96
- return None
97
- return OpenAI(api_key=api_key)
 
 
 
98
 
99
- client = get_openai_client()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
  # Function to generate PDF
102
  def create_pdf(script_content, business_name, platform, video_type):
@@ -151,7 +323,7 @@ def create_pdf(script_content, business_name, platform, video_type):
151
 
152
  # Function to generate script with enhanced prompting
153
  def generate_video_script(prompt_data):
154
- if not client:
155
  return None
156
 
157
  try:
@@ -211,7 +383,7 @@ def generate_video_script(prompt_data):
211
  Make it authentic, conversational, and optimized for {prompt_data['platform']} consumption patterns.
212
  """
213
 
214
- response = client.chat.completions.create(
215
  model="gpt-4",
216
  messages=[
217
  {"role": "system", "content": system_message},
@@ -220,7 +392,7 @@ def generate_video_script(prompt_data):
220
  temperature=0.8
221
  )
222
 
223
- return response.choices[0].message.content
224
 
225
  except Exception as e:
226
  st.error(f"Error generating script: {str(e)}")
@@ -270,6 +442,10 @@ if 'show_form' not in st.session_state:
270
  st.session_state.show_form = True
271
  if 'script_metadata' not in st.session_state:
272
  st.session_state.script_metadata = {}
 
 
 
 
273
 
274
  # Header
275
  st.markdown('<h1 class="main-header">🎬 AI Video Script Generator Pro</h1>', unsafe_allow_html=True)
@@ -288,55 +464,117 @@ st.markdown("""
288
  """, unsafe_allow_html=True)
289
 
290
  if st.session_state.show_form:
291
- # Input form in columns for better layout
292
- col1, col2 = st.columns([2, 1])
293
 
 
294
  with col1:
295
- st.markdown('<h2 class="section-header">📝 Tell Us About Your Business</h2>', unsafe_allow_html=True)
296
-
297
- # Basic business info
298
- business_description = st.text_area(
299
- "What does your business do?",
300
- placeholder="e.g., We're a local coffee shop that roasts our own beans and creates custom blends for coffee lovers.",
301
- height=80,
302
- help="Describe your business in simple terms that anyone can understand"
303
  )
304
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  problem_solved = st.text_input(
306
- "What specific problem do you solve for customers?",
307
- placeholder="e.g., We help busy professionals get amazing coffee without the wait",
308
- help="Focus on the main pain point you address - be specific"
 
309
  )
310
-
 
311
  services_offered = st.text_input(
312
- "What services/products should we highlight?",
313
- placeholder="e.g., Custom coffee subscriptions, corporate catering, barista training",
314
- help="List 2-3 key offerings you want to promote"
315
- )
316
-
317
- unique_aspects = st.text_input(
318
- "What makes you different from competitors?",
319
- placeholder="e.g., Only coffee shop in town with beans roasted daily on-site",
320
- help="Your unique selling proposition that sets you apart"
321
  )
322
-
 
 
 
323
  name_to_include = st.text_input(
324
- "Business name to include in the script:",
 
325
  placeholder="e.g., Downtown Coffee Co.",
326
- help="How you want your business referenced"
 
 
 
 
 
 
 
 
327
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
 
329
- call_to_action = st.text_input(
330
- "What specific action should viewers take?",
331
- placeholder="e.g., Visit us at 123 Main Street or order online at our website",
332
- help="One clear, specific action you want viewers to take"
 
333
  )
334
 
335
  with col2:
336
- st.markdown('<h2 class="section-header">🎯 Platform & Style Optimization</h2>', unsafe_allow_html=True)
337
-
338
  platform = st.selectbox(
339
- "Primary Platform:",
340
  [
341
  "Instagram Reels",
342
  "TikTok",
@@ -346,162 +584,134 @@ if st.session_state.show_form:
346
  "Twitter/X",
347
  "Email Marketing"
348
  ],
349
- help="Choose your main distribution platform for optimization"
350
- )
351
-
352
- # Platform-specific tips
353
- platform_tips = {
354
- "Instagram Reels": "📱 Vertical format essential • 15-90 seconds optimal • Use trending audio • Captions required",
355
- "TikTok": "🎵 31-60 seconds works best • Completion rate crucial • Native feel important • Trending sounds boost reach",
356
- "YouTube Shorts": "📺 Up to 3 minutes allowed • Educational content performs well • Mobile-first viewing",
357
- "LinkedIn": "💼 Professional tone essential • 30 seconds-2 minutes • Educational/business value focus",
358
- "Facebook": "👥 Native uploads preferred • 74% watch without sound • Captions essential",
359
- "Twitter/X": "⚡ 15 seconds optimal • Real-time relevance • Concise messaging",
360
- "Email Marketing": "📧 1-2 minutes max • Clear thumbnail • Value-focused preview"
361
- }
362
-
363
- st.markdown(f"""
364
- <div class="platform-tips">
365
- <strong>Platform Tips:</strong><br>
366
- {platform_tips.get(platform, "General optimization tips")}
367
- </div>
368
- """, unsafe_allow_html=True)
369
-
370
- video_type = st.selectbox(
371
- "Video Type:",
372
- [
373
- "Product/Service Showcase",
374
- "Problem-Solution Focused",
375
- "Educational/How-To",
376
- "Behind-the-Scenes",
377
- "Customer Success Story",
378
- "Brand Awareness",
379
- "Promotional Offer",
380
- "Comparison/Competition"
381
- ],
382
- help="Choose the primary purpose of your video"
383
- )
384
-
385
- target_audience = st.selectbox(
386
- "Target Audience:",
387
- [
388
- "Local Community",
389
- "Young Professionals (25-35)",
390
- "Small Business Owners",
391
- "Families with Children",
392
- "Seniors (55+)",
393
- "Students",
394
- "Health-Conscious Consumers",
395
- "Luxury Market",
396
- "Budget-Conscious Shoppers",
397
- "Industry Professionals"
398
- ],
399
- help="Who are you trying to reach?"
400
  )
 
 
 
 
 
 
 
 
 
 
 
401
 
402
- # Advanced options
403
- st.markdown('<h3 style="color: #1f4e79; margin-top: 1.5rem;">🧠 Psychology & Storytelling</h3>', unsafe_allow_html=True)
404
-
405
- hook_type = st.selectbox(
406
- "Hook Strategy:",
407
- [
408
- "Question Hook",
409
- "Problem Statement",
410
- "Curiosity Gap",
411
- "Direct Call-out",
412
- "Movement Hook",
413
- "Negative Hook",
414
- "Statistical Hook",
415
- "Story Hook"
416
- ],
417
- help="How do you want to grab attention in the first 3-5 seconds?"
418
- )
419
-
420
- storytelling_framework = st.selectbox(
421
- "Storytelling Framework:",
422
- [
423
- "Problem-Solution",
424
- "Before-After",
425
- "Hero's Journey",
426
- "Educational Value",
427
- "Testimonial Story",
428
- "Behind-the-Scenes",
429
- "Pixar Framework"
430
- ],
431
- help="Choose your narrative structure"
432
- )
433
-
434
- psychological_triggers = st.multiselect(
435
- "Psychological Triggers:",
436
- [
437
- "Social Proof (testimonials, statistics)",
438
- "Scarcity/FOMO (limited time, exclusive)",
439
- "Authority (expert endorsement)",
440
- "Reciprocity (free value first)",
441
- "Curiosity (information gaps)",
442
- "Empathy (shared experiences)",
443
- "Urgency (immediate action needed)"
444
- ],
445
- default=["Social Proof (testimonials, statistics)", "Curiosity (information gaps)"],
446
- help="Select psychological elements to include"
447
- )
448
-
449
- tone_options = [
450
- "Professional & Trustworthy",
451
- "Friendly & Conversational",
452
- "Exciting & Energetic",
453
- "Warm & Personal",
454
- "Confident & Bold",
455
- "Educational & Expert",
456
- "Inspiring & Motivational",
457
- "Urgent & Persuasive",
458
- "Authentic & Real"
459
- ]
460
-
461
- tone = st.selectbox("Script Tone:", tone_options, help="How do you want to sound?")
462
-
463
- script_length = st.slider(
464
- "Script Length (words):",
465
- min_value=50,
466
- max_value=300,
467
- value=150,
468
- step=25,
469
- help="Shorter = social media, Longer = detailed explanations"
470
- )
471
 
472
- # Length guide based on platform
473
- length_guides = {
474
- "Instagram Reels": "75-150 words (15-90 seconds)",
475
- "TikTok": "75-125 words (31-60 seconds)",
476
- "YouTube Shorts": "100-200 words (up to 3 minutes)",
477
- "LinkedIn": "100-175 words (30 seconds-2 minutes)",
478
- "Facebook": "100-200 words (1-3 minutes)",
479
- "Twitter/X": "50-75 words (15 seconds optimal)",
480
- "Email Marketing": "150-300 words (1-2 minutes)"
481
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
482
 
483
- st.markdown(f"""
484
- <div class="feature-box">
485
- <strong>📏 Recommended for {platform}:</strong><br>
486
- {length_guides.get(platform, "100-200 words for general use")}
487
- </div>
488
- """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
489
 
490
  # Generate button
491
  st.markdown("<br>", unsafe_allow_html=True)
492
  col1, col2, col3 = st.columns([1, 2, 1])
493
  with col2:
494
  if st.button("🚀 Generate My Optimized Video Script", use_container_width=True):
495
- # Validation
496
- required_fields = [
497
- business_description, problem_solved, services_offered,
498
- unique_aspects, name_to_include, call_to_action
499
- ]
500
 
501
  if not all(required_fields):
502
- st.error("⚠️ Please fill in all required fields to generate your script.")
503
  else:
504
  with st.spinner("🎬 Crafting your conversion-optimized video script..."):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  prompt_data = {
506
  'business': business_description,
507
  'problem': problem_solved,
@@ -516,7 +726,7 @@ if st.session_state.show_form:
516
  'audience': target_audience,
517
  'hook_type': hook_type,
518
  'storytelling': storytelling_framework,
519
- 'psychological_triggers': ", ".join(psychological_triggers)
520
  }
521
 
522
  script = generate_video_script(prompt_data)
 
1
  import streamlit as st
2
+ import openai
3
  import os
4
+ import requests
5
+ from bs4 import BeautifulSoup
6
+ from urllib.parse import urljoin, urlparse
7
+ import re
8
  from reportlab.lib.pagesizes import letter
9
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
10
  from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
 
91
  </style>
92
  """, unsafe_allow_html=True)
93
 
94
+ # Initialize OpenAI API key
95
  @st.cache_resource
96
+ def setup_openai():
97
  api_key = os.getenv("OPENAI_API_KEY")
98
  if not api_key:
99
  st.error("Please set your OPENAI_API_KEY environment variable")
100
+ return False
101
+ openai.api_key = api_key
102
+ return True
103
+
104
+ openai_ready = setup_openai()
105
 
106
+ # Website analysis functions
107
+ def scrape_website(url, max_pages=3):
108
+ """Scrape website content for business information"""
109
+ if not url.startswith("http"):
110
+ url = f"https://{url}"
111
+
112
+ visited = set()
113
+ to_visit = [url]
114
+ all_content = []
115
+ scrape_successful = False
116
+
117
+ while to_visit and len(visited) < max_pages:
118
+ current_url = to_visit.pop(0)
119
+ if current_url in visited:
120
+ continue
121
+
122
+ try:
123
+ response = requests.get(current_url, timeout=10, headers={
124
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
125
+ })
126
+ response.raise_for_status()
127
+ soup = BeautifulSoup(response.content, "html.parser")
128
+ visited.add(current_url)
129
+ scrape_successful = True
130
+
131
+ # Extract meaningful content
132
+ title = soup.find("title")
133
+ if title:
134
+ all_content.append(f"Title: {title.get_text(strip=True)}")
135
+
136
+ meta_description = soup.find("meta", {"name": "description"})
137
+ if meta_description and meta_description.get("content"):
138
+ all_content.append(f"Description: {meta_description['content']}")
139
+
140
+ # Extract headings
141
+ for heading in soup.find_all(["h1", "h2", "h3"])[:10]:
142
+ all_content.append(f"Heading: {heading.get_text(strip=True)}")
143
+
144
+ # Extract paragraphs
145
+ paragraphs = soup.find_all("p")[:15]
146
+ for para in paragraphs:
147
+ text = para.get_text(strip=True)
148
+ if len(text) > 20: # Only meaningful paragraphs
149
+ all_content.append(text)
150
+
151
+ # Look for about/services pages
152
+ links = soup.find_all("a", href=True)
153
+ for link in links[:10]:
154
+ href = link.get("href", "").lower()
155
+ if any(keyword in href for keyword in ["about", "service", "what-we-do", "our-story"]):
156
+ full_url = urljoin(current_url, link["href"])
157
+ if full_url not in visited and url in full_url:
158
+ to_visit.append(full_url)
159
+
160
+ except Exception as e:
161
+ continue
162
+
163
+ return " ".join(all_content[:2000]), scrape_successful # Limit content length
164
+
165
+ def search_business_info(url_or_name):
166
+ """Search for business information using web search"""
167
+ try:
168
+ if not openai_ready:
169
+ return "Unable to search - OpenAI not configured"
170
+
171
+ domain = urlparse(url_or_name).netloc if url_or_name.startswith('http') else url_or_name
172
+
173
+ response = openai.ChatCompletion.create(
174
+ model="gpt-4",
175
+ messages=[
176
+ {
177
+ "role": "system",
178
+ "content": "You are a business research assistant. Based on a website URL or business name, provide information about what the business does, what problems they solve, their target audience, and their unique value proposition. If you don't have specific information, make reasonable inferences based on the domain name or business name."
179
+ },
180
+ {
181
+ "role": "user",
182
+ "content": f"Research this business: {domain}. Provide information about: 1) What they do, 2) Problems they solve, 3) Target audience, 4) Services/products, 5) What makes them unique. Be specific and practical."
183
+ }
184
+ ],
185
+ temperature=0.3
186
+ )
187
+
188
+ return response["choices"][0]["message"]["content"]
189
+ except Exception as e:
190
+ return f"Unable to research business information: {str(e)}"
191
+
192
+ def extract_business_info(content):
193
+ """Extract structured business information from website content or research"""
194
+ try:
195
+ if not openai_ready:
196
+ return {}
197
+
198
+ response = openai.ChatCompletion.create(
199
+ model="gpt-4",
200
+ messages=[
201
+ {
202
+ "role": "system",
203
+ "content": """You are a business analyst. Extract key business information from website content and return it in a structured format. Extract:
204
+ 1. Business description (what they do)
205
+ 2. Problems they solve for customers
206
+ 3. Main services/products (2-3 key offerings)
207
+ 4. Unique value proposition
208
+ 5. Business name
209
+ 6. Target audience (be specific)
210
+
211
+ Return the information in this exact format:
212
+ BUSINESS_DESCRIPTION: [description]
213
+ PROBLEM_SOLVED: [problem]
214
+ SERVICES: [services]
215
+ UNIQUE_VALUE: [unique aspects]
216
+ BUSINESS_NAME: [name]
217
+ TARGET_AUDIENCE: [audience]
218
+
219
+ If any information is unclear, make reasonable inferences based on available context."""
220
+ },
221
+ {
222
+ "role": "user",
223
+ "content": f"Extract business information from this content: {content[:1500]}" # Limit content
224
+ }
225
+ ],
226
+ temperature=0.3
227
+ )
228
+
229
+ result = response["choices"][0]["message"]["content"]
230
+
231
+ # Parse the structured response
232
+ info = {}
233
+ lines = result.split('\n')
234
+ for line in lines:
235
+ if ':' in line:
236
+ key, value = line.split(':', 1)
237
+ key = key.strip()
238
+ value = value.strip()
239
+
240
+ if key == "BUSINESS_DESCRIPTION":
241
+ info['business'] = value
242
+ elif key == "PROBLEM_SOLVED":
243
+ info['problem'] = value
244
+ elif key == "SERVICES":
245
+ info['services'] = value
246
+ elif key == "UNIQUE_VALUE":
247
+ info['unique'] = value
248
+ elif key == "BUSINESS_NAME":
249
+ info['name'] = value
250
+ elif key == "TARGET_AUDIENCE":
251
+ info['audience'] = value
252
+
253
+ return info
254
+ except Exception as e:
255
+ return {}
256
+
257
+ def analyze_website(url):
258
+ """Main function to analyze website and extract business information"""
259
+ if not url:
260
+ return {}
261
+
262
+ # First, try to scrape the website
263
+ content, scrape_successful = scrape_website(url)
264
+
265
+ if not scrape_successful or len(content) < 100:
266
+ # If scraping failed, try searching for business information
267
+ content = search_business_info(url)
268
+
269
+ # Extract structured information
270
+ business_info = extract_business_info(content)
271
+ return business_info
272
 
273
  # Function to generate PDF
274
  def create_pdf(script_content, business_name, platform, video_type):
 
323
 
324
  # Function to generate script with enhanced prompting
325
  def generate_video_script(prompt_data):
326
+ if not openai_ready:
327
  return None
328
 
329
  try:
 
383
  Make it authentic, conversational, and optimized for {prompt_data['platform']} consumption patterns.
384
  """
385
 
386
+ response = openai.ChatCompletion.create(
387
  model="gpt-4",
388
  messages=[
389
  {"role": "system", "content": system_message},
 
392
  temperature=0.8
393
  )
394
 
395
+ return response["choices"][0]["message"]["content"]
396
 
397
  except Exception as e:
398
  st.error(f"Error generating script: {str(e)}")
 
442
  st.session_state.show_form = True
443
  if 'script_metadata' not in st.session_state:
444
  st.session_state.script_metadata = {}
445
+ if 'website_analyzed' not in st.session_state:
446
+ st.session_state.website_analyzed = False
447
+ if 'extracted_info' not in st.session_state:
448
+ st.session_state.extracted_info = {}
449
 
450
  # Header
451
  st.markdown('<h1 class="main-header">🎬 AI Video Script Generator Pro</h1>', unsafe_allow_html=True)
 
464
  """, unsafe_allow_html=True)
465
 
466
  if st.session_state.show_form:
467
+ # Website URL Analysis Section
468
+ st.markdown('<h2 class="section-header">🌐 Quick Business Analysis</h2>', unsafe_allow_html=True)
469
 
470
+ col1, col2 = st.columns([3, 1])
471
  with col1:
472
+ website_url = st.text_input(
473
+ "Enter your website URL (optional - we'll auto-fill details):",
474
+ placeholder="e.g., https://yourwebsite.com or yourwebsite.com",
475
+ help="We'll analyze your website to pre-fill business information"
 
 
 
 
476
  )
477
+
478
+ with col2:
479
+ st.markdown("<br>", unsafe_allow_html=True) # Add spacing
480
+ if st.button("🔍 Analyze Website", use_container_width=True):
481
+ if website_url:
482
+ with st.spinner("🔍 Analyzing your website..."):
483
+ extracted_info = analyze_website(website_url)
484
+ st.session_state.extracted_info = extracted_info
485
+ st.session_state.website_analyzed = True
486
+ if extracted_info:
487
+ st.success("✅ Website analyzed! Information has been pre-filled below.")
488
+ else:
489
+ st.warning("⚠️ Could not extract all information. Please fill in the details manually.")
490
+ st.rerun()
491
+
492
+ # Input form - consolidated to 8 key inputs
493
+ st.markdown('<h2 class="section-header">📝 Video Details (8 Quick Steps)</h2>', unsafe_allow_html=True)
494
+
495
+ # Get pre-filled values from website analysis
496
+ extracted = st.session_state.extracted_info
497
+
498
+ # Step 1: Business Description
499
+ business_description = st.text_area(
500
+ "1️⃣ What does your business do?",
501
+ value=extracted.get('business', ''),
502
+ placeholder="e.g., We're a local coffee shop that roasts our own beans and creates custom blends for coffee lovers.",
503
+ height=80,
504
+ help="Describe your business in simple terms"
505
+ )
506
+
507
+ # Step 2: Problem + Solution Combined
508
+ col1, col2 = st.columns(2)
509
+ with col1:
510
  problem_solved = st.text_input(
511
+ "2️⃣ What problem do you solve?",
512
+ value=extracted.get('problem', ''),
513
+ placeholder="e.g., Busy professionals need great coffee fast",
514
+ help="The main pain point you address"
515
  )
516
+
517
+ with col2:
518
  services_offered = st.text_input(
519
+ "3️⃣ Main services/products?",
520
+ value=extracted.get('services', ''),
521
+ placeholder="e.g., Custom blends, catering, subscriptions",
522
+ help="2-3 key offerings to highlight"
 
 
 
 
 
523
  )
524
+
525
+ # Step 3: Business Name + Unique Value
526
+ col1, col2 = st.columns(2)
527
+ with col1:
528
  name_to_include = st.text_input(
529
+ "4️⃣ Business name:",
530
+ value=extracted.get('name', ''),
531
  placeholder="e.g., Downtown Coffee Co.",
532
+ help="How to reference your business"
533
+ )
534
+
535
+ with col2:
536
+ unique_aspects = st.text_input(
537
+ "5️⃣ What makes you unique?",
538
+ value=extracted.get('unique', ''),
539
+ placeholder="e.g., Only shop with daily on-site roasting",
540
+ help="Your key differentiator"
541
  )
542
+
543
+ # Step 4: Target + Platform Combined
544
+ col1, col2 = st.columns(2)
545
+ with col1:
546
+ # Determine target audience from extracted info or provide options
547
+ audience_options = [
548
+ "Local Community",
549
+ "Young Professionals (25-35)",
550
+ "Small Business Owners",
551
+ "Families with Children",
552
+ "Seniors (55+)",
553
+ "Students",
554
+ "Health-Conscious Consumers",
555
+ "Industry Professionals",
556
+ "Budget-Conscious Shoppers",
557
+ "Luxury Market"
558
+ ]
559
+
560
+ # Try to match extracted audience to options
561
+ default_audience = 0
562
+ extracted_audience = extracted.get('audience', '').lower()
563
+ for i, option in enumerate(audience_options):
564
+ if any(keyword in extracted_audience for keyword in option.lower().split()):
565
+ default_audience = i
566
+ break
567
 
568
+ target_audience = st.selectbox(
569
+ "6️⃣ Target audience:",
570
+ audience_options,
571
+ index=default_audience,
572
+ help="Who are you trying to reach?"
573
  )
574
 
575
  with col2:
 
 
576
  platform = st.selectbox(
577
+ "7️⃣ Primary platform:",
578
  [
579
  "Instagram Reels",
580
  "TikTok",
 
584
  "Twitter/X",
585
  "Email Marketing"
586
  ],
587
+ help="Where will you post this video?"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
588
  )
589
+
590
+ # Step 5: Call to Action
591
+ call_to_action = st.text_input(
592
+ "8️⃣ What should viewers do next?",
593
+ placeholder="e.g., Visit us at 123 Main Street or order online",
594
+ help="One clear, specific action"
595
+ )
596
+
597
+ # Advanced Options (Collapsible)
598
+ with st.expander("🎯 Advanced Options (Optional)"):
599
+ col1, col2, col3 = st.columns(3)
600
 
601
+ with col1:
602
+ video_type = st.selectbox(
603
+ "Video Type:",
604
+ [
605
+ "Product/Service Showcase",
606
+ "Problem-Solution Focused",
607
+ "Educational/How-To",
608
+ "Behind-the-Scenes",
609
+ "Customer Success Story",
610
+ "Brand Awareness",
611
+ "Promotional Offer"
612
+ ]
613
+ )
614
+
615
+ tone = st.selectbox(
616
+ "Tone:",
617
+ [
618
+ "Friendly & Conversational",
619
+ "Professional & Trustworthy",
620
+ "Exciting & Energetic",
621
+ "Warm & Personal",
622
+ "Educational & Expert",
623
+ "Authentic & Real"
624
+ ]
625
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
626
 
627
+ with col2:
628
+ hook_type = st.selectbox(
629
+ "Hook Strategy:",
630
+ [
631
+ "Question Hook",
632
+ "Problem Statement",
633
+ "Curiosity Gap",
634
+ "Direct Call-out",
635
+ "Statistical Hook",
636
+ "Story Hook"
637
+ ]
638
+ )
639
+
640
+ storytelling_framework = st.selectbox(
641
+ "Story Structure:",
642
+ [
643
+ "Problem-Solution",
644
+ "Before-After",
645
+ "Educational Value",
646
+ "Testimonial Story",
647
+ "Behind-the-Scenes"
648
+ ]
649
+ )
650
 
651
+ with col3:
652
+ psychological_triggers = st.multiselect(
653
+ "Psychological Triggers:",
654
+ [
655
+ "Social Proof",
656
+ "Scarcity/FOMO",
657
+ "Authority",
658
+ "Curiosity",
659
+ "Empathy"
660
+ ],
661
+ default=["Social Proof", "Curiosity"]
662
+ )
663
+
664
+ script_length = st.slider(
665
+ "Length (words):",
666
+ min_value=50,
667
+ max_value=300,
668
+ value=150,
669
+ step=25
670
+ )
671
+
672
+ # Platform-specific tips
673
+ platform_tips = {
674
+ "Instagram Reels": "📱 Vertical format • 15-90 seconds • Use trending audio • Captions required",
675
+ "TikTok": "🎵 31-60 seconds optimal • Completion rate crucial • Native feel important",
676
+ "YouTube Shorts": "📺 Up to 3 minutes • Educational content performs well • Mobile-first",
677
+ "LinkedIn": "💼 Professional tone • 30 seconds-2 minutes • Business value focus",
678
+ "Facebook": "👥 Native uploads preferred • 74% watch without sound • Captions essential",
679
+ "Twitter/X": "⚡ 15 seconds optimal • Real-time relevance • Concise messaging",
680
+ "Email Marketing": "📧 1-2 minutes max • Clear thumbnail • Value-focused preview"
681
+ }
682
+
683
+ st.markdown(f"""
684
+ <div class="platform-tips">
685
+ <strong>📋 {platform} Tips:</strong> {platform_tips.get(platform, "General optimization")}
686
+ </div>
687
+ """, unsafe_allow_html=True)
688
 
689
  # Generate button
690
  st.markdown("<br>", unsafe_allow_html=True)
691
  col1, col2, col3 = st.columns([1, 2, 1])
692
  with col2:
693
  if st.button("🚀 Generate My Optimized Video Script", use_container_width=True):
694
+ # Validation - only require essential fields
695
+ required_fields = [business_description, problem_solved, services_offered, name_to_include, call_to_action]
 
 
 
696
 
697
  if not all(required_fields):
698
+ st.error("⚠️ Please fill in the required fields (1-5 and 8) to generate your script.")
699
  else:
700
  with st.spinner("🎬 Crafting your conversion-optimized video script..."):
701
+ # Set defaults for advanced options if not specified
702
+ if 'video_type' not in locals():
703
+ video_type = "Product/Service Showcase"
704
+ if 'tone' not in locals():
705
+ tone = "Friendly & Conversational"
706
+ if 'hook_type' not in locals():
707
+ hook_type = "Question Hook"
708
+ if 'storytelling_framework' not in locals():
709
+ storytelling_framework = "Problem-Solution"
710
+ if 'psychological_triggers' not in locals():
711
+ psychological_triggers = ["Social Proof", "Curiosity"]
712
+ if 'script_length' not in locals():
713
+ script_length = 150
714
+
715
  prompt_data = {
716
  'business': business_description,
717
  'problem': problem_solved,
 
726
  'audience': target_audience,
727
  'hook_type': hook_type,
728
  'storytelling': storytelling_framework,
729
+ 'psychological_triggers': ", ".join(psychological_triggers) if isinstance(psychological_triggers, list) else psychological_triggers
730
  }
731
 
732
  script = generate_video_script(prompt_data)