Use when the user wants a 王建硕-style WeChat article (article.md) turned into a narrated short MP4 video — TTS voiceover via 火山引擎 Volcano TTS, HyperFrames CSS/GSAP animation per scene, subtle SFX, abstract watercolor background, full pipeline rendering to 1080×1920 portrait MP4 (30-90s). Triggers — "把这篇文章做成视频", "做一个解说视频", "讲解视频", "/wjs-converting-text-to-video".
npx skills add https://github.com/jianshuo/claude-skills --skill wjs-converting-text-to-video
把一篇王建硕风格的微信公众号 article.md 做成 1080×1920 竖屏、30-90 秒 的中文解说短视频:TTS 旁白 + HyperFrames CSS/GSAP 动画 + 抽象水彩背景 + 转场 SFX。输出 MP4 给视频号 / 抖音 / 小红书 / Reels。
| 维度 | 默认 |
|---|---|
| 尺寸 | 1080×1920 竖屏 (9:16) |
| 时长 | 30-90 秒 |
| Scene 数 | 5-10 |
| 旁白 | 火山引擎 Volcano TTS,默认阿虎对话男声 |
| 背景 | GPT Image 2 生成的抽象水彩 (bg.png) + blur 30 + 暖黑半透明 overlay |
| 字体 | Noto Sans SC,hero 900,主文字暖奶白 |
| 输出 | <article-folder>/<slug>.mp4(与 video/ 平行,不放 video/ 里)|
| 发布 | 自动上传到 YouTube — Portrait → Shorts,Landscape → 普通 video;重新渲染会替换老视频(不累积)|
article.md,说「做成视频」「做一个解说」「讲一遍」/wjs-converting-text-to-video <article-folder>/wjs-publishing-wechat 写出 article.md,再来/wjs-burning-subtitles / /wjs-dubbing-video / /wjs-localizing-video视频不是文章的可视化朗读,而是文章的视觉重构。
每个 scene 是一个独立的视觉时刻 —— 一个对比、一个排比、一个数字、一个比喻。文字撑满屏幕,黑体加粗,重点字橙色高亮。背景是抽象水彩 (blur 后柔化),整体调子稳重、克制、有冲击力。
节奏 > 模板。一段 5-10 scene 的视频,如果从头到尾都是"两行对照"的同一种排版,就不是视频,是 slideshow。现代感来自对比 —— 极端字号差、不对称布局、短 scene 与长 scene 交替、纯文字 scene 与几何元素 scene 交替、水彩底 scene 与亮色 punch scene 交替。
默认是平庸的。如果只是从模板表顶端挑几种最容易的,结果一定是"平铺直叙的两行格式"。强制走 Step 1b Scene Mix Rule 配比。
读 <article-folder>/article.md,按论证结构拆成 5-10 个 scene(控制在 30-90 秒总时长)。短文(核心 1-2 个要点)做 5-6 scene / 30-50s;长文 8-10 scene / 60-90s。每个 scene 一段叙述(旁白)+ 一个清晰的视觉骨架。
模板表 —— 6 类共 16 种,按需混搭:
| 模板 | 适合 |
|---|---|
| A1. 全屏单字 hero | 1-3 字 climax 词撑满屏,字号 280-400px |
| A2. Outline hero | 空心字 -webkit-text-stroke: 4px #f5efe5; color: transparent; |
| A3. Color-flip punch | 整屏背景换亮色(橙/红/金/翠绿等),反白字 |
| A4. Gradient text hero | 大字加 background: linear-gradient(...); -webkit-background-clip: text; |
| 模板 | 适合 |
|---|---|
| B1. 双行对照 + strikethrough | 「以前 X,现在 Y」「不是 A,是 B」 — 整片最多 2 个 |
| B2. 左右分屏对照 | 屏幕一分为二(可加竖线分隔) |
| B3. 对角线对照 | 左上 ↔ 右下,中间大量留白 |
| 模板 | 适合 |
|---|---|
| C1. N 个卡片横排 | 3-5 个并列,用深暖黑 + 单色边框 |
| C2. 垂直堆叠关键词 | 6-8 个排比项,可加大数字编号 01-08 |
| C3. 真网格 | 2×2 / 3×2 网格,每格图标 + 标签(竖屏宽度有限,4 列横排会挤) |
| C4. 阶梯 / 错位列表 | 每项 margin-left 递增 |
| 模板 | 适合 |
|---|---|
| D1. 数字 ticker | 0 → N 滚动动画(gsap.to({textContent}))|
| D2. 数字 + 标签 | 主数字 200-400px + 60-80px 解释 |
| D3. 进度条 / 时间轴 | 横向 progress bar + 节点 |
| 模板 | 适合 |
|---|---|
| E1. 段落级 hero text | 一句 60-100px 金句,左对齐 + 左侧 emphasis bar |
| E2. 大引号 + 内文 | 巨大半透明开引号作背景装饰 |
| 模板 | 适合 |
|---|---|
| F1. 格子 + spinner / 进度条 | 多并发画面 |
| F2. 对话气泡 ↔ 回应 | 角色 A 说 → 角色 B 做 |
每个 scene 的旁白控制在 3-12 秒(短 punch 3-4s,长 breath 10-12s,不要全部都是 5-7s)。所有 scene 加起来 30-90 秒,不要超过 90 秒。文章短就做短,5 个 scene × 6s = 30s 也是合格。
写完 5-10 个 scene 设计后,按下面 checklist 自查。任何一条不满足 → 回去调整。
background: 色 — 让水彩 bg-image 透出;只有 A3 color-flip 才用纯色 bgnarration_chunks.json[
{"id": "s01", "text": "我们以前,是 AI 的领导。现在,我们就是它的维修工。"},
{"id": "s02", "text": "..."}
]
写旁白细节:
...、不写破折号 ——(TTS 会念出 "破折号" 三字)加粗 markdown,只留纯文字cd <article-folder>/video
python3 tts_narration.py
脚本默认用 zh_male_ahu_conversation_wvae_bigtts(阿虎对话)— 段间插 0.35s 静音,输出 narration.mp3 + timing.json。
Volcano TTS 注意事项(踩过的坑):
volc.service_type.10029,speaker 选 zh_*_*_bigttsemotion / emotion_scale — 大部分 _bigtts 声音会返回 data: null 静默失败zh_male_jieshuonansheng_mars_bigtts — 含英文专名(如 "Claude Code")会循环 hallucinate备用声音(按推荐顺序):
zh_male_ahu_conversation_wvae_bigtts (阿虎对话) — 默认,自然口语zh_male_M392_conversation_wvae_bigtts — 同 wvae 系列zh_male_wennuanahu_moon_bigtts (温暖阿虎) — 更暖、播音感zh_male_silang_mars_bigtts (思朗) — 沉稳思考,戏剧感强zh_male_baqiqingshu_mars_bigtts (霸气) — 更有力度切声音:python3 tts_narration.py --voice zh_male_silang_mars_bigtts
bg-image 是视觉主基调(柔化的抽象水彩)。不要用 article 的 illustration.png — 手绘示意图细节太多,blur 后变成均匀深色泥(视觉上仍是纯黑)。必须用专门生成的抽象水彩。
~/.claude/skills/wjs-converting-text-to-video/scripts/generate-bg.sh <article-folder> <theme>
<theme> 选(根据文章主题):
| theme | 色板 | 适合 |
|---|---|---|
| personal | bright warm yellow, soft coral pink, terracotta, sage green, cream | 个人、手作、温暖 |
| tech | cool teal, electric blue, deep purple, mint, white | AI、技术、数据 |
| reflection | sage green, dusty blue, lavender, pearl, cream | 反思、沉静 |
| warning | burnt orange, deep red, mustard, charcoal | 警示、张力 |
| growth | fresh green, gold, soft yellow, sky blue | 增长、复利 |
| abstract | lavender, dusty rose, sage, soft amber | 抽象、哲思 |
输出:<article-folder>/video/bg.png (1088×1920, ~3MB)。
⚠️ 图片必须在 video/ 目录内 — 不能用 ../illustration.png,hyperframes render 不解析跨目录相对路径,会渲染成纯黑。
index.html)读 timing.json,按每个 chunk 的 start/end 设计 scene。竖屏 1080×1920 结构:
<html><head><script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<style>
html, body {
width: 1080px; height: 1920px; margin: 0; overflow: hidden;
background: #0e0b08;
font-family: 'Noto Sans SC', 'PingFang SC', 'Heiti SC', sans-serif;
font-weight: 900;
color: #f5efe5;
letter-spacing: -0.02em;
-webkit-font-smoothing: antialiased;
}
#bg-image {
position: absolute; inset: 0;
background-image: url('bg.png');
background-size: cover;
background-position: center;
filter: blur(30px) brightness(0.65) saturate(0.85);
z-index: 0;
transform: scale(1.1);
}
#bg-overlay {
position: absolute; inset: 0;
background: rgba(14, 11, 8, 0.28);
z-index: 1;
}
.scene { position: absolute; inset: 0; overflow: hidden; opacity: 0; z-index: 2; }
#s1 { opacity: 1; }
/* ... scene-specific styles ... */
</style></head>
<body>
<div id="root" data-composition-id="main" data-start="0" data-duration="<total+2>" data-width="1080" data-height="1920">
<div id="bg-image"></div>
<div id="bg-overlay"></div>
<!-- scene divs s1..sN -->
<!-- audio: narration + ticks + chimes + bell -->
</div>
<script>
/* GSAP timeline: paused + register to window.__timelines['main'] */
</script>
</body></html>
视频 t=0 必须包含:
tl.from({y:30, scale:0.95}) 可,但 不要 tl.from({opacity:0}),否则 t=0 就是黑屏主文字 / 锚定色(design system,全片一致):
| 角色 | 值 | 用法 |
|---|---|---|
| 主文字 | #f5efe5 暖奶白 | hero / 主要内容 |
| 二级文字(副标题、caption)| #f5efe5 + opacity: 0.7 + 小字号 | 不要用灰色(#8a7e72 在水彩底上看不清)。用 opacity + 缩字号做 hierarchy |
| 划掉文字本身 | #f5efe5 + opacity: 0.5 + strikethrough line | 不要用 #6d635a 暗灰 — 在水彩底上看不清。改用 opacity 弱化 + 橙色 strike line |
| 装饰大编号(01-08)| #f5efe5 + opacity: 0.18 或 #e87a3e + opacity: 0.35 | 不要用 #2b2620 等深灰(水彩底上完全消失)|
| Outline 描边 | #f5efe5 4-8px stroke + color: transparent | A2 空心字 |
| 默认 fallback bg | #0e0b08 深暖黑 | 被 bg-image + overlay 覆盖;color-flip 不用 |
核心原则:所有文字用 #f5efe5 cream 或 #e87a3e 橙系(accent palette),用 opacity + size 做 hierarchy,不用色相变化。灰色是黑底时代的遗物,水彩底上一律不用。 详见 [[no-low-contrast-text]]
Color-flip 背景 palette(A3,不只是橙/蓝/白):
| hex | 适合 |
|---|---|
| #e87a3e 经典橙 | 警示、强调、climax punch |
| #6b9bc4 亮蓝 | 数据、技术 climax |
| #f5efe5 暖奶白 | 收尾、安静的反差 |
| #c45c3e 深红 | 警告、错误 climax |
| #d4a040 深金 | 成就、价值 climax |
| #5a8c6a 翠绿 | 增长、复利、生命力 |
| #4a8a8a 青松 | 冷静、长期主义 |
| #7a5a8a 暗紫 | 智慧、神秘 climax |
| #c48a8a 暗粉 | 柔软、人性 |
color-flip 上的文字用 #0e0b08 或 #f5efe5 反相。
Emphasis / Accent palette(不只是橙):
| hex | 适合 |
|---|---|
| #e87a3e 橙 | 默认 emphasis |
| #6b9bc4 蓝 | 数据、技术词、AI |
| #d4a040 金 | 价值、成就 |
| #5a8c6a 翠绿 | 增长、好结果 |
| #4a8a8a 青松 | 长期、稳定 |
| #c45c3e 深红 | 警告、反差 |
| #8a7aaa 暗紫 | 抽象、智慧 |
| #c48a8a 暗粉 | 柔软、人性化 |
整片 emphasis ≥ 2-3 种,根据 scene 主题选 accent。
| 项 | 值 |
|---|---|
| 字重 | hero 900 / 主文 800 / 二级 600-700 / caption 500 |
| 字距 | hero -0.04em 到 -0.06em / 主文 -0.02em / caption 0 |
| Punch hero (A1/A2,1-3 字) | 280-400px |
| 短句 hero (4-6 字) | 160-240px |
| 长句 hero (7-10 字) | 100-150px |
| 卡片内容 | 56-130px |
| 副标题 | 40-72px |
| Caption / 序号 / 标签 | 20-40px |
| 布局 | CSS 关键 | 适合 |
|---|---|---|
| 居中 | flex; center; center; | A 类 hero,但 ≤50% scene |
| 左对齐贴顶 | padding: 80px 80px 0 80px; | E 类金句、长 quote |
| 右下角锚定 | position: absolute; right: 80px; bottom: 80px; | 落款、climax 词 |
| 对角线 | top-left / bottom-right | B3 对角对照 |
| 网格 | display: grid; grid-template-columns: repeat(2, 1fr); | C3(竖屏 2×N 而非 3×N)|
| 阶梯 | 每项 margin-left: calc(60px * var(--i)); | C4 错位列表 |
| 贴底 + 上方留白 | position: absolute; bottom: 60px; 上方空白 | 呼吸 scene |
| 边角小元素 | 文字小贴一角,其他全空 | 极简 / 留白 punch |
Padding:撑满型 40-80px,呼吸型 120-200px。不要所有 scene 都用同一个 padding。
每隔几个 scene 用一个:
" 半透明超大置左上不要全片都 blur crossfade。每 4 个转场必须 ≥2 种类型。
T1. Blur crossfade(默认柔和)
sine.inOutopacity: 0, filter: blur(24px) → opacity: 1, filter: blur(0)T2. White flash cut(punch 切,最现代)
tl.to('.flash', { opacity: 1, duration: 0.06, ease: 'none' }, T - 0.06)
.set(prevScene, { opacity: 0 }, T)
.set(nextScene, { opacity: 1 }, T)
.to('.flash', { opacity: 0, duration: 0.12, ease: 'power2.out' }, T)
.from(nextScene, { scale: 1.05, duration: 0.25, ease: 'expo.out' }, T);
T3. Scale push(推进感)
scale: 1 → 0.85,后 scene scale: 1.15 → 1T4. Color flash cut(橙/蓝闪一下,强烈节奏)
flash overlay 在 HTML 里加 <div class="flash"> 全屏定位、默认 opacity 0、z-index 100。
tl.from(...) 入场(y/opacity/scale)power3.out / back.out(1.3) / expo.out / elastic.out(1, 0.5))gsap.to({opacity: 0}) 退场 — 转场已处理。只有最后 scene 可 fade-to-black平庸视频和现代视频的差别一半在排版、一半在 motion。下面 7 种每片必须用 ≥3 种(特定 scene 用,不要全片堆)。
<h1 class="kinetic">维 修 工</h1>
tl.from('.kinetic span', {
y: 180, opacity: 0, rotateX: -90,
duration: 0.7, stagger: 0.06,
ease: 'back.out(1.4)',
transformOrigin: '50% 100%',
}, T);
tl.from(scene, { scale: 1.15, opacity: 0, duration: 0.5, ease: 'expo.out' }, sceneStart);
.reveal { clip-path: inset(0 100% 0 0); }
tl.to('.reveal', { clipPath: 'inset(0 0% 0 0)', duration: 0.9, ease: 'expo.inOut' }, T);
<div class="ticker" data-end="3600">0</div>
const ticker = document.querySelector('.ticker');
const obj = { val: 0 };
tl.to(obj, {
val: parseInt(ticker.dataset.end),
duration: 1.8, ease: 'power2.out',
onUpdate: () => { ticker.textContent = Math.round(obj.val).toLocaleString(); },
}, T);
.morph { -webkit-text-stroke: 4px #f5efe5; color: transparent; }
tl.to('.morph', { color: '#e87a3e', webkitTextStrokeColor: '#e87a3e', duration: 0.5, ease: 'power2.out' }, T);
<span class="sweep"><span class="sweep-bg"></span>搭档</span>
.sweep { position: relative; display: inline-block; padding: 0 8px; }
.sweep-bg { position: absolute; inset: 0; background: #e87a3e; transform: scaleX(0); transform-origin: left; z-index: -1; }
tl.to('.sweep-bg', { scaleX: 1, duration: 0.5, ease: 'power3.inOut' }, T);
tl.to('.sweep', { color: '#0e0b08', duration: 0.1 }, T + 0.25);
tl.to(scene, { backgroundColor: '#e87a3e', duration: 0.08 }, T)
.to(scene, { backgroundColor: '#0e0b08', duration: 0.4, ease: 'power2.out' }, T + 0.1);
Strike-through 动画:用真实 DOM <span class="strike-line"> 而不是 ::after。伪元素 + CSS 变量在 hyperframes 某些渲染路径下不工作。
<span class="strike">领导<span class="strike-line"></span></span>
.strike-line { position: absolute; left: -10px; right: -10px; top: 56%; height: 10px; background: #e87a3e; transform: scaleX(0); transform-origin: left; }
tl.to('.strike .strike-line', { scaleX: 1, duration: 0.55, ease: 'power2.inOut' }, T);
~/.claude/skills/wjs-converting-text-to-video/scripts/synth-sfx.sh <article-folder>/video
生成 video/sfx/{tick,chime,bell}.mp3:
tick.mp3 — 80ms 1.2kHz sine,转场用(每次 scene 切换前 0.3s)chime.mp3 — 220ms 880+1320Hz 双音,对话/列表某项亮起时(可选)bell.mp3 — 1.5s 低频钟,最后 climax 词出来时(全片最多 1 次)接入 timeline:
<audio id="aud-narration" src="narration.mp3" data-start="0" data-duration="<total>" data-track-index="0" data-volume="1"></audio>
<audio id="aud-tick-s02" src="sfx/tick.mp3" data-start="<scene2.start - 0.3>" data-duration="0.1" data-track-index="2" data-volume="0.55"></audio>
<!-- 重复每个 scene 切换;T2/T4 flash 转场可不加 tick -->
<audio id="aud-chime-s08-1" src="sfx/chime.mp3" data-start="<T>" data-duration="0.3" data-track-index="3" data-volume="0.45"></audio>
<audio id="aud-bell-s12" src="sfx/bell.mp3" data-start="<climax-T>" data-duration="1.6" data-track-index="4" data-volume="0.55"></audio>
⚠️ 每个 <audio> 必须有 id,否则 render 出 silent(hyperframes 强制要求)。
不同 track-index 不冲突,同 track 不能时间重叠。
SFX 用量节制:转场 tick 必须;chime / bell 是装饰,scene 内容简单时不加;bell 全片只 1 次。
cd <article-folder>/video
# 必跑 1:linter(必须 0 errors)
npx hyperframes lint
# 必跑 2:layout inspect 找溢出(必须 0 errors)
npx hyperframes inspect --at 1,8,15,25,35,45,55,65
# 推荐:snapshot 看排版
npx hyperframes snapshot --at <t1>,<t2>,<t3> .
# 渲染(lint + inspect 都通过才能跑)
# ⚠️ 输出到上级目录,与 video/ 平行 —— 最终 MP4 不放 video/ 里
npx hyperframes render --quality standard --fps 30 --output ../<slug>.mp4
为什么 inspect 必跑:竖屏 1080 宽很窄,3-4 字 hero 在 280-400px 字号下就接近溢出。每次必须 inspect,0 errors 才能 render。
fix overflow:
white-space: nowrap 只在确认字数 × 字号 < 屏宽时.em 在 reveal-wrap 内溢出 → 加 line-height: 1 到 .em渲染质量:
--quality draft ~30s 渲染 — 迭代用--quality standard ~1.5min — 默认,发布够用--quality high ~3min — 投大屏 / 商务输出:<article-folder>/<slug>.mp4(与 video/ 平行,不在 video/ 内 —— video/ 留给中间文件)。
open <article-folder>/<slug>.mp4 给用户预览。不要自动上传到视频号(用户可能想先剪/调)。
新视频 render 完成后不立即上传 —— YouTube 有 daily quota 限制(默认 6 个/天 @ 1600 配额点/上传),渲染多了会卡 quota。
做法:cron 每天 10:00 自动跑 daily-upload-batch.sh,挑最多 5 个还没上传过的 MP4(按文章日期升序),上传后写 .youtube.json 记录。
cron 已注册(一次性,不用重复跑):
0 10 * * * /Users/jianshuo/.claude/skills/wjs-converting-text-to-video/scripts/daily-upload-batch.sh
手动触发(不要在 wjs-converting-text-to-video 流程里跑 — 让 cron 处理):
~/.claude/skills/wjs-converting-text-to-video/scripts/daily-upload-batch.sh
# 或单个文章立即上传
~/.claude/skills/wjs-converting-text-to-video/scripts/publish-to-youtube.py <article-folder>
每个上传的脚本行为:
#shorts、landscape 普通 video<article-folder>/.youtube.json:存在 → 尝试删老再传新(需 youtube.force-ssl scope,当前 token 没这个 scope → 跳过 delete + 上传新).youtube.json 记录详见 memory: [[auto-publish-youtube]]
<article-folder>/
├── article.md
├── illustration.png # 用户原始示意图,不直接用作 bg
├── <slug>.mp4 # ⭐ 最终视频(与 video/ 平行,不放 video/ 里)
└── video/ # 所有中间产物
├── narration_chunks.json # 5-10 个 scene 的旁白文本
├── tts_narration.py # bootstrap 复制进来
├── narration.mp3 # 合并的全段 TTS
├── narration/ # 单段 mp3 (s01..sN)
├── timing.json # 每段 start/end/duration
├── bg.png # GPT Image 2 生成的水彩背景
├── sfx/{tick,chime,bell}.mp3
├── index.html # HyperFrames composition
├── hyperframes.json
├── meta.json
├── package.json
└── snapshots/ # 渲染前快照
~/.claude/skills/wjs-converting-text-to-video/
├── SKILL.md
└── scripts/
├── bootstrap-project.sh # init video/ 目录 + 复制 helper + 生成 sfx
├── generate-bg.sh # 调 GPT Image 2 生成抽象水彩 bg.png
├── tts.py # Volcano TTS narration 生成
├── synth-sfx.sh # tick/chime/bell 合成 (ffmpeg)
├── retrofit-bg-image.py # 给已有视频补 bg-image 层
├── strip-dark-scene-bgs.py # 剥离 scene-level 暗色 bg,让 bg-image 透出
└── publish-to-youtube.py # 自动上传 MP4 到 YouTube(portrait→Shorts),可替换已有上传
| 不要 | 原因 |
|------|------|
| 所有 scene 都用 B1 双行 strikethrough | 历史最大失败模式。B1 整片最多 2 次 |
| 所有 scene 居中布局 | 死气沉沉。≥2 非居中 |
| 所有 scene 字号差不多 | 跨度必须 ≥240px |
| 所有 scene 时长 5-7s | 跨度必须 ≥6s |
| 整片只用 blur crossfade | 每 4 个转场 ≥2 种 |
| 整片没有 color-flip | ≥1 个 A3 是硬要求 |
| 整片没有几何元素 | ≥1 个 scene 加粗线 / 大编号 / 引号 |
| 整片只用 tl.from({y, opacity}) | ≥3 种 Modern Motion Techniques |
| 每个 scene 都堆满 | ≥1 个 scene 留白 ≥60% |
| 给每个 scene 都加 background: 色 | 盖住 bg-image,等于白生成水彩。普通 scene 不写 bg;只有 A3 color-flip 用纯色 |
| color-flip / emphasis 永远只用橙 | 至少 2-3 种 accent |
| 用灰色作 secondary text / strike / 装饰 | 水彩底上灰色对比度太低,会消失。改用 #f5efe5 cream + opacity 弱化(详见 [[no-low-contrast-text]])|
| 不要 | 原因 |
|------|------|
| 用 Kokoro 做中文 TTS | 中文质量差,用户明确不接受 |
| Volcano TTS 传 emotion 参数 | _bigtts 声音返回 data: null 静默失败 |
| 用 zh_male_jieshuonansheng_mars_bigtts | 含英文专名时循环 hallucinate |
| 用 serif 字体(Songti / 宋体 / Noto Serif) | 不够冲击 |
| 把整段文章贴屏 | 那是 PPT。视频每屏一个视觉时刻 |
| 超过 10 scene / 超过 90 秒 | 注意力放不下 |
| 短文硬填到 90 秒 | 文章短就做 30-50s,硬撑长会注水变浅 |
| 每个 scene 换字体配色风格 | 风格漂移。design system 固定,模板变化 |
| ::after 伪元素 + CSS 变量做 strike | hyperframes 渲染路径下失效。用真实 DOM <span class="strike-line"> |
| 最后 scene 之外用 gsap.to({opacity: 0}) | 退场动画 hyperframes 禁止 — 转场才是退场 |
| 每段 chunk 都加 chime | 太吵 |
| 用 ../illustration.png 作 bg url | hyperframes render 不解析跨目录路径,渲染成纯黑。bg.png 必须在 video/ 内 |
| <audio> 没 id | render 会 silent。每个 <audio> 必须 id="..." |
| s1 是 A3 color-flip | 第一帧看不到 bg-image。color-flip 放 s2+ |
| s1 标题元素都 from({opacity: 0}) | 第一帧黑屏。s1 主元素 opacity: 1 默认,只动 y/scale |
tts_narration.py 按 chunk id 缓存单段 mp3,改文案但 id 没变会复用旧音频(症状:timing.json 时长和上一版一模一样,明明文字变长了)。重合成前先 rm -rf narration/ narration.mp3 timing.json 再跑.scene 是否有 opacity: 0 默认(除了 s1).em 在 .reveal-wrap 里少量溢出(top/bottom 几 px) → 给 .em 加 line-height: 1npx hyperframes) — composition lint / inspect / snapshot / render~/.claude/skills/gpt-image-2-skill/) — 生成 bg.png;--provider codex 用 ChatGPT authVOLC_TTS_APPID / VOLC_TTS_ACCESS_TOKEN 在 ~/code/.env~/.claude/skills/wjs-uploading-video/) + OAuth token at ~/.config/youtube/token.json —— Step 9 自动发布Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Improves the quality of images, especially screenshots, by enhancing resolution, sharpness, and clarity. Perfect for preparing images for presentations, documentation, or social media posts.
Downloads videos from YouTube and other platforms for offline viewing, editing, or archival. Handles various formats and quality options.
Lightweight WSI tile extraction and preprocessing. Use for basic slide processing tissue detection, tile extraction, stain normalization for H&E images. Best for simple pipelines, dataset preparation, quick tile-based analysis. For advanced spatial proteomics, multiplexed imaging, or deep learning pipelines use pathml.
Microscopy data management platform. Access images via Python, retrieve datasets, analyze pixels, manage ROIs/annotations, batch processing, for high-content screening and microscopy workflows.
Python library for working with DICOM (Digital Imaging and Communications in Medicine) files. Use this skill when reading, writing, or modifying medical imaging data in DICOM format, extracting pixel data from medical images (CT, MRI, X-ray, ultrasound), anonymizing DICOM files, working with DICOM metadata and tags, converting DICOM images to other formats, handling compressed DICOM data, or processing medical imaging datasets. Applies to tasks involving medical image analysis, PACS systems, radiology workflows, and healthcare imaging applications.
This skill should be used when working with pre-trained transformer models for natural language processing, computer vision, audio, or multimodal tasks. Use for text generation, classification, question answering, translation, summarization, image classification, object detection, speech recognition, and fine-tuning models on custom datasets.
Take jianshuo/wjs-converting-text-to-video from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference npx.
Without those the skill loads but fails at the first command.