A Ruby CLI that converts Google Slides presentations into A4 PDFs with ruled note lines below each slide — built for printing lecture decks as handouts.
It connects to a running Chrome instance over the Chrome DevTools Protocol, so it captures slides using your own logged-in Google session rather than a headless browser or the Slides export API.
- Ruby + Bundler
- Google Chrome
- Node.js (used by the Playwright driver)
bundle install1. Launch Chrome with remote debugging enabled (keep this terminal open):
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222 \
--user-data-dir="$HOME/chrome-debug-profile"2. Add presentations to a queue CSV. Each row needs a pending status and a URL:
status,layout,name,number,url
pending,4,auto,01,https://docs.google.com/presentation/d/YOUR_ID/edit
| Column | Notes |
|---|---|
status |
Set to pending for new rows. The script updates it to done or error after processing — never overwrite a row yourself. |
layout |
1 — 1 slide/page, portrait, full width · 2 — 2 slides/page, portrait · 4 — 4 slides/page, landscape |
name |
PDF filename, or auto to derive it from the deck title |
number |
Optional filename prefix, e.g. 01 → 01_Deck_Title.pdf |
url |
Full Google Slides URL (edit or present link both work) |
3. Run a batch:
bundle exec ruby capture.rb --batch your_queue.csv --dir ~/Documents/"Your Slides"The script opens each presentation, advances through every slide, and builds one PDF per deck. Re-running is safe — done and error rows are skipped, so only pending rows are (re-)processed.
For one-off captures without a CSV:
bundle exec ruby capture.rb --url "https://docs.google.com/presentation/d/..." --layout 4| Flag | Default | Description |
|---|---|---|
--batch FILE |
— | CSV queue file (the normal workflow) |
--url URL |
(active tab) | Process a single URL without a CSV |
--layout N |
(asks interactively) | Slides per page — 1, 2, or 4 |
--name NAME |
(slide deck title) | Output filename without extension |
--dir PATH |
~/Documents/Slides |
Output folder |
--delay SECONDS |
0.8 |
Wait after each slide change before screenshotting (increase for slow-loading or image-heavy slides) |
--port PORT |
9222 |
Chrome remote debugging port |
--skip-last |
off | Drop the final slide of every deck (useful for removing blank/closing slides) |
| File | Role |
|---|---|
capture.rb |
Entry point — parses args, connects to Chrome, runs batch or single-URL flow |
lib/browser.rb |
Chrome connection, navigation, slide advancing |
lib/screenshot.rb |
Slide change detection, screenshot capture, stall re-screenshot for animations |
lib/pdf_builder.rb |
PDF layout — 1-up/2-up portrait or 4-up landscape, note lines, page numbers |
- Connects to Chrome via CDP rather than launching a headless browser, so it reuses your logged-in Google session and renders slides exactly as Google Slides displays them (fonts, embeds, animations included).
- Advances through slides one at a time, screenshotting each. When advancing produces no URL change (an animation step within a slide), it re-takes the screenshot and overwrites the previous one, so by the time the URL changes the saved image is the slide's fully-built final state.
- Lays out the screenshots onto A4 pages with a ruled note-taking area beneath each slide, plus light grey page numbers in the bottom-right corner.
This repo doesn't include queue CSVs — they hold your own presentation URLs and are gitignored. Create your own alongside capture.rb following the format above, or copy the header row:
status,layout,name,number,url