forked from xiaoxiae/videos
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild
executable file
·134 lines (99 loc) · 4.35 KB
/
build
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
#!/bin/python3
"""A script for building all of the files to be put together."""
import subprocess
import shutil
import os
import argparse
import soundfile as sf
import pyloudnorm as pyln
from glob import glob
video_directory = "video"
audio_directory = "audio"
parser = argparse.ArgumentParser(
description="A script for building files for the video."
)
parser.add_argument(
"-s", "--scene",
help="the name of the scene to build; builds all when omitted",
default=None,
)
parser.add_argument(
"--no-manim",
dest="no_manim",
action="store_true",
help="don't run Manim, just do the video post-processing",
default=False,
)
parser.add_argument(
"--no-sound-normalization",
dest="no_sound_normalization",
action="store_true",
help="don't normalize sound",
default=False,
)
parser.add_argument(
"-q", "--quality",
choices=["l", "m", "h", "k"],
default="k",
help="the quality of the video (k=4K by default)"
)
# licenses (to give as options)
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# get the parser and parse the commands
arguments = parser.parse_args()
# (possibly) call Manim
if not arguments.no_manim:
if arguments.scene is None:
# remove everything when no scene is specified
if os.path.exists(video_directory):
shutil.rmtree(video_directory)
process = subprocess.Popen(["python3", "-m", "manim", "scenes.py", f"-aq{arguments.quality}", "--disable_caching"])
else:
# remove only the scene and its folders when the scene is specified
scene_folder = os.path.join(video_directory, arguments.scene)
if os.path.exists(scene_folder):
shutil.rmtree(scene_folder)
scene_video = os.path.join(video_directory, arguments.scene + ".mp4")
if os.path.exists(scene_video):
os.remove(scene_video)
process = subprocess.Popen(["python3", "-m", "manim", "scenes.py", f"-q{arguments.quality}", "--disable_caching", arguments.scene])
result = process.communicate()
if process.returncode != 0:
print(f"\nBuild failed with exit code {process.returncode}")
quit()
# (possibly) normalize audio
if not arguments.no_sound_normalization:
raw_directory = os.path.join(audio_directory, "raw")
normalized_directory = os.path.join(audio_directory, "normalized")
for path in glob(os.path.abspath(os.path.join(raw_directory, "*.wav"))):
name = os.path.basename(path)
data, rate = sf.read(path)
meter = pyln.Meter(rate)
loudness = meter.integrated_loudness(data)
loudness_normalized_audio = pyln.normalize.loudness(data, loudness, -32.0)
sf.write(os.path.join(normalized_directory, name), loudness_normalized_audio, rate)
# rename to [1..n].mp4
for scene in os.listdir(video_directory):
if os.path.isdir(os.path.join(video_directory, scene)):
partial_file_path = os.path.join(video_directory, scene, "partial_movie_file_list.txt")
if os.path.exists(partial_file_path):
with open(partial_file_path) as f:
for i, video in enumerate(f.read().splitlines()[1:]):
path, name = os.path.split(video[11:-1])
video_folder = "vid"
image_folder = "img"
if not os.path.exists(os.path.join(path, video_folder)):
os.mkdir(os.path.join(path, video_folder))
if not os.path.exists(os.path.join(path, image_folder)):
os.mkdir(os.path.join(path, image_folder))
original_path = os.path.join(path, name)
changed_path = os.path.join(path, "vid", f"{i+1}.mp4")
image_path = os.path.join(path, "img", f"{i+1}.png")
video_from_image_path = os.path.join(path, "img", f"{i+1}.mp4")
os.rename(original_path, changed_path)
t = 10
# save the last frame from each video
subprocess.Popen(["ffmpeg", "-i", changed_path, "-vf", 'select=eq(n\,0)', "-vframes", "1", "-y", image_path]).communicate()
subprocess.Popen(["ffmpeg", "-loop", "1", "-i", image_path, "-c:v", "libx264", "-t", "5", "-pix_fmt", "yuv420p", video_from_image_path]).communicate()
os.remove(image_path)
os.remove(partial_file_path)