Re-landing #66 against main (it merged into its stacked base after that
branch had already been merged). Produced by scripts/bump_remotion.py
--smoke: lockfiles refreshed, frame-0 smoke render OK for all 8 projects
with an entry point, render-baseline A/B identical on all six frames.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Deterministic data source for /versions (#23 part 1): every Remotion pin
under templates/, examples/, showcase/, tests/ vs latest npm (patches
behind, pin age), flags caret ranges and disagreeing pins; uv.lock vs
pyproject plus outdated direct Python deps; registry vs latest release.
--json / --offline / --strict.
Also pins the stragglers it found to the template version 4.0.425:
sprint-review-cho-oyu (4.0.381), digital-samba-skill-demo (4.0.382),
showcase/transitions and showcase/banner (^4.0.0). Lockfiles refreshed.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Adopt uv for Python dependency management
Replace manual pip/venv setup with `uv sync` (pyproject.toml + uv.lock),
and switch all tool invocations across docs, skills, commands, and
examples to `uv run`. Optional extras: --extra whisper, --extra modal.
tools/requirements.txt is kept as a pip fallback.
* FIX: bring uv migration current with main — post-June deps and docs
Adds websocket-client (60db websocket transport) to core deps and a
'youtube' extra for the google-* packages (tools/youtube_upload.py),
regenerates uv.lock, bumps pyproject version to 0.18.0, and converts the
51 'python3 tools/…' invocations added since the PR was opened (60db,
YouTube, Kiro docs, publish command) to 'uv run'. Verified with
uv sync --frozen --extra youtube; voiceover, sixtydb_tts, youtube_upload
and migrate_to_kiro all run through the project environment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Asharib Ali <asharibarain4@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
projects/sprint-review-cho-oyu and projects/digital-samba-skill-demo have been
tracked since the initial release (fde30d3, 2025-12-09). .gitignore has listed
projects/ since that same commit, but ignore rules never apply to already-tracked
files, so the rule has been silently inert on these 67 files for the repo's whole
life.
Both were superseded the next day by 0d96c3b, which created examples/ and added
curated copies of both — with README.md and ASSETS-NEEDED.md written for public
consumption. The projects/ copies are the raw working originals; they carry
.DS_Store, .claude/, node_modules/, out/ and .venv alongside them. Only the
curated examples/ copies were ever meant to ship.
Removed from the index only (git rm --cached) — the local working copies stay on
disk, and projects/ now behaves as documented: local video work, not toolkit
content.
Eight media files existed only under projects/. Seven are audio that
examples/*/ASSETS-NEEDED.md already documents as regenerable via
/generate-voiceover, tools/music.py and tools/sfx.py. The eighth, build-app.cast,
was referenced by three examples/ docs but shipped nowhere, so ASSETS-NEEDED.md
now documents recording and converting it — matching how every other asset in
these examples is handled.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019s6SvNiz9a8XpD8r2cQTiq
* Add concept-explainer-short template: 9:16 TikTok/Reels explainer shorts (Python/moviepy)
First non-Remotion template. The whole video derives from scenes.json
(per-scene narration text + visual asset); a three-script pipeline turns
it into a finished vertical short:
- gen_vo.py — per-scene TTS via tools/voiceover.py (clone or built-in
speaker, batch mode, --max-wpm pacing clamp), writes the
vo_durations.json timeline anchor; warns past the 3-minute
Shorts/Reels ceiling
- gen_captions.py — burned karaoke caption timing: whisper word
timestamps force-aligned to the ground-truth script text via difflib
(never burns whisper's own transcription, which mishears TTS)
- build.py — audio-anchored moviepy composite: Ken Burns on stills,
boomerang-looped clips (asset extension decides), caption pills with
width cap and platform-safe positioning, ducked looped music; renders
at every stage (gradient placeholder cards before assets exist,
word-count timing estimates before VO, silent before audio)
Pattern proven on a 3:41 hallucinations explainer; tested end-to-end
(out-of-box placeholder render + full Modal clone pipeline with three
takes auto-clamped 181-188→165 wpm). Registered in the toolkit registry,
CLAUDE.md, and /video (with Python-flow notes); openai-whisper documented
as an optional dependency.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Add sky-blue-short showcase example + fix Modal qwen3-tts batch custom_voice
examples/sky-blue-short: complete worked example of the
concept-explainer-short template — a 52s vertical "Why is the sky blue?"
short with Qwen3 VO (built-in Ryan, warm tone), two Ideogram diagram/CTA
cards, two LTX sky clips, ACE-Step music bed, and burned aligned captions
(~$0.80 total generation cost). All source assets committed; re-renders
in place with python3 build.py.
Building it surfaced two real bugs, fixed here:
- Modal qwen3-tts handler: batch custom_voice hit the same qwen-tts
tensor-aliasing crash the clone path already works around — now
iterates per text with the shared speaker (redeployed and verified)
- gen_vo.py: failed batch scenes crashed with KeyError instead of
reporting which scenes failed and why
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Add hallucinations-short and sky-blue-short demo videos to README showcase
Both produced with the concept-explainer-short pipeline: sky-blue-short
uses the stock Qwen3-TTS Ryan voice; hallucinations-short uses a Qwen3
voice clone from a Pixabay voice-over sample.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The two examples used "^4.0.0" instead of pinned versions, so running
"rm -rf node_modules && npm install" today would resolve to whatever's
current on npm (4.0.464+) rather than the version the example was
authored and rendered against.
Pins each example to its own lockfile-resolved version:
- digital-samba-skill-demo: 4.0.382
- sprint-review-cho-oyu: 4.0.381
Manifest now matches lockfile; npm install dry-run confirms no installed
versions change. Matches the exact-pin convention used across the
toolkit's templates.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Curated reference showing the LTX-2 crt-terminal LoRA producing amber
phosphor footage, plus a PIL post-processing chain that tints the white
SVG wordmark, adds a phosphor halo, scanlines, chromatic aberration and
grain so the brand mark reads as part of the same CRT world. moviepy
composites the crossfade + hold. Self-bootstraps from the committed SVG
and the one LTX-2 output we couldn't cheaply reproduce locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both examples/quick-spot/build.py and examples/data-viz-chart/build.py
hardcoded `/System/Library/Fonts/Supplemental/Arial Bold.ttf` and would
crash with FileNotFoundError on Linux or Windows when PIL tried to open
the font — despite the READMEs promising the examples run with "zero
external assets."
Replaced with a `platform.system()`-keyed fallback chain:
- Darwin → Arial Bold / Arial (Supplemental, then /Library/Fonts)
- Linux → DejaVu Sans Bold / DejaVu Sans (multiple path locations)
- Windows → arialbd.ttf / arial.ttf
If none of the candidate paths resolve (exotic distro, minimal install,
etc.), falls back to PIL's bitmap `load_default()` so the example still
runs — ugly rendering but no crash.
Verified by deleting both .text_cache directories and re-rendering both
examples on macOS. Output is visually identical to previous runs because
the macOS paths are still the first candidates in the fallback chain.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The two new moviepy examples (quick-spot, data-viz-chart) imported
moviepy, Pillow, and matplotlib but had no declaration anywhere in
the toolkit — anyone cloning the repo and running `python3 build.py`
would hit a bare ModuleNotFoundError with no guidance.
This also fixes a pre-existing latent gap: tools/flux2.py and
tools/image_edit.py both `from PIL import Image` inside a try/except
guard but Pillow was never declared in tools/requirements.txt either.
The "friendly error" message was the only signal users got that they
needed to install Pillow themselves. Adding Pillow to the central
file as a free rider.
Changes
-------
- tools/requirements.txt: adds Pillow>=10.0, moviepy>=2.0, matplotlib>=3.7
with comments explaining which tools/examples use each
- examples/quick-spot/build.py, examples/data-viz-chart/build.py: wrap
the third-party imports in a try/except ImportError matching the
existing flux2.py/image_edit.py pattern, with a precise error
message pointing at `python3 -m pip install -r tools/requirements.txt`
- examples/*/README.md: Quick Start now lists the toolkit-level pip
install as step one, then `python3 build.py`
- README.md: updates the optional Python install callout to use
`python3 -m pip install` (avoids the pip/python3 env mismatch
footgun) and mentions moviepy examples alongside AI voiceover/
image gen/music in the "what this installs" note
- .claude/skills/moviepy/SKILL.md: adds a short Dependencies note so
Claude Code knows where the deps live and what to run on ImportError
Net effect: one install command covers every Python feature in the
toolkit. Both AI agents (via stderr-reactive friendly errors) and
humans (via the README Quick Start) can recover from a missing-dep
state without guesswork.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The root README has been pointing at `examples/hello-world` as the
zero-config quick-start ("cd examples/hello-world && npm install &&
npm run render") for six weeks, but the example itself was never
actually committed — the source tree existed locally but had zero
git history on any branch.
This commits the working example as-is:
- Minimal 25s Remotion sprint-review video (4 animated slides:
Title → Overview → Stats → Credits)
- Zero API keys, zero Python, zero external services — just
Remotion + React
- Config-driven content via src/config/sprint-config.ts
- Remotion 4.0.425, matching all current toolkit templates
- Slide components are byte-identical to templates/sprint-review/
(no drift, no stale copies)
Gitignore already handles node_modules/, out/, and *.mp4 correctly,
so the staged tree is 24 source files only.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two runnable example projects demonstrating the moviepy patterns
introduced in the previous commit. Both render end-to-end with zero
external assets via `python3 build.py` and serve as the public
references for the moviepy skill.
quick-spot
15-second ad-style spot. Solid colour backgrounds, PIL-rendered
text, audio-anchored timeline, optional VO + ducked music mixing.
Includes VOICEOVER-SCRIPT.md showing how to extend with per-scene
audio via tools/voiceover.py.
data-viz-chart
Animated time-series chart from data/star_series.json (real GitHub
star history). Demonstrates the matplotlib (data) + moviepy
(trustworthy text) split: matplotlib draws line/fill/axes, moviepy
composites the title, headline number, and source attribution
deterministically on top. Cache-aware — re-renders the matplotlib
step only when the data file changes.
moviepy skill
Replaces three references to local-only projects/_lib/townhall_video.py
paths (which were broken for anyone cloning the repo) with pointers
to the new public examples.
examples/README.md
Adds both examples to the table, distinguishes Remotion vs moviepy
examples in the "Using Examples" section.
.gitignore
Adds examples/*/.text_cache/ and examples/*/chart_anim.mp4 to keep
auto-generated build artefacts out of git.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Make it clear that videos render with just Node.js installed. Reorganize
.env.example with commented-out defaults, add "Try It Now" quick start
pointing to hello-world example, and replace terse API key errors in all
Python tools with actionable guidance (add key, use alternative, or skip).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>