关于 html-reel
html-reel 是将帖子、网页或视频等现有素材制作成配音短片的 Skill。它把 HTML 场景与口播词语时间点同步,并可按创作者的实际录制节奏重新调整场景。
主要功能
- 01提取来源事实与视觉风格
- 02编写脚本并规划分镜
- 03渲染按词语定时的 HTML 场景
- 04按录制语音重新定时
- 05预览场景、字幕与音频
- 06通过 Fil 组装并导出
适用场景
- 01将帖子改编为配音短片
- 02把着陆页制作成视频
- 03用录制素材替换镜头占位图
MCP 相关
该 Skill 通过 MCP 使用 Fil 视频编辑器,组装场景、叠加画面、语音、字幕和章节。README 还说明 Fil 可逐帧播放 HTML 场景。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mengto/ skills --skill html-reel安装后在 Claude Code 中输入/html-reel确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamldemo/PROMPT.mdindex.htmlreferences/retime.mdjudging.mdformula.mdsource.mdstructures.mdfil-editor.mdscripts/bubble.mjschoreo-example.mjsflash-crop.mjsfil-words.pynamed-times.pyjoin-takes.pydecursor.pyframe-video.mjsreel-clock.cssrecord-window.mjsreel-clock.jsrender-frames.mjssplit-flip.mjstighten-voice.pytimemap.pyread-source.mjspreview-reel.mjsverify-export.mjsvo-words.py详细介绍
HTML Reel
HTML 场景 · DreamCut · Fil 的 MCP 视频编辑器 · ffmpeg。 一个无需框架的场景引擎,位于 scripts/reel-clock.js。
Reel 是配上图片剪辑的声音。本技能从已有素材制作 Reel,例如推文、落地页、YouTube 视频或视频文件,因此 Reel 讲述的内容与素材一致,外观也与之相符:素材中的文字变成脚本,媒体素材变成画面,字体和颜色变成标题。每个画面都紧扣文字:标题在对应词语出现时落下,演示画面在提到它的那句台词处切换,音效在揭晓时响起。创作者从初稿起就置身其中:背光剪影站在他们拍摄的位置,因此他们还没录下一个字,Reel 就已经完整;他们录制的片段会替换剪影。由于场景是由同一个时钟驱动的 HTML,所有内容都会根据他们真实的表达节奏重新定时,无需重新制作任何动画。
适用范围。 网页上的实时应用窗口(不生成视频文件)请使用 html-demo。单独制作精致的屏幕录制,请使用 browser-video-recording。要将网页制作成固定时长、没有旁白的动态作品,请使用 website-to-motion-design。当交付内容是根据素材剪辑、配有人声的竖屏视频时,请使用本技能。
来源。 提取自 Meng To 于 2026 年 10 月制作的 HTML Demo 上线 Reel(fil.design/skills/html-demo):研究了一支 24.7 秒参考 Reel 中的八种布局;用他克隆的 ElevenLabs 声音录制了一段临时旁白;用 DreamCut 录制了四段技能页面素材;逐帧渲染了 HTML 开场和结尾;在 Fil 的视频编辑器中制作了三版草稿;每轮由两位盲评者评审;最后将他用手机录制的两段素材,按他本人的词语时间点剪辑成一支 33.7 秒的 Reel。之后,他又录制了一段横屏素材,剪去停顿,并用同样的方法重新定时,成片为 37.5 秒。随后将此方法推广:把他的三篇帖子(MiniMax 落地页、逆向工程智能家居、Anatomy 技能)分别按各自风格制作成 Reel,先不露脸,再使用镜头布局中的占位形象重做(先是他的墨水画肖像,随后是工作室里的背光剪影),并加入电影感字体和字幕,在 Fil 中处理之前先在本地预览。以下文件和数据均来自这些制作过程。
原理
所有内容都按词语时间点放置,所有绘制内容都是 t 的纯函数。 每个 HTML 场景都通过 window.__frame(t),根据场景内的时间 t(秒)设置每个元素;场景在固定的 540 × 960 舞台上以 2× 渲染(1080 × 1920)。渲染器每帧调用一次并截图;没有任何内容会读取时钟。因此,真实录制素材到位后,词语锚点就能建立从真实时间 τ 到临时旁白时间 t 的分段线性映射,场景再以 t = W(τ) 重新渲染:同一段动画适配新的表达节奏,不会产生抖动。
如果没有这一机制,Reel 就无法跟随录制者。使用 CSS 时间轴、GSAP 时间轴或计时器制作的动画场景会按自身节奏播放;要适配新的录制素材,就必须逐行手动重新制作动画,每次剪辑点都会偏移几帧。屏幕录制也无法重新定时,因此只能按录制内容中的事件剪辑,并单独调整每个片段的播放速度。
// hook.js, on reel-clock.js: times are the scratch voice's words.
const T = { look: 0.27, recording: 1.1, zoom: 3.25, sharp: 4.54, html: 7.22 };
HTMLReel.scene({
dur: 8.6,
anchors: ANCHORS, // [[τ, t], …] once the real take exists
draw(t, $) {
$('#win').style.transform = `scale(${1 + 2.8 * ease(t, T.zoom, T.zoom + 1.2)})`;
$('#w-recording').style.transform = `translateY(${(1 - word(t, T.recording, 2.2)) * 135}%)`;
$('#tags').style.opacity = ease(t, T.html - 0.3, T.html);
},
});
scripts/render-frames.mjs 可将此类页面渲染成 MP4(并逐帧检查安全区域);Fil 的视频编辑器将同一页面作为 HTML 场景播放,逐帧推进时钟;浏览器则可通过 ?controls 实时播放。
工作流
- 阅读源内容(
scripts/read-source.mjs <tweet | page | YouTube | file> --out source --follow、references/source.md)。完成Source.md:逐字记录原文、短视频可以提及的事实、一个核心观点、钩子、作品归属和行动号召。根据测量结果和画面完成Look.md:形状、底色、墨色、强调色,以及三种作用的字体(铺垫、揭晓、标签)、背景、母题和动态效果。 - 选择结构、画面比例和布局(
references/structures.md):宣传片(参考短视频中研究得来的references/formula.md)、作品展示、“发现了这个”、讲解、前后对比;9:16、4:5、1:1 或 16:9;并为每个节拍选择布局,让创作者的脸随着行动号召逐渐增大(钩子里不出现、气泡式、占半屏、行动号召时占满画面)。只有创作者不会出镜时才制作无露脸版本。创作者喜欢的参考短视频只用于借鉴结构和节奏,不能借鉴其视觉风格。- 制作摄像头占位图:一张逆光影棚剪影照,使用创作者(或任意模特)的照片;仅从背后打光,背景为柔和发光的暖奶油色,面部处于阴影中、五官隐约可见;人物头肩朝向镜头,直立的 9:16 构图,鼻子位于画面中央,鼻尖距画面底部约 60%,标注 CAMERA · PLACEHOLDER(在 Fil 中,使用由 Nano Banana 编辑照片的图像节点)。所有摄像头布局都先放入这张占位图,直到有正式拍摄镜头替换;如果正式镜头的构图相同,就无需重新构图。
- 用创作者的口吻撰写脚本,依据
Source.md,每个节拍写一行:使用创作者自己的句子并加以缩短;只写Source.md列出的事实;明确标注他人姓名。按说话速度而不是阅读速度控制篇幅:克隆语音每秒约读 2.2–2.4 个词(包含句间停顿),真人出镜约每秒 2.6 个词,因此 30 秒大约能容纳 65–70 个词。按听感来写:数字和姓名写成实际读法(“five point oh”、“Rea”),大写只用于画面文字。每行标出布局、画面内容,以及每个动作落下时对应的词。 - 制作带有逐词时间戳的语音(
scripts/vo-words.py:ElevenLabswith-timestamps,使用创作者的克隆语音,密钥从环境中读取且绝不打印;脚本会保存完整回复,因此可以免费重新生成语音,并打印语速)。无露脸短视频使用最终语音;有正式拍摄镜头时先用临时语音。然后:- 开始制作前先核对语音内容:使用 Fil 的字幕,或本地 whisper,将语音逐词与脚本对照(尤其是姓名和数字);
- 如果超时一两秒:运行
scripts/tighten-voice.py,剪掉每段长停顿的中间部分,并同步移动词语时间戳,无需再花钱录一遍; - 为每个词命名(
scripts/named-times.py:T.zoom、T.skill2、T.htmlEnd),后续所有剪辑都使用这些名称。 任何超过 $1 的支出都要先询问。
- 按照源内容的视觉风格制作画面,所有场景都使用
scripts/reel-clock.js,并在其:root中设置Look.md的变量,再调用HTMLReel.scene({ shape }):- 先制作封面:在短视频开头的 0.2 秒内呈现钩子的最佳时刻(完整标题出现在最佳画面上),然后从那里继续播放钩子(在完整场景中使用
HTMLReel.scene({ cover: T.payoffEnd });在带标题图层的主体视频上使用scripts/frame-video.mjs --cover 3.6);标题必须位于网格预览所示的 3:4 裁切范围内; - 为屏幕录制画面去除光标,然后再裁切构图:3D 场景或画布的录制画面通常会显示 macOS 手形光标;
scripts/decursor.py会在片段实际播放的时间范围内识别它(抓取手势和张开手势,六种尺寸)(scan src.mp4 track.json --pieces pieces.json),并用前后画面对比的拼图检查识别结果(sheet),再将光标从src-clean.mp4中抹除(clean);之后frame-video都使用清理后的视频帧(--video src-clean.mp4);需要在 venv 中安装 OpenCV(references/source.md); - 让演示视频按词的时间戳完成裁切与构图:将片段(
from、to,以及片段结束前最后一个词)传入scripts/frame-video.mjs;在同一个主体中使用多个视频(帖子的视频和它引用的帖子的视频);可将完整画面卡片插入为一个片段;在视频上方绘制由 t 驱动的标题图层(scripts/render-frames.mjs --alpha);先将标题静帧叠在主体视频上检查(--test … --under body.mp4); - 钩子、标题卡或结尾使用由
scripts/render-frames.mjs渲染的完整场景;如果钩子要在自身画框中展示源视频,则把视频帧绘制成图片(只提取一次,帧率为 60 fps,在setup中解码,在draw中设置 t 对应的帧并等待加载),这样它就能像其他内容一样重新定时; - 使用 DreamCut 录制源内容中没有展示的产品(
scripts/record-window.mjs、scripts/flash-crop.mjs),并将指针移动时机对准词语。 所有需要阅读的内容都必须位于安全区域内(9:16 画面中,从 y 280 到 1640,画布高度为 1920)。
- 先制作封面:在短视频开头的 0.2 秒内呈现钩子的最佳时刻(完整标题出现在最佳画面上),然后从那里继续播放钩子(在完整场景中使用
- 在本地预览(
scripts/preview-reel.mjs plan.json):查看画面、每种摄像头布局中按编辑器自身set值放置的占位图、逐词呈现的电影风格字幕、语音和音效;响度为 −14 LUFS;同时生成联系表。此时检查文字叠加后的布局;在这里修改只需一分钟,导出却要等待一段时间。 - 通过 MCP 在 Fil 的视频编辑器中组装(
references/fil-editor.md):以画面作为主体叙事;在每种摄像头布局中,将占位图作为覆盖层置于画面上方(全屏、缩小后的气泡式、半屏),这样之后便可用正式镜头替换占位图,同时保留所有裁切、位置和关键帧;语音单独放在一条轨道上;音效音量设为 0.1–0.2;电影风格字幕放在剪辑接缝处或画面下方;全屏人像布局中,字幕放在下巴以下(使用字幕范围),绝不能遮住脸;将各节拍设为章节。导出、下载并检查画面帧。 - 通过盲评达到 8/10(
references/judging.md):安排两位只看画面帧和联系表的绝对评分员,取较低分;另安排一位评审对比修改前后的版本。根据两位评分员都指出的问题进行修改;连续两轮评分不变时停止。 - 创作者录制:将脚本放入画布文档,作为提词器(标题和
[directions]会显示,但不会被读出);在手机上添加 Record,并把二维码图片交给创作者。录制片段会出现在画布上,语音也会经过清理。用正式镜头逐一replace占位图,然后根据创作者实际说出的词重新调整所有时间(references/retime.md):- 合并录制片段(
scripts/join-takes.py):裁掉超过约 0.45 秒的停顿,添加 15 ms 淡入淡出,并在布局改变处拼接; - 从 Fil 的字幕获取词语时间(
look.max_words: 1,然后使用get_video的字幕list、scripts/fil-words.py); - 使用
scripts/timemap.py将临时录音和正式录音中的词语对齐为锚点,再根据锚点重新渲染场景、拆分视频片段并调整播放速度; - 添加摄像头画面:气泡式布局(在编辑器中使用
set.corner_radius,或运行scripts/bubble.mjs)和分屏布局(scripts/split-flip.mjs); - 根据正式语音重新生成字幕,添加章节,导出,并运行
scripts/verify-export.mjs。
- 合并录制片段(
规则及其防止的故障
- 只说来源中写明的内容。 每个数字、名称和主张都必须来自 Source.md 中的事实。为一篇真实帖子制作短视频,却编造结果,是作者最不能容忍的事,而观众也会核查。
- 从来源中获取视觉风格。 字体、颜色、图案和动效都来自 Look.md;时钟的默认样式(一种衬线字体、粗重的窄体重点字、一个橙色圆点)只是某一条短视频的风格。短视频风格不对,看起来就像在替别人打广告。
- 电影感排版,放大到足够醒目。 来源提供字体;短视频则赋予字体尺寸和节奏:在钩子、尾声和每张标题卡中,铺垫句在 540 画布上约为 52 px,重点词为 90–110 px、粗重,并通过遮罩落在对应的词上,最后落在强调色上;号召语中的关键词要尽可能大,直到刚好能放进画面(窄体短词约为 200 px,长词或较宽的字体则要小一些)。把标题挤在带框视频上方的一条窄带里,看起来就像幻灯片;大字才是让人停下滑动的关键。
- 字幕也要有电影感。 使用约 78 px 的粗黑体(Inter Tight 800,或 Fil 字体列表中的来源自带粗体),文字用墨色,正在说的词用强调色,添加 5 px 深色描边,逐词显示,每行最多 3 个词,放在分屏接缝处或画面下方。普通的小字幕会破坏排版效果。
- 第一帧就是封面。 Instagram 和 TikTok 的个人主页网格、短视频播放前的信息流,以及 Fil 的视频编辑节点,都会显示短视频的第一帧,除非设置了封面。因此,如果钩子从动画中途开始,开场就会是空白画面上一个只升起一半的词(前四版草稿都是如此:“This”“Reverse engin…”“One”)。应直接以封面开场:选用钩子的最佳瞬间,让完整标题落在最佳画面上,停留前 0.2 秒,然后再从头播放钩子。标题应放在 3:4 裁切范围内(1920 高度中的 y 280–1640),在 360 px 宽的画面上仍清晰可读,不要让字幕盖住标题(第一行字幕从 0.2 秒后开始),并将这一帧保存为 cover.jpg,供各平台上传封面。
- 草稿中要有创作者本人。 如果创作者脸部所在位置是空的,就无法评判短视频;在每种镜头布局中加入背光剪影,草稿才看起来像完成版,每段拍摄内容都用
replace插入。 - 在画面中注明他人的作品。 引用了帖子、链接到仓库或提到某人的技能时,应在观众能看到的位置注明对方的姓名和账号,也要在旁白中提及。如果把这些作品说成自己的,就会在评论区被指出。
- 演示就是画面;每 2–4 秒切换一次构图。 换一段内容、裁切细节、插入标题卡都可以。如果画面始终只有一个不变的方框,看起来就像带字幕的屏幕录制。快速念出清单(“灯、门、空调、机器人”)是个例外:每项对应一个片段,并在念到该词时出现,哪怕只停留很短时间。
- 在据此制作内容之前,先核对配音实际说了什么。 克隆语音会把“5.0”读成“five”,把名字读成另一个词,也会把首字母大写的词逐个字母读出来。对照脚本核对配音中的每个词(查看 Fil 的字幕或使用 whisper);如果等场景都按配音节奏定好后才修正词语,就得重新渲染。
- 留意来源本身的瑕疵。 演示视频可能会掩盖掉帧或页面切换时的闪烁。read-source 会列出场景切换点(
cuts),但不会标出镜头内部的短暂故障或扫描线(Anatomy 在 15.8 秒处以及 20.6 秒后都出现了);保留片段前,以 0.1 秒的间隔查看每段的首尾,并以 0.25 秒的间隔检查片段内容。 - 从帖子视频中去掉光标。 帖子屏幕录制中的光标,是盲评者最先指出的问题:在两条根据 Meng 的帖子制作的短视频草稿中(Opus 5.5 发布内容和山谷中的船只场景),四位评审都先指出了 macOS 手形光标,之后才注意到文字、布局或号召语。
scripts/decursor.py在 854 帧和 1,138 帧中找到了光标,并用其柔和阴影一并擦除。清理前先查看检测结果图。另一种带深色描边的白色光标(指向的手)要先从同一段录屏的一帧中裁出模板(template),绝不能使用 Apple 自带的光标文件。它无法找到箭头光标(黑色、白色描边)。 - 按词剪辑,绝不凭猜测。 第一版按阅读速度计时,每个节拍都早了或晚了;第二版按照试录配音的词语时间戳剪辑,所有节拍都准确对上了。用对应的词命名每个时间点(
T.zoom、T.html),让脚本读起来像旁白。 - 场景只根据 t 绘制。 画布上不得使用 CSS 动画、过渡、计时器或
Math.random:如果场景在其他地方计时,每次渲染的结果都会不同,也无法重新定时。reel-clock.css 会关闭#stage上的动画和过渡。 - 根据锚点调整时间,不要整体拉伸。 把整个场景拉伸到新的时长,会让每个节拍产生不同的偏差。词语锚点(8.6 秒钩子中有 24 个)将每个节拍固定在对应的词上,只有词与词之间的间隔会被拉伸。保持映射单调;如果创作者改写了某一行(“happens”“jumps”“demos”“fil”),就添加手动配对。
- 变速会改变时长。 一段 3.853 秒的屏幕录制,速度设为 1.471 后,在时间线上会持续 2.619 秒。根据事件(滚动、每次步骤跳转)拆分录屏,并调整每个片段的速度,让事件落在对应的词上;速度保持在 0.5 到 2.2 之间,否则动作看起来会像快进。
- 在布局变化处衔接不同拍摄段落。 在全屏人脸镜头中间直接跳切会很明显;如果切点藏在气泡缩小或分屏翻转的过程中,就不会明显。
- 字幕使用单条轨道,根据拉伸调整位置。 整条短视频中的字幕都位于分屏接缝处(
position: "middle"、offset: 0),因此要为每段全屏真人镜头单独设置字幕范围:{"op":"captions","ranges":[{"start":6.23,"end":7.33,"position":"bottom","offset":-380}]}会将一行 78 px 字幕的中心放在 y 1332,即比例为 1 的绘图中人物下巴下方(鼻子在 y 960);该镜头结束后,字幕会回到接缝处(Fil 0.433.0)。每条命令都会替换所有范围,因此要一次性发送全部范围,并在get_video中读回检查。保持人脸在原拍摄构图中的位置(scale: 1、y: 0),不要把人脸重新构图到接缝上方(scale 1.3,y −290);保留该镜头的字幕,不要移除。大字已经显示相同内容时(钩子、署名、号召语),应移除其下方重复的字幕行({"op":"caption","caption":…,"remove":true}):大字本身就是文字,而最终发布的短视频中,钩子下方没有字幕。 - 别让文字挡住人脸。 字幕应位于画面中部的分屏接缝处(y ≈ 960),或全屏真人镜头中人物下巴下方(底部范围,offset −380:y ≈ 1332),绝不能挡住人脸或窗口控件;钩子和尾声的标题应限制在 y 280–1640 之间,避免被应用按钮或 3:4 裁切切掉。
- 号召越强,人物画面越大。 钩子中不出现人脸,展示证明时用气泡,演示时占半屏,提出方案和号召时占全屏。人脸出现得太早会削弱钩子;号召语时还用气泡则会削弱信任感。
- 音效要低于人声: 音量设为 0.1 到 0.2,只用于真实事件(按下按钮、揭晓内容、卡片落下),并在最后按绝对时间点放置。
- Fil 中的叠加内容应保持为叠加内容。 添加摄像头占位内容、气泡和卡片时使用
overlay: true:这样它们就会叠加在故事之上,修剪、替换或移除它们都不会移动场景(Fil 0.424.0;在此之前,replace会把图片叠加内容变成故事场景,而对视频叠加内容使用trim from会把场景压缩到 0.1 秒)。不过,合并空隙仍会移动其后所有内容,包括音效:移除内容时使用close_gap: false,否则之后要把音效移回原位。 - 圆角气泡只需一个设置。 在 Fil 中对视频或图片设置
set: { corner_radius: 30 },即可将其放入带柔和阴影的圆角框中;方形裁切时若圆角半径为宽度的一半,就会变成圆形。在 0.424.0 之前,气泡必须在本地合成。 - 图片在缩放比例为 1 时会铺满画面。 在 Fil 编辑器中,图片的
scale: 1会铺满画面;卡片或气泡 PNG 需要设置fit: "fit"(这样 scale 设为 1 时就能完整显示)。 - 在新窗口中导出。
export_video会在打开了画布的 Fil 窗口中渲染。若上传文件前就打开了窗口,该窗口可能会接手任务并报错:“This file isn't available”。请关闭该窗口,或在新标签页中打开剪辑并使用 Export › Save to canvas,然后通过get_video读取链接。 - 以图片形式交付手机链接。 链接只会在首次打开它的设备上生效。如果在 Agent 的浏览器面板中点击链接,链接就会在该处被占用,而且无法使用摄像头。请将二维码作为图片发送,绝不要打开链接来测试。
- 设置保存在云端的节点上。 提词器的脚本、提词器本身以及跟随我的语音功能都属于录制节点(使用
update_node的script_doc),并且在每个窗口和手机上相同。绝不要把短视频设置保存在某个窗口的本地存储中。 - 渲染需要几分钟,机器繁忙时更久。 每一帧都要通过浏览器截图或 ffmpeg 处理:负载平均值为 350 时,一层包含 1,017 帧的字幕花了 9 分钟。使用
nice -n 10降低进程优先级,在后台逐个运行;完整影片渲染前,先用--test静帧和联系表评估效果。 - 检查导出文件,而不是时间线。 下载 MP4,以每 0.5 秒一帧的频率拼接成图,测量响度(ebur128),在爆破音处检查口型同步,并将人声高频段与原始录音对比,确认其中包含 Studio Sound。文档中读取的位置有两次出错;帧才是准的。
三条帖子的数字(带占位符的草稿)
| 项目 | 数值 |
|---|---|
| 时长 | 29.5–33.9 s,1080 × 1920,30 fps,−14.4 至 −14.7 LUFS |
| 配音 | 每条各录制一次 ElevenLabs 配音,约 400 个字符;每秒 2.2–2.4 个词;其中一条从 31.8 s 精简至 29.5 s |
| 镜头 | 开场(3–6 s)不露脸;全画面 0.9–2.7 s;气泡 3–7.5 s;半屏 9–22 s;提问时用上半屏,持续 3.7–4.1 s |
| 片段 | 每条短视频 7–19 个片段,速度从 0.26(一帧静止画面)到 2.02,每隔几个片段就裁切放大细节 |
| 标题 | 引入部分在 540 舞台上使用 52 px,点题部分使用 100–104 px;提问中的关键词适配 492 px(七个字母:96–112 px) |
| 字幕 | Inter Tight 78 px,800 字重,使用 Look.md 中的墨色和强调色,5 px 描边,放在分界线上;20–29 行,在大字或全屏人脸下方删去 3–5 行(字幕时间范围生成前) |
| 音效 | 每条 4 个,音量 0.10–0.16,用于揭示内容、卡片和关键词 |
| 封面 | 取开场在 2.8–3.6 s 的画面(标题已完整显示),停留 0 → 0.2 s;标题位于 y 900–1300 之间,处于 3:4 裁剪范围内 |
已发布的数字(HTML Demo 短视频)
| 项目 | 数值 |
|---|---|
| 时长 | 37.5 s,1080 × 1920,30 fps,−14 LUFS |
| 段落 | 开场 0–5.12 · 转折 –8.53 · 证明 –12.50 · 演示 –18.72 · 优点 –25.24 · 提供内容 –28.97 · 价值组合 –35.08 · CTA –37.50 |
| 节奏 | 每秒约 2.6 个词;草稿配音 37.8 s,正式录音剪至 33.4 s |
| 录音 | 两段竖屏手机录制;剪掉超过 0.45 s 的停顿;淡入淡出 15 ms;在 “it's HTML” 后留 0.8 s 的节拍 |
| 舞台 | 540 × 960 CSS,2×;安全区域为 1920 高度中的 y 280–1640 |
| 标题 | Instrument Serif 52 px,接着是全大写的 Anton 100 px,带 0.17 em 强调色圆点;蒙版内边距为 0.14 em / 0.2 em |
| 气泡 | 268 × 375,位于 x 721、y 1072,圆角 30 px,边框 2 px、白色不透明度 55%;在 0.35 s 内从全画面缩小 |
| 分屏 | 在 y 960 处硬切;镜头使用中间的 1080 × 960 区域,在 0.35 s 内从 0.86 → 1 缩放;在 0.32 s 内翻转至上半屏,缓动为 cubic in-out |
| 字幕 | Inter Tight 78 px,字重 800,白色,正在说的词使用 #efb36c,深色 5 px 描边,居中,每行最多 3 个词 |
| 音效 | 音量 0.1–0.2:切换时轻柔呼啸声,按下时咔嗒声,卡片出现时啵声,打字时加入打字声,CTA 处加入撞击声 |
| 锚点 | 开场 24 个,单调递增,4 对手动调整 |
| 屏幕片段 | 速度为 1.13–2.07,让拖动和逐步跳转在对应词语处落点 |
| 评审 | 两位盲测绝对评分评审(数量较少)+ 一位成对评审;开场评分从 6.5 → 6.0 → 7.3 → 7.0,最终持平 |
验证
- 第一帧就是封面:开场最佳画面上显示完整标题,位于 3:4 裁剪范围内,在 360 px 宽度下清晰可读,且没有字幕。
- 导出视频中的每个节拍都与对应词语对齐(打开声音,以 0.25× 速度抽查几处)。
- 每隔 0.5 s 检查一帧:标题没有超出 y 280–1640 的范围,也没有距两侧不足 16 px;人脸上没有字幕,视频展示内容上没有字幕;气泡没有遮住窗口控件;演示片段中没有光标。
- 屏幕上的每个名称、数字和账号名都与 Source.md 一致,并注明其他所有人的作品来源。
- 在相同 t 渲染两次,画面应完全相同。
- 检查开头、中间和结尾处的口型同步(爆破音:p、b、m)。
- 综合响度为 −14 LUFS ± 1,真峰值低于 −1 dBTP;配音的高频段低于原始录音(使用清理后的配音)。
- 字幕与实际说出的内容逐字一致,名称拼写正确。
- 章节标题标明各个节拍(宣传视频为 8 个,作品展示或“发现了这个”为 5–7 个)。
文件
scripts/read-source.mjs:将推文、网页、YouTube 视频或文件读入文字、媒体、帧、测量得到的视觉风格、Source.md 和 Look.md。scripts/reel-clock.js、scripts/reel-clock.css:场景引擎:HTMLReel.scene({ dur, draw, anchors, shape })、变形、四种形状的舞台、通过变量定义的三种类型角色、用于适配未知长度单行文字的fit、用于首帧的cover,以及控件。scripts/frame-video.mjs:将演示视频置于卷轴形状的画框中,背景叠加模糊副本;将视频片段切分到词语;在上方添加标题图层;以封面开场(--cover)。scripts/decursor.py、scripts/cursors/:识别屏幕录制中的 macOS 手形光标(从录制中截取的抓取和张开手形模板),并将其擦除,生成src-clean.mp4。scripts/render-frames.mjs:逐帧将__frame页面渲染为 MP4(或透明标题图层,--alpha),支持变形或不变形,并检查安全区域。scripts/timemap.py:将草稿和实际词语时间转换为锚点、映射 W 和场景的局部锚点。scripts/vo-words.py:生成带词语时间戳的 ElevenLabs 旁白,保存其回复并打印语速。scripts/tighten-voice.py:缩短语音中的长停顿,并同步调整词语时间。scripts/named-times.py:为场景和片段中的每个词命名(T.zoom、T.skill2、T.htmlEnd)。scripts/fil-words.py:从 Fil 的字幕列表提取词语时间。scripts/join-takes.py:将手机录制片段拼接成一条口播音轨,并生成剪辑列表。scripts/record-window.mjs、scripts/choreo-example.mjs、scripts/flash-crop.mjs:通过 playwright 驱动 DreamCut 录制,并根据闪光进行裁剪和修剪。scripts/bubble.mjs、scripts/split-flip.mjs:在本地合成摄像头画面,制成圆角气泡或翻转的半屏画面。scripts/preview-reel.mjs:在本地预览 Fil 将要排布的内容:画面、按编辑器设定值排列的摄像头图层、电影式字幕、旁白和音效。scripts/verify-export.mjs:检查导出文件的尺寸、响度、画面表和纯净语音。references/source.md:将源内容读入 Source.md(文字)和 Look.md(视觉风格)。references/structures.md:结构(宣传片、展示、发现分享、讲解、前后对比)和布局库,涵盖无露脸和出镜形式。references/formula.md:宣传片的 8 个部分和 6 种摄像头布局,以及如何研究参考卷轴视频。references/fil-editor.md:通过 MCP 在 Fil 的视频编辑器中组装内容,包括手机录制片段和导出。references/retime.md:拼接录制片段,并根据实际词语为每个部分重新定时。references/judging.md:评估标准、盲测评审,以及何时停止。demo/index.html:一个使用时钟的钩子场景,可播放草稿旁白,也可根据实际录制重新定时。