Use this skill whenever the user wants to turn a video URL or a local video file into local study notes, including reusing existing subtitles when available, transcribing only when no usable subtitle text exists, extracting keyframes, and producing a concise Markdown learning note with embedded screenshots. If the input is a link, run the probe/download flow. If the input is a local video file, skip downloading and work from the local media plus any sidecar subtitle files.
This skill is self-contained under its own skill directory. In this workspace the canonical path is .agent/skills/video-study-notes/, and .codex/skills/video-study-notes/ resolves there as a compatibility symlink.
Reuse the bundled companion skills instead of re-deriving their workflows:
subskills/yt-dlp/SKILL.md for media download, subtitle probing, cookies, and authenticated access.subskills/media-transcribe/SKILL.md when no usable subtitle track is available and a transcription fallback is needed.The main skill keeps only project-wide helpers under scripts/:
scripts/extract_keyframes.pyscripts/prepare_audio.pyscripts/bootstrap_linux.shscripts/check_linux_env.pySubskill-specific helpers live with their subskills:
subskills/yt-dlp/scripts/run_yt_dlp.pysubskills/yt-dlp/scripts/resolve_project_root.pysubskills/media-transcribe/scripts/transcribe_audio.pysubskills/media-transcribe/scripts/find_local_subtitles.pyGiven one video source, build a local note project that:
This skill is intended to run on Linux machines and must use uv to manage the environment stored in the skill-local .venv.
Minimum system dependencies:
python3ffmpeguvRecommended bootstrap flow from the repo root:
cd .agent/skills/video-study-notes
sudo apt install -y python3 python3-venv ffmpeg
bash scripts/bootstrap_linux.sh
.venv/bin/python scripts/check_linux_env.py
Notes:
uv.Before creating any directories, resolve the folder layout first.
subskills/yt-dlp/scripts/resolve_project_root.py to sanitize names and compute the project root.
--output-base, the default base directory is <workspace_root>/output/, where <workspace_root> is the parent directory of the nearest .agent or .codex directory<workspace_root>/output/<Series Title>/<Video Title>/--entry-index for the selected item or pass its title explicitly with --video-title<workspace_root>/output/<Video Title>/Use human-readable names, but strip or replace path separators, control characters, and other filesystem-hostile characters.
Route the workflow from the user's input before doing any heavy work.
subskills/media-transcribe/scripts/find_local_subtitles.pymedia-transcribeAfter choosing the project root, keep everything for that video inside it.
If this is a standalone video:
<workspace_root>/output/<Video Title>/video/<workspace_root>/output/<Video Title>/audio/<workspace_root>/output/<Video Title>/subtitles/<workspace_root>/output/<Video Title>/transcripts/<workspace_root>/output/<Video Title>/keyframes/<workspace_root>/output/<Video Title>/notes.md<workspace_root>/output/<Video Title>/keyframe_timestamps.txtIf this video belongs to a series, add one more level first:
<workspace_root>/output/<Series Title>/<Video Title>/video/<workspace_root>/output/<Series Title>/<Video Title>/audio/<workspace_root>/output/<Series Title>/<Video Title>/subtitles/<workspace_root>/output/<Series Title>/<Video Title>/transcripts/<workspace_root>/output/<Series Title>/<Video Title>/keyframes/<workspace_root>/output/<Series Title>/<Video Title>/notes.md<workspace_root>/output/<Series Title>/<Video Title>/keyframe_timestamps.txtThe user explicitly wants all screenshots under the chosen project root's keyframes/ directory.
subskills/yt-dlp/scripts/resolve_project_root.py before any download step.--entry-index or explicit titles.--entry-index or --video-title to resolve_project_root.py.subskills/yt-dlp/scripts/resolve_project_root.py from the local file path and skip download steps entirely.video/, audio/, subtitles/, transcripts/, and keyframes/ inside that project root.yt-dlp subskill. If the site may require login, make subtitle probes with the same cookies strategy used for subtitle downloads.subskills/media-transcribe/scripts/find_local_subtitles.py.<project_root>/video/.<project_root>/subtitles/ and use them as the primary text source.<project_root>/subtitles/ and use them as the primary text source.<project_root>/audio/ and invoke the media-transcribe subskill to create an SRT transcript under <project_root>/transcripts/.
scripts/prepare_audio.py so the audio artifact lives deterministically under <project_root>/audio/<project_root>/audio/ or point prepare_audio.py at it so the note project stays self-containedscripts/extract_keyframes.py into <project_root>/keyframes/.The helper script only extracts candidate frames. It does not score, rank, deduplicate, or select them for you. It does clear stale scene-*.jpg and cue-*.jpg candidates before rewriting those sets, so reruns stay deterministic.
Use the bundled helper script:
cd .agent/skills/video-study-notes
.venv/bin/python scripts/extract_keyframes.py --video "<project_root>/video/example.mp4" --output-dir "<project_root>/keyframes"
After you decide which subtitle/transcript timestamps are important, place them in a text file such as <project_root>/keyframe_timestamps.txt:
12.5
85.0
<project_root>/keyframe_timestamps.txt, one timestamp per line, then run scripts/extract_keyframes.py again with --timestamps-file.<project_root>/notes.md by filling assets/note-template.md as the primary structure. Only diverge when the video clearly requires it.Edit PDFs with natural-language instructions using the nano-pdf CLI.