Extract slides from YouTube presentations with transcript text
Project description
yt-slide-mark
Extract slides from YouTube presentations and pair them with transcript text.
Takes a YouTube video URL, downloads the video, extracts unique slide frames using SSIM comparison, fetches the transcript with timestamps, maps text to slides, restores punctuation, and generates a Markdown document with embedded slide images and clickable YouTube timestamps.
Installation
pip install yt-slide-mark
Or with uv:
uv pip install yt-slide-mark
Usage
# Single video
yt-slide-mark "https://youtube.com/watch?v=VIDEO_ID"
# Batch — from a file with URLs
yt-slide-mark -b urls.txt
# Without installing (via uvx)
uvx yt-slide-mark "https://youtube.com/watch?v=VIDEO_ID"
# Or via python -m
python -m yt_slide_mark "https://youtube.com/watch?v=VIDEO_ID"
Options
yt-slide-mark <url> [-b FILE]
-b, --batch FILE Text file with URLs (one per line)
-l, --language Transcript language (default: en)
-o, --output Output directory (default: ./output)
--similarity SSIM threshold 0.0-1.0 (default: 0.85)
--sample-interval Seconds between frame checks (default: 1.0)
--cooldown Seconds to skip after new slide detected (default: 10.0)
--include REGION Only compare within this region (repeatable)
--exclude REGION Ignore this region during comparison (repeatable)
--no-punctuate Disable punctuation restoration
--keep-video Keep the downloaded video file
-v, --verbose Verbose logging
Region of interest (--include / --exclude)
Lecture videos often show the speaker alongside slides, causing excessive slide detections. Use --include or --exclude to limit which part of the frame is used for SSIM comparison. Full frames are still saved as slide images.
Format: x1,y1-x2,y2 — two diagonal corners of a rectangle. Values can be pixels or percents:
--exclude 0,400-200,720 # pixels: exclude bottom-left speaker area
--include 25%,0%-100%,100% # percents: only compare right 75% of frame
Multiple regions can be specified by repeating the flag:
--exclude 0,80%-25%,100% --exclude 75%,80%-100%,100%
--include and --exclude are mutually exclusive.
Batch file format
One URL per line. Blank lines and # comments are ignored:
# lectures.txt
https://youtube.com/watch?v=VIDEO1
https://youtube.com/watch?v=VIDEO2
# this one is optional
https://youtube.com/watch?v=VIDEO3
Examples
# Basic usage
yt-slide-mark "https://youtube.com/watch?v=dQw4w9WgXcQ"
# Custom output directory, verbose
yt-slide-mark "https://youtube.com/watch?v=dQw4w9WgXcQ" -o ./my_notes -v
# Skip punctuation, keep video, lower similarity threshold
yt-slide-mark "https://youtube.com/watch?v=dQw4w9WgXcQ" --no-punctuate --keep-video --similarity 0.80
# Faster sampling for long lectures, wider cooldown
yt-slide-mark "https://youtube.com/watch?v=dQw4w9WgXcQ" --sample-interval 2.0 --cooldown 15.0
# Exclude speaker area in bottom-left corner (pixels)
yt-slide-mark "https://youtube.com/watch?v=dQw4w9WgXcQ" --exclude 0,500-250,720
# Only compare the slide area (right 75% of frame, percents)
yt-slide-mark "https://youtube.com/watch?v=dQw4w9WgXcQ" --include 25%,0%-100%,100%
# Batch: process a list of videos from file
yt-slide-mark -b lectures.txt -o ./lectures -v
Output
output/video-title/
├── video-title.md
└── slides/
├── slide_001.jpg
├── slide_002.jpg
└── ...
The Markdown file contains:
- Video title, author, and source link
- Each unique slide as a JPEG image
- Clickable YouTube timestamps linking to the exact moment
- Transcript text mapped to each slide with restored punctuation
In batch mode, each video gets its own subfolder. A summary is printed at the end showing successes and failures; one failed video does not stop the rest.
Pipeline
YouTube URL
→ extract video ID
→ get video info (noembed.com API)
→ download video (yt-dlp, 720p)
→ fetch transcript (youtube-transcript-api, 4-level fallback)
→ extract unique frames (OpenCV + SSIM)
→ map transcript to slides (by timestamps)
→ restore punctuation (punctuators pcs_en, ONNX)
→ generate Markdown
Dependencies
- youtube-transcript-api — transcript fetching with fallbacks
- yt-dlp — video downloading
- opencv-python-headless — frame extraction
- scikit-image — SSIM structural similarity
- punctuators — punctuation/capitalization restoration (ONNX, CPU)
- requests — video metadata via noembed.com
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file yt_slide_mark-1.0.0.tar.gz.
File metadata
- Download URL: yt_slide_mark-1.0.0.tar.gz
- Upload date:
- Size: 13.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06d868ea1e43115565fe8fc15a5316822f2385c7eed1650a9f81be720c339132
|
|
| MD5 |
1ed92ca1da670efb5493346659e6cfe7
|
|
| BLAKE2b-256 |
3c9613f095ddc71245c9ec98ef51c3f90dcf41770a6cb06875ae36f5b1921887
|
File details
Details for the file yt_slide_mark-1.0.0-py3-none-any.whl.
File metadata
- Download URL: yt_slide_mark-1.0.0-py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c89e6c51d7632eaa11c7ac74823c5a2d7ba3c92f255eaccbb542078d17d192ff
|
|
| MD5 |
0d0e6ca6f249c2ebdae3447baebb2475
|
|
| BLAKE2b-256 |
27f77568bef1797adece2ebd6438d54180c7d022fc4677ab10360e0620ff5b13
|