Turn a book into chapter-by-chapter YouTube videos: each chapter uses a VoiceDrop audiobook mp3 as the audio track, distill 1-3 central ideasfrom the chapter content, design a prompt for each central idea, generate visuals with GPT Image 2 (Ken Burns slow push + crossfade), overlay the central idea as large text on the visuals, and finally composite a 1920×1080 landscape video and upload it to YouTube.
What this skill produces
| Dimension | Default |
|---|---|
| Size | 1920×1080 landscape (16:9), 30fps |
| Granularity | One video per chapter(the video is as long as the chapter mp3) |
| Audio track | VoiceDrop chapter audiobook mp3 (no re-TTS) |
| Visuals | 1-3 GPT Image 2 generated images per chapter, Ken Burns slow push, 1s crossfade between segments |
| Text | For each central idea: large title (≤12 characters) + one explanatory sentence, fade in/out, rendered with Pillow |
| Project directory | ~/code/book-videos/<book-slug>/ |
| Output | <slug>-chNN.mp4 × N chapters + UPLOAD_META.md |
| Publish | wjs-uploading-video upload (landscape regular video), default public |
When this skill fires
- The user gives a book and says "make it into a video" or "add visuals to the audiobook and post it to YouTube"
- The user runs
/wjs-creating-video-book <书名或书架章节>
When NOT to use
- What they want is a 30-90 second vertical explainer short →
/wjs-converting-text-to-video - They only want the audiobook mp3, no video →
/wjs-voicedrop-reading-aloud - They want to write a book review article →
/wjs-publishing-wechat
Core Principle
This is a "listening-first, watching-second" video. The audio track is the full-chapter narration, and the audience is "listening to a book"; the job of the visuals is to give the eyes an anchor to rest on, not to put on an animated performance. So:
- Fewer central ideas rather than more — pick 1-3 true pillar points per chapter; it is normal for one image to stay on screen for several minutes
- One visual style for the whole book — the art style must be consistent from chapter to chapter (same medium, same color family), so the audience isn't pulled out of the experience when switching chapters
- Draw concrete scenes, not abstract concepts — for "leverage", draw a long pole prying up a boulder, not the word "leverage" or an abstract arrow chart
- Copyright self-check — narrating the full original text of a chapter + public release only applies to public-domain books or books the user has rights to; for copyrighted books, confirm with the user before publishing
Workflow
Step 0: Project directory
SLUG=<book-slug> # 优先用书的英文名短 slug(如 naval-almanack);没有英文名才用拼音
BOOK=~/code/book-videos/$SLUG
mkdir -p $BOOK/chapters/{01,02,...} # 每章一个两位数目录
Step 1: Get the text + audiobook mp3 for each chapter
| Material | Source (by priority) |
|---|---|
| Chapter mp3 | ① Download the already-composited chapter mp3 from the jianshuo.dev bookshelf audiobook (R2, see memory [[jianshuo-dev-audiobook]]) ② If not available → use /wjs-voicedrop-reading-aloud to generate from the chapter text |
| Chapter text | Bookshelf page / PDF or EPUB provided by the user (for EPUB first pandoc x.epub -t plain, if pandoc isn't installed first brew install pandoc) |
Save as chapters/NN/audio.mp3 and chapters/NN/chapter.md。
Step 2: Distill 1-3 central ideas per chapter → ideas.json
Read chapter.md, pick the truly load-bearing ideas. The number follows audio length: 1-2 for <5 minutes, 2-3 for 5-15 minutes, and for >15 minutes alsoat most 3(the visuals are anchors, not subtitles).
[
{"title": "杠杆是新的钱", "caption": "代码和媒体是无需许可的杠杆", "image": "img-1.png", "start": 0},
{"title": "把自己产品化", "caption": "独特知识乘以杠杆才有复利", "image": "img-2.png", "start": 312}
]
title≤12 characters (large text);captionone sentence ≤20 characters; neither ends with punctuationstart(seconds) = the position where that idea starts being spoken in the narration; estimating by text position ratio is fine; if all are omitted, divide the audio evenly- The central idea must stay faithful to the chapter content — this is not a derivative work, it is highlighting key points for the listener
Step 3: One visual per central idea (GPT Image 2)
First givethe whole booka style base draft $BOOK/style.md(do it only once):the medium must be illustration(editorial illustration / watercolor illustration / minimalist flat illustration, etc.; do not use photorealism — illustration holds up best under Ken Burns slow push-in and text overlay), color family, lighting mood, 2-3 sentences.
Assemble each image's prompt according to thevideo-friendly illustration template= whole-book illustration style + a concrete scene for that idea + fixed ending:
node ~/.claude/skills/gpt-image-2-skill/scripts/gpt_image_2_skill.cjs \
--json --provider codex images generate \
--prompt "<全书插画风格>. <这个中心思想的具象场景>. Wide horizontal panoramic composition, landscape orientation, cinematic 16:9 framing. Generous negative space, calm lower left area for text overlay. Illustration, not a photograph. No text, no words, no letters." \
--out $BOOK/chapters/NN/img-1.png --format png --size 1920x1088 --quality high
The fixed ending's three sentences are all indispensable; each fixes a pitfall actually encountered:
- "Wide horizontal panoramic composition, landscape orientation" — the Codex side
--sizeis only a reference; the composition actually follows the prompt; if you do not write this sentence, it returns a square image or even a vertical image (after a vertical image is center-cropped to 16:9, most of the frame is lost). Although the rendering script has fallback cropping, getting a horizontal image at the source is the right solution - "Generous negative space, calm lower left area" — the lower-left corner is the fixed position for the large central-idea text, and the main subject of the image must avoid it
- "No text, no words, no letters" + "Illustration, not a photograph" — the text is overlaid by the rendering script with Pillow; AI drawing Chinese text will definitely fail; photorealism looks cheap under slow push-in + large text
Other requirements:
- Draw concrete scenes (people, objects, light, space), not conceptual diagrams / charts / arrows
- Multiple images in the same chapter must have visual connections (different angles of the same space, different times of the same day)
- Check the dimensions after generation: if it still produces a vertical image (height > width), regenerate with more explicit horizontal-scene wording; do not settle
Step 4: Synthesize the chapter video
cd $BOOK/chapters/NN
uvx --with pillow python ~/.claude/skills/wjs-creating-video-book/scripts/render-chapter.py .
mv chapter.mp4 $BOOK/$SLUG-chNN.mp4
What the script (already verified on this machine) does: after upsampling each image to 3840, zoompan slow push-in (about 1.09× for 12s), 1s xfade between segments, render the large central-idea text + explanatory sentence with Pillow into a transparent PNG and then overlay it (1s alpha fade in/out, avoiding 0.8s/0.5s at the start and end of each segment), use the chapter mp3 directly as the audio track,-crf 19 output. The font is auto-detected as PingFang → Hiragino Sans GB → STHeiti.
Note: ffmpeg on this machine was not compiled with drawtext, so text must go through the Pillow path in the script; do not try to hand-write a drawtext filter.
Step 5: Thumbnail (per chapter)
Use a video frame + large text (do not draw another AI illustration): pick the frame where the chapter title text is clearest:
ffmpeg -y -ss <标题完全显示的秒数> -i $BOOK/$SLUG-chNN.mp4 -frames:v 1 -vf scale=1280:720 $BOOK/thumb-chNN.jpg
uploader does not support setting thumbnails via API — after uploading, remind the user to set it manually in YouTube Studio.
Step 6: UPLOAD_META.md + upload
The format must strictly copy the skeleton below — upload_youtube.py the parser only recognizes ## NN · 文件名 block headers + **短标题** / **视频描述** sections + #tagin the body; other formats parse to 0 blocks and exit directly. One block per chapter:
## 01 · <slug>-ch01.mp4
**短标题**
《书名》第一章:<章名或一句话钩子>
**视频描述**
<本章讲什么,2-3 句> + 本章的中心思想列表
有声书朗读来自 VoiceDrop。
#有声书 #听书 #<书名> #<作者> #读书
---
uvx --with google-auth --with requests python \
~/.claude/skills/wjs-uploading-video/scripts/upload_youtube.py --dir $BOOK
When there are many chapters, pay attention to the YouTube daily quota (about 6/day by default): create a upload-batch-N/ staging directory to hold soft links to the mp4s to upload that day + UPLOAD_META.md soft links,--dir point to the staging directory and upload day by day.
--dir mode automatically pairs the mp4 in the directory with the UPLOAD_META.md(Do not use --video + --meta — --meta only takes effect on the --dir branch,--video branch requires --title and ignores meta files). For multi-chapter videos, it is recommended to add --playlist <id> to group them into the same playlist. After uploading, send the link back to the user.
Step 7: Attach the full transcript as comments
After each video is uploaded, attach that chapter's transcript below the video in the form of a "pinned comment + replies split by section" (people listening to the audiobook can read along):
uvx --with google-auth --with requests python \
~/.claude/skills/wjs-creating-video-book/scripts/post-transcript-comments.py \
<video_id> chapters/NN/chapter.md \
--header "📖《书名》第 N 章「章名」全文文稿"
Script behavior: automatically strips the site header and footer from chapter.md, splits by ## sections into 3-6 comments (the first is the pinned main comment, the rest are replies to it, each ≤4200 characters, labeled with k/N numbering), with a 2s interval between replies to prevent spam detection.
Permission: requires the youtube.force-ssl scope. If the token only has youtube.upload(posting comments returns 403 / the script prompts re-auth), run uvx --with google-auth-oauthlib python ~/.claude/skills/wjs-creating-video-book/scripts/reauth-youtube.py once — it will pop up a browser for the user to click authorize once, and the new token will contain both upload + force-ssl, so it won't pop up again in the future.
Directory structure
~/code/book-videos/<slug>/
├── style.md # 全书视觉风格底稿(一次定)
├── <slug>-ch01.mp4 ... # ⭐ 每章最终视频(在根目录,供 --dir 上传扫描)
├── thumb-ch01.jpg ... # 每章缩略图(YouTube Studio 手动设)
├── UPLOAD_META.md
└── chapters/
└── 01/
├── chapter.md # 章节文本
├── audio.mp3 # VoiceDrop 读书 mp3
├── ideas.json # 1-3 个中心思想
├── img-1.png ... # GPT Image 2 画面
└── overlay-1.png ... # 脚本生成的文字层(中间产物)
Anti-Patterns
| Do not | Reason |
|---|---|
| Re-TTS the chapter text | The audio track is the VoiceDrop reading mp3; re-synthesizing is both wasteful and inconsistent |
| Cram 5-6 central ideas into one chapter | The visuals become a subtitle machine. Fewer anchors are better than more, ≤3 |
| Have the AI draw text in the prompt | GPT Image 2 always breaks when drawing Chinese. Force "No text" in the prompt, and overlay text via Pillow |
| Not writing landscape/wide composition in the prompt | On the Codex side, --size is only a reference; it will return square or portrait images, and 16:9 cropping loses most of the frame |
| Use a photo-realistic style | Only illustration can withstand Ken Burns slow push + large text overlay; the photo style looks cheap |
| Draw abstract concept diagrams (arrows/charts/concept words) | Draw concrete scenes and let the visuals breathe on their own |
| Change the art style for each chapter | One style.md for the whole book, consistent across chapters |
| Hand-write the drawtext filter | The local ffmpeg was not compiled with drawtext, so it will say "No such filter". Use the script's Pillow path |
| Publish copyrighted books directly and publicly | The copyright risk of reading the full original text of an entire chapter is far greater than that of a book review. Only publish by default for public-domain books / books you have rights to; otherwise confirm first |
| Draw a separate AI illustration for the thumbnail | Use a video frame + large text (same cover convention) |
For upload use --video + --meta |
This combination does not hold (--video requires --title and ignores meta), use --dir |
Dependencies
- ffmpeg(already installed; note that this machine's build has no drawtext, and the script already bypasses it with Pillow)
- uvx + pillow — text layer rendering (
uvx --with pillow python ...) - GPT Image 2(
~/.claude/skills/gpt-image-2-skill/,--provider codex) — image generation - wjs-voicedrop-reading-aloud — generated when the chapter mp3 does not exist
- wjs-uploading-video + OAuth token
~/.config/youtube/token.json— upload - pandoc — only needed for EPUB input, not installed by default on this machine, first
brew install pandoc