本文档引用的文件
本故障排除文档面向AI有声书生成平台的运维与开发团队,聚焦以下典型问题:
后端采用Koa框架,模块化组织TTS、播放器、书籍生成、队列、鉴权、支付等业务;前端基于uni-app,提供App/H5/小程序多端运行。
graph TB
subgraph "服务端"
A["应用入口<br/>server/src/app.ts"]
B["配置中心<br/>server/src/config/index.ts"]
C["错误处理中间件<br/>server/src/middleware/errorHandler.ts"]
D["日志服务<br/>server/src/services/logger.service.ts"]
E["TTS服务<br/>server/src/modules/tts/tts.service.ts"]
F["播放器服务<br/>server/src/modules/player/player.service.ts"]
G["存储服务<br/>server/src/services/storage.service.ts"]
H["OSS服务<br/>server/src/services/oss.service.ts"]
I["Redis服务<br/>server/src/services/redis.service.ts"]
J["WebSocket服务<br/>server/src/services/websocket.service.ts"]
K["性能监控中间件<br/>server/src/middleware/performance.ts"]
L["数据库Schema<br/>server/prisma/schema.prisma"]
end
A --> B
A --> C
A --> D
A --> E
A --> F
A --> G
G --> H
A --> I
A --> J
A --> K
A --> L
图示来源
章节来源
章节来源
系统由Koa应用承载,通过中间件链处理请求,路由分发至各模块控制器;TTS服务负责音频合成与上传,播放器服务负责章节合并与播放进度;存储层支持OSS与本地;缓存层为Redis;日志与性能监控贯穿全链路;数据库使用Prisma/MySQL。
graph TB
Client["客户端/浏览器/App"]
Koa["Koa应用<br/>server/src/app.ts"]
MW1["错误处理<br/>errorHandler.ts"]
MW2["性能监控<br/>performance.ts"]
MW3["HTTP日志<br/>logger.service.ts"]
Routers["路由注册<br/>/api/*"]
TTS["TTS服务<br/>tts.service.ts"]
Player["播放器服务<br/>player.service.ts"]
Store["存储服务<br/>storage.service.ts"]
OSS["OSS服务<br/>oss.service.ts"]
Redis["Redis服务<br/>redis.service.ts"]
WS["WebSocket服务<br/>websocket.service.ts"]
DB["数据库<br/>Prisma/MySQL"]
Client --> Koa
Koa --> MW1
Koa --> MW2
Koa --> MW3
Koa --> Routers
Routers --> TTS
Routers --> Player
TTS --> Store
Store --> OSS
Player --> DB
TTS --> DB
Koa --> Redis
Koa --> WS
Koa --> DB
图示来源
预览音频:短文本快速生成,Mock模式生成占位文件。
sequenceDiagram
participant C as "客户端"
participant T as "TTS服务"
participant P as "提供商(阿里云/Minimax/Mock)"
participant M as "音频合并器"
participant S as "存储服务"
participant W as "WebSocket"
C->>T : "提交生成请求"
T->>T : "选择提供商/分段/并发"
loop "按批生成"
T->>P : "合成音频片段"
P-->>T : "本地文件/云端URL"
end
alt "存在云端URL"
T->>T : "下载云端音频"
T->>S : "上传到OSS/本地"
else "仅本地文件"
T->>M : "合并音频"
T->>S : "上传到OSS/本地"
end
T->>T : "生成LRC歌词/更新章节/记录"
T->>W : "推送生成完成事件"
T-->>C : "返回音频URL/状态"
图示来源
章节来源
最近播放:关联书籍封面与标题,计算进度百分比。
flowchart TD
Start(["开始"]) --> CheckLevel["检查章节级别(level=1?)"]
CheckLevel --> |否| ReturnUrl["返回原音频URL"]
CheckLevel --> |是| ListSections["列出子节(level=2)"]
ListSections --> HasSections{"是否有子节?"}
HasSections --> |否| ReturnNull["返回null"]
HasSections --> |是| ListSubs["列出小节(level=3)音频"]
ListSubs --> HasAudios{"是否有音频?"}
HasAudios --> |否| ReturnNull
HasAudios --> |是| Merge["合并音频并写入uploads"]
Merge --> Update["更新章节audioUrl"]
Update --> Done(["结束"])
图示来源
章节来源
连接测试:本地创建/删除测试文件,OSS获取Bucket信息。
classDiagram
class StorageService {
-storageType
+uploadAudio()
+uploadVideo()
+uploadCover()
+uploadFile()
+uploadBuffer()
+deleteFile()
+deleteDirectory()
+downloadFile()
+getSignedUrl()
+testConnection()
}
class OSSService {
-client
-bucket
-cdnDomain
+uploadFile()
+uploadBuffer()
+uploadAudio()
+uploadVideo()
+uploadCover()
+deleteFile()
+deleteDirectory()
+getSignedUrl()
+downloadFile()
+getFileUrl()
+testConnection()
}
StorageService --> OSSService : "OSS模式委托"
图示来源
章节来源
Winston日志:控制台、错误文件、综合文件、HTTP文件,记录请求耗时与用户代理。
sequenceDiagram
participant Client as "客户端"
participant App as "Koa应用"
participant MW as "错误处理中间件"
participant Log as "Winston日志"
Client->>App : "请求"
App->>MW : "进入中间件链"
MW-->>App : "抛出错误"
App->>Log : "记录错误与堆栈"
App-->>Client : "统一错误响应"
图示来源
章节来源
指标路由:返回总请求数、平均响应时间、慢请求数、错误数、端点明细与错误率。
flowchart TD
Req["请求到达"] --> Start["记录开始时间"]
Start --> Next["执行后续中间件/路由"]
Next --> Ok{"是否成功?"}
Ok --> |是| Calc["计算耗时并更新指标"]
Ok --> |否| Err["错误计数+端点错误计数"]
Calc --> Slow{"是否慢请求?"}
Slow --> |是| Warn["记录慢请求警告"]
Slow --> |否| Resp["设置响应头X-Response-Time"]
Err --> Throw["抛出错误"]
Resp --> End["返回响应"]
Throw --> End
图示来源
章节来源
关键索引:用户phone/openid、订单userId/status/orderNo、播放记录userId/chapterId唯一、书籍userId/status等。
erDiagram
USER {
int id PK
string phone UK
string openid UK
string nickname
string avatar
int memberLevel
datetime memberExpireAt
int dailyUsage
string lastUsageDate
int usedAudioMinutes
datetime subscriptionResetDate
datetime createdAt
datetime updatedAt
}
BOOK {
int id PK
int userId
string title
string subtitle
text description
string coverUrl
string targetAudience
string style
string bookScale
int totalChapters
int estimatedWords
int progress
boolean isPublished
longtext outlineJson
text foreword
text afterword
text errorMsg
string failedStage
string genStage
string status
text bookAnalysis
datetime createdAt
datetime updatedAt
}
BOOKCHAPTER {
int id PK
int bookId FK
int parentId
int level
int number
string title
longtext content
int wordCount
text contentError
datetime generatedAt
string audioUrl
int audioDuration
string videoUrl
int videoDuration
boolean isPublic
string genStage
longtext lrcLyrics
string status
datetime createdAt
datetime updatedAt
}
PLAYRECORD {
int id PK
int userId FK
int chapterId FK
float progress
float duration
datetime createdAt
datetime updatedAt
}
ORDER {
int id PK
int userId
string orderNo UK
int planId
string productType
decimal amount
string status
string paymentMethod
string paymentId
datetime paidAt
datetime createdAt
datetime updatedAt
}
SUBSCRIPTIONPLAN {
int id PK
string name
int level
decimal priceMonthly
decimal priceYearly
text description
text features
boolean isRecommended
boolean isActive
int sortOrder
int dailyGenerations
int perGenerationLimit
int monthlyTokens
int monthlyMinutes
int yearlyTokens
int voiceOptions
string audioQuality
boolean apiAccess
boolean batchProcessing
boolean teamManagement
boolean overageEnabled
decimal overagePrice
datetime createdAt
datetime updatedAt
}
SUBSCRIPTION {
int id PK
int userId
int planId FK
datetime startDate
datetime endDate
string status
boolean autoRenew
datetime createdAt
datetime updatedAt
}
TOKENBALANCE {
int id PK
int userId UK
int totalTokens
int usedTokens
datetime resetDate
datetime createdAt
datetime updatedAt
}
TOKENUSAGE {
int id PK
int userId
string type
int amount
int contentLength
int orderId
text description
datetime createdAt
}
AUDIORECORD {
int id PK
int userId
string audioId UK
string title
longtext text
int wordCount
string voiceId
string voiceParams
string audioUrl
int audioDuration
int audioSize
string status
text errorMsg
int bookId
datetime createdAt
datetime updatedAt
}
USER ||--o{ BOOK : "拥有"
BOOK ||--o{ BOOKCHAPTER : "包含"
USER ||--o{ PLAYRECORD : "播放"
BOOKCHAPTER ||--o{ PLAYRECORD : "被播放"
USER ||--o{ ORDER : "下单"
SUBSCRIPTIONPLAN ||--o{ SUBSCRIPTION : "被订阅"
USER ||--o{ SUBSCRIPTION : "订阅"
USER ||--o{ TOKENBALANCE : "拥有"
USER ||--o{ TOKENUSAGE : "产生"
ORDER ||--o{ TOKENUSAGE : "关联"
AUDIORECORD }o--|| BOOKCHAPTER : "属于章节"
图示来源
章节来源
关键耦合点:TTS服务依赖存储服务与WebSocket;播放器服务依赖数据库与合并器;存储服务依赖OSS或本地文件系统;Redis提供缓存能力;日志与性能中间件贯穿全链路。
graph LR
App["server/src/app.ts"] --> Sentry["Sentry初始化"]
App --> DB["connectDatabase()"]
App --> Redis["redisService.testConnection()"]
App --> Storage["storageService.testConnection()"]
App --> WS["initWebSocket()"]
App --> Queue["initBookGenerationQueue()"]
TTS["tts.service.ts"] --> Storage
TTS --> WS
Player["player.service.ts"] --> DB
图示来源
章节来源
章节来源
章节来源
章节来源
章节来源
章节来源
章节来源
章节来源
章节来源
章节来源
章节来源
章节来源
章节来源
章节来源
本故障排除文档围绕TTS生成、播放器、存储、缓存、日志、性能与第三方服务等关键环节提供了系统化的诊断与解决路径。建议在生产环境中: