jsxreel 是做什么的?
概述
这里的视频是通过 Remotion 动画渲染的 React 场景,由 ElevenLabs 配音,每个节拍与解说词精确对齐。应用和供应商的 UI 始终重新构建,绝不使用截图、屏幕录制或故事板幻灯片。如果提供的图像本身就是内容(如签名、徽标、产品照片),则可以作为图像出现。每个产品保留其自己的视频项目和风格;本技能掌握流程和 scripts/ 中的工具(位于技能基础目录下,技能加载时会显示)。
项目
首先读取 ~/.claude/jsxreel/projects.md(如果存在)(这是用户的私有列表,保存在技能之外,更新不会影响它:包含文件夹、要阅读的笔记、语音命令、约定)。然后读取该项目自己的笔记。如果项目不在列表中:询问用户它在哪里,然后在那里添加一行。
新项目:位于产品仓库内的 Remotion 项目,复制本技能中的 scripts/tts.mjs 和 scripts/stills.mjs(stills.mjs 放在 qa/ 中)。绝不能使用其他产品的视觉效果。
工作流
- 类型: 应用指南、故事板公告或宣传短片。阅读其在
kinds.md中的章节。 - 提问 使用 AskUserQuestion(推荐先提出,最多4个问题):格式、长度目标、结尾,以及材料和项目笔记无法解答的内容。
- 在编写前检查素材: 故事板文案(错误的技术声明、破折号、文字过长难以配音);每个屏幕上的指令(菜单路径、标签)要与供应商当前文档或应用代码核对;提供的资产中的个人数据。使用用户提供的内容,标记问题,提问。切勿无声替换。秘密(如有效的二维码、令牌、密码)绝不出现在屏幕上;绘制占位符。
- 脚本
scripts/<video>.json:每场景一行,marks标记每个节拍(精确、区分大小写的短语,在其行内唯一),say表示口语形式(数字、URL)。预算约每秒2.6词,每场景加0.5秒。以表格形式展示整个脚本;仅批准后花费积分。 - 语音: 每个语音一次性录制,通过对齐切割(对于单个旁白者,执行
node scripts/tts.mjs <video>)。转录音频片段(ElevenLabs 语音转文本,POST /v1/speech-to-text,模型scribe_v1,或项目自己的工具)以确认每个片段包含其自己的单词;每次录制花费几美分。然后收紧:python3 -I <技能目录>/scripts/tighten.py "$PWD" <video> <prefix>(原始文件保留在.voice-orig/中,参见--help)。短片保留其喜剧停顿。在云端会话中,ElevenLabs 密钥来自网络密钥(ELEVENLABS_API_KEY=proxy,参见 README 的浏览器部分);绝不要让用户在聊天中粘贴密钥。 - 构建:
data.ts、timeline.ts、场景、CSS(使用新的类前缀存放在单独文件中)。场景长度 = max(MIN, LEAD + 片段 + TAIL),LEAD 约0.15,TAIL 约0.2;MIN 覆盖场景最后事件 + 0.6秒;点击演示需要更长的 LEAD,以便在首次点击前 UI 可见。在Root.tsx中注册,添加voice:/render:脚本,并在项目笔记(README 或计划)中记录该视频。 - 质量检查(见下文),然后报告:绝对 mp4 路径、与目标对比的长度、需要确认的假设(样本数据、重建的 UI 标签、任何已批准的改动,新旧对比)、需通过耳朵检查的内容。仅在要求时提交。
质量检查
npx tsc --noEmit;node qa/stills.mjs <Comp> <帧…>(如果编辑后首次调用崩溃,则重新运行)。- 每次点击或轻按的按下帧,堆叠在一张联系表中:手指或光标位于目标上。
- 每个过渡取4到5帧。
- ffprobe 检查长度;每项目音量(指南:平均约 -21 dB;社交媒体:约 -14 LUFS,峰值最多 -0.8 dB);使用 silencedetect 检测超过约1.3秒且非故意喜剧停顿的空白。
- 修改了共享文件:渲染旧视频的一帧,PSNR 必须为
inf。 - 删除质量检查的 PNG 文件。
常见错误
| 错误 | 修复方法 |
|---|---|
| ElevenLabs 自然语速 | 用户觉得慢。在首次渲染前收紧。 |
| 录制前未检查 UI 标签 | 先检查供应商文档或应用代码;重录需要花费积分。 |
| 每行一个 TTS 请求 | 语音在不同行之间变化。每个语音一次性录制。 |
| 硬编码节拍时间 | 使用 Marks;新的录制会重新调整所有时间。 |
| 盲目信任对齐 | eleven_v3 对话漂移约0.75秒。转录音频片段。 |
| 使用其他项目的风格 | 每个产品有自己的工具包;故事板保留自己的风格。 |
调用方的 style 传播到设置 transform 的包装器上 | 调用方的 transform 会获胜,导致缩放丢失。将调用方样式放在外层 div 上。 |
zsh:$LIST 不会分词,==== 是错误 | 内联列表;用 Python 构建 ffmpeg 过滤器。 |
| 端口3000被占用 | 指定一个空闲的 --port。 |
| 机器上没有 Chrome | 任何 Chromium 浏览器均可(Chromium、Edge、Brave 通过 --browser-executable);如果没有,则删除该标志,Remotion 会下载自己的无头 Chrome。stills.mjs 会自动选择浏览器。Firefox 和 Safari 无法渲染。 |
| 报告中手动输入 URL | 仅使用本地路径。 |