Communitygithub.com

aleksanderstevens191-sudo/course-video-skill

Turn a student's own course material (lecture transcripts, slides, notes, problem sets) into narrated, animated study videos with graphs, worked examples, quizzes, captions, sound effects and optional Blender 3D scenes. Every number in the video must come from the course material; a checker enforces it. Use when someone asks to make study or review videos from their lectures or class materials.

What is course-video-skill?

course-video-skill is a Codex agent skill that turn a student's own course material (lecture transcripts, slides, notes, problem sets) into narrated, animated study videos with graphs, worked examples, quizzes, captions, sound effects and optional Blender 3D scenes. Every number in the video must come from the course material; a checker enforces it. Use when someone asks to make study or review videos from their lectures or class materials.

Works with~Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/aleksanderstevens191-sudo/course-video-skill/tree/HEAD

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Course video

You turn the student's course material into study videos. The one rule that sets this skill apart:

Every number, example and claim comes from the student's course material. Nothing is invented. Students use these videos to study for exams graded by their professor. A "nicer" example with made-up numbers, a formula in a different notation, or a fact from outside the course is a bug, even if it is correct economics/physics/etc.

0. Requirements (check once)

python3 -m pip install -r requirements.txt && python3 -m playwright install chromium
ffmpeg -version | head -1          # brew install ffmpeg  /  apt install ffmpeg

Optional: Blender 4.2+ for 3D scenes and the mascot presenter (BLENDER=/path/to/blender if it is not on PATH), pdftotext (poppler) or pip install pypdf to read PDF slides, openai-whisper to transcribe recordings, XAI_API_KEY for the Grok voice (otherwise the free Microsoft neural voice is used).

1. Collect the sources

Make a folder <course>/sources/ and put only course material in it: lecture transcripts (.txt/.srt/.vtt), slides (.pdf or exported text), the student's notes, problem sets, practice exams.

  • Recording but no transcript → whisper lecture.mp4 --model base --output_format txt --output_dir sources/
  • .docx → textutil -convert txt file.docx (macOS) or pandoc file.docx -t plain -o file.txt
  • Ask the student which lectures/topics the video should cover. Do not pad with material from other weeks unless asked.

Read the sources fully before writing anything. Note the professor's exact notation, terms, worked examples and numbers.

2. Write the script (content JSON)

Write <course>/<name>.json following engine/SCHEMA.md (visual types, cue words, quiz format, layout limits). examples/lemonade/ is a complete small example.

Rules:

  • Examples: use the lecture's own worked examples with the lecture's own numbers. If the lecture works "price $4, 3 units", the video works "price $4, 3 units", not "price $10, 5 units".
  • Quizzes: take them from the course's practice problems, clicker questions or worked examples. If you write a new question, build it only from numbers in the sources, and say so in the quiz label ("Practice", not "Exam question").
  • Derived numbers (a total you computed, a difference) are fine, but declare each one in the top-level "derived" map with the arithmetic, using only source numbers: "derived": {"16": "4 * 4", "-6": "120 - 126"}.
  • Small counts that are not data ("Three things to remember", "Step 2") go in "allow": ["3"]. 0 and 1 are always allowed.
  • Notation and terms: use the professor's (if the lecture writes "MR = MC", don't switch to "∂R/∂q").
  • If a fact the video needs is not in the sources, stop and ask the student for the material, or leave it out. Never fill the gap from general knowledge.
  • Narration (say) is written for the ear: words, not symbols ("4 times 4 is 16 dollars").

3. Check every number against the sources (required, before building)

python3 tools/check_sources.py <course>/<name>.json <course>/sources --report <course>/<name>.sources.md

It extracts every number from the narration, on-screen text, quiz options and any 3D scene labels, and finds each one in the sources (digits or spelled-out words, e.g. "one hundred twenty"). Derived numbers are re-computed and their operands checked. It must exit 0 before you build. For each problem it reports:

  • the number is a typo or invented → fix the script to use the source's number;
  • it is a real calculation → add it to "derived";
  • it is in the sources in a form the checker missed (e.g. in an image) → ask the student to confirm, then add it to "derived" or "allow" with a note in your reply.

Then read the report's Evidence section yourself, spot-checking that each number is used in the same meaning as in the source (the checker matches values, not meaning: "$40" the price vs. "40 units" the quantity).

4. Build and render

cd engine
python3 build.py ../<course>/<name>.json              # voice, timing, captions, music (TTS=xai XAI_API_KEY=... for Grok)
python3 lint.py build/<video-id>/spec.json            # visuals that arrive late
python3 qa.py <video-id>                              # stills of every beat + contact sheets: LOOK at them
OUT=../out python3 render.py <video-id> --workers 6   # full 1080p render -> ../out/<video-id>.mp4 + .srt

Look at the QA contact sheets before rendering: overlapping text, empty screens, wrong numbers on screen.

5. Optional: 3D scenes, mascot, sound effects

A beat with "v": {"type": "clip", "scene": "<name>"} plays a Blender scene from engine/blender/scene_defs/<name>.py (see the docstring in engine/blender/scenelib.py; market.py and safe.py are full examples, written for an economics course, so their labels carry that course's numbers. Change the labels to match your sources). Scene labels are checked by check_sources.py too.

cd engine
python3 blend.py prep <video-id>                         # mascot timeline + per-scene inputs
python3 blender/stills.py <scene> --dry                  # catch errors fast, then without --dry for stills
python3 blend.py clips <video-id>                        # render the 3D scenes (slow: minutes per scene)
python3 blend.py mascot <video-id> && python3 blend.py pack <video-id>
python3 sfx.py mix <video-id>                            # sound effects under the narration
OUT=../out python3 blend.py comp <video-id>              # -> ../out/<video-id>-3d.mp4
OUT=../out python3 blend.py site <id1>,<id2> --title "My course" --out ../out/site   # a web page with chapters

Rendering is slow and disk-hungry (several GB of frames per video while it runs). Check free space first, render one scene at a time on laptops, and keep the machine awake.

6. Hand-off

Tell the student: where the video is, how long it is, which lectures it covers, and the source-check result (numbers checked, any derived or allowed ones). If anything in the sources was ambiguous, say what you assumed. Remind them the video is a study aid built from their materials, not a replacement for the lecture, and that course materials may not be theirs to publish: check before posting a video publicly.

Related Skills