-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcreate_video_from_images.py
154 lines (131 loc) · 6.73 KB
/
create_video_from_images.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import os
from PIL import Image, ImageDraw, ImageFont
import subprocess
from datetime import datetime
# Define directories
base_dir = '.'
visualizations_dir = os.path.join(base_dir, 'visualizations_geopandas')
dated_images_dir = os.path.join(base_dir, 'visualizations_with_dates')
square_images_dir = os.path.join(base_dir, 'visualizations_square')
vertical_images_dir = os.path.join(base_dir, 'visualizations_vertical')
square_dated_images_dir = os.path.join(base_dir, 'visualizations_square_with_dates')
vertical_dated_images_dir = os.path.join(base_dir, 'visualizations_vertical_with_dates')
# Get the current date in YYYYMMDD format
current_date = datetime.now().strftime('%Y%m%d')
# Define the video output paths with the current date
video_output_path = os.path.join(base_dir, f'visualization_video_{current_date}.mp4')
video_output_path_square = os.path.join(base_dir, f'visualization_video_square_{current_date}.mp4')
video_output_path_vertical = os.path.join(base_dir, f'visualization_video_vertical_{current_date}.mp4')
# Create new directory for images with date text
os.makedirs(dated_images_dir, exist_ok=True)
os.makedirs(square_dated_images_dir, exist_ok=True)
os.makedirs(vertical_dated_images_dir, exist_ok=True)
# Add a toggle for recreating images
recreate_images = True
# Introduce the overwrite variable
overwrite = True
# Define the path to the JetBrains font
font_path = os.path.join(base_dir, 'static', 'droid', 'droid.ttf')
# Path to the background music file
background_music_path = os.path.join(base_dir, 'static', 'timecode.mp3')
# Function to add date text to images and save them in a new directory
def add_date_to_image(image_path, date_text, output_dir):
output_path = os.path.join(output_dir, os.path.basename(image_path))
if not recreate_images and os.path.exists(output_path):
print(f"Image {output_path} already exists. Skipping creation.")
return
# Format date to German preferences (DD.MM.YYYY)
formatted_date = datetime.strptime(date_text, '%Y%m%d').strftime('%d.%m.%Y')
with Image.open(image_path) as img:
draw = ImageDraw.Draw(img)
# Calculate font size based on desired text height
text_height = 150
# Use a truetype font if available
try:
font = ImageFont.truetype(font_path, text_height)
except IOError:
print("JetBrains font not found. Using default font.")
sleep(50)
font = ImageFont.load_default()
# Calculate text width and adjust position
text_bbox = draw.textbbox((0, 0), formatted_date, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_position = (10, img.height - text_height - 10)
# Draw text on the image
draw.text(text_position, formatted_date, font=font, fill='black')
# Save the modified image
img.save(output_path)
# Function to add date text to images in different formats
def add_date_to_cropped_images(image_dir, output_dir, position):
for filename in os.listdir(image_dir):
if filename.endswith('.png'):
img_path = os.path.join(image_dir, filename)
output_path = os.path.join(output_dir, filename)
if not recreate_images and os.path.exists(output_path):
print(f"Image {output_path} already exists. Skipping creation.")
continue
img = Image.open(img_path)
draw = ImageDraw.Draw(img)
date_text = filename.split('_')[0]
formatted_date = datetime.strptime(date_text, '%Y%m%d').strftime('%d.%m.%Y')
# Calculate font size based on desired text height
text_height = 150
# Use a truetype font if available
try:
font = ImageFont.truetype(font_path, text_height)
except IOError:
print("JetBrains font not found. Using default font.")
sleep(50)
font = ImageFont.load_default()
# Calculate text width and adjust position
text_bbox = draw.textbbox((0, 0), formatted_date, font=font)
text_width = text_bbox[2] - text_bbox[0]
if position == 'center':
text_position = ((img.width - text_width) / 2, img.height - text_height - 10)
else: # 'bottom_left'
text_position = (10, img.height - text_height - 10)
draw.text(text_position, formatted_date, font=font, fill='black')
img.save(output_path)
image_files = sorted(os.listdir(visualizations_dir))
for image_file in image_files:
if image_file.endswith('_visualization.png'):
date_text = image_file.split('_')[0]
image_path = os.path.join(visualizations_dir, image_file)
add_date_to_image(image_path, date_text, dated_images_dir)
add_date_to_cropped_images(square_images_dir, square_dated_images_dir, 'bottom_left')
# Add date to vertical images
add_date_to_cropped_images(vertical_images_dir, vertical_dated_images_dir, 'center')
# Create video using ffmpeg with all files in order at 30 fps
ffmpeg_command = [
'ffmpeg', '-y', '-pattern_type', 'glob', '-framerate', '30', '-i', os.path.join(dated_images_dir, '*.png'),
'-i', background_music_path, '-c:v', 'libx264', '-r', '30', '-pix_fmt', 'yuv420p', '-shortest',
video_output_path
]
# Check if the video file already exists
if not overwrite and os.path.exists(video_output_path):
print(f"Video {video_output_path} already exists. Skipping creation.")
else:
subprocess.run(ffmpeg_command)
print(f'Video created at {video_output_path}')
# Check if the square video file already exists
if not overwrite and os.path.exists(video_output_path_square):
print(f"Square video {video_output_path_square} already exists. Skipping creation.")
else:
# Create square video
subprocess.run([
'ffmpeg', '-y', '-pattern_type', 'glob', '-framerate', '30', '-i', os.path.join(square_dated_images_dir, '*.png'),
'-i', background_music_path, '-vf', 'scale=1080:1080,setsar=1:1', '-c:v', 'libx264', '-r', '30', '-pix_fmt', 'yuv420p', '-shortest',
video_output_path_square
])
print(f'Square video created at {video_output_path_square}')
# Check if the vertical video file already exists
if not overwrite and os.path.exists(video_output_path_vertical):
print(f"9:16 video {video_output_path_vertical} already exists. Skipping creation.")
else:
# Create vertical 9:16 video
subprocess.run([
'ffmpeg', '-y', '-pattern_type', 'glob', '-framerate', '30', '-i', os.path.join(vertical_dated_images_dir, '*.png'),
'-i', background_music_path, '-vf', 'scale=1080:1920,setsar=1:1', '-c:v', 'libx264', '-r', '30', '-pix_fmt', 'yuv420p', '-shortest',
video_output_path_vertical
])
print(f'9:16 video created at {video_output_path_vertical}')