--- id: "e46ca815-cb86-4a1c-9e59-92d6e80cfdba" name: "Title cards and chapters (ffmpeg)" micro_summary: "ffmpeg drawtext (Arial, no PIL) via textfile= to dodge escaping; title cards rendered as JPEG (must match frame codec for concat demuxer); fast-forward loading + hold the payoff frame; chapters via ffmetadata remux; prints mm:ss report. Script: agent-workspace/screencast_encode.py." status: "resolved" see_also: [] scope: "Add intro/step title cards + seekable chapters to a screencast, and tighten dead loading time (fast-forward loads, hold payoffs)." --- ## Recipe (script: agent-workspace/screencast_encode.py) Reads `manifest.json` (frames + per-segment start/reveal/end from the recorder) and builds a titled, chaptered, tightened mp4. - **Title cards:** ffmpeg `drawtext` with `fontfile=/System/Library/Fonts/Supplemental/Arial.ttf` (no PIL on this box). Use `textfile=` to avoid filtergraph escaping entirely; one `drawtext` per line so each line can have its own font size. Render cards as **JPEG** (see discarded child re: PNG). - **Tighten dead video:** the fully-loaded record page is the LAST frame of each segment (page goes static before URL commit). Fast-forward loading frames (cap gap ~0.10s) and HOLD the last frame ~4s as the payoff. - **Chapters:** accumulate output time while building the concat; write an ffmetadata `[CHAPTER]` block (TIMEBASE=1/1000) and mux with `-i chapters.txt -map_metadata 1 -codec copy`. QuickTime shows them via View -> Chapters. - **Report:** print mm:ss for each chapter + payoff so the human can seek/cut.