Files
dj/huobao-source/docs/video-delivery-implementation.md

10 KiB
Raw Permalink Blame History

视频交付与任务恢复实施方案

采用 Firemux 按渠道异步转存,加短剧端下载恢复。先保存已生成的结果,再进行交付;恢复操作只查询已有任务、下载已有文件,不提交新的生成请求。MiniMax 响应保持 task.status、task.content.url 结构,保留实际时长。

问题依据与处理链路

提供的响应能确认上游任务已成功,但不能确认用户电脑已经下载成功。原实现先下载视频,再保存 result_url;下载异常会使整个本地任务失败,且丢失可供补下载的地址。原 MiniMax 同步响应解析也未保存嵌套 task.id 和实际 duration。这些代码问题足以解释“上游成功、本地失败”的现象;缺少用户电脑日志,无法认定具体网络故障是超时、DNS、签名过期还是其他原因。

当前链路为 Vue/Nuxt 制作页面 → Hono/TypeScript 任务服务 → SQLite sys_task → 厂商适配器 → Firemux Spring Boot 网关 → 上游模型。视频成功后经本地文件存储和 FFmpeg 海报处理回写分镜。新增 Firemux 交付队列使用 MySQL 和已有 COS 配置,把上游媒体下载从用户电脑转移到服务端;短剧端仍需下载自有链接以供本地播放和导出。

实施分为三层:保留直链模式作为兼容开关;对指定渠道启用服务端异步转存;客户端始终具备补下载、重查原任务和重启恢复。自有链接也可能下载失败,因此服务端转存与客户端恢复需要同时保留。

实施范围

部分 实现 交付位置
Firemux MiniMax 后台转存、租约抢占、有限重试、签名链接、交付恢复接口 相邻 firemux 仓库的 gateway/delivery
短剧后端 保存任务来源和生成结果、原子下载、恢复接口、启动恢复、诊断接口 backend/src/services/generation.ts、video-download.ts
短剧前端 URL 在线预览及链接、本地视频自动切换、单条与批量恢复、显式重新生成确认、持续状态同步、复制诊断 frontend/app/views/drama/episode.vue

Firemux 开关关闭时保持上游链接直连;启用后可限制到指定渠道。流式代理和客户端自动多地址竞速不在此次实现范围内。

状态与数据

短剧端继续使用 processing/completed/failed 状态,以兼容已有页面和查询接口。新增 stage 表示 submitting/polling/transferring/downloading/saving/completed,新增 error_code 表示交付失败、上游明确失败、提交结果未知或恢复失败。

sys_task 增加 config_id、config_base_url,只记录配置来源,不复制密钥。旧 SQLite 启动时幂等增加字段。MiniMax 同步结果中的 task.id、响应头中的 Firemux 内部任务 ID、实际 duration 都会保留。视频 URL 在下载前保存,实际时长保存到 params.resultDuration。

生成配置已删除、停用或地址变化时,不任意改用其他配置查询。历史任务没有配置 ID 时,仅允许使用同厂商唯一启用的视频配置;配置不明确时停止恢复并提示核对。

Firemux 增加独立 video_delivery_task 表,保存来源地址、对象 key、状态、次数、下一次执行时间和租约。生成原始状态、原始响应及账单保持原状。对外查询视图反映交付状态:

生成状态 交付状态 MiniMax 查询状态 行为
已成功 等待或转存中 running 不返回上游链接,继续查询
已成功 可下载 succeeded 返回新签名的自有存储链接
已成功 转存失败 failed,error.code=video_transfer_failed delivery.generation_status=succeeded,允许恢复交付

同步上游成功响应也可转为待交付响应,并额外提供顶层 task_id,兼容旧客户端。每次查询签发有效期最多一小时的链接;对象可用期限默认到生成完成后的第六天,不承诺永久保存。

视频展示

任务已有 result_url、尚未完成本地保存时,播放器使用返回 URL,并显示可直接打开的完整链接和“恢复下载”。在线播放加载失败时保留链接及恢复入口。下载完成后自动切换本地文件,并隐藏临时链接提示。HTTP(S) 地址不添加本地路径前缀,保留签名查询参数;临时链接不写为分镜主视频,拼接导出仍使用已保存的视频。历史视频预览同样正确识别远程地址。

恢复接口

  • POST /api/v1/tasks/:id/recover:短剧端只恢复已有任务。已有地址先补下载,失败且有任务 ID 时重新查询;没有地址和任务 ID 的记录拒绝恢复。
  • GET /api/v1/tasks/:id/diagnostics:返回阶段、错误码、任务编号、厂商、模型和时间,移除密钥及签名链接。
  • POST /minimax/v2/query/video_generation/{taskId}/recover:Firemux 在验证原任务归属后重置失败的交付任务,不调用生成或计费服务。
  • 原 POST /api/v1/tasks:同分镜已有运行中任务时拒绝;存在失败任务时,必须显式传入 force_new: true 才允许新生成。页面会提示可能再次计费。

同进程重复恢复由任务锁合并。完成状态与分镜回写在 SQLite 事务内提交;如果同一分镜已创建更晚的视频任务,恢复旧任务只保留历史视频,不覆盖分镜主视频。运行中任务不允许删除。

下载与转存策略

短剧端每次下载最长 120 秒,最多三次尝试,瞬时网络错误及 HTTP 408/429/5xx 退避重试。HTTP 4xx、格式错误、大小超限及本地文件错误不盲目重试。流式写入 .part 文件,校验 MP4/WebM 文件头后原子改名,最大 512 MiB;失败清理临时文件。没有扩展名的视频 URL 也会落为正确的 .mp4 或 .webm。

Firemux 默认每实例最多两个交付任务并行,每个任务有数据库租约;默认扫描周期十秒,租约十五分钟,异常退出后由过期租约恢复。下载总时限 120 秒,独立 COS 客户端每次请求时限 120 秒,不由 SDK 隐式重试。整个一次执行预算低于租约期限。

自动转存最多尝试五次,退避上限五分钟。对象 key 由内部任务 ID 确定;上传成功而数据库写回失败时,下次复用已存在对象。上传时设置 video/mp4 并校验远端对象大小。失败只保留安全错误码,不将带签名 URL 写入诊断日志。

默认只允许 HTTPS 的 files.metaso.cn 下载源;重定向逐跳验证,DNS 解析拒绝私有、回环和链路本地地址,不向视频地址发送渠道鉴权信息。需要新增 CDN 域名时显式加入允许列表。

验收场景

  1. 使用提供的 MiniMax 成功响应,正确解析任务 ID、地址与实际 12 秒时长。
  2. 上游成功、本地下载失败,任务仍保留地址与来源;恢复后生成请求次数不增加。
  3. 同时多次恢复,仅执行一次下载;文件下载中断不残留可见的半成品。
  4. 服务重启,有结果的任务恢复;没有上游编号的中断提交保留为待核对。
  5. 恢复旧任务不覆盖新视频;诊断信息不泄露签名链接和密钥。
  6. Firemux 转存等待期间隐藏源地址,完成后使用自有签名链接;失败不改变生成记录。
  7. 两个工作实例同时抢占只有一个成功;旧租约不能覆盖新租约结果;过期对象不再签发有效链接。
  8. 开关关闭或渠道不匹配时,原有返回内容不变。

上线顺序

  1. Firemux 执行 backend/src/main/resources/sql/20261013_video_delivery.sql,先保持功能开关关闭并发布后端。
  2. 发布带任务恢复功能的短剧前后端;桌面版需重新构建后端和前端资源,源码变更不会更新用户已安装版本。
  3. 检查 COS 配置、存储桶权限与生命周期,确保 video-delivery/ 前缀至少保留七天。
  4. 在 Firemux 测试环境或小范围渠道开启转存,验证自有链接下载、Range 播放和真实文件大小。
  5. 观察转存成功率、排队时间、失败次数与磁盘使用,确认后逐步扩展渠道。

Firemux 的环境变量、回滚和运维命令见相邻仓库 deploy/video-delivery-rollout.md。没有执行生产迁移、开启生产开关或真实视频生成。

本次验证结果(2026-10-13)

  • 短剧任务恢复、下载和适配器测试共 13 项通过;后端 TypeScript 检查、前端静态构建通过。
  • Firemux 转存、存储、原有轮询回归及数据库集成测试共 18 项通过。数据库集成使用独立临时 MySQL 9.5,验证并发抢占、过期租约恢复和旧执行者不能覆盖新结果;部署目标 MySQL 8 仍需发布环境验证。
  • Playwright 使用独立 SQLite、模拟配置和本地生成的测试视频,验证诊断复制、重新生成计费提示、补下载完成后自动显示历史视频和播放器。恢复期间仅调用恢复接口,任务总数未增加。
  • 选取的原有结构检查有 3 项失败;在未改动 HEAD 上复现同样失败,涉及已删除的 mysql-schema.ts、旧前端模型路径匹配和旧 Firemux 域名断言,不是此次新增回归。
  • URL 展示补充验收:浏览器验证远程链接保留签名参数且可播放;点击恢复下载后无需刷新页面,播放器自动切换 /static/videos/task-1.mp4,并隐藏远程链接区域。仅发生恢复请求,没有新增生成请求。
  • 尚未执行真实 COS/CDN 上传和播放、生产数据库迁移或桌面安装包发布。这些属于上述灰度上线验收步骤。

历史任务边界

客户已有任务如果保存了任务编号或视频地址,可以尝试恢复。没有这些信息时,不能仅凭账单截图关联回本地分镜。已失效的上游签名链接如果查询接口不能刷新,也无法保证找回原视频;此时应先人工核对上游记录。

回滚

Firemux 设置 GATEWAY_VIDEO_DELIVERY_ENABLED=false 并重启即可恢复返回原始链接,保留交付表供后续恢复和诊断。新 SQLite 字段均为可空附加字段,回退应用代码时无需删列。不要删除已保存的任务 ID、result_url 或本地媒体文件。