caojunfei
pushed to fix/oss-3tb-orphan at caojunfei/audio_codebuddy
bc37cbfca9 fix(oss): 治根 OSS 3TB 垃圾 (#oss-3tb-orphan)
设计原则: 1 个内容 = 1 个文件, 同一内容 N 次调用永远只覆盖同一 OSS 对象,
垃圾物理上不可能暴涨。
根因:
- audio-scanner 每 30s 触发 mergeChapterAudios
- AudioMerger.merge 远程 URL 分支调 FFmpegProcessor.mergeAudio
- FFmpegProcessor.mergeAudio 内部用 uuidv4() 上传, 每次产生 1 份 UUID 垃圾
- 整个流程 1 个月堆出 3.4TB, 单天涨 100GB
修复:
- storageService.uploadAudioByContentHash(kind, contentKey): sha256 算稳定 key
- tts.service.ts generatePreview/synthesizeSync 改 content-hash 稳定路径
- FFmpegProcessor.mergeAudio 默认 upload=false, 调用方控制
- audio-merger.ts 远程 URL 分支改本地下载+本地合并
- 加 SCANNERS_ENABLED 紧急止血开关 (audio-scanner + book-recovery-scanner)
- uploadChapterAudio 稳定路径 (chapterId -> audio/chapter/{id}/full.mp3)
清理:
- 删 25.9 万个 OSS UUID 孤儿, 释放 3.4TB (3.39TB -> 1.19GB)
- 清 260 个 DB 死链 (audioUrl 指向已删 OSS 文件)
防回归:
- 加 6 个单元测试 (tests/unit/backend/services/storage/stable-key.test.ts)
- 修复 .env.production (bucket=rrbrr-book-audio, region=cn-shanghai)
- 加 deploy 后 OSS 配置校验脚本 (check-oss-config.cjs)
- 加 clean-oss-orphans.cjs / inspect-oss-usage.cjs 应急工具
测试: type-check OK | 138/138 storage/tts/ffmpeg/audio 单元测试 OK
线上: API smoke 200 | 5 分钟 OSS 0 增长 | ffmpeg 0 进程
Co-Authored-By: Claude <noreply@anthropic.com>
5689fdf41e feat(create-book): 将试试示例提示框移到输入框下方
原结构:试试示例 → 输入框 → AI推荐按钮
新结构:输入框 → 试试示例 → AI推荐按钮
理由:用户先看到输入框聚焦核心任务,遇到空白时再看示例获取灵感,
比放在上方引导效果更自然,也避免初始页面太长。
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
d0ff1c72fd chore(tts): 线上部署确认 + bookapi 域名废弃
线上 bookapi.rrbrr.com:
- 现在 book.rrbrr.com 既承载前端(H5)又承载后端 API(/api/* 走 80 端口)
- 老的 bookapi.rrbrr.com 子域名废弃(返回 410)
- 运维想用后端,直接 curl 127.0.0.1:3100 或前端 /api/ 走 book.rrbrr.com
server/src/config/alicloud-tts-lang-voice-matrix.json:
- RECOMMENDED 简化为 6 个通用语种(中文普通话/美英/英英/日/韩/印尼)
- 15 lang_key 完整数据保留,后续 v2 加'高级选项'暴露方言
deploy-package/scripts/build-lang-matrix-json.js:
- RECOMMENDED 同步简化
线上已验证:
- 6 个推荐语言接口返回正常
- zh-CMN 选中文 → 大模型写中文 + 普通话朗读
- en-US 选英文 → 大模型写英文 + 美音朗读
- zh-YUE 暂未在推荐集(粤语属方言,放 v2)
5bc6743050 chore(tts): 入仓本次研究用的辅助脚本
- parse-cosyvoice-dom.py: DOM 文本 → 阿里云 CosyVoice 音色 JSON
- trigger-tts-and-check.js: 触发 TTS 任务入队 + 查 status
- check-tts-result.js: 查 TtsTask 完成状态 + audioUrl
46ca781f32 test(tts): 端到端测试脚本 + toBook 支持 targetLanguage/voiceSpeed
新增 deploy-package/scripts/test-language-e2e.sh:
- 创建 zh-CMN + en-US 各一本书
- 等 AI 生成内容
- 查 Book.targetLanguage + 章节内容语言(中文/英文各一份)
- 触发 TTS 生成
- 查 TtsTask.targetLanguage/preferredVendor/preferredModel
server/src/modules/book-generator/book-generator.store.ts:
- toBook() 补 targetLanguage + voiceSpeed 字段(Prisma client 类型未自动包含,cast)
- 修复 schema 返回字段后,前端 'language 字段未设' 显示问题
server/src/modules/book-generator/book-generator.types.ts:
- BookBase 加 targetLanguage?: string 字段
测试结果(2026-07-12):
- book 77 zh-CMN: 内容='普通话语音合成测试文本'(中文 ✅), audioUrl=OSS ✅
- book 78 en-US: 内容='A Morning at the Corner Café'(English ✅), audioUrl=OSS ✅
- TtsTask 写入 targetLanguage/preferredVendor/preferredModel 三字段固化路由结果
3 weeks ago