Improved stage_scenes and refactored get_movie_output_directory methods

This commit is contained in:
Grant Sanderson
2018-04-29 10:47:53 -07:00
parent 517ad24791
commit 65783e2738
4 changed files with 68 additions and 43 deletions

View File

@ -2,7 +2,7 @@ import os
import numpy as np import numpy as np
# Things anyone wishing to use this repository for their # Things anyone wishing to use this repository for their
# own use will want to change this # own use will want to change
MEDIA_DIR = os.path.join( MEDIA_DIR = os.path.join(
os.path.expanduser('~'), os.path.expanduser('~'),
"Dropbox (3Blue1Brown)/3Blue1Brown Team Folder" "Dropbox (3Blue1Brown)/3Blue1Brown Team Folder"

View File

@ -146,7 +146,7 @@ def handle_scene(scene, **config):
if (platform.system() == "Linux"): if (platform.system() == "Linux"):
commands = ["xdg-open"] commands = ["xdg-open"]
elif (platform.system() == "Windows"): elif (platform.system() == "Windows"):
commands = ["start"] commands = ["start"]
if config["show_file_in_finder"]: if config["show_file_in_finder"]:
commands.append("-R") commands.append("-R")
@ -238,10 +238,10 @@ def main():
module = get_module(config["file"]) module = get_module(config["file"])
scene_names_to_classes = dict(inspect.getmembers(module, is_scene)) scene_names_to_classes = dict(inspect.getmembers(module, is_scene))
config["output_directory"] = os.path.join( # config["output_directory"] = os.path.join(
ANIMATIONS_DIR, # ANIMATIONS_DIR,
config["file"].replace(".py", "") # config["file"].replace(".py", "")
) # )
scene_kwargs = dict([ scene_kwargs = dict([
(key, config[key]) (key, config[key])
@ -250,7 +250,6 @@ def main():
"frame_duration", "frame_duration",
"skip_animations", "skip_animations",
"write_to_movie", "write_to_movie",
"output_directory",
"save_pngs", "save_pngs",
"movie_file_extension", "movie_file_extension",
"start_at_animation_number", "start_at_animation_number",

View File

@ -29,6 +29,32 @@ def add_extension_if_not_present(file_name, extension):
return file_name return file_name
def get_scene_output_directory(scene_class):
file_path = os.path.abspath(inspect.getfile(scene_class))
# TODO, is there a better way to do this?
parts = file_path.split(os.path.sep)
if "manim" in parts:
sub_parts = parts[parts.index("manim") + 1:]
file_path = os.path.join(*sub_parts)
file_path = file_path.replace(".pyc", "")
file_path = file_path.replace(".py", "")
return os.path.join(ANIMATIONS_DIR, file_path)
def get_movie_output_directory(scene_class, camera_config, frame_duration):
directory = get_scene_output_directory(scene_class)
sub_dir = "%dp%d" % (
camera_config["pixel_shape"][0],
int(1.0 / frame_duration)
)
return os.path.join(directory, sub_dir)
def get_image_output_directory(scene_class, sub_dir="images"):
return os.path.join(get_scene_output_directory(scene_class), sub_dir)
class Scene(Container): class Scene(Container):
CONFIG = { CONFIG = {
"camera_class": Camera, "camera_class": Camera,
@ -41,14 +67,12 @@ class Scene(Container):
"save_frames": False, "save_frames": False,
"save_pngs": False, "save_pngs": False,
"pngs_mode": "RGBA", "pngs_mode": "RGBA",
"output_directory": ANIMATIONS_DIR,
"movie_file_extension": ".mp4", "movie_file_extension": ".mp4",
"name": None, "name": None,
"always_continually_update": False, "always_continually_update": False,
"random_seed": 0, "random_seed": 0,
"start_at_animation_number": None, "start_at_animation_number": None,
"end_at_animation_number": None, "end_at_animation_number": None,
"include_render_quality_in_output_directory": True,
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
@ -543,10 +567,10 @@ class Scene(Container):
self.get_image().show() self.get_image().show()
def get_image_file_path(self, name=None, dont_update=False): def get_image_file_path(self, name=None, dont_update=False):
folder = "images" sub_dir = "images"
if dont_update: if dont_update:
folder = str(self) sub_dir = str(self)
path = os.path.join(self.output_directory, folder) path = get_image_output_directory(self.__class__, sub_dir)
file_name = add_extension_if_not_present(name or str(self), ".png") file_name = add_extension_if_not_present(name or str(self), ".png")
return os.path.join(path, file_name) return os.path.join(path, file_name)
@ -562,16 +586,9 @@ class Scene(Container):
image.save(path) image.save(path)
def get_movie_file_path(self, name=None, extension=None): def get_movie_file_path(self, name=None, extension=None):
directory = self.output_directory directory = get_movie_output_directory(
if self.include_render_quality_in_output_directory: self.__class__, self.camera_config, self.frame_duration
sub_dir = "%dp%d" % ( )
self.camera.pixel_shape[0],
int(1.0 / self.frame_duration)
)
directory = os.path.join(directory, sub_dir)
if not os.path.exists(directory):
os.makedirs(directory)
if extension is None: if extension is None:
extension = self.movie_file_extension extension = self.movie_file_extension
if name is None: if name is None:

View File

@ -1,59 +1,68 @@
import inspect import inspect
import itertools as it
import os import os
import shutil
import sys import sys
from constants import ANIMATIONS_DIR from constants import ANIMATIONS_DIR
from constants import STAGED_SCENES_DIR from constants import PRODUCTION_QUALITY_CAMERA_CONFIG
from constants import PRODUCTION_QUALITY_FRAME_DURATION
from extract_scene import get_module from extract_scene import get_module
from extract_scene import is_scene from extract_scene import is_scene
from scene.scene import get_movie_output_directory
def get_sorted_scene_names(module_name): def get_sorted_scene_classes(module_name):
module = get_module(module_name) module = get_module(module_name)
line_to_scene = {} line_to_scene = {}
for name, scene_class in inspect.getmembers(module, is_scene): for name, scene_class in inspect.getmembers(module, is_scene):
if inspect.getmodule(scene_class) != module:
continue
lines, line_no = inspect.getsourcelines(scene_class) lines, line_no = inspect.getsourcelines(scene_class)
line_to_scene[line_no] = name line_to_scene[line_no] = scene_class
return [ return [
line_to_scene[line_no] line_to_scene[index]
for line_no in sorted(line_to_scene.keys()) for index in sorted(line_to_scene.keys())
] ]
def stage_animations(module_name): def stage_animations(module_name):
scene_names = get_sorted_scene_names(module_name) scene_classes = get_sorted_scene_classes(module_name)
animation_dir = os.path.join( if len(scene_classes) == 0:
ANIMATIONS_DIR, module_name.replace(".py", "") print("There are no rendered animations from this module")
return
animation_dir = get_movie_output_directory(
scene_classes[0],
PRODUCTION_QUALITY_CAMERA_CONFIG,
PRODUCTION_QUALITY_FRAME_DURATION,
) )
files = os.listdir(animation_dir) files = os.listdir(animation_dir)
sorted_files = [] sorted_files = []
for scene in scene_names: for scene_class in scene_classes:
for clip in filter(lambda f : f.startswith(scene), files): scene_name = scene_class.__name__
sorted_files.append( for clip in filter(lambda f: f.startswith(scene_name + "."), files):
os.path.join(animation_dir, clip) sorted_files.append(os.path.join(animation_dir, clip))
)
staged_scenes_dir = os.path.join(animation_dir, "staged_scenes") animation_subdir = os.path.dirname(animation_dir)
count = 0 count = 0
while True: while True:
staged_scenes_dir = os.path.join( staged_scenes_dir = os.path.join(
animation_dir, "staged_scenes_%d"%count animation_subdir, "staged_scenes_%d" % count
) )
if not os.path.exists(staged_scenes_dir): if not os.path.exists(staged_scenes_dir):
os.makedirs(staged_scenes_dir) os.makedirs(staged_scenes_dir)
break break
#Otherwise, keep trying new names until # Otherwise, keep trying new names until
#there is a free one # there is a free one
count += 1 count += 1
for count, f in enumerate(sorted_files): for count, f in enumerate(sorted_files):
symlink_name = os.path.join( symlink_name = os.path.join(
staged_scenes_dir, staged_scenes_dir,
"Scene_%03d"%count + f.split(os.sep)[-1] "Scene_%03d" % count + f.split(os.sep)[-1]
) )
os.symlink(f, symlink_name) os.symlink(f, symlink_name)
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv) < 2: if len(sys.argv) < 2:
raise Exception("No module given.") raise Exception("No module given.")
module_name = sys.argv[1] module_name = sys.argv[1]
stage_animations(module_name) stage_animations(module_name)