openclaw-thumbnail-forge
v0.1.0
A practical thumbnail generator for videos. Builds the kind of professional-looking thumbnails creators normally make in Photoshop or Canva, but as a local CLI workflow with no API keys, no online services, and no AI dependencies.
What this skill does
scripts/check_deps.sh— verifyffmpeg,ffprobe,python3(and thePillowPython package) are installed.scripts/pick_frames.py— extract candidate frames from a video and rank them by a composite score combining sharpness (Laplacian variance), brightness, contrast, and ffmpeg scene-change scores. Outputs the top-N frames as PNG files plus a JSON report.scripts/compose_thumbnail.py— turn one source frame into a finished thumbnail with bold title text, subtitle, gradient bar, optional logo overlay, and auto contrast boost. Supports custom fonts and color schemes.scripts/export_sizes.py— re-export a finished thumbnail to all common platform sizes in one command (YouTube, Shorts, Instagram square, X/Twitter, LinkedIn).scripts/make_variants.py— generate four A/B-testable variants of the same thumbnail (different color schemes, text placements, contrast levels) for split-testing.
What this skill does not do
To set expectations honestly:
- It does not use AI subject detection or face recognition. Frame ranking is statistical, not semantic.
- It does not download fonts, stock photos, or any remote asset. You provide your own font path or use the system default.
- It does not perform OCR, transcription, or generative editing.
- It does not write outside the directory you provide.
Required dependencies
bash scripts/check_deps.sh
Verifies ffmpeg, ffprobe, python3, and that PIL (Pillow) is importable. Pillow is the only Python dependency:
pip install Pillow
Workflows
1. Pick the best candidate frames from a video
python3 scripts/pick_frames.py input.mp4 ./frames/ \
--top 10 --interval 2.0
Extracts a frame every 2 seconds, scores each one, and writes the top 10 as frames/frame_001.png through frames/frame_010.png plus a frames/report.json with per-frame scores.
Tunable flags:
--interval <seconds>— sampling interval (default 2.0)--top <N>— how many top frames to keep (default 10)--min-brightness <0-255>and--max-brightness <0-255>— reject frames that are too dark or blown out--min-sharpness <float>— reject blurry frames (Laplacian variance floor)
2. Compose a finished thumbnail from a frame
python3 scripts/compose_thumbnail.py frames/frame_003.png thumb.png \
--title "10 ffmpeg Tricks I Wish I Knew Sooner" \
--subtitle "A practical tour" \
--color-scheme bold-yellow \
--position bottom
Color schemes shipped: bold-yellow, clean-white, red-alert, cool-blue, tech-green. Each scheme defines title color, outline color, shadow, and gradient bar opacity.
Position options: top, bottom, center. The script auto-fits the title size to the available width and adds a readable gradient bar behind the text so the thumbnail reads at small sizes too.
Optional logo overlay:
python3 scripts/compose_thumbnail.py frames/frame_003.png thumb.png \
--title "Your Title" \
--logo logo.png --logo-corner top-right --logo-scale 0.12
3. Export to all platform sizes at once
python3 scripts/export_sizes.py thumb.png ./out/
Writes:
out/youtube_1280x720.pngout/shorts_1080x1920.pngout/instagram_1080x1080.pngout/x_1200x675.pngout/linkedin_1200x627.png
Each platform uses smart resize: source is fitted into the target with smart-cropped letterboxing so the title area stays visible.
4. Generate A/B variants
python3 scripts/make_variants.py frames/frame_003.png ./variants/ \
--title "10 ffmpeg Tricks" \
--subtitle "A practical tour"
Writes 4 variants:
variant_a_bold_yellow_bottom.pngvariant_b_clean_white_top.pngvariant_c_red_alert_center.pngvariant_d_cool_blue_bottom.png
Same source frame, different color and layout choices, ideal for click-rate split testing.
Full pipeline example
# 1) Find the best candidate frames
python3 scripts/pick_frames.py my_video.mp4 ./frames/ --top 5 --interval 1.5
# 2) Compose a thumbnail from the highest-scored frame
python3 scripts/compose_thumbnail.py frames/frame_001.png thumb.png \
--title "Your Title Here" --subtitle "Optional subtitle" \
--color-scheme bold-yellow --position bottom
# 3) Export at every platform size
python3 scripts/export_sizes.py thumb.png ./out/
# 4) Optional: split-test variants
python3 scripts/make_variants.py frames/frame_001.png ./variants/ \
--title "Your Title Here"
Safety properties
- All Python helpers use
subprocess.runwith argument lists (nevershell=True) and reject input/output paths containing shell metacharacters via a strict regex allowlist. - The skill never reads or writes outside the input/output paths the user provides.
- No environment variables are read for credentials. No tokens, secrets, or API keys are required.
- No remote calls of any kind. The skill only invokes locally installed
ffmpegand the PythonPillowlibrary.
Known limitations
- Frame scoring is heuristic, not AI-based. It is not aware of "is the subject's face visible" — it just maximises sharpness, healthy brightness, and scene-change importance.
- Default font is the system default if
--fontis not provided. If no usable font is found, the script falls back to Pillow's bitmap font, which looks plain. Pass--fontfor nice typography. compose_thumbnail.pydoes not do automatic background removal. If you want isolated subjects, do the subject-cutout step in a different tool first.
License
MIT. See LICENSE.