About ray-explainer
Ray Explainer is a skill for turning source material into narrated explainer videos, aimed at Ray’s short-form video production. It coordinates scripting, storyboarding, voice work, visuals, rendering, and delivery, with deterministic frame rendering and review checkpoints.
Key features
- 01Script and storyboard creation
- 02Voice generation and transcription checks
- 03Real-footage-first visual planning
- 04Deterministic frame-based rendering
- 05Still-frame and audio quality checks
- 06Video and publishing-package export
Use cases
- 01Producing a short explainer from an article
- 02Planning scenes around real footage
- 03Reviewing narration timing and pronunciation
- 04Rendering and packaging a finished video
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ imraywang/ rayskills --skill ray-explainerAfter installing, type/ray-explainerin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
agents/openai.yamlassets/canvas.jsonassets/hf-template/build.pyhost_build.pymake_beats.pystyle.example.cssWORKER.mdassets/hf-template/figures/designer.svgengineer.svghand.svgREADME.mdassets/huashu/clip.htmlclip.jsassets/huashu/clips/t1_3b1b.jst2_keynote_ui.jst3_finance_chart.jsy1_kurzgesagt.jsy2_vox.jsy3_whiteboard.jsy4_storytime.jsy5_kinetic_type.jsassets/huashu/lib/camera.jschart.jscollage.jsdiagram.jsfonts.jskit.jsmedia.jsmotion.jsassets/huashu/lib/fonts/LICENSES.mdDetails
From the project READMERay Explainer
把一篇文章压成一条“开头吸引人、看完有收获”的解说片。Claude 同时当导演和程序员:写稿、分镜、给每一幕选画法、写每一帧的绘制代码、看截图返工;浏览器和 FFmpeg 只负责把代码变成像素和文件。
核心约束:每一帧只由时间 t 决定。不读当前时间,不用 Math.random(用 rng(seed)),渲染时不联网。守住这三条,同一份代码每次都渲染出完全一样的视频,改一处只影响一处。
链路
素材 ─▶ ① 解说稿 script.json ─▶ ①b 分镜表 storyboard.py【Ray 确认】
─▶ ② 配音 tts.py(默认 Ray 复刻音色;没注册时用 Gemini 预置音色)
─▶ ③ Whisper 校对 qa_tts.py(合格判定 + 逐字时间写入 timeline)
─▶ ③c 原声插入 splice_clips.py【有原声时】
─▶ ③b 数字人主持人 host.py(左下角口型默认带;大机位用户确认后才做)
─▶ ④ 分镜:kit 场景写 scenes.js;语法场景只写 cues
─▶ ⑤ 静帧检查 render.js sheet ─▶ ⑥ 出片 render.js video + 听感检查 audio_check.py ─▶ ⑧ 发布包 publish.py
专属风格模式(HyperFrames,近几期的主要做法):要适合这期内容的风格、要有录屏 / 真实画面 / 截图时(按下面「真实画面优先」,多数科普片都是这样),②③ 照旧,④⑤⑥ 换成 HyperFrames 合成,流程、骨架、取材要点和安全区见 hyperframes.md。这个模式自带:按章节分段的进度条顶栏、原声插入(splice_clips.py)、本地生成配乐(gen_bgm.py / mix_bgm.py)、用锚点定位的少量音效。会动的网页(交互图解、WebGL 演示)用 scripts/record_clip.mjs 按虚拟时钟录成确定的片段。
真实画面优先(Ray 2026-10-15):观众愿意看的是真实的东西,手绘、代码动画看久了审美疲劳。每一幕先找真实素材,动态的优先于静态的:录屏、本机实跑、产品官方演示片段、新闻 / 发布会画面、别人视频里被讨论到的那一段、Ray 自己的视频和后台数据;其次才是真实截图、原文、照片。代码动画只做两件事:把真实素材串起来(转场、标注、计数、对比),以及真实画面拍不到的抽象机制。别人的作品可以作为引用进成片,画面上标「来源 · 日期」。分镜关每幕写 footage(用什么真实素材、从哪来、是不是动态),storyboard.py 会列出来,整片动态真实素材太少会提醒。真实视频默认全屏(Ray 2026-10-15,《Roadster 真能飞》复盘:素材装在小机位窗口里冲击力不够):科普 / 解说片里的真实视频素材默认用 .fullshot 铺满整个画面播放——竖屏原片直接铺满,横屏素材裁成竖屏、跟着主体走(object-position);不装进机位窗口。窗口只留给截图、原帖、静态图和需要并排对比的场合。提问句之后可以用 splice_clips.py 插一段带原声的全屏插片,播完切回画板。分镜关每条 footage 写 fullscreen: true/false。主体是整台设备或宽画面时整幅横放(Ray 2026-10-16,宝可梦那期:双手横握 iPhone 的横屏素材被裁成竖屏,手机被切掉,返工):footage 写 "framing": "band",横屏原片按原比例横贯舞台中部,上下用同一段视频虚化压暗垫底(.bandshot);storyboard.py 见到手机、掌机、超宽屏一类素材没写 framing 会提醒。
两道确认关口:稿子关(只看旁白)和分镜关(看每幕画什么、用什么画法)。两关都在配音和写画面之前,这时改动不花钱,过了这两关再开始做,可以避免返工。用户说“直接做”时两关都跳过;说“稿子我看过了”时只过分镜关。
画幅:默认竖屏 1080×1920(抖音、视频号)。Ray 要横屏时(YouTube、视频号 / 抖音横屏)才出 1920×1080:new_project.sh <slug> --landscape,即 script.json 顶层 "aspect": "landscape"。一个项目只出一种画幅,不同时出两版。横屏只能用语法片段或 HyperFrames 模式(手绘套路是竖屏坐标,render.js 会拒绝);没有进度条,字幕白字黑描边,主持人是只在关键句出现的小圆窗、按幕在左下 / 右下之间换(host.md「横屏」)。尺寸、安全区、字幕和主持人版位都在 assets/canvas.json,各脚本从那里读。
脚本都在本 skill 的 scripts/ 下,下文用 $SK 指代本 skill 目录。
0. 环境自检
$SK/scripts/check_setup.sh
必须看到 READY。缺 GEMINI_API_KEY 就向用户要 key,不要换别的服务凑合。输出里会列出已注册的复刻音色。
1. 读素材,写解说稿
读完整素材(剪藏、候选选题卡、已有口播稿都算)。库里有 Ray 的已录口播稿时,先读一篇找语感。
$SK/scripts/new_project.sh <英文-slug> # 默认建在 ~/Movies/ray-explainer/YYYY-MM-DD-<slug>/;横屏加 --landscape
视频文件不要放进 Obsidian vault:vault 带 git 自动快照,大文件会进历史。
按 script-rules.md 写 script.json:按场景分组,每场景 1–4 句,每句是一次配音调用,也是一个画面节拍。顶层写 title、central_judgment、header(顶部小标题)、theme(全片色板,见 grammars.md「全片色板」;新项目默认 "ray-ip",即 Ray 的 IP 规范,见 ip-style.md:开场和结尾那一幕写 "sig": true)、voice、to_confirm。
1b. 分镜关
稿子定了以后,先按 grammars.md 给这一期定一种画法(一期只用一种),再从 style-refs.md 挑一张参考卡定风格(Ray 指定了就用他的;他丢来新链接就按那里的方法抽帧建卡),script.json 顶层写 "style_ref",再给每一幕补三个字段,并用这种画法写好 grammar 或 pattern(都不写表示手写 kit):
beat:这一幕讲什么,一句话visual:画面按出现顺序依次是什么,用大白话写anchors:哪个词触发哪个画面事件
题材本身是一个大众 IP 时,第一版分镜就给主题外壳(Ray 2026-10-16,宝可梦那期:看完分镜才要求「宝可梦元素多一点」,多走一轮):童年游戏、动漫、电影、知名产品这类题材,在 script.json 顶层写 "design": {"shell": …, "audio": …, "boundary": …},把外壳一起贴给 Ray:
- 外壳:用这个 IP 的界面语言改造全片骨架——顶栏进度条、章节标记、标签和问句的框、换章转场(宝可梦那期:经验条、道馆徽章、DS 对话框、遭遇闪屏),每幕再挑 1–2 处和原理有关的梗(选御三家 = 多种写法只有一个对、队伍界面 = 多个 Agent 并行)。
- 声音:本地生成该 IP 年代感的配乐(8-bit、胶片管弦…),音效自己合成同类短音,不用原曲原音效。
- 边界:外壳全部是仿制 UI,颜色守 IP 色板(黑白灰 + 墨绿,原作的红蓝换成墨绿 / 灰);不画 IP 角色本体、不用游戏 / 官方图片做 UI,角色只出现在作为引用的真实画面里。
python3 $SK/scripts/storyboard.py <project> # 打印分镜表并写入 storyboard.md
把表格原样贴给用户,等确认。用户关心三件事:每一幕画什么、画法对不对、要不要合并、拆分或删掉某一幕。预计时长按每秒约 5.8 字估算,误差在几秒以内。确认后才进入配音;分镜阶段改了旁白,先把 lines 改掉,再往下走。
左下角主持人是 IP 的一部分,大机位默认不加。 新项目模板带 "host": {"avatar": "ray", "big": []}:Ray 的形象全片缩在左下角,嘴型跟着配音换,不调视频模型、不花钱,第 3 步之后跑一次 host.py 生成口型即可。大机位(MiniMax H3 生成的手势视频,要花钱)仍然默认不加:贴分镜表时附一句「这条要不要加大机位」,用户明确要加才按 host.md 标句子、先给估价、同意后再生成。
2. 配音
python3 -I $SK/scripts/tts.py <project>
配音前先查念法:tts.py 开头会跑 scripts/lint_readings.py(离线、不花钱),把容易念错的写法列出来并停下:字母数字混写(a16z、M3、GPT-4o)、三位以上数字、小数、百分号、~ × / 这类符号。改法是正文写读法、顶层 display 映射回屏幕写法("A 十六 Z": "a16z"、"百分之二十三": "23%");确认没问题的加 --allow-readings。稿子阶段可以单独跑 python3 $SK/scripts/lint_readings.py <project>。2026-10-15 那期 a16z 和 23% 都是配完才发现,各重配了一次。
多音字:同一步还会拦「数字后面当量词用的多音字」(几十万行 → 行读 háng,MiniMax 念成了 xíng rén,2026-10-16 是 Ray 看片才发现的):换同音字写进正文(行 → 航),display 映射回原字。其余读音和常用音不同的多音字(重制版、长跑、一行代码)只列 POLY 提示、不拦;配完音 check_numbers.py 把它们切成 poly_listen.wav,交付时附上,请 Ray 听几秒。这类不交给 Gemini 听:它按语义纠正,把念错的 xíng 听成了 háng。
旁白整体响度统一到 −21 LUFS(Ray 认可的云端版水平,原声片段切在 −17),换哪个音色都一样,不用再手动调;要改就写 script.json 的 "loudness"。
选音色(script.json 的 "voice"):
voices.json里注册过的名字,比如"ray":Ray 的复刻音色,直接调 MiniMax API 的speech-2.8-hd(scripts/minimax_api.py,需要MINIMAX_API_KEY;国内平台 platform.minimax.cn 的 key 另设MINIMAX_API_HOST=https://api.minimax.cn;国内账号默认档每分钟请求数低,偶尔 1002 限流,tts.py 会自动退避重试),每千字约 0.1 美元。model以fal-ai/开头的旧条目是经 fal 复刻的音色,只能继续走 fal。新项目模板默认就是它,语速1.1(Ray 2026-10-13 定的)。"ray-local":本地复刻音色,走 VoxCPM2(mlx-community/VoxCPM2-8bit,MLX 8bit;2026-10-14 两轮盲听,12 句里赢了 MiniMax 9 句),不花钱,样本也不出本机。voices.json条目写"provider": "voxcpm2",记录模型目录(模型约 3 GB,可以放外置盘,如/Volumes/<盘名>/ai-models/VoxCPM2-8bit;盘没挂上会直接报错)、参考片段、cfg3.0、takes3。每句合成 3 遍,由 Whisper 挑最贴稿的一遍(VoxCPM2 每次输出不同,常见问题是英文词念坏、句首吞字)。它不能直接调语速,靠后期变速;native_speed1.1 表示原速就相当于 MiniMax 的 1.1,所以模板的speed1.1 不会再加速。速度约 1.3 倍实时,一期 3 分钟要合 10 分钟上下。运行环境在~/.local/share/ray-explainer/voxcpm-env(uv venv -p 3.12,装mlx-audio==0.5.9 soundfile mlx-whisper)。- 其他值都当作 Gemini 预置音色:Charon(男、利落,没注册复刻音色时的首选)、Puck(男、活泼)、Kore(女)。
"speed":语速,模板默认 1.1。MiniMax 支持 0.5–2;Gemini 只能用 1.0。改语速就是全部重配:专属风格模式里重跑 tts → qa_tts → splice_clips → host.py --plan-only → make_beats → build,画面和锚点音效自动跟上。
用 Ray 自己录的口播当配音(他先录一遍、自己剪掉气口,Claude 按句对上画面):script.json 写 "recording": {"src": "<视频或音频>", "continuous": true, "takes": {"<幕>.<句>": [[起, 止]]}}。先用 Whisper(mlx_whisper 带词级时间)转写整条,按句定起止,lines 改成他实际说的话(只修听错的字),整条连续切开、首尾相接,不加停顿、不裁边;没剪过的原始录音可去掉 continuous,每句可拼几段(接口 20 ms 淡入淡出)。之后照常 qa_tts → host.py --plan-only → make_beats → build。出镜:从同一个源按句切竖屏片段,裁肩部以上的方块,在画面左下 / 右下空着的句子里放圆形小窗。
还没有复刻音色时:请用户提供 1–3 分钟干净的口播录音(手机录音或已发视频的原片都行),然后:
python3 $SK/scripts/clone_voice.py <录音> --name ray # 只在本地处理:抽人声、降噪、统一响度,先听一下
python3 $SK/scripts/clone_voice.py <录音> --name ray --upload # 用户在对话里同意后再上传
声音属于个人生物特征数据,--upload 之前必须在对话里得到用户明确同意。复刻是一次性费用(以 MiniMax 价目为准),注册信息写到 ~/.config/ray-explainer/voices.json,不放进任何仓库。脚本复刻完会立刻合成一句试听:MiniMax 会删除 7 天内没被使用过的复刻音色,这一步就是为了保住它。
通用规则:
- 只送正文。Gemini TTS 会把“用自信的语气说:”这类指令原样念出来,中文、英文都一样。
- 按服务、模型、音色、语速、文本做缓存,改一句只重做那一句;换音色就是全部重做。
- 标了
SLOW的句子语速异常,多半是念进了多余内容。Gemini 遇到 429 会自动退避,整片要等几分钟,不要加并发。
3. Whisper 校对 + 逐字时间
python3 $SK/scripts/qa_tts.py <project>
每句转写两遍:普通转写用来比对稿子,判定合不合格;带词级时间戳的那遍只用来对齐时间。后一遍会在句尾静音处产生幻觉,冒出"染染染""请点赞订阅"这类内容,所以不能拿来判定合格。不合格的片段会被改名为 .bad,重跑 tts.py 就会重新合成。必须 bad: 0 才能往下走。
稿子里有年份、编号时(按 script-rules.md 写成汉字逐位并配 display),再跑一遍:
python3 $SK/scripts/check_numbers.py <project> # Gemini 按实际读音听写含数字的句子,几美分;多音字切成 poly_listen.wav 给人听
看到“两千零一十九”这类数值读法就改稿重配那一句。对齐结果写成每句的 chars,也就是每个字开口的绝对时间;kit 的 at()、语法 cue 和字幕切换都会用到。
3b. 左下角主持人(IP 默认带)与大机位(可选,用户确认后才做)
python3 $SK/scripts/host.py <project> # big 为空:只生成左下角口型,不花钱,直接跑
python3 $SK/scripts/host.py <project> --dry-run # big 里写了大机位句子时:先列段落和预计费用,贴给用户等同意
python3 $SK/scripts/host.py <project> # 用户同意后:H3 生成大机位 + 角落口型,写 host/plan.json
大机位(开头、金句、结尾,每集约 30 秒)默认用 MiniMax H3 生成带手势、嘴在动的视频(不逐字对口型),约 $0.08/秒;要逐字对口型时 "model": "pro" 换 Kling,约 $0.115/秒;其余时间主持人缩在左下角,用同一形象的换嘴型图层,不花钱。形象、选句原则、画面避让见 host.md。没有 host 字段的片子不受任何影响。
大机位默认不加。 big 为空时 host.py 只算角落口型、不花钱,直接跑;只有用户明确要大机位(或被问到时确认要加),才往 big 里写句子、--dry-run 估价、同意后再生成。
4. 分镜:先定这一期的画法,再写每一幕
按 grammars.md 的选型表,按这期整体讲什么挑一种画法,每一幕都用它:
- 语法场景:在
script.json的这一幕里写"grammar"和"cues",不用写代码。cue 的时间写成{"line": 1, "phrase": "创造新行为"},就能精确卡到这个词开口的时刻。 - 手绘套路场景(kit 模式里优先于手写场景;整片仍先按「真实画面优先」找素材):在这一幕写
"pattern"、"data"、"cues",不用写代码。可用的套路有排行榜、金句、N 宫格与排除法、故事到规律、漏斗、路径、因果互换、清单,见 patterns.md。全套路范例:assets/template/script.patterns.example.json。 - 手写场景(最后才用):套路覆盖不到的独特画面,在
scenes.js里写S.<sceneId> = (t, sc) => {...};同名函数也可以叠画在套路上面补小元素。API 见 kit-api.md,范例是assets/template/scenes.example.js。一个画面如果以后还会再用,就把它做成新套路加进patterns.js。不要为了某一条片子去改 kit.js 或已有的套路。 - 一期只用一种画法:手绘套路、某一种语法、或整期 HyperFrames,三选一,开场和结尾也用它(开场结尾的记号靠签名幕给)。混用时
storyboard.py和render.js会提醒,确实要混写"mix": true并说明理由。 - 横屏(
"aspect": "landscape",Ray 2026-10-14 定):画面基本不被遮挡,四周留 5%。不放进度条和小标题;字幕白字黑描边、无底框,居中压底(y 946–1036);主持人是左下角直径 164 的小圆窗(卡片色底 + 墨绿细圈),只在关键句出现:host.show标 3–6 句(写法同big,不花钱),其余时间不在画面上;主画面偏左的那一幕写"host_side": "right"换到右下(学小Lin说)。贴分镜表时附上选的关键句。语法片段自动让出上 60、下 150(有主持人时下 230)。深色版用"theme": "ray-ip-dark"(深灰 + 墨绿,AI、科技题材优先考虑)。 - 竖屏安全区:按 1080×1920 出片,所有信息只放在 y 200–1680(上方 200 会被灵动岛和状态栏挡住,下方 240 被平台的作者名、文案、互动栏盖住),这两条带里只放底纹。进度条和小标题在 y 200–290。默认带角落主持人:字幕条上移到 y≈1470(
host.py的caption_y),主持人从 1560 往下,主画面只放 y 300–1440,语法片段会自动让开;去掉host的片子字幕条回到 y 1560–1656,主舞台可用到 y 1520。
5. 静帧检查(必做,不能跳过)
node $SK/scripts/render.js <project> sheet 18 # 均匀抽 18 帧拼成 contact.jpg
node $SK/scripts/render.js <project> stills 7,36.3,95 # 指定时刻(全片时间)
用 Read 看 contact.jpg,逐项检查:
- 有没有元素重叠、超出画布、压住字幕
- 有没有空镜:说话的时候画面却是空的
- 图标、表情、颜色是否符合原意(例如笑脸画成了皱眉、灯泡被填成黑色)
- 每一幕是否都有东西在动、在出现
- 开头 3 秒内画面是否已经抓人
- 语法场景的 cue 是否在对应的话说出来时出现。对不上就调
phrase或offset
内置浏览器面板不执行本地 HTML 里的脚本,预览只能靠 render.js。语法场景启动失败时,渲染会直接报错退出,错误信息里写着是哪一幕、哪个 cue。
6. 出片
node $SK/scripts/render.js <project> video 30
2.5 分钟的片子约 1 分钟渲染完(HyperFrames 模式约 1:1 实时)。出片后用 ffmpeg -ss <t> -i out.mp4 -frames:v 1 从成片里抽 3–5 帧复查,再跑听感检查,然后用 SendUserFile 交付:
python3 $SK/scripts/audio_check.py <project> [out.mp4]
它量人声和句间配乐的音量差(低于 −32 dB 等于听不见,高于 −8 dB 抢人声)、每段原声下面的配乐、音效个数(超过 15 个提醒)。只看截图验收会漏掉声音的问题:配乐听不见、音效太密,Ray 看片时一耳朵就听出来。
运动量检查(自动,只报告不拦片):video 渲完会自动跑 scripts/film_gate.py(来自 huashu-art-motion),结果写进 <project>/gate.json,终端打两行 gate:。对已有成片单独跑:node $SK/scripts/render.js <project> gate [文件名.mp4](不要直接 python3 film_gate.py:本机 python 没装 cv2,render.js 用 uv run 带着依赖跑)。三项门禁:
- 快动帧占比:镜头内画面在动的帧占多少,阈值是花叔按他自己的片子标的(认可最低 0.068,红线 0.035)。对 Ray 的片子参考价值不高(Ray 2026-10-16:我们以真实动态视频为主,画面元素没动但视频本身在动),只在交付说明里报一行数字,红灯也不要求回看「最差 30 秒」、不为它补镜头。
- 中段空画面:连续 0.3 秒以上几乎没有任何边缘的帧。红灯就是真问题,去看报出的时间码。纸纹桌面这类有纹理的空镜它查不出,第 5 步静帧检查要自己看。
- 蓝紫占比:蓝紫底画面占全片的比例。黄、红灯说明用了深紫星空一类的底,换底色。
SendUserFile 发到手机 / 网页端的上限是 30 MB,超过只在本机桌面端可见。成片超过 30 MB 时同时压一份手机版一起交付,码率按时长算,保证不超过 28 MB(固定 900k 时 4 分钟的片子压出过 30.4 MB):
python3 $SK/scripts/phone_export.py <project> # → out_phone.mp4
7. 交付说明
回复里给出:
- 时长、画幅、音色
- 内容结构:开头怎么钩住人、主体讲了哪几步、结尾的收获是什么
- 每一幕用的画法
- 待确认:编补的说法、夸张的说法、事实存疑之处、Whisper 相似度在 0.8–0.9 之间的句子(附时间点)
- 运动量:
gate.json一行数字即可;只有「中段空画面」红灯要处理(那是真空镜) - 费用:
python3 $SK/scripts/cost.py <project>给出配音和数字人大机位的部分;Claude 的 token 从会话记录汇总 - 能改什么:音色、单句、单幕、换一幕的画法。改稿只需重跑 2→3→5→6;只改画面只需重跑 5→6
不自动发布到任何平台。
8. 发布包
用户认可成片后,在 script.json 里写 cover_t(封面取第几秒那一帧)和 publish(titles 标题备选、description 描述、tags 标签,写法遵循 Ray 的写作规则:直接、口语化),然后:
python3 $SK/scripts/publish.py <project> --vault <知识库根目录>
- 生成
cover.jpg:这一帧不带字幕和进度条 - 生成
publish.md:标题、描述、标签,可以直接复制粘贴 - 在 vault 的
10-创作/25-口播草稿/<日期>-<标题>.md写一篇笔记:frontmatter 记录视频路径、时长、音色、画法、待确认条数;正文是分镜表、逐字稿和发布文案。视频本身不复制进 vault - 视频来自一篇已有的口播母稿(ray-kb 快速口播等)时,在
script.json写"draft": "<母稿在 vault 里的相对路径>":脚本不新建笔记,只给母稿加video_*字段和「发布文案」一节(重跑会替换,不会叠两份),避免和母稿同名撞文件 - 成片不叫
out.mp4时,在publish里写"video": "<文件名>";HyperFrames 项目(有hf/build.py)的封面用 COVER 版单独渲一帧,见 hyperframes.md - 用户手动改过这篇笔记的话,脚本会拒绝覆盖;确认要替换才加
--force - 交付时提醒:平台的「AI 生成内容」声明要勾(复刻音色、数字人),CC 授权图片要在简介署名
- 封面交给
ray-cover的视频封面流程(Ray 真人照片 + 大标题,黑白灰 + 墨绿 IP):- 竖屏片默认只出 3:4(
xhs,风格默认小Lin风A),拷成项目根的cover_3x4.png;9:16 只在 Ray 明确要时出。 - 横屏片出
landscape(16:9,1920×1080,另出一份 jpg 给 YouTube)。 cover.jpg(成片里的一帧)只作备用。
- 竖屏片默认只出 3:4(
边界
- 写实画面、人脸、动物近景:代码画不好。需要时建议实拍,或转视频模型。卡通数字人主持人是例外,见 host.md。
- kit 的手写体依赖 macOS 自带的 Hannotate SC;语法片段和字幕用的是随 skill 带的思源黑体和霞鹜文楷,换机器也不会变样。
- kit / 语法模式没接背景音乐和音效,要加的话用 FFmpeg 在合成时混入,音效时刻从 timeline.json 里取;专属风格模式(HyperFrames)自带配乐、给人声让路和逐幕音效。
assets/huashu/来自 huashu-art-motion(MIT),只带了解说部分,并做了竖屏改动(横屏走上游原版版式)。来源、范围和改动清单见assets/huashu/NOTICE.md。