Faceless Shorts
您可以根据主题制作完整的竖屏短视频:脚本、语音、单词同步字幕、动画片段、音效和音乐,渲染为 MP4。一切皆代码:Canvas 绘图、Headless Chrome 捕捉、ffmpeg、本地 Kokoro 语音、本地 Whisper 单词计时、numpy 音效。无 AI 图像或视频,无 API 密钥,无额外积分。
SKILL = 本文件所在的文件夹。项目存放在 ~/faceless-shorts/<short-name>/。
一种风格:吉祥物解说(mascot-explainer)。您作为一个扁平卡通吉祥物(由代码根据一张照片绘制、绑定骨骼、口型同步),展示“N 个快速步骤”:一次一张卡片,编号牌会撞击角落徽章,带有实时清单、逐词标题字幕、每次撞击的镜头晃动和音效。时长 30-45 秒 · 9:16 比例。最适合操作指南、技巧、"N 个步骤……"、科技/理财/生产力解说类视频,其中创作者本身即是品牌。
该风格 = styles/mascot-explainer/style-sheet.png(一张图像呈现外观,由自己的代码绘制)+ STYLE.md(规则 + 引擎手册)+ example/(一个可直接渲染的完整项目)。在规划前,请完整阅读 STYLE.md。
0. 在计算机上首次使用
运行 bash SKILL/scripts/setup.sh 直到打印 All set(检查 Node 22+、ffmpeg、Chrome;构建 ~/.faceless-shorts/venv;下载 Kokoro 语音 ~340 MB 和 Whisper small.en ~0.5 GB)。以免费、官方方式安装缺失的任何组件,并在需要密码的任何操作前询问。然后运行 bash SKILL/scripts/selftest.sh,必须打印 SELFTEST PASSED:打开联络表并裁剪其名称,然后查看它们。
1. 初始输入(一条消息,默认值已填写)
仅询问未知内容,一次性提出:主题(或“你推荐 3 个创意”)、他们喜欢的短视频格式链接(可选)、时长(默认 ~30 秒)、语音(SKILL/scripts/py SKILL/scripts/voice.py --list;默认 am_michael)、画外音模式:AI 语音(默认)· 用户自己的录音(他们在看到脚本后录音;使用 words.py --audio)· 仅字幕(暂无语音;使用 estimate.py)、音乐(内置背景音乐 · 无 · 用户自己的免版税文件)、结尾语/用户名、一张清晰正脸照片(可选)和一套服装,或者保存在 ~/faceless-shorts/_mascots/ 中的吉祥物名称。“直接开始” = 使用默认值。
2. 计划(一个屏幕,然后等待)
显示:标题 · 完整旁白,每个剪辑占一行,带其字幕块(1. 查看 | 真实的 *发件人地址) · 分镜头列表,每行一条(我们看到什么、什么在移动、它落在哪个词上) · 您将添加到工具包中的新组件(如果有) · 事实及其来源。询问 “开始构建?” 并等待。
脚本规则。 以一个人实际与朋友交谈的方式编写:完整、流畅的句子,使用连接词(“那么”、“其中”、“但是”、“所以”、“这意味着”),而不是一系列类似字幕的简短陈述。35 秒大约 90-110 个词。一行就是一个剪辑,而不是一个句子:将每个句子在自然停顿处(逗号、“和”、“其中”)分成 1-3 行,以便画面每 1.5-3.5 秒变化一次,同时语音保持流畅(voice.py 一次说出整个句子)。结构:以一个带有真实、有来源数字的钩子开头,一句承诺,3-6 个以“第一……”开头的步骤,一个明确的结束动作。按说话方式写出数字(“七”)。在脑海中大声朗读:如果听起来像字幕,请重写。仅限原创写作:借鉴您喜欢的格式,但绝不抄袭其他创作者的脚本或镜头。每个事实都要对照可靠来源进行核查(在 script.json 的“sources”中列出)。
3. 构建
- 运行
bash SKILL/scripts/new_video.sh mascot-explainer <short-name>将示例复制到~/faceless-shorts/<short-name>/。 - 编写
script.json(行 + 字幕块 + 间隔;参见 STYLE.md)。首先创建吉祥物(mascot.json,STYLE.md §2),渲染其姿态表并让用户确认,然后再编写任何镜头。 - 计时:
SKILL/scripts/py SKILL/scripts/voice.py <proj>然后SKILL/scripts/py SKILL/scripts/words.py <proj>(用户自己录音:words.py <proj> --audio their.m4a;仅字幕:estimate.py <proj>)。 - 重写
src/shots.js:每个镜头一行(长镜头可占两行),每个镜头使用cut(i)放置,其关键时刻在单词上使用Wd('word', line)。重用工具包(src/core/kit.js);在该风格的外观下,向其中添加新组件。 - 在项目中:
node tools/capture.mjs check(必须显示 CHECK OK)→node tools/capture.mjs cues→SKILL/scripts/py tools/mix.py .→ 质量检查(第 4 节)→node tools/capture.mjs video renders/<name>.mp4。迭代单个镜头:node tools/capture.mjs frames review/f "4.2,4.6"并查看。
4. 质量检查:绝不展示未查看的帧
运行 node tools/capture.mjs sheet review/all.jpg 0.5 10(每 0.5 秒一帧,带时间戳)并阅读整个表,然后全尺寸查看关键帧。对每一帧询问:
- 画面合理吗? 一次只显示一张卡片;吉祥物的姿态适合该行;道具随其承载物移动。任何内容在出现之前都应有原因。
- 画面是否与当前时刻的旁白匹配? 画面在对应行开始前变化;揭示内容正好落在其单词上。
- 是否有任何碰撞? 手臂、印章和爆发效果绝不能意外地与标题、卡片、徽章、清单或彼此交叉。
- 字幕: 1-4 个词,最多一个紫色强调词,拼写正确,绝不能在单词说出前显示。
- 风格表: 仅使用调色板、扁平形状、硬色墨迹阴影,红色仅用于危险。
- 声音: 语音清晰,盖过音乐;音效柔和(无刺耳的滴答声或蜂鸣声)。
修复,重新渲染表,重新检查。向用户告知您发现并修复的问题。
5. 交付
为用户打开 MP4 文件。同时提供:如果文件大于 35 MB,提供共享副本(ffmpeg -i in.mp4 -c:v libx264 -crf 21 -preset slow -c:a aac -b:a 160k -movflags +faststart share.mp4),最佳封面帧(capture.mjs frames),标题,字幕和 5-8 个话题标签。对于用户自己录音模式,同时向他们提供带每行计时的脚本以便对照朗读。提供一轮精确修改,并仅重新渲染更改过的部分。
5b. 通过 Zapier 发布到 YouTube(仅当用户要求上传时)
所有调用都是代码模式工具:在 execute 内部作为 tools.zapier.* 运行(不要将它们作为普通工具调用)。在真实上传中验证一次;以下值完全准确。
- 连接。 如果
list_zapier_skills有用于上传的已保存技能,则使用它。否则,确保 YouTube 应用已启用:discover_zapier_actions({ app: "YouTube" })→enable_zapier_action({ selected_api: "YouTubeV4CLIAPI", app_display_name: "YouTube", action: "upload_video" })。如果尚不存在连接,manage_zapier_connections({ selected_api: "YouTubeV4CLIAPI" })将返回一个供用户使用的连接 URL。 - 托管文件。 该操作的
video/thumbnail参数需要一个 Zapier 服务器可以获取的 URL;本地路径会静默失败。将 MP4 上传到临时主机,按此顺序(均于 2026-11-03 测试;在 Windows 上使用curl.exe):- a. litterbox(有效期 1 小时到 72 小时,最大 1 GB):
curl -F "reqtype=fileupload" -F "time=1h" -F "fileToUpload=@renders/<name>.mp4" https://litterbox.catbox.moe/resources/internals/api.php→ 返回纯文本格式的直接 URL。 - b. uguu.se(有效期约 3 小时,适合小于 35 MB 的短视频):
curl -F "files[]=@renders/<name>.mp4" https://uguu.se/upload→ 返回 JSON;使用files[0].url(即d.uguu.se/...链接)。 - c. catbox(永久,无过期):调用方式与 (a) 相同,但不带
-F "time=1h"。永久公开,因此仅在征得用户同意后使用。 - 跳过以下服务(已验证于 2026-11-03 失效,不要浪费重试次数):0x0.st(上传已禁用)、tmpfiles.org(链接是查看页面,非原始文件)、gofile.io(原始下载需要账户令牌)、file.io(curl API 重定向到其 Web 应用)、bashupload.com、temp.sh(已失效)。
- 始终在使用前验证 URL:
curl -sSI <url>必须返回 200/206 状态码且内容类型为视频。绝不要仅凭主机的 JSON 响应就信任它。 - 告知用户,这会将其视频放置在一个自动过期的公共临时主机上。
- a. litterbox(有效期 1 小时到 72 小时,最大 1 GB):
- 先确认。 此操作将写入用户的真实频道,因此在执行前确认:标题、可见性(私密/不公开列出/公开)和类别。
如有需要,使用
inspect_zapier_actions({ tool_name: "youtube_upload_video", enum_property: "category_id" })解析category_id。 教育 = 27(操作指南类短视频的默认值),喜剧 = 23,如何与风格 = 26。 - 上传。
execute_zapier_write_action({ selected_api: "YouTubeV4CLIAPI", action: "upload_video", tool_name: "youtube_upload_video", params: { video: "<临时 URL>", title, description(以 #shorts 结尾), tags: [5-8 个不带 # 的话题标签], category_id: "27", privacy_status, made_for_kids: false, embeddable: true, notify_subscribers: true, default_language: "en", license: "youtube" } }) - 报告。 结果包含
id;链接为https://www.youtube.com/watch?v=<id>。时长 60 秒或更短的竖屏视频将自动成为 Shorts(无需额外字段)。 为用户打开本地文件(tools.browser.preview({ path: "renders/<name>.mp4" }))并以文本形式提供 YouTube URL。应用内浏览器通常无法加载 youtube.com 并显示 ERR_ABORTED;这不代表上传失败。 - 缩略图。 不公开列出的上传无法通过此操作设置自定义缩略图;如果用户稍后将该视频设为公开,则提供保存的封面帧。
禁止事项
使用 AI 生成图像或视频;花费用户的金钱或积分;在未由用户要求并确认的情况下上传到 YouTube 或任何主机;抄袭其他创作者的脚本、镜头或帧; 未经询问覆盖用户的项目;交付未查看过的帧。