|
1 | 1 | import json |
2 | 2 | import os |
| 3 | +import platform |
3 | 4 | import shutil |
| 5 | +import subprocess |
4 | 6 |
|
5 | | -from manim import Scene, ThreeDScene, config |
| 7 | +from manim import Scene, ThreeDScene, config, logger |
| 8 | +from tqdm import tqdm |
| 9 | + |
| 10 | +try: # For manim<v0.16.0.post0 |
| 11 | + from manim.constants import FFMPEG_BIN as ffmpeg_executable |
| 12 | +except ImportError: |
| 13 | + ffmpeg_executable = config.ffmpeg_executable |
6 | 14 |
|
7 | 15 | from .defaults import FOLDER_PATH |
8 | 16 |
|
9 | 17 |
|
| 18 | +def reverse_video_path(src: str) -> str: |
| 19 | + file, ext = os.path.splitext(src) |
| 20 | + return f"{file}_reversed{ext}" |
| 21 | + |
| 22 | + |
| 23 | +def reverse_video_file(src: str, dst: str): |
| 24 | + command = [config.ffmpeg_executable, "-i", src, "-vf", "reverse", dst] |
| 25 | + process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| 26 | + process.communicate() |
| 27 | + |
| 28 | + |
10 | 29 | class Slide(Scene): |
11 | 30 | def __init__(self, *args, output_folder=FOLDER_PATH, **kwargs): |
12 | 31 | super().__init__(*args, **kwargs) |
@@ -79,14 +98,31 @@ def render(self, *args, **kwargs): |
79 | 98 | os.mkdir(scene_files_folder) |
80 | 99 |
|
81 | 100 | files = list() |
82 | | - for src_file in self.renderer.file_writer.partial_movie_files: |
| 101 | + for src_file in tqdm( |
| 102 | + self.renderer.file_writer.partial_movie_files, |
| 103 | + desc=f"Copying animation files to '{scene_files_folder}' and generating reversed animations", |
| 104 | + leave=config["progress_bar"] == "leave", |
| 105 | + ascii=True if platform.system() == "Windows" else None, |
| 106 | + disable=config["progress_bar"] == "none", |
| 107 | + ): |
83 | 108 | dst_file = os.path.join(scene_files_folder, os.path.basename(src_file)) |
84 | 109 | shutil.copyfile(src_file, dst_file) |
| 110 | + rev_file = reverse_video_path(dst_file) |
| 111 | + reverse_video_file(src_file, rev_file) |
85 | 112 | files.append(dst_file) |
86 | 113 |
|
87 | | - f = open(os.path.join(self.output_folder, "%s.json" % (scene_name,)), "w") |
| 114 | + logger.info( |
| 115 | + f"Copied {len(files)} animations to '{os.path.abspath(scene_files_folder)}' and generated reversed animations" |
| 116 | + ) |
| 117 | + |
| 118 | + slide_path = os.path.join(self.output_folder, "%s.json" % (scene_name,)) |
| 119 | + |
| 120 | + f = open(slide_path, "w") |
88 | 121 | json.dump(dict(slides=self.slides, files=files), f) |
89 | 122 | f.close() |
| 123 | + logger.info( |
| 124 | + f"Slide '{scene_name}' configuration written in '{os.path.abspath(slide_path)}'" |
| 125 | + ) |
90 | 126 |
|
91 | 127 |
|
92 | 128 | class ThreeDSlide(Slide, ThreeDScene): |
|
0 commit comments