Skip to content

Commit

Permalink
update invoke tasks to build and stitch videos.
Browse files Browse the repository at this point in the history
  • Loading branch information
michelp committed Nov 1, 2024
1 parent fc27f46 commit ff59957
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Chapter0/Scene0.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def construct(self):
self.set_speech_service(GTTSService(lang="en"))

# Load all logo images from the imgs/ directory
img_dir = "Chapter0/imgs"
img_dir = "imgs"
logo_filenames = [
"aristotle.png", "anaconda.png", "berkeley.png",
"cmu.png", "cwi.png", "du.png",
Expand Down
Binary file added Chapter0/video_480p15.mp4
Binary file not shown.
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
# IllustratedGraphBLAS
# IllustratedGraphBLAS

To build a scene in a chapter

```
invoke build-scene --chapter Chapter0 --scene Scene0 --quality l
```

To build all scenes in a chapter:

```
invoke build-chapter --chapter Chapter0 --quality l
```

To stich all scenes in a final video

```
invoke stitch-videos --chapter Chapter0 --quality l
```

74 changes: 55 additions & 19 deletions tasks.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,63 @@
import os
import shutil
import glob
from invoke import task
from pathlib import Path
import subprocess

MANIM = "manim"
MANIM_FLAGS = "-ql"
OUTPUT_DIR = Path("media/videos")
@task
def build_scene(ctx, chapter, scene, quality='l'):
command = f"manim -q{quality} {scene}.py"
with ctx.cd(chapter):
ctx.run(command)

def scenes_in_chapter(chapter):
return sorted(Path(chapter).glob("Scene*.py"))
@task
def build_chapter(ctx, chapter, quality='l'):
for filename in sorted(os.listdir(chapter)):
if filename.startswith("Scene") and filename.endswith(".py"):
scene = filename.replace(".py", "")
build_scene(ctx, chapter, scene, quality)

@task
def render_scene(c, chapter, scene):
"""Render a specific scene from a chapter."""
scene_file = f"{chapter}/{scene}.py"
def stitch_videos(ctx, chapter, quality="l"):
os.chdir(chapter)
media_folder = os.path.join("media", "videos")
video_files = []
resolution = dict(l='480p15', m='720p30', h='1080p60')[quality]

search_pattern = os.path.join(media_folder, f"Scene*/{resolution}/Scene*.mp4")
for video in glob.glob(search_pattern):
if video.endswith(".mp4"):
video_files.append(video)

# Sort videos based on scene order (Scene0, Scene1, etc.)
video_files.sort(key=lambda x: int(x.split("Scene")[-1].split(".")[0]))

if not video_files:
print(f"No videos found for resolution '{resolution}' in {media_folder}")
return

# Create temporary file list for ffmpeg
with open(f"videos_to_stitch.txt", "w") as f:
for video in video_files:
f.write(f"file '{video}'\n")

# Stitch videos using ffmpeg
ctx.run(f"ffmpeg -f concat -safe 0 -i videos_to_stitch.txt -c copy video_{resolution}.mp4")
os.unlink('videos_to_stitch.txt')
os.chdir('..')

if Path(scene_file).exists():
c.run(f"{MANIM} {MANIM_FLAGS} {scene_file} {scene}")
else:
print(f"Scene {scene_file} not found.")

@task
def build_chapter(c, chapter):
"""Render all scenes in a chapter."""
for scene_file in scenes_in_chapter(chapter):
scene_name = scene_file.stem
render_scene(c, chapter, scene_name)
def clean_media(ctx, chapter):
media_folder = os.path.join(chapter, "media")

if not os.path.exists(media_folder):
print(f"No media folder found in {chapter}")
return

for root, dirs, files in os.walk(media_folder):
for file in files:
os.remove(os.path.join(root, file))
for dir in dirs:
shutil.rmtree(os.path.join(root, dir))

print(f"Cleaned media folder in {chapter}")

0 comments on commit ff59957

Please sign in to comment.