角色: 后端开发 状态: pending 分配的任务: OPT-02, OPT-08, OPT-12, OPT-17 及相关 API
| 优化项 | 后端变更 |
|---|---|
| OPT-02 | WebSocket 推送 audio_generation_complete, video_generation_complete 事件 |
| OPT-03 | 提供 /api/player/recent 最近播放记录 API |
| OPT-08 | POST /api/book-generator/books/:id/batch-generate 编排接口 |
| OPT-12 | POST /api/feedback 反馈提交接口 |
| OPT-17 | TTS 生成时返回 LRC 格式时间戳 |
文本内容生成和 TTS 音频生成逻辑审查,发现以下待优化问题
| # | 分类 | 问题 | 优先级 | 文件 |
|---|---|---|---|---|
| BK-1 | 状态机 | safeTransitionChapter 状态冲突时静默 return,调用方无法感知失败 |
P0 | stage-manager.ts:98-121 |
| BK-2 | 状态机 | 书籍阶段计算用"最落后章节",一坏俱坏,无法查看已完成章节 | P0 | book-generator.store.ts:24-75 |
| BK-3 | 内容生成 | 父节点完成检查只验证直接子节点,不递归检查所有后代 | P0 | content.node.ts:22-59 |
| BK-4 | 状态机 | 内容生成两阶段推进(content_generating → content_completed)存在竞态 | P1 | book-generator.store.ts:1600-1618 |
| BK-5 | TTS | realtime 长文本模式被强制禁用(shouldUseLongText 恒返 false) | P1 | tts.service.ts:95-97 |
| BK-6 | TTS | Provider 全部降级后无兜底,直接抛错无 fallback | P1 | tts.service.ts:537-538 |
| BK-7 | TTS | processAudioGeneration 写 audioUrl 后 onComplete 再做 advanceChapter,任一失败导致 tryAutoMerge 不触发 |
P1 | book-generator.store.ts:1326-1348 |
| BK-8 | TTS | LRC 生成对无标点纯英文文本按40字硬切,LRC行数爆炸 | P2 | tts.service.ts:884-895 |
// stage-manager.ts:98-121
if (result.count === 0) {
// ... 状态冲突处理
console.warn(`[safeTransition] 章节 ${chapterId} 状态冲突...`);
return; // ← 问题:调用方以为成功了,继续执行下游
}
建议:失败时 throw Error,或返回 boolean 让调用方判断。
// book-generator.store.ts:24-75
let minIdx = stageOrder.length;
for (const ch of chapters) {
if (idx < minIdx) minIdx = idx; // 取最小(最落后)阶段
}
影响:20章中1章 failed,整本书显示 failed,用户无法访问其他19章已完成的音频。
建议:增加 book.finishedChapters 字段,与 genStage 解耦;或改用 most_common 逻辑。
// content.node.ts:22-59
const allChildrenDone = children.every(
c => c.genStage === 'content_completed' || c.genStage === 'audio_generating' ...
);
只检查直接子节点(level+1),如果节(level=2)下还有小节(level=3)在 content_generating,节会被错误推进到 content_completed。
建议:递归检查所有后代节点,或改用 BFS 收集叶节点后统一判断。
// book-generator.store.ts:1600-1618
if (currentChapter.genStage !== 'content_generating') {
await advanceChapter(chapterId, 'content_generating').catch(() => {});
}
await advanceChapter(chapterId, 'content_completed');
两次 advanceChapter 之间如果有并发的音频生成任务抢占了 content_generating,第二次调用会失败。
建议:合并为单次 safeTransitionChapter(chapterId, curStage, 'content_completed') 调用。
// tts.service.ts:95-97
export function shouldUseLongText(text: string): boolean {
return false; // 强制返回 false,禁用 realtime 模式
}
注释说 WebSocket 连接问题导致禁用,但 MiniMax 支持100万字符异步模式,长文本应优先走异步而非分段。
建议:修复 WebSocket 问题,启用 MiniMax 异步长文本模式。
// tts.service.ts:537-538
throw new Error('所有 TTS Provider 都已尝试,均无法生成音频');
建议:mock provider 作为最后兜底,保证服务可用性。
// book-generator.store.ts:1326-1348
async (audioUrl: string, duration: number) => {
await advanceChapter(chapterId, 'audio_completed'); // 可能失败
tryAutoMerge(chapterId, ...); // 失败则不会触发
}
建议:用 tryAutoMerge 替换 advanceChapter 失败的兜底逻辑,或在 processTtsTask 中等待回调完成后再推进状态。
// tts.service.ts:884-895
const chunkSize = 40; // 纯英文按40字切分,万字文本=250+行
建议:增加英文句号 . 作为断句依据,与中文标点一致处理。
| 任务 | 建议处理人 |
|---|---|
| BK-1, BK-4 | backend-dev(状态机逻辑修复) |
| BK-2 | backend-dev(数据库 schema 变更) |
| BK-3 | backend-dev(递归检查逻辑) |
| BK-5, BK-6, BK-7, BK-8 | backend-dev(TTS 服务层) |