面向 Cola 与 Codex 的教程视频生产技能。它会依次引导用户提供录屏、PPT/HTML、说明文档,先形成全片规划,再执行“自动完整句候选与逐词语义剪辑 → 代理音轨复核 → 中段持续录屏的无音乐画面剪辑 → 内部画面 QA 与生成基线锁 → 有/无原声分支 → ListenHub CLI AI Voice 音乐与独立音效 → 完整混音 HyperFrames Studio 审阅 → 实际 MP4/AAC 语义复核与哈希发布”。
默认片长 90 秒;用户指定时长时,全时间线、场景、持续录屏区间、媒体、检查和渲染目标会动态缩放。
下文的 node scripts/... 命令均从本仓库根目录执行。技能在 Cola/Codex
中运行时会解析安装目录的绝对路径,不依赖任务当前目录。
Cola 一键安装主技能和七个 HyperFrames 依赖:
git clone https://github.com/huntingrin/make-90s-tutorial-video.git /tmp/make-90s-tutorial-video
/tmp/make-90s-tutorial-video/install.sh --cola安装完成后重启 Cola。
安装器只分发运行所需源码、轻量回归 fixture 与七个依赖,不会复制本地
deliverables/、tests/.work/、缓存或其他审片产物;升级安装也会清理
旧版本曾误留在技能目录中的这些文件。若目标技能目录是符号链接,安装器会
拒绝镜像写入,避免误删链接后的源码或个人文件。
其他选项:
./install.sh # Codex + Cola
./install.sh --cola # ~/.cola/skills
./install.sh --codex # ~/.codex/skills
./uninstall.sh建议目录:
job/
.workflow/ # 可恢复状态、画面锁
intake/manifest.json # 素材清单与 SHA-256
sources/ # 冻结后的三份素材
analysis/
FULL_FILM_PLAN.md
audio/
hyperframes/ # 可编辑的 HyperFrames 项目
node scripts/stage-input.mjs --project job --slot recording --file recording.mp4
node scripts/stage-input.mjs --project job --slot presentation --file deck.pptx
node scripts/stage-input.mjs --project job --slot brief --file brief.md
node scripts/workflow-state.mjs status --project job --json录屏阶段可加 --duration 60;未给时默认 90。槽位顺序、文件类型、替换意图和断点恢复均由状态机约束。
三份材料整体分析后写 job/FULL_FILM_PLAN.md,经用户批准再生成项目:
node scripts/validate_episode.mjs --config episode.json
node scripts/init_episode.mjs --config episode.json --output job/hyperframesepisode.json 可设置:
{
"targetDurationSeconds": 90
}使用录屏原声时,先把 ASR 统一为逐词 JSON,再用“完整预期句子”生成 安全切点。不要手写一个大概的出点:
node scripts/prepare-dialogue-edit.mjs transcribe \
--input recording.mp4 \
--output job/analysis/source-transcript.json \
--language zh
node scripts/prepare-dialogue-edit.mjs propose \
--transcript job/analysis/source-transcript.json \
--episode episode.json \
--output job/analysis/DIALOGUE_CANDIDATES.json
node scripts/prepare-dialogue-edit.mjs draft \
--transcript job/analysis/source-transcript.json \
--episode episode.json \
--region-start 6 --region-end 84 \
--keywords "教程主题关键词" \
--output job/analysis/DIALOGUE_PLAN.json
node scripts/prepare-dialogue-edit.mjs build \
--episode episode.json \
--transcript job/analysis/source-transcript.json \
--plan job/analysis/DIALOGUE_PLAN.json \
--output episode.json
node scripts/init_episode.mjs --config episode.json --output job/hyperframes
node scripts/dialogue-qa.mjs auto --project job/hyperframes候选器按完整句、停顿、边界静音和 ASR 置信度评分;重复文案自动选择
边界最安全的 take,draft 会在中段时长预算内优先保留相关完整句。构建器
自动保留词前/词后静音、使用 40ms 淡化,并把多余时长变成
audio:false 的录屏画面保持段。代理 ASR 会逐段核对完整文本、结尾语义
锚点和意外混入的前后语音;macOS 默认优先使用本地 MLX Whisper,其余环境
回退到 HyperFrames ASR。任何切点、淡化、转写或代理文件变化都会使 QA
失效。
npm --prefix job/hyperframes run build:fonts
npm --prefix job/hyperframes run check:dialogue
npm --prefix job/hyperframes run check:picture
node scripts/workflow-state.mjs advance --project job --to picture_qa --json
node scripts/picture-lock.mjs prepare --project job/hyperframes --workflow job
node scripts/picture-lock.mjs lock --project job/hyperframes --workflow job --confirmed录屏必须从开场结束持续显示到结尾开始;90 秒成片对应 6–84 秒,其他时长按场景比例计算。此阶段不向用户打开 Studio。画面候选与锁定之间发生任何变化都会被拒绝。
node scripts/analyze-recording-audio.mjs analyze \
--project job/hyperframes \
--workflow job \
--transcript transcript.txt \
--decision auto \
--apply- 有可用原声:直接进入音乐/音效。
- 无可用原声:先生成并采用旁白,内部对齐画面,再次画面锁定。
- 只有“活动音频”但没有转录:保持歧义,不会把音乐/噪声误判成语音。
生成后先验证脚本与实际旁白,再采用:
node scripts/narration-qa.mjs auto \
--project job/hyperframes \
--workflow job \
--file job/audio/narration.wav \
--text-file job/audio/NARRATION.txt
node scripts/adopt-audio.mjs voice \
--project job/hyperframes \
--workflow job \
--file narration.wavListenHub CLI 里的 AI Voice 就是本流程调用 SeedAudio 的入口,两者不是需要用户选择的两个供应商。旁白、音乐和音效都走同一条调用链,并分层记录:
- 调用层:
transport=listenhub-cli、surface=ai-voice、capability=listenhub-voice、productModel=listenhub-voice-1.0; - 底层引擎:
engine=seedaudio;只有任务元数据明确返回时才填写具体engineModel; - 三类音频分别生成和冻结,不能合成一个不可编辑的黑盒文件。
本项目只调用官方 listenhub openapi listenhub-voice CLI,不构造私有 REST 请求,也不切换到其他音乐供应商。
先从 assets/audio-design.example.json 建立最终音频设计:
node scripts/build-audio-request.mjs build \
--project job/hyperframes \
--workflow job \
--design job/audio/AUDIO_DESIGN.json \
--plan job/FULL_FILM_PLAN.md检查 CLI、认证和账户状态:
node scripts/listenhub-audio.mjs doctor没有可用原声时,先生成旁白:
node scripts/listenhub-audio.mjs generate \
--kind voice \
--project job/hyperframes \
--workflow job \
--text-file job/audio/NARRATION.txt \
--output job/audio/narration.wav画面最终锁定后,可先用 --dry-run 做零提交预检,再实际生成音乐与逐事件音效:
node scripts/listenhub-audio.mjs generate \
--kind music \
--project job/hyperframes \
--workflow job \
--request job/audio/audio-generation-request.json \
--output job/audio/music-bed.wav
node scripts/listenhub-audio.mjs generate \
--kind sfx \
--project job/hyperframes \
--workflow job \
--request job/audio/audio-generation-request.json \
--directory job/audio/generated-sfx适配器先以 --no-wait 获取并原子保存任务 ID,再用 task --wait 恢复同一任务。并发锁、请求指纹和 submitting 检查点会阻止自动重复提交付费任务。每个 WAV 都有私有的 .task.json 与 .provenance.json,并绑定当前 workflow、picture lock、请求 SHA 和文件 SHA。
duration-hint 是 1–110 秒的非强制提示;即使客户锁定的成片更长,客户时长仍然优先,只把提交给服务端的提示封顶到 110 秒。旁白保留自然时长且绝不拉伸;音乐的小偏差做有限变速,明显偏短时先把同一段返回演奏的尾部与头部交叉淡化成无缝循环,偏长时裁切,最后淡出并精确贴合成片;短音效至少以一秒提示生成,再裁到锁定事件的最大时长。
配音采用使用独占锁与私有 pending journal。恢复前会对目标资产、episode.json、EDIT_PLAN.json、index.html、采用回执和音频 manifest 做事务前/目标 SHA 比对;若崩溃后出现第三种外部编辑状态,会停止并报告冲突,绝不静默覆盖。完成回执也支持“已提交但客户端未收到响应”后的幂等重试。
大幅循环或裁切会在 provenance 中标记 requiresHumanReview: true。波形交叉淡化只能消除接缝,不能凭空保证乐句收束;因此 studio_full_mix_review 必须试听所有循环边界与结尾,听感不自然就重新生成或调整音乐,未通过前不得批准渲染。
采用音乐与逐事件 SFX:
node scripts/adopt-audio.mjs music \
--project job/hyperframes \
--workflow job \
--file job/audio/music-bed.wav
node scripts/adopt-audio.mjs sfx \
--project job/hyperframes \
--workflow job \
--request job/audio/audio-generation-request.json \
--directory job/audio/generated-sfx
node scripts/adopt-audio.mjs finish \
--project job/hyperframes \
--workflow job
npm --prefix job/hyperframes run preview:edit音乐只在根时间线挂载一次并根据对白窗口 duck;SFX 保持独立 stem。这里才第一次把 Studio URL 提供给用户,因此打开时已经有原声或旁白、音乐和计划内 SFX。若用户修改画面时间:
node scripts/adopt-audio.mjs reopen-picture \
--project job/hyperframes \
--workflow job该命令卸载音乐与 SFX、保留已生成文件和旁白,然后重新进入画面 QA、锁定与混音流程。
审片 MP4 和最终 MP4 都会直接转写其 AAC 音轨,不再只相信剪辑代理:
npm --prefix job/hyperframes run render:preview
npm --prefix job/hyperframes run verify:preview
npm --prefix job/hyperframes run render:final
node scripts/release-video.mjs complete \
--project job/hyperframes \
--workflow job \
--confirmedverify:preview/verify:final 同时检查时长、H.264、AAC、48kHz 立体声、
全流解码和每个完整语义结尾。最终发布门禁还会核对当前 picture lock、
音频 request/manifest、ListenHub task/provenance sidecar、已采用音乐/SFX
的实际文件 SHA-256,写入
.workflow/final-release.json 后才允许状态进入 completed。
SKILL.md # Cola/Codex 主合同
scripts/workflow-state.mjs # 可恢复生产状态机
scripts/stage-input.mjs # 三素材顺序接收与冻结
scripts/picture-lock.mjs # 内部 QA 后画面基线哈希锁
scripts/dialogue-contract.mjs # 逐词转写、完整句 EDL、语义与淡化检查
scripts/prepare-dialogue-edit.mjs
scripts/dialogue-qa.mjs # 对白代理 WAV 与 ASR 硬门禁
scripts/local-asr.mjs # MLX Whisper / HyperFrames 统一逐词 ASR
scripts/narration-qa.mjs # 旁白脚本—ListenHub 音频语义门禁
scripts/release-video.mjs # 最终 MP4/AAC 与发布凭证门禁
scripts/analyze-recording-audio.mjs
scripts/build-audio-request.mjs
scripts/audio-provider-contract.mjs
scripts/listenhub-audio.mjs # ListenHub CLI AI Voice / SeedAudio 适配器
scripts/adopt-audio.mjs # voice/music/SFX 冻结与挂载
assets/template-project/ # 动态 HyperFrames 模板
references/ # 输入、编辑、视觉、音频、状态、QA
bundle/skills/ # 七个依赖技能
轻量核心测试:
node scripts/test_config_validation.mjs
node scripts/test_audio_automation.mjs
node scripts/test_dialogue_semantics.mjs
node scripts/test_dialogue_pipeline.mjs
node scripts/test_golden_semantic.mjs
node scripts/test_release_gate.mjs
node scripts/test_dynamic_duration.mjs
node scripts/test_verify_render.mjs
node scripts/test_workflow_state.mjs
node scripts/test_listenhub_audio.mjs
node scripts/test_audio_workflow.mjs完整测试:
scripts/self_test.sh
tests/run-all.sh
SKIP_T2=1 SKIP_T4=1 tests/run-all.shtest_dialogue_semantics.mjs 固定复现历史“话没说完”错误,并覆盖旁白截断/重复、意外下一句开头、自动候选、重复 take 和 40ms 安全淡化;test_dialogue_pipeline.mjs 验证缺失代理 QA、真实渲染音轨缺尾句、切点变更都会失败;test_golden_semantic.mjs 在本机黄金素材存在时冻结验证真实 90 秒母版、9 段原声、候选和自动草案;test_release_gate.mjs 覆盖最终确认、编码/全解码、实际 AAC 语义 QA、采用音频哈希、发布凭证、幂等重试和已发布母版篡改。test_listenhub_audio.mjs 覆盖 CLI 参数、有限变速/无缝循环/裁切、并发锁、付费任务恢复、缓存和 provenance;test_audio_workflow.mjs 覆盖无原声 → 旁白脚本 QA → 可恢复采用 → 安全尾字淡出 → 二次锁 → 音乐/SFX → full-mix review → 画面改动失效的完整离线链路。
- Node ≥ 22
- FFmpeg / ffprobe
- 已认证的 ListenHub CLI(实际生成时)
- Python FontTools (
fonttools,pyftsubset) - HyperFrames 渲染所需 Chromium
- 首次字体与
npx hyperframes需要网络 - 单元与工作流测试使用本地音频/mock,不消耗 ListenHub 额度;
--dry-run不提交生成任务
官方音频资料和产品边界见 references/seedaudio-integration.md。