Skip to content

Repository files navigation

make-90s-tutorial-video

面向 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 项目

1. 依次接收三份素材

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。槽位顺序、文件类型、替换意图和断点恢复均由状态机约束。

2. 全片规划与动态项目

三份材料整体分析后写 job/FULL_FILM_PLAN.md,经用户批准再生成项目:

node scripts/validate_episode.mjs --config episode.json
node scripts/init_episode.mjs --config episode.json --output job/hyperframes

episode.json 可设置:

{
  "targetDurationSeconds": 90
}

3. 无音乐剪辑与内部画面基线锁

使用录屏原声时,先把 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。画面候选与锁定之间发生任何变化都会被拒绝。

4. 原声判断

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.wav

5. 实际音频调用

ListenHub CLI 里的 AI Voice 就是本流程调用 SeedAudio 的入口,两者不是需要用户选择的两个供应商。旁白、音乐和音效都走同一条调用链,并分层记录:

  • 调用层:transport=listenhub-clisurface=ai-voicecapability=listenhub-voiceproductModel=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.jsonEDIT_PLAN.jsonindex.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、锁定与混音流程。

6. 实际成片语义验收与发布

审片 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 \
  --confirmed

verify: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.sh

test_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

About

Reusable Codex Skill and HyperFrames template for polished 90-second tutorial videos.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages