shaheerawan3 commited on
Commit
014d890
·
verified ·
1 Parent(s): 4646582

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +296 -0
app.py CHANGED
@@ -1273,6 +1273,302 @@ class VideoGeneratorUI:
1273
  st.error(f"Error generating video: {str(e)}")
1274
  print(f"Video generation error: {str(e)}") # For debugging
1275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1276
  def generate_video(self, prompt: str, style: str, duration: int, selected_images: List[str]):
1277
  """Handle video generation with improved error handling"""
1278
  if not selected_images:
 
1273
  st.error(f"Error generating video: {str(e)}")
1274
  print(f"Video generation error: {str(e)}") # For debugging
1275
 
1276
+ class VideoGenerator:
1277
+ def __init__(self):
1278
+ self.temp_dir = Path(tempfile.mkdtemp())
1279
+ self.setup_resources()
1280
+
1281
+ def setup_resources(self):
1282
+ # Initialize font
1283
+ try:
1284
+ font_options = [
1285
+ "arial.ttf",
1286
+ "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
1287
+ "/System/Library/Fonts/Helvetica.ttc"
1288
+ ]
1289
+ for font_path in font_options:
1290
+ try:
1291
+ self.font = ImageFont.truetype(font_path, 40)
1292
+ break
1293
+ except OSError:
1294
+ continue
1295
+ else:
1296
+ self.font = ImageFont.load_default()
1297
+ except Exception as e:
1298
+ print(f"Font loading error: {e}")
1299
+ self.font = ImageFont.load_default()
1300
+
1301
+ def create_video_frame(self, image, text, frame_number, total_frames, size=(1920, 1080)):
1302
+ try:
1303
+ # Resize and pad image to maintain aspect ratio
1304
+ img_aspect = image.size[0] / image.size[1]
1305
+ target_aspect = size[0] / size[1]
1306
+
1307
+ if img_aspect > target_aspect:
1308
+ new_height = size[1]
1309
+ new_width = int(new_height * img_aspect)
1310
+ else:
1311
+ new_width = size[0]
1312
+ new_height = int(new_width / img_aspect)
1313
+
1314
+ image = image.resize((new_width, new_height), Image.LANCZOS)
1315
+
1316
+ # Create new background
1317
+ frame = Image.new('RGB', size, (0, 0, 0))
1318
+
1319
+ # Paste resized image in center
1320
+ paste_x = (size[0] - new_width) // 2
1321
+ paste_y = (size[1] - new_height) // 2
1322
+ frame.paste(image, (paste_x, paste_y))
1323
+
1324
+ # Add text overlay
1325
+ draw = ImageDraw.Draw(frame)
1326
+
1327
+ # Text background
1328
+ text = textwrap.fill(text, width=50)
1329
+ text_bbox = draw.textbbox((0, 0), text, font=self.font)
1330
+ text_width = text_bbox[2] - text_bbox[0]
1331
+ text_height = text_bbox[3] - text_bbox[1]
1332
+
1333
+ text_x = (size[0] - text_width) // 2
1334
+ text_y = size[1] - text_height - 100
1335
+
1336
+ # Semi-transparent background
1337
+ padding = 20
1338
+ draw.rectangle(
1339
+ [
1340
+ text_x - padding,
1341
+ text_y - padding,
1342
+ text_x + text_width + padding,
1343
+ text_y + text_height + padding
1344
+ ],
1345
+ fill=(0, 0, 0, 180)
1346
+ )
1347
+
1348
+ # Draw text
1349
+ draw.text((text_x, text_y), text, fill=(255, 255, 255), font=self.font)
1350
+
1351
+ # Add progress bar
1352
+ self.draw_progress_bar(draw, frame_number, total_frames, size)
1353
+
1354
+ return np.array(frame)
1355
+
1356
+ except Exception as e:
1357
+ print(f"Frame creation error: {e}")
1358
+ return np.zeros((*size, 3), dtype=np.uint8)
1359
+
1360
+ def draw_progress_bar(self, draw, frame_number, total_frames, size):
1361
+ progress = frame_number / total_frames
1362
+ bar_width = int(size[0] * 0.8)
1363
+ bar_height = 6
1364
+ x_offset = (size[0] - bar_width) // 2
1365
+ y_position = size[1] - 40
1366
+
1367
+ # Background bar
1368
+ draw.rectangle(
1369
+ [x_offset, y_position, x_offset + bar_width, y_position + bar_height],
1370
+ fill=(100, 100, 100, 160)
1371
+ )
1372
+
1373
+ # Progress bar
1374
+ progress_width = int(bar_width * progress)
1375
+ draw.rectangle(
1376
+ [x_offset, y_position, x_offset + progress_width, y_position + bar_height],
1377
+ fill=(255, 255, 255, 200)
1378
+ )
1379
+
1380
+ def generate_video(self, script: str, images: List[str], duration: int, output_path: str) -> str:
1381
+ try:
1382
+ # Create temporary directory for processing
1383
+ os.makedirs(os.path.dirname(output_path), exist_ok=True)
1384
+
1385
+ # Process images
1386
+ processed_images = []
1387
+ for img_url in images:
1388
+ try:
1389
+ response = requests.get(img_url)
1390
+ img = Image.open(BytesIO(response.content)).convert('RGB')
1391
+ processed_images.append(img)
1392
+ except Exception as e:
1393
+ print(f"Image processing error: {e}")
1394
+ continue
1395
+
1396
+ if not processed_images:
1397
+ raise ValueError("No valid images to process")
1398
+
1399
+ # Generate frames
1400
+ fps = 30
1401
+ total_frames = duration * fps
1402
+ frames_per_image = total_frames // len(processed_images)
1403
+
1404
+ # Split script into sections
1405
+ words = script.split()
1406
+ words_per_image = len(words) // len(processed_images)
1407
+
1408
+ frames = []
1409
+ frame_count = 0
1410
+
1411
+ # Generate video frames
1412
+ for idx, img in enumerate(processed_images):
1413
+ # Get text section for this image
1414
+ start_idx = idx * words_per_image
1415
+ end_idx = start_idx + words_per_image if idx < len(processed_images) - 1 else len(words)
1416
+ section_text = ' '.join(words[start_idx:end_idx])
1417
+
1418
+ # Generate frames for this section
1419
+ for frame in range(frames_per_image):
1420
+ if frame_count < total_frames:
1421
+ frame_img = self.create_video_frame(
1422
+ img,
1423
+ section_text,
1424
+ frame_count,
1425
+ total_frames
1426
+ )
1427
+ frames.append(frame_img)
1428
+ frame_count += 1
1429
+
1430
+ # Add transition frames
1431
+ if idx < len(processed_images) - 1:
1432
+ next_img = processed_images[idx + 1]
1433
+ for t in range(15): # 15 frame transition
1434
+ if frame_count < total_frames:
1435
+ alpha = t / 15
1436
+ transition_frame = Image.blend(
1437
+ img,
1438
+ next_img,
1439
+ alpha
1440
+ )
1441
+ frame_img = self.create_video_frame(
1442
+ transition_frame,
1443
+ section_text,
1444
+ frame_count,
1445
+ total_frames
1446
+ )
1447
+ frames.append(frame_img)
1448
+ frame_count += 1
1449
+
1450
+ # Generate audio
1451
+ audio_path = self.temp_dir / "audio.mp3"
1452
+ tts = gTTS(text=script, lang='en')
1453
+ tts.save(str(audio_path))
1454
+
1455
+ # Create video
1456
+ clip = ImageSequenceClip(frames, fps=fps)
1457
+ audio_clip = AudioFileClip(str(audio_path))
1458
+
1459
+ # Adjust video length to match audio
1460
+ if audio_clip.duration < clip.duration:
1461
+ clip = clip.subclip(0, audio_clip.duration)
1462
+ else:
1463
+ audio_clip = audio_clip.subclip(0, clip.duration)
1464
+
1465
+ final_clip = clip.set_audio(audio_clip)
1466
+
1467
+ # Write video
1468
+ final_clip.write_videofile(
1469
+ output_path,
1470
+ fps=fps,
1471
+ codec='libx264',
1472
+ audio_codec='aac',
1473
+ ffmpeg_params=['-pix_fmt', 'yuv420p']
1474
+ )
1475
+
1476
+ return output_path
1477
+
1478
+ except Exception as e:
1479
+ print(f"Video generation error: {e}")
1480
+ raise
1481
+ finally:
1482
+ # Cleanup
1483
+ try:
1484
+ if 'clip' in locals():
1485
+ clip.close()
1486
+ if 'final_clip' in locals():
1487
+ final_clip.close()
1488
+ if 'audio_clip' in locals():
1489
+ audio_clip.close()
1490
+ except Exception as e:
1491
+ print(f"Cleanup error: {e}")
1492
+
1493
+ def cleanup(self):
1494
+ try:
1495
+ import shutil
1496
+ shutil.rmtree(self.temp_dir)
1497
+ except Exception as e:
1498
+ print(f"Cleanup error: {e}")
1499
+
1500
+ def create_ui():
1501
+ st.title("VaultGenix Video Generator")
1502
+ st.markdown("Create professional videos for your digital legacy management platform")
1503
+
1504
+ # File upload section
1505
+ st.subheader("Upload Content")
1506
+ uploaded_file = st.file_uploader(
1507
+ "Upload your content (PDF, DOCX, PPTX, or TXT)",
1508
+ type=['pdf', 'docx', 'pptx', 'txt']
1509
+ )
1510
+
1511
+ # Text input section
1512
+ script = ""
1513
+ if uploaded_file:
1514
+ try:
1515
+ file_processor = FileProcessor()
1516
+ if uploaded_file.type == "text/plain":
1517
+ script = file_processor.read_txt(uploaded_file)
1518
+ elif uploaded_file.type == "application/pdf":
1519
+ script = file_processor.read_pdf(uploaded_file)
1520
+ elif uploaded_file.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
1521
+ script = file_processor.read_docx(uploaded_file)
1522
+ elif uploaded_file.type == "application/vnd.openxmlformats-officedocument.presentationml.presentation":
1523
+ script = file_processor.read_pptx(uploaded_file)
1524
+ except Exception as e:
1525
+ st.error(f"Error processing file: {str(e)}")
1526
+
1527
+ script = st.text_area("Enter or edit your video script", value=script, height=200)
1528
+
1529
+ if st.button("Generate Video") and script:
1530
+ try:
1531
+ # Initialize video generator
1532
+ generator = VideoGenerator()
1533
+
1534
+ # Get stock images (replace with your image selection logic)
1535
+ images = [
1536
+ "https://images.pexels.com/photos/60504/security-protection-anti-virus-software-60504.jpeg",
1537
+ "https://images.pexels.com/photos/5380642/pexels-photo-5380642.jpeg",
1538
+ "https://images.pexels.com/photos/2582937/pexels-photo-2582937.jpeg"
1539
+ ]
1540
+
1541
+ # Generate video
1542
+ output_path = "output_video.mp4"
1543
+ with st.spinner("Generating video..."):
1544
+ video_path = generator.generate_video(script, images, 30, output_path)
1545
+
1546
+ # Display video
1547
+ if os.path.exists(video_path):
1548
+ st.success("Video generated successfully!")
1549
+ with open(video_path, 'rb') as video_file:
1550
+ video_bytes = video_file.read()
1551
+ st.video(video_bytes)
1552
+
1553
+ # Download button
1554
+ st.download_button(
1555
+ label="Download Video",
1556
+ data=video_bytes,
1557
+ file_name="vaultgenix_video.mp4",
1558
+ mime="video/mp4"
1559
+ )
1560
+
1561
+ except Exception as e:
1562
+ st.error(f"Error generating video: {str(e)}")
1563
+ print(f"Error details: {str(e)}")
1564
+
1565
+ if __name__ == "__main__":
1566
+ create_ui()
1567
+
1568
+
1569
+
1570
+
1571
+
1572
  def generate_video(self, prompt: str, style: str, duration: int, selected_images: List[str]):
1573
  """Handle video generation with improved error handling"""
1574
  if not selected_images: