Skip to content

Repository files navigation

Moonlit Stories

本地可复用的 AI 儿童英文绘本工作台:React 阅读器负责表单、封面与 12 页阅读体验;Codex 的 moonlit-book-workflow Skill 负责编排故事、统一画风插画、本地授权成人声音克隆、校验与单文件发布。

本仓库采用 MIT License。模型权重不会进入仓库,而是在用户本机从对应模型页面下载;第三方模型及其 tokenizer 仍分别受各自模型页面所列条款约束。

最短上手方式

把仓库拉到 Apple Silicon Mac 后,在 Codex 中打开这个文件夹,直接说:

运行这个程序

仓库内的 AGENTS.md 会让 Codex 执行唯一入口。也可以自己在终端运行同一条命令:

npm start

首次运行会自动检查环境;检测到 Homebrew 时会补装缺少的 uv 和 FFmpeg,然后安装 Node/Python 依赖、下载约 3.2 GB 的固定 TTS 模型、构建阅读器、安装 Codex Skill、复检服务并自动打开页面。后续运行通过 doctor 后会跳过安装和下载,直接打开本地工作台。

这个入口仍有两个无法安全绕过的前置条件:

  • 电脑需要是 Apple Silicon Mac,并已安装符合版本要求的 Node.js/npm;没有 Node 就无法执行 npm start 本身。
  • 如果电脑既缺少 uv/FFmpeg 又没有 Homebrew,启动器会给出明确安装提示,不会静默执行远程脚本或要求管理员密码。

填完表单后,本地任务会自动保存,并显示一条“复制 Codex 指令”。点击一次复制并发回当前 Codex 任务,它就会继续推进故事、统一画风插画、本地 TTS、12 页合成和单文件发布。流程仍会在两个人工检查点暂停:第 1 页声音试听,以及分享孩子显示名与生成形象的监护人授权。这里仍需一次回到 Codex,因为浏览器不能直接调用用户账户里的 Codex 内置生图能力。

能力边界

  • 浏览器不能直接把 Codex 内置生图当作本地 HTTP API 调用。真实插画任务由 Skill 调用 built-in imagegen,并把返回的确切文件写入可恢复任务清单。
  • “本地”只指任务文件、模型与 TTS;内置生图仍由图像生成服务处理提示词和参考图。默认建议只用名字与文字外貌描述,上传真实儿童照片前必须取得监护人同意。
  • TTS 在 Apple Silicon Mac 本地运行;模型和声音参考均保存在本机。
  • 声音克隆只接受已明确授权的成人讲述者,不克隆儿童、公众人物或无法核实同意的人。
  • 没有授权参考音频时,故事和插画仍可完成,但不能把语音部分标记为完成。

隐私与开源边界

  • .moonlit/.local-models/.venv-tts/dist/、上传目录和本地生成音频均被 Git 忽略。
  • 公开源码只带虚构的 Luna Demo 和身份中性的画风锚点,不包含真实任务、孩子资料、家长录音、转录稿、授权档案、克隆音频、缓存哈希或模型权重。
  • 单文件发布器只内联当前 book.json 明确引用的阅读资产,并拒绝 private/ 路径和声音授权元数据。
  • 克隆音频即使由本机生成,也应当在取得相应声音权利人与监护人许可后再分享。

安装与自检细节

本地 TTS 仅支持 Apple Silicon macOS(darwin arm64)。需要 Node.js ^20.19.0>=22.12.0 和 npm。本地声音克隆和公开模型下载不需要 API Key。

推荐始终使用会自动安装、复检、启动并打开页面的一键入口:

npm start

如需只查看状态或手动拆分排查,才使用下面的底层命令:

npm start -- --dry-run
npm run setup -- --dry-run
npm run setup
npm run doctor

npm run setup 会幂等地完成以下工作:

  1. 检查 macOS/arm64、Node、npm、uvffmpegffprobe
  2. 安装 Node 依赖,创建或同步 .venv-tts
  3. 下载精确固定 revision 的 Chatterbox Multilingual V3 和 S3Tokenizer;已完整安装时跳过下载。
  4. 构建 dist/moonlit-stories-single.html
  5. 将仓库内的 moonlit-book-workflow 安装到 $CODEX_HOME/skills(已设置时)或默认的 ~/.codex/skills

安装器不会覆盖同名但来源不同的用户 Skill,也不会抹掉已安装 Skill 上的本地修改;遇到这种情况会报冲突并停止,请先人工核对现有目录。安装后可以执行只读自检:

npm run doctor
npm run --silent doctor -- --json

默认输出是简洁文本,--json 输出适合脚本读取的完整 JSON。doctor 只检查平台、命令、Python、固定模型、Codex Skill 和阅读器构建,不会写入文件。

Codex 内置 imagegen 不是这个项目提供的离线 HTTP API。插画仍由已安装的 Skill 在 Codex 会话中调用内置生图能力,可能需要网络和可用的 Codex 账户权限;不需要在本项目里配置 OpenAI API Key。

阅读器开发模式

npm install
npm run dev

录入页支持中文填写孩子资料,并额外要求一个只用于英文故事和朗读的“英文故事名”。“家长声音”默认不使用;开启后可以直接使用浏览器录音,或上传 WAV、MP3、M4A 等成人授权录音,并填写授权人和两项明确确认。切回“不使用”会立即清掉前端内存中的原始录音与授权字段;这不会生成所谓默认正式音色,工作流会在 TTS 前暂停等待授权成人声音。

需要注意:静态网页不能自行启动本机工作流或 TTS 模型;正式任务要通过 npm start 打开的本机服务页面进入。点击“创建正式绘本任务”后,页面会创建真实的 .moonlit/jobs/<job-id>,并显示一条可复制给 Codex 的继续指令。浏览器不会用 Luna Demo 冒充正式成品。

任务接口使用 multipart:公开孩子资料和声音授权元数据放在 request JSON,原始录音只放在私有 voice_sample 二进制部分。服务会在临时目录中把录音规范化为任务级 reference.wav、转录稿和授权档案,然后删除原始上传;授权人、同意记录、转录稿和私有声音文件都不会进入 PictureBook、公开状态响应或分享 HTML。未选择家长声音时,可以先完成故事和插画,但 Codex 会在正式 TTS 前暂停,不会把系统预览音色冒充为已完成的本地克隆。

构建默认演示:

npm run build
npm run build:single-preview

默认单文件输出为 dist/moonlit-stories-single.html。当前 Luna demo 已停用原先偏生硬的固定 Karen MP3,改用安全筛选后的本机英文系统音色作为预览兜底;正式定制书只使用经过试听确认的本地克隆音频。

启动本机 TTS 服务

家长声音功能不能从 file:// 单文件直接启动模型。正常使用只运行:

npm start

启动器会自动完成缺失安装、复检、托管页面与打开浏览器。服务默认只监听 127.0.0.1:4191,不会暴露到局域网;如果默认端口被其他程序占用,会安全尝试 41924200,不会结束未知进程。也可以明确指定另一个本机端口:

npm start -- --port 4291

npm run local:startnpm run tts:service 保留为开发者底层入口;它们只启动已经安装好的服务,不负责自动安装或打开浏览器。

底层服务入口会先检查构建后的单文件阅读器、.venv-tts Python、本地渲染脚本、固定模型及其必要权重、ffmpegffprobe。如需手动排查 TTS 安装,可以执行:

npm run tts:setup
npm run tts:model:download

使用期间保持该终端运行,按 Ctrl+C 会中止当前本地声音任务、删除任务级临时声音资料并关闭服务。服务不会在终端打印浏览器使用的会话令牌。家长声音仍会先只生成第 1 页供试听,只有确认声音温和、发音正常后才继续其余 11 页。

127.0.0.1 只代表当前这台电脑。将 HTML 发给其他家长并不会让他们自动连上这台 Mac 的 TTS 服务;对外产品化仍需要托管后端或安装在用户电脑上的本地伴随应用。

一次性安装本地 TTS

npm run tts:setup
npm run tts:model:download

默认语音链路由两个精确固定的本地组件组成:

  • mlx-community/chatterbox-multilingual-v3,revision 03565773edd72e949572557597af8063bb49a18a,安装到 .local-models/chatterbox-multilingual-v3
  • mlx-community/S3TokenizerV2,revision e0c9886f0e1c35ae85b1f27277416fb19fc72bec,安装到 .local-models/s3-tokenizer-v2

两者合计约 3.2 GB。渲染器会逐页串行复用一个模型实例,并在生成阶段强制使用本地文件;缺少精确 revision、必要权重或 tokenizer 文件时会直接停止,不会静默换模型。建议使用至少 16 GB 内存的 Apple Silicon Mac。

准备一段 7–10 秒、干净且有明确授权的成人英文朗读。请用温暖、连续、有自然起伏的绘本语气,不要逐字慢念或留下长停顿:

npm run voice:prepare -- \
  --voice-id family-narrator \
  --source /absolute/path/reference.wav \
  --transcript "Exact words spoken in the recording." \
  --speaker-label "Authorized adult narrator" \
  --rights-holder "Rights holder name" \
  --consent-confirmed \
  --speaker-is-adult

声音档案默认保存在 .moonlit/voices/,该目录已忽略,不会进入前端产物。

一套书的生产流程

最短路径是在本地工作台填写表单并点击“创建正式绘本任务”,然后把页面返回的整段指令粘贴给当前项目里的 Codex。指令包含唯一 job ID,Skill 会从该任务继续,不会重复创建或丢失已经批准的页面。

在 Codex 中直接说:

请使用 $moonlit-book-workflow,根据这份孩子资料生成一本新绘本并在每个视觉检查点继续执行。

Skill 会执行以下固定链路:

  1. 校验中文显示名与英文故事名,生成 12 句英文、12 条中文翻译和 12 个场景提示。
  2. 建立 .moonlit/jobs/<job-id>/manifest.json,所有任务可中断恢复。
  3. 始终使用 moonlit-watercolor-v1 中性画风锚点。
  4. 每本书先生成并批准一张专属角色设定图。
  5. 封面和 12 页都同时引用同一画风锚点与该角色设定图;逐张查看,不合格只重做当前页。
  6. 先用 Chatterbox 本地克隆第 1 页供试听;确认温柔度、速度和发音后再渲染全部 12 页。默认情感参数是 exaggeration=0.7cfg_weight=0.3temperature=0.8,每页使用可复现的独立 seed。
  7. 校验图片、音频、哈希、页码、英文中无中文字符以及隐私边界。
  8. 组装 book.json,再输出可直接打开的定制单文件阅读器。

底层命令也可单独使用:

npm run book:workflow -- create --job-id luna-001 --profile /absolute/path/profile.json
npm run book:workflow -- commit-story --job-id luna-001 --story /absolute/path/story.json
npm run book:workflow -- plan --job-id luna-001
npm run book:workflow -- status --job-id luna-001

图片任务必须使用 imagegen 返回的确切路径:

npm run book:workflow -- start --job-id luna-001 --kind image --task character-sheet
npm run book:workflow -- record-image --job-id luna-001 --task character-sheet --source /exact/imagegen/output.png --reference-ids style-key
npm run book:workflow -- approve --job-id luna-001 --kind image --task character-sheet

TTS 首次试听与全量渲染:

npm run tts:render -- \
  --story .moonlit/jobs/luna-001/stories/story-0123456789abcdef.json \
  --voice-profile .moonlit/voices/family-narrator \
  --model-dir .local-models/chatterbox-multilingual-v3 \
  --tokenizer-dir .local-models/s3-tokenizer-v2 \
  --output-dir .moonlit/jobs/luna-001/tts \
  --exaggeration 0.7 \
  --cfg-weight 0.3 \
  --temperature 0.8 \
  --seed 20260804 \
  --pages 1

# 第 1 页试听通过后,去掉 --pages 1 再运行一次。

上面的故事文件名只是格式示例;实际路径必须从该任务的 manifest.json 读取,不能猜哈希。

逐页 record-audioapprove 后完成组装与发布:

npm run book:workflow -- record-audio \
  --job-id luna-001 \
  --task page-01 \
  --source .moonlit/jobs/luna-001/tts/page-01.mp3 \
  --tts-manifest .moonlit/jobs/luna-001/tts/tts-manifest.json
npm run book:workflow -- approve --job-id luna-001 --kind audio --task page-01

npm run book:workflow -- assemble --job-id luna-001
npm run book:workflow -- validate --job-id luna-001
npm run build
node scripts/build-single-preview.mjs \
  --book .moonlit/jobs/luna-001/book.json \
  --output dist/luna-001.html

单文件构建只内联 book.json 精确引用的封面、画风锚点、角色设定图、12 页插画和 12 条 MP3;会拒绝声音参考、转录稿、同意记录及 private/ 路径。

数据结构

最终书使用 PictureBook schema 1.1,并保留最初要求的核心字段:

{
  "book_title": "",
  "child_name": "",
  "pages": [
    {
      "page": 1,
      "image": "",
      "english": "",
      "chinese": "",
      "audio": ""
    }
  ]
}

此外还保存固定的 art_direction、角色参考和每页 image_generation 规范。生产状态、私密声音资料、模型权重和缓存不写入最终书。

关键文件

  • AGENTS.md:用户说“运行这个程序”时的 Codex 一键启动与续作规则
  • scripts/start-local.mjs:自动安装、复检、启动、端口复用和打开浏览器的一键入口
  • workflow/styles/moonlit-watercolor-v1/style.json:固定画风契约
  • scripts/book-workflow.mjs:可恢复任务 CLI
  • workflow/tts/render_cloned_book.py:本地克隆试听与批量渲染
  • scripts/build-single-preview.mjs:定制书单文件发布器
  • src/config/runtimeBook.ts:运行时注入并校验定制 book.json
  • src/services/createBookSubmission.ts:表单到本地生产服务的私有 multipart 契约
  • src/types/narration.ts:只存在于生成请求中的声音数据类型
  • src/data/luna-book.json:12 页 demo 数据
  • skills/moonlit-book-workflow/SKILL.md:仓库内可安装的 Codex 生产 Skill
  • scripts/setup-local.mjs:Apple Silicon 本机安装入口
  • scripts/doctor.mjs:只读环境自检与 JSON 报告

验证

npm test
npm run build

npm test 覆盖任务恢复/依赖、哈希和路径安全、私密语音隔离、定制书注入、单文件资源内联、英文中混入中文的拒绝以及 TTS 缓存和单页试听选择。

About

Reusable AI English picture-book workflow with consistent illustrations and local Chatterbox TTS.

Resources

Stars

170 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages