agentsclimarketplace

Screen recording to pdf

Skill Denlie-code/screen-recording-to-pdf

Convert a screen recording / screencast / demo video (.mp4, .mov, .mkv, .webm, .gif, etc.) into a single multi-page PDF by extracting key frames and assembling them. Use when the user has a recording and wants it as a PDF document. TWO modes: (1) `--capture-all` -- scroll-aware capture for CONTINUOUS content like a scrolling CHAT-RECORDING, captures EVERY message (一条不差, no skips) by measuring scroll and keeping a frame each half-screen; (2) `--auto` / manual scene-detection / max-frames -- key-frame extraction for demos/tutorials. Triggers (CN/EN): 录屏转pdf, 录屏做成PDF, 把这段录屏转成PDF, 录屏导出PDF, 聊天记录转pdf, 聊天记录导出, chat history to pdf, screen recording to pdf, video to pdf, 视频转PDF. Requires Python 3 + ffmpeg (system PATH, or `pip install imageio-ffmpeg`) + numpy (for --capture-all) + Pillow; `pip install img2pdf` for lossless JPEG-to-PDF assembly.From its SKILL.md

Install
npx -y skills add Denlie-code/screen-recording-to-pdf

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

9.7 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it

Screen Recording to PDF

Turn a screen recording (or any video) into a multi-page PDF. Pick the mode by what the recording IS:

  • Scrolling / continuous content (a chat-history recording, a long page you scrolled through, a feed) where every item must be captured -> use --capture-all. It measures the scroll and keeps a frame each half-screen so nothing scrolls past uncaught.
  • Demonstrations / tutorials / click-throughs where you only want the moments that change -> use --auto (or manual --scene-threshold / --max-frames).

Two scripts, pipelined:

video.mp4 --extract_frames.py--> frame_*.jpg --frames_to_pdf.py--> output.pdf

extract_frames.py is adapted from mugnimaestra/video-frames-skill (see references/video-frames-source.md). Local additions: an ffmpeg/ffprobe resolution layer (no system ffmpeg needed), a fix to the scene-detection filter for ffmpeg >= 7, --auto (smart key-frame + pause de-dup), and --capture-all (scroll-aware complete capture).

Prerequisites

python -c "import imageio_ffmpeg, PIL, numpy; print('core OK')"
python -c "import img2pdf; print('img2pdf OK (lossless)')" || echo "optional"

Install anything missing (one line, no admin / no system ffmpeg):

pip install imageio-ffmpeg Pillow numpy img2pdf

numpy is required only for --capture-all (scroll matching). The other modes work without it.

Quick Start

Chat-history / scrolling recording (capture every message):

python scripts/extract_frames.py chat.mp4 --capture-all \
  | python scripts/frames_to_pdf.py --json - -o chat.pdf

Demo / tutorial (key frames only):

python scripts/extract_frames.py demo.mp4 --auto \
  | python scripts/frames_to_pdf.py --json - -o demo.pdf

Workflow

  1. Get the video path and confirm it exists.
  2. Pick the mode by content (see Decision Guide). If unsure whether it's "scrolling chat" vs "demo", ask the user, or default to --capture-all when completeness matters.
  3. Extract frames with extract_frames.py -> JSON to stdout (frames, output_dir, resolution, summary, plus strategy/capture/dedup).
  4. Assemble the PDF with frames_to_pdf.py (frames dir or piped JSON).
  5. Report output path, page count, size. For --capture-all, mention the capture.kept count and that adjacent pages overlap (~50%+) so every message is on multiple pages.
  6. Clean up the temp frames dir if throwaway.

Decision Guide

ModeWhen to useExample
--capture-allScrolling / continuous content -- chat-history recording, long-page scroll, feed. Captures EVERY message (no skips). Measures scroll, keeps a frame each half-screen.--capture-all
--autoDemos / tutorials / click-throughs -- wants only the moments that change; de-duplicates pauses.--auto
--scene-threshold TManual scene detection (distinct screen changes).--scene-threshold 0.4
--max-frames NPredictable page count, smooth/gradual content.--max-frames 30
--fps NFixed-rate sampling. Rarely best.--fps 1

All modes are mutually exclusive at the CLI (--capture-all overrides the others).

--capture-all tuning

OptionDefaultMeaning
--sample-fps FPS10.0Dense sampling rate. Must be high enough that no message scrolls all the way past between samples. Raise for fast scrolls.
--overlap FRAC0.5Keep a frame each time content scrolls by this fraction of the frame height. Lower = more pages / safer; higher = fewer pages. 0.5 = adjacent pages overlap ~50%.

How it guarantees completeness: it densely samples (default 10fps), measures the vertical scroll between consecutive frames, and only advances to a new page once the content has scrolled by overlap of the screen. Adjacent pages therefore always overlap, so any message that was ever on screen appears on at least one (usually several) pages. For a 133s phone chat scroll this yields ~50 pages with ~79% adjacent overlap. If you see gaps, lower --overlap (e.g. 0.35) or raise --sample-fps.

--auto tuning

OptionDefaultMeaning
--target-density SECS2.0Target seconds between kept frames (auto-raised for long videos).
--dedup-threshold DIFF6.0Grayscale mean-abs-diff below which two frames are duplicates (higher = keep more).

Quality presets

PresetMax dimJPEG qBest for
balanced1024px3General (default)
detailed1568px2UI detail, small text, color fidelity
ocr1568px1 (gray+sharpen)Text-heavy -- loses color

PDF Options (frames_to_pdf.py)

OptionDefaultMeaning
<frames_dir>--Directory of frame images
--json FILE--Read frame list from extract JSON (- = stdin)
-o / --outputrequiredOutput PDF path
--pagenonea4/a4l/letter/letterl/none (none = native pixel size)
--margin0Page margin in points (needs --page)
--backendautoimg2pdf (lossless JPEG embed) / pillow / auto

Troubleshooting

  • Chat recording is missing messages. You used a key-frame mode (--auto / --max-frames) -- those skip frames and miss messages that scroll past. Use --capture-all instead. If still gappy, lower --overlap 0.35 and/or raise --sample-fps 15.
  • --capture-all page count too high. Raise --overlap (e.g. 0.65 = fewer pages, less overlap) -- but stay below ~0.8 or you risk gaps on fast scrolls.
  • --capture-all says it needs numpy. pip install numpy.
  • Scene detection returns 0 frames. Normal for smooth scrolls -- use --capture-all (chat) or --auto (it falls back to fixed-rate).
  • ffmpeg not found. pip install imageio-ffmpeg (bundled, no admin) or winget install Gyan.FFmpeg.
  • Text blurry. --preset ocr (grayscale, sharpened) or --preset detailed --max-dimension 1920.
  • No img2pdf. Falls back to Pillow (re-encodes). pip install img2pdf.

Files

  • scripts/extract_frames.py -- video -> JPEG frames. Modes: --capture-all (scroll-aware complete capture), --auto (smart key-frames + pause dedup), --scene-threshold/--max-frames/--fps (manual). Prints JSON.
  • scripts/frames_to_pdf.py -- frames -> one PDF (img2pdf lossless embed, or Pillow).
  • references/video-frames-source.md, references/llm-image-specs.md -- upstream refs.
  • references/THIRD-PARTY-LICENSES.md -- full third-party license texts.
  • LICENSE -- Mixed license (WDenlie Commercial-Authorization for original work + MIT for upstream-derived).

License & Third-Party Notices

This skill uses a mixed license (see LICENSE for the full text):

  • Original workframes_to_pdf.py, the --capture-all / --auto / pause-de-dup / ffmpeg-resolution additions in extract_frames.py, and SKILL.md — is © 2026 WDenlie under the PolyForm Noncommercial License 1.0.0: free for personal / academic / non-commercial use with attribution; commercial use requires a separate license. To license commercially, contact WDenlie via WeChat (ID: WDenlie).
  • Upstream-derived code — the core frame-extraction logic in extract_frames.py, plus references/video-frames-source.md and references/llm-image-specs.md — is adapted/copied from mugnimaestra/video-frames-skill and remains under its MIT License (MIT permits commercial use of those portions; this cannot be revoked).

No binaries, no vendored libraries are shipped; deps are pip-installed by the user and ffmpeg is invoked only as an external process.

  • Runtime deps (not bundled): img2pdf (LGPL-3.0-or-later), imageio-ffmpeg (BSD-2-Clause), Pillow (PIL Software License), numpy (BSD-3-Clause, only for --capture-all).
  • ffmpeg is the GPL (--enable-gpl) build when fetched by imageio-ffmpeg, invoked only as a separate subprocess -- the skill does not link, bundle, or redistribute it, so GPL copyleft does not reach this skill's code. For commercial distribution prefer an LGPL-only ffmpeg build (configure without --enable-gpl/x264/x265) -- this skill only decodes video and encodes JPEG.

Full third-party license texts: references/THIRD-PARTY-LICENSES.md.

Not legal advice. Engineering-level license guidance; have counsel review before commercial distribution.

Claude, OpenAI, and Gemini are trademarks of their respective owners; this skill is independent and not affiliated with or endorsed by them.

What ships with it: 8 files

76.6 KB alongside SKILL.md, 2 of them executable

scripts/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.