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
~200 MB total (vs ~900 MB in v1.0.0 — torch, scipy, scikit-image eliminated):
- youtube-transcript-api — transcript fetching with fallbacks
- yt-dlp — video downloading
- opencv-python-headless — frame extraction + SSIM
- onnxruntime — punctuation model inference
- sentencepiece — tokenization for punctuation
- numpy — numerical operations
- requests — video metadata + one-time model download
The 200 MB ONNX punctuation model is downloaded automatically on first run and cached in %LOCALAPPDATA%/yt-slide-mark (Windows) or ~/.cache/yt-slide-mark (Linux/macOS).
License
MIT
Metadata
Release files for yt-slide-mark 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| yt_slide_mark-1.1.0.tar.gz | 19.6 kB | Without provenance | Details for yt_slide_mark-1.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| yt_slide_mark-1.1.0-py3-none-any.whl | Python 3 | none | any | Details for yt_slide_mark-1.1.0-py3-none-any.whl |
Total release size: 38.8 kB
Release files / yt_slide_mark-1.1.0.tar.gz
| Download URL | yt_slide_mark-1.1.0.tar.gz |
|---|---|
| Size | 19.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
716028b79c44c90206e5c59b1829458c85a14137bd4c2cd0212b356231e8c1b2
|
|
BLAKE2b-256 checksum How to use checksums |
3400b1c24f8a960ccb99d74dbf5eddcafbc9d9968a814976a8182e5fa917d0e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|
Release files / yt_slide_mark-1.1.0-py3-none-any.whl
| Download URL | yt_slide_mark-1.1.0-py3-none-any.whl |
|---|---|
| Size | 19.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
93db3b9a5c76ca3ad6e301150445e0c9a7fa6d1c2d9522d39e39c9dcda6e0095
|
|
BLAKE2b-256 checksum How to use checksums |
d9d06f61c6896a1d67051695bcab7379f254205ca3dd459c5ab2284dd7ad6675
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|
Security for yt-slide-mark 1.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.