Generate share posters for a 小宇宙 (xiaoyuzhoufm.com) podcast episode. Use this skill whenever the user gives a xiaoyuzhou episode URL and asks for a 海报/poster/分享图/封面图, or says "做一张图/生成海报/出个分享图" with a podcast episode link. Produces 1080×1440 (social, 3:4) and optional 1080×1920 (endcard, 9:16) PNGs with cover + title + shownotes highlights + CTA, in 4 social styles (magazine/clean/warm/blur) and 2 endcard styles (endcard-dark/magazine).
How this skill is triggered — by the user, by Claude, or both
Slash command
/podcast-video-toolkit:podcast-posterThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Given a 小宇宙 episode URL, fetch the episode data, let the user pick highlights + style, then render share-ready posters.
Given a 小宇宙 episode URL, fetch the episode data, let the user pick highlights + style, then render share-ready posters.
The user provides a https://www.xiaoyuzhoufm.com/episode/... URL and wants visual share assets. Examples:
If the user already has structured episode data (not a URL), skip step 1 and start at step 2.
Pick a work directory once: WORK="$(mktemp -d)". Use it for all intermediate files.
Always run plugin preflight first to bootstrap the shared Python venv (Pillow + qrcode). It builds the venv at ${CLAUDE_PLUGIN_DATA}/.venv (survives plugin upgrades), validates imports, and prints the python path. First run takes ~10s; subsequent runs are ~100ms.
PY="$(bash "${CLAUDE_PLUGIN_ROOT}/scripts/preflight.sh")"
Use ${PY} for every Python invocation below. ${CLAUDE_PLUGIN_ROOT} is provided by Claude Code and resolves to this plugin's install directory.
"${PY}" "${CLAUDE_PLUGIN_ROOT}/skills/podcast-poster/scripts/fetch_episode.py" <URL> -o "${WORK}/episode.json"
This uses only stdlib (no deps). The output JSON contains:
episode_url, cover_url, title, ep_numtimestamps: array of [mm:ss, description] (can be 6–14+ entries depending on episode)Read ${WORK}/episode.json and look at timestamps. Pick 6 highlights (the renderer's social template fits 5 and endcard fits 7, so 6 is a safe default that works for both).
How to pick:
mm:ss timestamp string.Show the user your picks before rendering, in a compact format like:
我从 14 个时间戳里选了 6 条作为亮点:
- 02:06 起床从 9 点提前到 7 点
- 12:03 为什么更愿意说「机器学习」而非「AI」
...
要调整哪一条?或者直接渲染?
| Template | Style | When to use |
|---|---|---|
| social (1080×1440) | magazine ⭐ | 推荐默认。深色杂志风,金色点缀,最稳 |
| social | clean | 浅米色极简 |
| social | warm | 米色书页 + 宋体,适合人文 / 情感类话题 |
| social | blur | 模糊封面 + 奶油卡片 |
| endcard (1080×1920) | endcard-dark | 视频片尾卡专用,深色 |
| endcard | magazine | 视频片尾卡,杂志风 |
Default: render all 4 social styles + 2 endcard styles (6 images total). If the user indicated a specific use ("发小红书" → social only, "视频片尾" → endcard only), narrow accordingly.
Ask: "默认渲染全部 6 张(4 social + 2 endcard),还是只要某个特定风格 / 模板?"
Overwrite ${WORK}/episode.json with the user-chosen highlights array. Example:
{
"episode_url": "https://www.xiaoyuzhoufm.com/episode/...",
"cover_url": "https://image.xyzcdn.net/...",
"title": "14. 你每天在练习什么,你就会擅长什么",
"ep_num": "EP 14",
"highlights": [
["07:40", "怎么解释每天经历的事,决定你的情绪"],
["17:20", "幸福真的可以练习吗?"],
["21:20", "全心全意做一件事,找到自己喜欢的"],
["32:50", "刷牙不看手机、用左手吃饭"],
["46:00", "刻意照顾自己的鼻子,练就洗鼻神功"],
["54:35", "不那么害怕春天的过敏季"]
]
}
Optional fields (defaults applied if omitted): cta, handle, handle_sub, show_qr.
Then render using the interpreter from preflight ($PY):
OUT="${WORK}/poster_out"
mkdir -p "${OUT}"
# Render all (recommended default)
"${PY}" "${CLAUDE_PLUGIN_ROOT}/skills/podcast-poster/scripts/render_poster.py" \
--config "${WORK}/episode.json" --all -o "${OUT}/"
# Or just one combo
"${PY}" "${CLAUDE_PLUGIN_ROOT}/skills/podcast-poster/scripts/render_poster.py" \
--config "${WORK}/episode.json" --template social --style magazine \
-o "${OUT}/poster.png"
# Or filter
"${PY}" "${CLAUDE_PLUGIN_ROOT}/skills/podcast-poster/scripts/render_poster.py" \
--config "${WORK}/episode.json" --templates social --styles magazine,clean \
-o "${OUT}/"
Tell the user where the files are (${OUT}/) and list them with dimensions. Suggest they open the folder in Finder/Preview to compare.
og:image is often podcast-level, not episode-level — episodes of the same show may share a cover URL. Title differentiates the post.00:00 is usually intro / 灵感来源 — often skippable as a highlight.Hiragino Sans GB, Songti, Apple Color Emoji) are macOS-specific. Linux will break — known limit.scripts/fetch_episode.py — URL → JSON (stdlib only)scripts/render_poster.py — JSON → PNG (uses Pillow + qrcode from the shared plugin venv)Python deps are managed at the plugin level — see ${CLAUDE_PLUGIN_ROOT}/scripts/preflight.sh.
npx claudepluginhub pierrelzw/podcast-video-toolkit --plugin podcast-video-toolkitCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.