Skip to content

Commit 08b8909

Browse files
committed
github ci video build action.
1 parent 4283a22 commit 08b8909

12 files changed

Lines changed: 172 additions & 1 deletion
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
name: Build Videos and Deploy Site
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'Chapter*/**'
8+
- 'scene_utils/**'
9+
- 'imgs/**'
10+
- 'docs/**/*.md'
11+
- 'mkdocs.yml'
12+
- 'manim.cfg'
13+
- 'requirements.txt'
14+
workflow_dispatch:
15+
inputs:
16+
chapters:
17+
description: 'Chapters to rebuild (comma-separated, e.g. "0,3,5" or "all")'
18+
required: false
19+
default: 'all'
20+
prod:
21+
description: 'Use ElevenLabs TTS for production quality narration'
22+
required: false
23+
type: boolean
24+
default: false
25+
26+
permissions:
27+
contents: read
28+
pages: write
29+
id-token: write
30+
31+
concurrency:
32+
group: pages
33+
cancel-in-progress: false
34+
35+
jobs:
36+
build-and-deploy:
37+
runs-on: ubuntu-latest
38+
container:
39+
image: manimcommunity/manim:latest
40+
environment:
41+
name: github-pages
42+
url: ${{ steps.deployment.outputs.page_url }}
43+
steps:
44+
- uses: actions/checkout@v4
45+
with:
46+
fetch-depth: 2
47+
48+
- name: Install dependencies
49+
run: |
50+
pip install manim-voiceover[gtts] invoke python-graphblas networkx matplotlib python-dotenv mkdocs mkdocs-material pymdown-extensions
51+
if [ "${{ inputs.prod }}" = "true" ]; then
52+
pip install 'elevenlabs>=0.2.27,<0.3.0'
53+
fi
54+
55+
- name: Restore video cache
56+
uses: actions/cache@v4
57+
with:
58+
path: .video-cache
59+
key: videos-${{ hashFiles('Chapter**/Scene*.py', 'Chapter**/Thumb.py', 'scene_utils/**/*.py', 'imgs/**', 'manim.cfg') }}
60+
restore-keys: videos-
61+
62+
- name: Restore voiceover cache
63+
uses: actions/cache@v4
64+
with:
65+
path: |
66+
Chapter0/media/voiceovers
67+
Chapter1/media/voiceovers
68+
Chapter2/media/voiceovers
69+
Chapter3/media/voiceovers
70+
Chapter4/media/voiceovers
71+
Chapter5/media/voiceovers
72+
Chapter6/media/voiceovers
73+
Chapter7/media/voiceovers
74+
Chapter8/media/voiceovers
75+
Chapter9/media/voiceovers
76+
key: voiceovers-${{ hashFiles('Chapter**/Scene*.py') }}
77+
restore-keys: voiceovers-
78+
79+
- name: Determine chapters to build
80+
id: chapters
81+
run: |
82+
mkdir -p .video-cache
83+
84+
# On workflow_dispatch, use the input
85+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
86+
if [ "${{ inputs.chapters }}" = "all" ]; then
87+
echo "rebuild=0,1,2,3,4,5,6,7,8,9" >> "$GITHUB_OUTPUT"
88+
else
89+
echo "rebuild=${{ inputs.chapters }}" >> "$GITHUB_OUTPUT"
90+
fi
91+
else
92+
# On push, rebuild chapters that have cache misses
93+
# (the cache key is based on source file hashes, so a miss means something changed)
94+
REBUILD=""
95+
for N in 0 1 2 3 4 5 6 7 8 9; do
96+
CHAPTER="Chapter${N}"
97+
if [ ! -f ".video-cache/${CHAPTER}_480p15.mp4" ] || [ ! -f ".video-cache/${CHAPTER}.png" ]; then
98+
if [ -d "$CHAPTER" ]; then
99+
REBUILD="${REBUILD:+${REBUILD},}${N}"
100+
fi
101+
fi
102+
done
103+
echo "rebuild=${REBUILD}" >> "$GITHUB_OUTPUT"
104+
fi
105+
106+
- name: Build chapters
107+
env:
108+
ELEVEN_API_KEY: ${{ secrets.ELEVEN_API_KEY }}
109+
run: |
110+
REBUILD="${{ steps.chapters.outputs.rebuild }}"
111+
echo "Chapters to rebuild: ${REBUILD:-none}"
112+
113+
# Copy cached videos for chapters we are NOT rebuilding
114+
for N in 0 1 2 3 4 5 6 7 8 9; do
115+
CHAPTER="Chapter${N}"
116+
if [ -f ".video-cache/${CHAPTER}_480p15.mp4" ] && [ -f ".video-cache/${CHAPTER}.png" ]; then
117+
echo "Using cached video for ${CHAPTER}"
118+
cp ".video-cache/${CHAPTER}_480p15.mp4" "docs/${CHAPTER}_480p15.mp4"
119+
cp ".video-cache/${CHAPTER}.png" "docs/${CHAPTER}.png"
120+
fi
121+
done
122+
123+
# Build chapters that need rebuilding
124+
if [ -n "$REBUILD" ]; then
125+
IFS=',' read -ra CHAPTERS <<< "$REBUILD"
126+
for N in "${CHAPTERS[@]}"; do
127+
N=$(echo "$N" | tr -d ' ')
128+
CHAPTER="Chapter${N}"
129+
if [ ! -d "$CHAPTER" ]; then
130+
echo "Skipping ${CHAPTER} (directory not found)"
131+
continue
132+
fi
133+
134+
echo "=========================================="
135+
echo "Building ${CHAPTER}"
136+
echo "=========================================="
137+
138+
# Build and stitch the chapter
139+
if [ "${{ inputs.prod }}" = "true" ]; then
140+
invoke build-chapter --chapter "$CHAPTER" --quality l --pause-time 0 --prod
141+
else
142+
invoke build-chapter --chapter "$CHAPTER" --quality l --pause-time 0
143+
fi
144+
145+
# Render thumbnail
146+
cd "$CHAPTER"
147+
manim -ql -s Thumb.py Thumb -o "../../../../docs/${CHAPTER}.png"
148+
cd ..
149+
150+
# Cache the results
151+
cp "docs/${CHAPTER}_480p15.mp4" ".video-cache/${CHAPTER}_480p15.mp4"
152+
cp "docs/${CHAPTER}.png" ".video-cache/${CHAPTER}.png"
153+
154+
echo "${CHAPTER} complete"
155+
done
156+
fi
157+
158+
- name: Build MkDocs site
159+
run: mkdocs build
160+
161+
- name: Upload Pages artifact
162+
uses: actions/upload-pages-artifact@v3
163+
with:
164+
path: site
165+
166+
- name: Deploy to GitHub Pages
167+
id: deployment
168+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,7 @@ cython_debug/
160160
# and can be added to the global gitignore or merged into this file. For a more nuclear
161161
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
162162
#.idea/
163-
media/
163+
media/
164+
165+
# Built videos (generated by CI)
166+
docs/*.mp4

docs/Chapter0_480p15.mp4

-8.64 MB
Binary file not shown.

docs/Chapter1_480p15.mp4

-7.68 MB
Binary file not shown.

docs/Chapter2_480p15.mp4

-13.8 MB
Binary file not shown.

docs/Chapter3_480p15.mp4

-19.1 MB
Binary file not shown.

docs/Chapter4_480p15.mp4

-11.3 MB
Binary file not shown.

docs/Chapter5_480p15.mp4

-21.1 MB
Binary file not shown.

docs/Chapter6_480p15.mp4

-10.5 MB
Binary file not shown.

docs/Chapter7_480p15.mp4

-6.81 MB
Binary file not shown.

0 commit comments

Comments
 (0)