shaheerawan3 commited on
Commit
cb13d56
·
verified ·
1 Parent(s): 2a32b91

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -173
app.py CHANGED
@@ -1,7 +1,7 @@
1
  import streamlit as st
2
  from pathlib import Path
3
  import torch
4
- from transformers import pipeline, AutoModelForCausalLM, AutoTokenizer
5
  from PIL import Image, ImageDraw, ImageFont
6
  import tempfile
7
  import os
@@ -13,8 +13,6 @@ from concurrent.futures import ThreadPoolExecutor
13
  import io
14
  import unicodedata
15
  import re
16
- import requests
17
- import random
18
  import logging
19
  from typing import Optional, List, Dict, Tuple
20
 
@@ -24,13 +22,13 @@ class EnhancedVideoGenerator:
24
  try:
25
  self.setup_logging()
26
  self.setup_device()
27
- self.initialize_models()
28
  self.setup_workspace()
29
  self.load_assets()
30
  self.setup_themes()
 
31
  except Exception as e:
32
- logging.error(f"Initialization failed: {str(e)}")
33
- raise RuntimeError("Failed to initialize video generator")
34
 
35
  def setup_logging(self):
36
  """Configure logging for the application"""
@@ -52,22 +50,15 @@ class EnhancedVideoGenerator:
52
  def initialize_models(self):
53
  """Initialize all AI models"""
54
  try:
55
- # Text generation model
56
  self.text_generator = pipeline(
57
  'text-generation',
58
- model='gpt2',
59
  device=0 if self.device == "cuda" else -1
60
  )
61
-
62
- # Initialize free image generation model
63
- self.image_model = AutoModelForCausalLM.from_pretrained(
64
- "CompVis/stable-diffusion-v1-4",
65
- torch_dtype=torch.float16 if self.device == "cuda" else torch.float32
66
- ).to(self.device)
67
-
68
  except Exception as e:
69
  self.logger.error(f"Model initialization failed: {str(e)}")
70
- raise
71
 
72
  def setup_workspace(self):
73
  """Set up working directory and resources"""
@@ -117,24 +108,29 @@ class EnhancedVideoGenerator:
117
 
118
  except Exception as e:
119
  self.logger.error(f"Asset loading failed: {str(e)}")
 
120
 
121
  def generate_visual_assets(self, script: str, style: str) -> List[Dict]:
122
- """Generate relevant visual assets based on script content"""
123
  try:
124
- # Extract key topics from script
125
- topics = self.extract_key_topics(script)
 
 
 
 
 
 
126
 
127
  assets = []
128
- for topic in topics:
129
- # Generate AI image
130
- image = self.generate_ai_image(topic, style)
131
- if image:
132
- assets.append({
133
- 'type': 'image',
134
- 'data': image,
135
- 'topic': topic
136
- })
137
-
138
  return assets
139
 
140
  except Exception as e:
@@ -148,13 +144,12 @@ class EnhancedVideoGenerator:
148
  frame_number: int,
149
  total_frames: int,
150
  background_image: Optional[Image.Image] = None,
151
- size: Tuple[int, int] = (1920, 1080) # Upgraded to 1080p
152
  ) -> np.ndarray:
153
  """Create a visually enhanced frame with background, text, and effects"""
154
  try:
155
  # Create base frame
156
  if background_image:
157
- # Resize and crop background to fit
158
  bg = background_image.resize(size, Image.LANCZOS)
159
  frame = np.array(bg)
160
  else:
@@ -164,15 +159,6 @@ class EnhancedVideoGenerator:
164
  img = Image.fromarray(frame)
165
  draw = ImageDraw.Draw(img, 'RGBA')
166
 
167
- # Add subtle gradient overlay
168
- overlay = Image.new('RGBA', size, (0, 0, 0, 0))
169
- overlay_draw = ImageDraw.Draw(overlay)
170
- overlay_draw.rectangle(
171
- [0, 0, size[0], size[1]],
172
- fill=(255, 255, 255, 100) # Semi-transparent white
173
- )
174
- img = Image.alpha_composite(img.convert('RGBA'), overlay)
175
-
176
  # Add text with improved styling
177
  text = self.clean_text(text)
178
  wrapped_text = textwrap.fill(text, width=50)
@@ -182,7 +168,7 @@ class EnhancedVideoGenerator:
182
  text_width = text_bbox[2] - text_bbox[0]
183
  text_height = text_bbox[3] - text_bbox[1]
184
  text_x = (size[0] - text_width) // 2
185
- text_y = size[1] - text_height - 100 # Position at bottom
186
 
187
  # Draw text background
188
  padding = 20
@@ -193,7 +179,7 @@ class EnhancedVideoGenerator:
193
  text_x + text_width + padding,
194
  text_y + text_height + padding
195
  ],
196
- fill=(0, 0, 0, 160) # Semi-transparent black
197
  )
198
 
199
  # Draw text
@@ -204,7 +190,7 @@ class EnhancedVideoGenerator:
204
  font=self.font
205
  )
206
 
207
- # Add progress bar with animation
208
  self.draw_animated_progress_bar(
209
  draw,
210
  frame_number,
@@ -217,7 +203,6 @@ class EnhancedVideoGenerator:
217
 
218
  except Exception as e:
219
  self.logger.error(f"Frame creation failed: {str(e)}")
220
- # Return fallback frame
221
  return np.full((size[1], size[0], 3), theme['bg'], dtype=np.uint8)
222
 
223
  def draw_animated_progress_bar(
@@ -228,10 +213,10 @@ class EnhancedVideoGenerator:
228
  size: Tuple[int, int],
229
  theme: dict
230
  ):
231
- """Draw an animated progress bar with effects"""
232
  try:
233
  progress = frame_number / total_frames
234
- bar_width = int(size[0] * 0.8) # 80% of screen width
235
  bar_height = 6
236
  x_offset = (size[0] - bar_width) // 2
237
  y_position = size[1] - 40
@@ -242,28 +227,18 @@ class EnhancedVideoGenerator:
242
  fill=(200, 200, 200, 160)
243
  )
244
 
245
- # Draw progress with gradient effect
246
  progress_width = int(bar_width * progress)
247
- for x in range(progress_width):
248
- alpha = int(255 * (x / bar_width)) # Gradient effect
249
- draw.line(
250
- [x_offset + x, y_position, x_offset + x, y_position + bar_height],
251
- fill=(theme['accent'][0], theme['accent'][1], theme['accent'][2], alpha)
252
- )
253
-
254
- # Add animated highlight
255
- highlight_pos = x_offset + progress_width
256
- if highlight_pos < x_offset + bar_width:
257
- draw.rectangle(
258
- [highlight_pos-2, y_position-1, highlight_pos+2, y_position + bar_height+1],
259
- fill=(255, 255, 255, 200)
260
- )
261
 
262
  except Exception as e:
263
  self.logger.error(f"Progress bar drawing failed: {str(e)}")
264
 
265
  def generate_voice_over(self, script: str) -> AudioFileClip:
266
- """Generate voice-over audio using gTTS"""
267
  try:
268
  audio_path = self.temp_dir / "voice.mp3"
269
  tts = gTTS(
@@ -285,7 +260,7 @@ class EnhancedVideoGenerator:
285
  duration: int,
286
  output_path: str
287
  ) -> str:
288
- """Create full video with all enhanced features"""
289
  try:
290
  # Generate visual assets
291
  assets = self.generate_visual_assets(script, style)
@@ -293,7 +268,7 @@ class EnhancedVideoGenerator:
293
  # Generate voice-over
294
  audio = self.generate_voice_over(script)
295
 
296
- # Create frames with visual assets
297
  frames = []
298
  fps = 30
299
  total_frames = int(duration * fps)
@@ -302,16 +277,13 @@ class EnhancedVideoGenerator:
302
  frame_futures = []
303
 
304
  for i in range(total_frames):
305
- # Calculate current text segment
306
  progress = i / total_frames
307
  text_index = int(progress * len(script.split()))
308
  current_text = " ".join(script.split()[:text_index + 1])
309
 
310
- # Get appropriate background
311
  asset_index = int(progress * len(assets))
312
  current_asset = assets[asset_index] if assets else None
313
 
314
- # Submit frame creation to thread pool
315
  future = executor.submit(
316
  self.create_enhanced_frame,
317
  current_text,
@@ -322,7 +294,6 @@ class EnhancedVideoGenerator:
322
  )
323
  frame_futures.append(future)
324
 
325
- # Collect frames
326
  frames = [future.result() for future in frame_futures]
327
 
328
  # Create video clip
@@ -331,14 +302,6 @@ class EnhancedVideoGenerator:
331
  # Add voice-over
332
  video = video.set_audio(audio)
333
 
334
- # Add background music (if available)
335
- try:
336
- music = AudioFileClip("assets/music/background.mp3")
337
- music = music.volumex(0.1).loop(duration=video.duration)
338
- video = video.set_audio(CompositeAudioClip([video.audio, music]))
339
- except Exception as e:
340
- self.logger.warning(f"Background music addition failed: {str(e)}")
341
-
342
  # Write final video
343
  video.write_videofile(
344
  output_path,
@@ -361,84 +324,25 @@ class EnhancedVideoGenerator:
361
  if not isinstance(text, str):
362
  text = str(text)
363
 
364
- # Normalize unicode characters
365
  text = unicodedata.normalize('NFKD', text)
366
-
367
- # Remove non-ASCII characters
368
  text = text.encode('ascii', 'ignore').decode('ascii')
369
 
370
- # Replace problematic characters
371
  replacements = {
372
- '–': '-', # en dash
373
- '—': '-', # em dash
374
- '"': '"', # smart quotes
375
- '"': '"', # smart quotes
376
- ''': "'", # smart apostrophe
377
- ''': "'", # smart apostrophe
378
- '…': '...', # ellipsis
379
  }
380
  for old, new in replacements.items():
381
  text = text.replace(old, new)
382
 
383
- # Remove any remaining non-standard characters
384
  text = re.sub(r'[^\x00-\x7F]+', '', text)
385
 
386
  return text.strip()
387
 
388
- def extract_key_topics(self, script: str) -> List[str]:
389
- """Extract main topics from the script for visual asset generation"""
390
- try:
391
- # Simple keyword extraction based on noun phrases
392
- # In a production environment, you might want to use a proper NLP library
393
- sentences = script.split('.')
394
- topics = []
395
-
396
- for sentence in sentences:
397
- words = sentence.strip().split()
398
- if len(words) >= 2:
399
- # Extract potential noun phrases (pairs of words)
400
- topics.append(' '.join(words[:2]))
401
-
402
- # Remove duplicates and limit to top 5 topics
403
- return list(dict.fromkeys(topics))[:5]
404
-
405
- except Exception as e:
406
- self.logger.error(f"Topic extraction failed: {str(e)}")
407
- return ["default topic"]
408
-
409
- def generate_ai_image(self, prompt: str, style: str) -> Optional[Image.Image]:
410
- """Generate an AI image using Stability AI"""
411
- try:
412
- if not self.stability_api:
413
- return None
414
-
415
- # Enhance prompt based on style
416
- style_prompts = {
417
- 'Professional': "professional, corporate, clean, modern",
418
- 'Creative': "artistic, vibrant, innovative, dynamic",
419
- 'Educational': "clear, informative, academic, detailed"
420
- }
421
-
422
- enhanced_prompt = f"{prompt}, {style_prompts.get(style, '')}, high quality, 4k"
423
-
424
- # Generate image
425
- response = self.stability_api.generate(
426
- prompt=enhanced_prompt,
427
- samples=1,
428
- width=1920,
429
- height=1080
430
- )
431
-
432
- if response and len(response) > 0:
433
- image_data = response[0].image
434
- return Image.open(io.BytesIO(image_data))
435
-
436
- return None
437
-
438
- except Exception as e:
439
- self.logger.error(f"AI image generation failed: {str(e)}")
440
- return None
441
-
442
  def cleanup(self):
443
  """Clean up temporary files and resources"""
444
  try:
@@ -463,7 +367,6 @@ class EnhancedVideoGenerator:
463
  def __exit__(self, exc_type, exc_val, exc_tb):
464
  self.cleanup()
465
 
466
- # Streamlit UI Class
467
  class VideoGeneratorUI:
468
  def __init__(self):
469
  self.generator = EnhancedVideoGenerator()
@@ -474,11 +377,10 @@ class VideoGeneratorUI:
474
  st.write("Create professional videos with AI-generated content")
475
 
476
  with st.form("video_generator_form"):
477
- # Input fields
478
  prompt = st.text_area(
479
- "Enter your video topic/prompt",
480
  height=100,
481
- help="Describe what you want your video to be about"
482
  )
483
 
484
  col1, col2 = st.columns(2)
@@ -497,41 +399,17 @@ class VideoGeneratorUI:
497
  step=10
498
  )
499
 
500
- advanced_options = st.expander("Advanced Options")
501
- with advanced_options:
502
- use_premium_voice = st.checkbox(
503
- "Use premium voice-over",
504
- value=False,
505
- help="Requires ElevenLabs API key"
506
- )
507
-
508
- include_music = st.checkbox(
509
- "Include background music",
510
- value=True
511
- )
512
-
513
- fps = st.slider(
514
- "Frames per second",
515
- min_value=24,
516
- max_value=60,
517
- value=30
518
- )
519
-
520
  submit_button = st.form_submit_button("Generate Video")
521
 
522
  if submit_button:
523
  if not prompt:
524
- st.error("Please enter a prompt for your video.")
525
  return
526
 
527
  try:
528
  with st.spinner("Generating your video..."):
529
  output_path = f"generated_video_{int(time.time())}.mp4"
530
 
531
- # Update generator settings based on advanced options
532
- self.generator.use_premium_voice = use_premium_voice
533
-
534
- # Generate video
535
  video_path = self.generator.create_video(
536
  prompt,
537
  style,
@@ -539,7 +417,6 @@ class VideoGeneratorUI:
539
  output_path
540
  )
541
 
542
- # Show success message and download button
543
  st.success("Video generated successfully!")
544
 
545
  with open(video_path, 'rb') as f:
@@ -552,7 +429,7 @@ class VideoGeneratorUI:
552
 
553
  except Exception as e:
554
  st.error(f"Failed to generate video: {str(e)}")
555
- st.error("Please try again with different settings or contact support.")
556
 
557
  if __name__ == "__main__":
558
  ui = VideoGeneratorUI()
 
1
  import streamlit as st
2
  from pathlib import Path
3
  import torch
4
+ from transformers import pipeline
5
  from PIL import Image, ImageDraw, ImageFont
6
  import tempfile
7
  import os
 
13
  import io
14
  import unicodedata
15
  import re
 
 
16
  import logging
17
  from typing import Optional, List, Dict, Tuple
18
 
 
22
  try:
23
  self.setup_logging()
24
  self.setup_device()
 
25
  self.setup_workspace()
26
  self.load_assets()
27
  self.setup_themes()
28
+ self.initialize_models()
29
  except Exception as e:
30
+ self.logger.error(f"Initialization failed: {str(e)}")
31
+ raise RuntimeError(f"Failed to initialize video generator: {str(e)}")
32
 
33
  def setup_logging(self):
34
  """Configure logging for the application"""
 
50
  def initialize_models(self):
51
  """Initialize all AI models"""
52
  try:
53
+ # Text generation model - using a smaller model for better compatibility
54
  self.text_generator = pipeline(
55
  'text-generation',
56
+ model='distilgpt2',
57
  device=0 if self.device == "cuda" else -1
58
  )
 
 
 
 
 
 
 
59
  except Exception as e:
60
  self.logger.error(f"Model initialization failed: {str(e)}")
61
+ self.text_generator = None
62
 
63
  def setup_workspace(self):
64
  """Set up working directory and resources"""
 
108
 
109
  except Exception as e:
110
  self.logger.error(f"Asset loading failed: {str(e)}")
111
+ self.font = ImageFont.load_default()
112
 
113
  def generate_visual_assets(self, script: str, style: str) -> List[Dict]:
114
+ """Generate or fetch relevant visual assets based on script content"""
115
  try:
116
+ # Generate simple colored backgrounds instead of AI images
117
+ colors = [
118
+ (240, 248, 255), # AliceBlue
119
+ (240, 255, 255), # Azure
120
+ (245, 245, 245), # WhiteSmoke
121
+ (255, 250, 250), # Snow
122
+ (248, 248, 255) # GhostWhite
123
+ ]
124
 
125
  assets = []
126
+ for i in range(5): # Generate 5 different backgrounds
127
+ img = Image.new('RGB', (1920, 1080), colors[i])
128
+ assets.append({
129
+ 'type': 'image',
130
+ 'data': img,
131
+ 'topic': f'background_{i}'
132
+ })
133
+
 
 
134
  return assets
135
 
136
  except Exception as e:
 
144
  frame_number: int,
145
  total_frames: int,
146
  background_image: Optional[Image.Image] = None,
147
+ size: Tuple[int, int] = (1920, 1080)
148
  ) -> np.ndarray:
149
  """Create a visually enhanced frame with background, text, and effects"""
150
  try:
151
  # Create base frame
152
  if background_image:
 
153
  bg = background_image.resize(size, Image.LANCZOS)
154
  frame = np.array(bg)
155
  else:
 
159
  img = Image.fromarray(frame)
160
  draw = ImageDraw.Draw(img, 'RGBA')
161
 
 
 
 
 
 
 
 
 
 
162
  # Add text with improved styling
163
  text = self.clean_text(text)
164
  wrapped_text = textwrap.fill(text, width=50)
 
168
  text_width = text_bbox[2] - text_bbox[0]
169
  text_height = text_bbox[3] - text_bbox[1]
170
  text_x = (size[0] - text_width) // 2
171
+ text_y = size[1] - text_height - 100
172
 
173
  # Draw text background
174
  padding = 20
 
179
  text_x + text_width + padding,
180
  text_y + text_height + padding
181
  ],
182
+ fill=(0, 0, 0, 160)
183
  )
184
 
185
  # Draw text
 
190
  font=self.font
191
  )
192
 
193
+ # Add progress bar
194
  self.draw_animated_progress_bar(
195
  draw,
196
  frame_number,
 
203
 
204
  except Exception as e:
205
  self.logger.error(f"Frame creation failed: {str(e)}")
 
206
  return np.full((size[1], size[0], 3), theme['bg'], dtype=np.uint8)
207
 
208
  def draw_animated_progress_bar(
 
213
  size: Tuple[int, int],
214
  theme: dict
215
  ):
216
+ """Draw an animated progress bar"""
217
  try:
218
  progress = frame_number / total_frames
219
+ bar_width = int(size[0] * 0.8)
220
  bar_height = 6
221
  x_offset = (size[0] - bar_width) // 2
222
  y_position = size[1] - 40
 
227
  fill=(200, 200, 200, 160)
228
  )
229
 
230
+ # Draw progress
231
  progress_width = int(bar_width * progress)
232
+ draw.rectangle(
233
+ [x_offset, y_position, x_offset + progress_width, y_position + bar_height],
234
+ fill=theme['accent']
235
+ )
 
 
 
 
 
 
 
 
 
 
236
 
237
  except Exception as e:
238
  self.logger.error(f"Progress bar drawing failed: {str(e)}")
239
 
240
  def generate_voice_over(self, script: str) -> AudioFileClip:
241
+ """Generate voice-over audio"""
242
  try:
243
  audio_path = self.temp_dir / "voice.mp3"
244
  tts = gTTS(
 
260
  duration: int,
261
  output_path: str
262
  ) -> str:
263
+ """Create full video with all features"""
264
  try:
265
  # Generate visual assets
266
  assets = self.generate_visual_assets(script, style)
 
268
  # Generate voice-over
269
  audio = self.generate_voice_over(script)
270
 
271
+ # Create frames
272
  frames = []
273
  fps = 30
274
  total_frames = int(duration * fps)
 
277
  frame_futures = []
278
 
279
  for i in range(total_frames):
 
280
  progress = i / total_frames
281
  text_index = int(progress * len(script.split()))
282
  current_text = " ".join(script.split()[:text_index + 1])
283
 
 
284
  asset_index = int(progress * len(assets))
285
  current_asset = assets[asset_index] if assets else None
286
 
 
287
  future = executor.submit(
288
  self.create_enhanced_frame,
289
  current_text,
 
294
  )
295
  frame_futures.append(future)
296
 
 
297
  frames = [future.result() for future in frame_futures]
298
 
299
  # Create video clip
 
302
  # Add voice-over
303
  video = video.set_audio(audio)
304
 
 
 
 
 
 
 
 
 
305
  # Write final video
306
  video.write_videofile(
307
  output_path,
 
324
  if not isinstance(text, str):
325
  text = str(text)
326
 
 
327
  text = unicodedata.normalize('NFKD', text)
 
 
328
  text = text.encode('ascii', 'ignore').decode('ascii')
329
 
 
330
  replacements = {
331
+ '–': '-',
332
+ '—': '-',
333
+ '"': '"',
334
+ '"': '"',
335
+ ''': "'",
336
+ ''': "'",
337
+ '…': '...',
338
  }
339
  for old, new in replacements.items():
340
  text = text.replace(old, new)
341
 
 
342
  text = re.sub(r'[^\x00-\x7F]+', '', text)
343
 
344
  return text.strip()
345
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  def cleanup(self):
347
  """Clean up temporary files and resources"""
348
  try:
 
367
  def __exit__(self, exc_type, exc_val, exc_tb):
368
  self.cleanup()
369
 
 
370
  class VideoGeneratorUI:
371
  def __init__(self):
372
  self.generator = EnhancedVideoGenerator()
 
377
  st.write("Create professional videos with AI-generated content")
378
 
379
  with st.form("video_generator_form"):
 
380
  prompt = st.text_area(
381
+ "Enter your video script",
382
  height=100,
383
+ help="Enter the text you want in your video"
384
  )
385
 
386
  col1, col2 = st.columns(2)
 
399
  step=10
400
  )
401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
  submit_button = st.form_submit_button("Generate Video")
403
 
404
  if submit_button:
405
  if not prompt:
406
+ st.error("Please enter a script for your video.")
407
  return
408
 
409
  try:
410
  with st.spinner("Generating your video..."):
411
  output_path = f"generated_video_{int(time.time())}.mp4"
412
 
 
 
 
 
413
  video_path = self.generator.create_video(
414
  prompt,
415
  style,
 
417
  output_path
418
  )
419
 
 
420
  st.success("Video generated successfully!")
421
 
422
  with open(video_path, 'rb') as f:
 
429
 
430
  except Exception as e:
431
  st.error(f"Failed to generate video: {str(e)}")
432
+ st.error("Please try again with different settings.")
433
 
434
  if __name__ == "__main__":
435
  ui = VideoGeneratorUI()