# 后台转码链路打通 ## 现状取证 - 上传完成时 `MediaService.complete` 已为视频调用 `TranscodeService.enqueue`。 - 分集创建/替换视频地址时 `EpisodeService` 已调用 `EpisodeTranscodeBindingService.bind`,会复用并绑定同一媒体的未完成任务。 - 转码失败原因已写入 `transcode_task.error_msg`,最终状态写入 `status`。 - 缺口是后台手动触发/重转接口,以及对应幂等和链路测试。 ## 实现 1. 保留上传完成和改片自动入队逻辑,补测试锁定行为。 2. `TranscodeService` 增加手动触发: - QUEUED/RUNNING 直接返回现有任务; - FAILED 重置原任务为 QUEUED; - SUCCESS 才创建新任务,紧接着重复触发会复用新 QUEUED 任务。 3. 新增 `POST /admin/media/{id}/transcode`,校验媒资存在,复用 `episode:upload`。 4. 返回任务 id 与状态,便于后台提示。 实现时对同一媒资行使用 `FOR UPDATE`,让重复请求在事务内串行判定; 平台不存在的媒资保持 `DATA_NOT_FOUND`,不产生任务或 500。 ## TDD 测试矩阵 | 场景 | 断言 | | --- | --- | | 视频上传完成 | `MediaService.complete` 调用一次 `enqueue(assetId, 0, 0, sourceUrl)` | | 图片上传完成 | 不创建转码任务 | | 手动触发成功媒资 | 新建一个 QUEUED 任务,重复调用复用同一任务 | | 手动触发进行中媒资 | 直接返回 QUEUED/RUNNING 任务,不新增记录 | | 手动触发失败媒资 | 原任务重置为 QUEUED,保留任务 id | | 媒资不存在 | 返回既有 `DATA_NOT_FOUND`,控制器不产生 500 | | worker 最终失败 | 任务状态 FAILED,`error_msg` 保留 ffmpeg 原因 | ## 验证 - 先提交失败测试,再提交实现。 - `mvn -pl fruitshorts-module-media,fruitshorts-transcode-worker test` - 不启停任何服务,不执行数据库变更,不改 Web/Flutter/specs/API 文档。