rairo commited on
Commit
9903c4d
·
verified ·
1 Parent(s): a6314a0

Update video_gen.py

Browse files
Files changed (1) hide show
  1. video_gen.py +165 -0
video_gen.py CHANGED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -----------------------
2
+ # Video Creation Functions
3
+ # -----------------------
4
+ import os
5
+ import re
6
+ import time
7
+ import tempfile
8
+ import requests
9
+ import json
10
+ import io
11
+ import base64
12
+ import numpy as np
13
+ import cv2
14
+ import logging
15
+ import uuid
16
+ import subprocess
17
+ from pathlib import Path
18
+ import urllib.parse
19
+ import pandas as pd
20
+ from PyPDF2 import PdfReader
21
+ import plotly.graph_objects as go
22
+ import matplotlib.pyplot as plt
23
+ import matplotlib
24
+ import matplotlib.pyplot as plt
25
+ from io import BytesIO
26
+ import dataframe_image as dfi
27
+ from PIL import ImageFont, ImageDraw, Image
28
+ import seaborn as sns
29
+
30
+
31
+
32
+ def create_silent_video(images, durations, output_path, logo_path="sozo_logo2.png", font_path="lazy_dog.ttf"):
33
+ try:
34
+ height, width = 720, 1280
35
+ fps = 24
36
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
37
+ video = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
38
+
39
+ if not video.isOpened():
40
+ st.error("Failed to create video file.")
41
+ return None
42
+
43
+ # Load font for text overlay
44
+ font_size = 45
45
+ font = ImageFont.truetype(font_path, font_size)
46
+
47
+ # Load logo for fallback and full-screen display at the end
48
+ logo = None
49
+ if logo_path:
50
+ logo = cv2.imread(logo_path)
51
+ if logo is not None:
52
+ logo = cv2.resize(logo, (width, height)) # Resize logo to full screen
53
+ else:
54
+ st.warning(f"Failed to load logo from {logo_path}. No fallback image will be used.")
55
+
56
+ for img, duration in zip(images, durations):
57
+ try:
58
+ img = img.convert("RGB")
59
+ img_resized = img.resize((width, height))
60
+ frame = np.array(img_resized)
61
+ except Exception as e:
62
+ print(f"Invalid image detected, replacing with logo: {e}")
63
+ if logo is not None:
64
+ frame = logo # Use the logo as a fallback
65
+ else:
66
+ # If no logo is available, create a blank frame
67
+ frame = np.zeros((height, width, 3), dtype=np.uint8)
68
+
69
+ # Convert to PIL for text drawing
70
+ pil_img = Image.fromarray(frame)
71
+ draw = ImageDraw.Draw(pil_img)
72
+
73
+ # Add "Sozo Dream Lab" text at bottom right
74
+ text1 = "Made With"
75
+ text2 = "Sozo Dream Lab"
76
+
77
+ # Calculate the height of the first text to adjust the second text's position
78
+ bbox = draw.textbbox((0, 0), text1, font=font)
79
+ text1_width = bbox[2] - bbox[0]
80
+ text1_height = bbox[3] - bbox[1]
81
+
82
+ text_position1 = (width - 270, height - 120) # position for "Made with"
83
+ text_position2 = (width - 330, height - 120 + text1_height + 5) # position for "Sozo dream lab", +5 for a little gap.
84
+
85
+ draw.text(text_position1, text1, font=font, fill=(81, 34, 97, 255)) # RGB: Purple
86
+ draw.text(text_position2, text2, font=font, fill=(81, 34, 97, 255)) # RGB: Purple
87
+
88
+ # Convert back to OpenCV format
89
+ frame = np.array(pil_img)
90
+ frame_cv = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
91
+
92
+ # Write frame multiple times to match duration
93
+ for _ in range(int(duration * fps)):
94
+ video.write(frame_cv)
95
+
96
+ # Add full-screen logo frame at the end
97
+ if logo is not None:
98
+ for _ in range(int(3 * fps)): # Display for 3 seconds
99
+ video.write(logo)
100
+
101
+ video.release()
102
+ return output_path
103
+
104
+ except Exception as e:
105
+ st.error(f"Error creating silent video: {e}")
106
+ return None
107
+
108
+
109
+ def combine_video_audio(video_path, audio_files, output_path=None):
110
+ try:
111
+ if output_path is None:
112
+ output_path = f"final_video_{uuid.uuid4()}.mp4"
113
+ temp_audio_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
114
+ temp_audio_file.close()
115
+ if len(audio_files) > 1:
116
+ concat_list_path = tempfile.NamedTemporaryFile(delete=False, suffix=".txt")
117
+ with open(concat_list_path.name, 'w') as f:
118
+ for af in audio_files:
119
+ f.write(f"file '{af}'\n")
120
+ concat_cmd = [
121
+ 'ffmpeg', '-y', '-f', 'concat', '-safe', '0',
122
+ '-i', concat_list_path.name, '-c', 'copy', temp_audio_file.name
123
+ ]
124
+ subprocess.run(concat_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
125
+ os.unlink(concat_list_path.name)
126
+ combined_audio = temp_audio_file.name
127
+ else:
128
+ combined_audio = audio_files[0] if audio_files else None
129
+ if not combined_audio:
130
+ return video_path
131
+ combine_cmd = [
132
+ 'ffmpeg', '-y', '-i', video_path, '-i', combined_audio,
133
+ '-map', '0:v', '-map', '1:a', '-c:v', 'libx264',
134
+ '-crf', '23', '-c:a', 'aac', '-shortest', output_path
135
+ ]
136
+ subprocess.run(combine_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
137
+ os.unlink(temp_audio_file.name)
138
+ return output_path
139
+ except Exception:
140
+ return video_path
141
+
142
+ def create_video(images, audio_files, output_path=None):
143
+ try:
144
+ try:
145
+ subprocess.run(['ffmpeg', '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
146
+ except FileNotFoundError:
147
+ st.error("ffmpeg not installed.")
148
+ return None
149
+ if output_path is None:
150
+ output_path = f"output_video_{uuid.uuid4()}.mp4"
151
+ silent_video_path = f"silent_{uuid.uuid4()}.mp4"
152
+ durations = [get_audio_duration(af) if af else 5.0 for af in audio_files]
153
+ if len(durations) < len(images):
154
+ durations.extend([5.0]*(len(images)-len(durations)))
155
+ silent_video = create_silent_video(images, durations, silent_video_path)
156
+ if not silent_video:
157
+ return None
158
+ final_video = combine_video_audio(silent_video, audio_files, output_path)
159
+ try:
160
+ os.unlink(silent_video_path)
161
+ except Exception:
162
+ pass
163
+ return final_video
164
+ except Exception:
165
+ return None