# 播课功能技术方案 ## 一、需求背景 课程管理员需要为课程生成播课音频,学员可以在课程卡片上点击"播课"按钮收听课程内容,支持音频播放控制。 ## 二、核心设计 ### 2.1 触发方式 - **管理员手动触发**:在课程编辑页的"学习资料与知识点"选项卡,点击"生成播课"按钮 - **生成范围**:一个课程生成一个综合播课音频(多个资料合并生成) - **存储方式**:只存储 mp3 URL,不存储在本地服务器 ### 2.2 技术选型 | 技术项 | 选型 | 说明 | |--------|------|------| | AI 工作流 | Coze 工作流 | workflow_id: 7561161554420482088 | | SDK | cozepy 0.2.0 | 已安装,与陪练功能共用 | | 认证方式 | Personal Access Token | 与陪练功能共用 token | | 数据库字段 | `broadcast_audio_url` | 存储 mp3 URL | | 前端播放器 | HTML5 audio | 原生支持,无需额外依赖 | ### 2.3 数据流程 ``` 管理员点击"生成播课" → 前端调用后端 API → 后端调用 Coze 工作流 → Coze 生成 mp3 音频 → 返回 mp3 URL → 后端保存到数据库 → 前端显示成功提示 学员点击"播课" → 前端查询播课信息 → 跳转到播放页面 → 加载并播放音频 ``` ## 三、数据库设计 ### 3.1 courses 表新增字段 ```sql ALTER TABLE courses ADD COLUMN broadcast_audio_url VARCHAR(500) NULL COMMENT '播课音频URL', ADD COLUMN broadcast_generated_at DATETIME NULL COMMENT '播课生成时间'; ``` **字段说明**: - `broadcast_audio_url`: 存储 Coze 工作流返回的 mp3 文件 URL - `broadcast_generated_at`: 记录生成时间,用于判断是否需要重新生成 **索引**: 无需额外索引(查询通过主键 course_id) ## 四、后端架构 ### 4.1 配置层 **文件**: `app/core/config.py` ```python class Settings(BaseSettings): # 播课工作流配置 COZE_BROADCAST_WORKFLOW_ID: str = Field(default="7561161554420482088") COZE_BROADCAST_SPACE_ID: str = Field(default="7474971491470688296") ``` ### 4.2 服务层 **文件**: `app/services/coze_broadcast_service.py` **职责**: - 封装 Coze 工作流调用逻辑 - 解析返回的 mp3 URL - 错误处理和日志记录 **关键方法**: ```python class CozeBroadcastService: async def generate_broadcast(self, course_id: int) -> str: """ 调用 Coze 工作流生成播课音频 Args: course_id: 课程ID Returns: mp3 音频文件 URL Raises: CozeError: Coze API 调用失败 ValueError: 返回结果解析失败 """ ``` ### 4.3 API 层 **文件**: `app/api/v1/broadcast.py` **接口1**: 生成播课 - 路径: `POST /api/v1/courses/{course_id}/generate-broadcast` - 权限: manager, admin - 超时: 180秒 - 功能: 调用工作流生成音频,更新数据库 **接口2**: 获取播课信息 - 路径: `GET /api/v1/courses/{course_id}/broadcast` - 权限: trainee, manager, admin - 功能: 查询课程是否有播课以及播课 URL ### 4.4 Schema 定义 ```python class GenerateBroadcastResponse(BaseModel): """生成播课响应""" mp3_url: str = Field(..., description="播课音频URL") generated_at: datetime = Field(..., description="生成时间") class BroadcastInfo(BaseModel): """播课信息""" has_broadcast: bool = Field(..., description="是否有播课") mp3_url: Optional[str] = Field(None, description="播课音频URL") generated_at: Optional[datetime] = Field(None, description="生成时间") ``` ## 五、前端架构 ### 5.1 类型定义 **文件**: `src/types/broadcast.ts` ```typescript export interface BroadcastInfo { has_broadcast: boolean mp3_url?: string generated_at?: string } export interface GenerateBroadcastResponse { mp3_url: string generated_at: string } ``` ### 5.2 API 封装 **文件**: `src/api/broadcast.ts` ```typescript export const broadcastApi = { generate(courseId: number): Promise> getInfo(courseId: number): Promise> } ``` ### 5.3 页面改造 **1. 课程编辑页** (`src/views/manager/edit-course.vue`) 新增功能: - 在"学习资料与知识点"选项卡添加"生成播课"按钮 - 查询并显示播课信息(是否已生成、生成时间) - 生成中显示 Loading 状态 - 生成成功后显示"重新生成"按钮 **2. 播放页面** (`src/views/trainee/broadcast-course.vue`) 播放器功能: - 播放/暂停控制 - 进度条拖动 - 当前时间/总时长显示 - 播放速度调节(1.0x, 1.25x, 1.5x, 2.0x) **3. 课程卡片** (`src/views/trainee/course-center.vue`) 修改播课按钮点击事件: - 查询播课信息 - 如无播课,提示"该课程暂无播课内容" - 如有播课,跳转到播放页面 ## 六、交互流程 ### 6.1 生成播课流程 ``` 1. 管理员进入课程编辑页 2. 切换到"学习资料与知识点"选项卡 3. 点击"生成播课"按钮 4. 前端调用 POST /api/v1/courses/{id}/generate-broadcast 5. 后端调用 Coze 工作流(约10分钟) 6. Coze 返回 mp3 URL 7. 后端更新数据库 broadcast_audio_url 和 broadcast_generated_at 8. 前端显示"生成成功"提示 9. 按钮文本变为"重新生成",显示生成时间 ``` ### 6.2 播放流程 ``` 1. 学员在课程中心查看课程卡片 2. 点击"播课"按钮 3. 前端调用 GET /api/v1/courses/{id}/broadcast 4. 如 has_broadcast=false,显示"暂无播课内容" 5. 如 has_broadcast=true,跳转到播放页面 6. 播放页面加载 mp3 音频 7. 学员使用播放器控制播放 ``` ## 七、性能与安全 ### 7.1 性能优化 - **超时配置**: 前后端统一设置 180 秒超时 - **缓存策略**: 音频 URL 从数据库读取,无需额外缓存 - **CDN 加速**: mp3 文件由 Coze 托管,自带 CDN 加速 ### 7.2 错误处理 | 场景 | 处理方式 | |------|---------| | 工作流调用超时 | 提示"生成超时,请稍后重试" | | 工作流执行失败 | 记录 logid,提示"生成失败,请联系管理员" | | mp3 URL 解析失败 | 记录错误日志,提示"结果解析失败" | | 播放加载失败 | 提示"音频加载失败,请检查网络" | ### 7.3 日志记录 ```python # 生成开始 logger.info(f"开始生成播课: course_id={course_id}, user_id={user_id}") # 生成成功 logger.info(f"播课生成成功: course_id={course_id}, mp3_url={mp3_url}, duration={duration}") # 生成失败 logger.error( f"播课生成失败: course_id={course_id}", extra={"logid": logid, "error": str(error)} ) ``` ## 八、测试策略 ### 8.1 单元测试 - CozeBroadcastService 工作流调用测试 - broadcast API 接口测试 - 前端 broadcastApi 封装测试 ### 8.2 集成测试 - 管理员生成播课端到端测试 - 学员播放端到端测试 - 错误场景测试(无播课、生成失败、播放失败) ### 8.3 性能测试 - 工作流调用耗时(预期 10 分钟左右) - 前端音频加载时间 - 并发生成请求测试 ## 九、部署与监控 ### 9.1 配置检查 部署前确认以下配置: - ✅ COZE_API_TOKEN 正确配置 - ✅ COZE_BROADCAST_WORKFLOW_ID = 7561161554420482088 - ✅ COZE_BROADCAST_SPACE_ID = 7474971491470688296 - ✅ 工作流已在 Coze 平台发布 ### 9.2 监控指标 - 生成成功率(目标 >95%) - 平均生成时长(预期 10 分钟) - 播放失败率(目标 <5%) - Coze API 调用错误率 ## 十、后续优化方向 1. **自动生成**:资料上传后自动触发生成(需评估资源消耗) 2. **进度提示**:显示生成进度(需 Coze 工作流支持进度回调) 3. **音频预览**:生成后在编辑页预览播放 4. **历史版本**:保存多个版本的播课音频 5. **字幕支持**:工作流返回字幕文件,前端同步显示 --- **文档版本**: v1.0 **创建日期**: 2025-10-14 **维护人**: 考培练系统开发团队