shaheerawan3 commited on
Commit
c00b679
·
verified ·
1 Parent(s): 48c897c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +168 -120
app.py CHANGED
@@ -18,17 +18,59 @@ import random
18
  import logging
19
  import time
20
  from typing import Optional, List, Dict, Tuple
 
 
 
21
 
22
- class EnhancedVideoGenerator:
23
  def __init__(self):
24
- """Initialize the video generator with all required components"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  try:
26
- self.setup_logging()
27
- self.setup_device()
28
- self.initialize_models()
29
- self.setup_workspace()
30
- self.load_assets()
31
- self.setup_themes()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  except Exception as e:
33
  logging.error(f"Initialization failed: {str(e)}")
34
  raise RuntimeError("Failed to initialize video generator")
@@ -284,88 +326,77 @@ class EnhancedVideoGenerator:
284
  self.logger.error(f"Voice-over generation failed: {str(e)}")
285
  return AudioFileClip(duration=len(script.split()) * 0.3)
286
 
287
- def create_video(self, script: str, style: str, duration: int, output_path: str) -> str:
288
- """Create full video with all enhanced features"""
289
- try:
290
- # Progress bar
291
- progress_bar = st.progress(0)
292
- status_text = st.empty()
293
-
294
- # Generate visual assets (20%)
295
- status_text.text("Generating visual assets...")
296
- assets = self.generate_visual_assets(script, style)
297
- progress_bar.progress(20)
298
-
299
- # Generate voice-over (40%)
300
- status_text.text("Creating voice-over...")
301
- audio = self.generate_voice_over(script)
302
- progress_bar.progress(40)
303
-
304
- # Create frames
305
- fps = 30
306
- total_frames = int(duration * fps)
307
- frames = []
308
-
309
- # Use smaller batch size for better memory management
310
- batch_size = 10
311
- num_batches = (total_frames + batch_size - 1) // batch_size
312
 
313
- with ThreadPoolExecutor(max_workers=4) as executor:
314
- for batch in range(num_batches):
315
- status_text.text(f"Generating frames: {batch*batch_size}/{total_frames}")
316
- start_frame = batch * batch_size
317
- end_frame = min((batch + 1) * batch_size, total_frames)
318
-
319
- frame_futures = []
320
- for i in range(start_frame, end_frame):
321
- progress = i / total_frames
322
- text_index = int(progress * len(script.split()))
323
- current_text = " ".join(script.split()[:text_index + 1])
 
 
 
 
 
 
 
 
 
 
324
 
325
- asset_index = int(progress * len(assets)) if assets else 0
326
- current_asset = assets[asset_index] if assets else None
327
-
328
- future = executor.submit(
329
- self.create_enhanced_frame,
330
- current_text,
331
- self.themes[style],
332
- i,
333
- total_frames,
334
- current_asset['data'] if current_asset and current_asset['type'] == 'image' else None
335
- )
336
- frame_futures.append(future)
337
-
338
- batch_frames = [future.result() for future in frame_futures]
339
- frames.extend(batch_frames)
340
-
341
- progress = int(60 + (batch/num_batches) * 30)
342
- progress_bar.progress(progress)
343
-
344
- # Create video clip (90%)
345
- status_text.text("Compiling video...")
346
- video = ImageSequenceClip(frames, fps=fps)
347
- video = video.set_audio(audio)
348
- progress_bar.progress(90)
349
-
350
- # Write final video (100%)
351
- status_text.text("Saving video...")
352
- video.write_videofile(
353
- output_path,
354
- fps=fps,
355
- codec='libx264',
356
- audio_codec='aac',
357
- threads=4,
358
- preset='ultrafast' # Faster encoding
359
- )
360
-
361
- progress_bar.progress(100)
362
- status_text.text("Video generation complete!")
363
- return output_path
364
-
365
- except Exception as e:
366
- self.logger.error(f"Video creation failed: {str(e)}")
367
- raise
368
 
 
369
  def generate_visual_assets(self, script: str, style: str) -> List[Dict]:
370
  """Generate relevant visual assets based on script content"""
371
  try:
@@ -504,42 +535,59 @@ class VideoGeneratorUI:
504
 
505
  def setup_ui(self):
506
  st.title("Enhanced Video Generator")
507
-
508
- with st.form("video_generator_form"):
509
- prompt = st.text_area("Enter your video topic/prompt", height=100)
510
- col1, col2 = st.columns(2)
 
 
 
 
511
 
512
- with col1:
513
- style = st.selectbox("Choose style", options=list(self.generator.themes.keys()))
514
- with col2:
515
- duration = st.slider("Video duration (seconds)", 10, 300, 60, 10)
516
-
517
- submit_button = st.form_submit_button("Generate Video")
518
-
519
- if submit_button and prompt:
520
- try:
521
- output_path = os.path.join(os.getcwd(), f"generated_video_{int(time.time())}.mp4")
522
-
523
- video_path = self.generator.create_video(prompt, style, duration, output_path)
524
-
525
- if os.path.exists(video_path):
526
- st.success("Video generated successfully!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
527
 
528
- with open(video_path, 'rb') as video_file:
529
- st.video(video_file) # Display video
530
- video_bytes = video_file.read()
531
 
532
- st.download_button(
533
- "Download Video",
534
- video_bytes,
535
- file_name=os.path.basename(video_path),
536
- mime="video/mp4"
537
- )
538
- else:
539
- st.error("Video file not found")
540
-
541
- except Exception as e:
542
- st.error(f"Failed to generate video: {str(e)}")
543
 
544
  if __name__ == "__main__":
545
  ui = VideoGeneratorUI()
 
18
  import logging
19
  import time
20
  from typing import Optional, List, Dict, Tuple
21
+ from bs4 import BeautifulSoup
22
+ import requests
23
+ from io import BytesIO
24
 
25
+ class ImageScraper:
26
  def __init__(self):
27
+ self.headers = {
28
+ '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'
29
+ }
30
+
31
+ def scrape_pexels(self, query: str) -> List[str]:
32
+ urls = []
33
+ try:
34
+ url = f"https://www.pexels.com/search/{query.replace(' ', '%20')}/"
35
+ response = requests.get(url, headers=self.headers)
36
+ soup = BeautifulSoup(response.text, 'html.parser')
37
+ for img in soup.find_all('img', src=True):
38
+ if 'photos' in img['src'] and 'pexels.com' in img['src']:
39
+ urls.append(img['src'])
40
+ except Exception as e:
41
+ print(f"Pexels scraping error: {e}")
42
+ return urls
43
+
44
+ def scrape_unsplash(self, query: str) -> List[str]:
45
+ urls = []
46
  try:
47
+ url = f"https://unsplash.com/s/photos/{query.replace(' ', '-')}"
48
+ response = requests.get(url, headers=self.headers)
49
+ soup = BeautifulSoup(response.text, 'html.parser')
50
+ for img in soup.find_all('img', src=True):
51
+ if 'images.unsplash.com' in img['src']:
52
+ urls.append(img['src'])
53
+ except Exception as e:
54
+ print(f"Unsplash scraping error: {e}")
55
+ return urls
56
+
57
+ def get_images(self, query: str, num_images: int = 15) -> List[str]:
58
+ all_urls = []
59
+ all_urls.extend(self.scrape_pexels(query))
60
+ all_urls.extend(self.scrape_unsplash(query))
61
+
62
+ # Remove duplicates and limit to num_images
63
+ return list(set(all_urls))[:num_images]
64
+
65
+ class EnhancedVideoGenerator:
66
+ def __init__(self):
67
+ self.setup_logging()
68
+ self.setup_device()
69
+ self.initialize_models()
70
+ self.setup_workspace()
71
+ self.load_assets()
72
+ self.setup_themes()
73
+ self.image_scraper = ImageScraper()
74
  except Exception as e:
75
  logging.error(f"Initialization failed: {str(e)}")
76
  raise RuntimeError("Failed to initialize video generator")
 
326
  self.logger.error(f"Voice-over generation failed: {str(e)}")
327
  return AudioFileClip(duration=len(script.split()) * 0.3)
328
 
329
+ def create_video(self, script: str, style: str, duration: int, output_path: str, selected_images: List[str]) -> str:
330
+ """Create video with selected images"""
331
+ try:
332
+ # Progress bar
333
+ progress_bar = st.progress(0)
334
+ status_text = st.empty()
335
+
336
+ # Generate voice-over (20%)
337
+ status_text.text("Creating voice-over...")
338
+ audio = self.generate_voice_over(script)
339
+ progress_bar.progress(20)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
 
341
+ # Process selected images (40%)
342
+ status_text.text("Processing images...")
343
+ processed_images = []
344
+ for img_url in selected_images:
345
+ response = requests.get(img_url)
346
+ img = Image.open(BytesIO(response.content))
347
+ img = img.resize((1920, 1080), Image.Resampling.LANCZOS)
348
+ processed_images.append(np.array(img))
349
+ progress_bar.progress(40)
350
+
351
+ # Create frames with transitions
352
+ fps = 30
353
+ total_frames = int(duration * fps)
354
+ frames = []
355
+
356
+ status_text.text("Generating frames...")
357
+ frames_per_image = total_frames // len(processed_images)
358
+
359
+ for idx, img in enumerate(processed_images):
360
+ for _ in range(frames_per_image):
361
+ frames.append(img)
362
 
363
+ # Add transition frames
364
+ if idx < len(processed_images) - 1:
365
+ next_img = processed_images[idx + 1]
366
+ for alpha in np.linspace(0, 1, 15):
367
+ transition_frame = (1 - alpha) * img + alpha * next_img
368
+ frames.append(transition_frame.astype(np.uint8))
369
+
370
+ progress_bar.progress(70)
371
+
372
+ # Create video clip
373
+ status_text.text("Compiling video...")
374
+ video = ImageSequenceClip(frames, fps=fps)
375
+ video = video.set_audio(audio)
376
+
377
+ progress_bar.progress(90)
378
+
379
+ # Write final video
380
+ status_text.text("Saving video...")
381
+ video.write_videofile(
382
+ output_path,
383
+ fps=fps,
384
+ codec='libx264',
385
+ audio_codec='aac',
386
+ threads=4,
387
+ preset='ultrafast'
388
+ )
389
+
390
+ progress_bar.progress(100)
391
+ status_text.text("Video generation complete!")
392
+
393
+ return output_path
394
+
395
+ except Exception as e:
396
+ self.logger.error(f"Video creation failed: {str(e)}")
397
+ raise
 
 
 
 
 
 
 
 
398
 
399
+
400
  def generate_visual_assets(self, script: str, style: str) -> List[Dict]:
401
  """Generate relevant visual assets based on script content"""
402
  try:
 
535
 
536
  def setup_ui(self):
537
  st.title("Enhanced Video Generator")
538
+
539
+ # Step 1: Input prompt
540
+ prompt = st.text_input("Enter your video topic/prompt")
541
+
542
+ if prompt:
543
+ # Step 2: Image Selection
544
+ st.subheader("Select Images for Your Video")
545
+ images = self.generator.image_scraper.get_images(prompt)
546
 
547
+ if not images:
548
+ st.warning("No images found. Try a different search term.")
549
+ return
550
+
551
+ selected_images = []
552
+ cols = st.columns(3)
553
+ for idx, img_url in enumerate(images):
554
+ with cols[idx % 3]:
555
+ try:
556
+ response = requests.get(img_url)
557
+ img = Image.open(BytesIO(response.content))
558
+ st.image(img, use_column_width=True)
559
+ if st.checkbox(f"Select Image {idx + 1}", key=f"img_{idx}"):
560
+ selected_images.append(img_url)
561
+ except:
562
+ continue
563
+
564
+ # Step 3: Video Generation (only show if images are selected)
565
+ if selected_images:
566
+ st.subheader("Video Generation Settings")
567
+ col1, col2 = st.columns(2)
568
+ with col1:
569
+ style = st.selectbox("Choose style", options=list(self.generator.themes.keys()))
570
+ with col2:
571
+ duration = st.slider("Video duration (seconds)", 10, 300, 60, 10)
572
+
573
+ if st.button("Generate Video"):
574
+ try:
575
+ output_path = os.path.join(os.getcwd(), f"generated_video_{int(time.time())}.mp4")
576
+ video_path = self.generator.create_video(prompt, style, duration, output_path, selected_images)
577
 
578
+ if os.path.exists(video_path):
579
+ st.success("Video generated successfully!")
580
+ st.video(video_path)
581
 
582
+ with open(video_path, 'rb') as video_file:
583
+ st.download_button(
584
+ "Download Video",
585
+ video_file.read(),
586
+ file_name=os.path.basename(video_path),
587
+ mime="video/mp4"
588
+ )
589
+ except Exception as e:
590
+ st.error(f"Failed to generate video: {str(e)}")
 
 
591
 
592
  if __name__ == "__main__":
593
  ui = VideoGeneratorUI()