# 恢复已有视频 API 任务，再保存生成结果

这是面向 MiniMax H3 公共 API 的 Node.js 24 技术配方。它只接收**已有任务 ID**，没有创建生成任务的操作。配套证据来自已执行的**本机 localhost 测试夹具**，不是生产生成、模型效果测试，也不代表线上服务此刻可用。

## 核对过的接口契约

源码提交：`a4818c0862ec04ac75e871ab114bcb5fa3152550`。

- `src/app/api/v1/tasks/[id]/route.ts`：`GET /api/v1/tasks/{id}`，Bearer 认证，检查任务所属 API 用户及 `public_api_v1` 来源，验证任务 ID，找不到或不属于该用户时返回 404。
- `src/shared/services/public-api.ts`：直接返回任务对象，没有 `data` 包裹。公开状态只有 `processing`、`completed`、`failed`；内部取消状态归入 `failed`。成功结果在 `output.video_url`。已完成但无可用输出时，序列化结果会转成 `failed`。
- `src/shared/lib/public-api-contract.ts`：限制为每 60 秒 30 次请求，429 使用 `Retry-After`。本配方正常每 5 秒查询一次，重试仍受总期限和次数限制。

在网页工作台创建的任务可能不属于公共 API 查询范围。404 应先检查任务 ID、所属用户与来源，不应自动新建付费任务。查询会刷新已有任务状态，本客户端不会提交新生成任务。

## 1. 先运行可重复的本机测试

把 `client.mjs` 和 `run-fixture.mjs` 下载到同一目录：

```sh
node --version
node run-fixture.mjs
```

测试服务器仅绑定 `127.0.0.1` 的临时端口，使用假凭据，并在 `finally` 中关闭服务器、删除临时输出。结果写入 `execution-receipt.json`。本次 Node v24.14.0 实际运行通过 24 项场景，没有访问生产 API，也没有提交付费任务。测试媒体只是带 MP4 `ftyp` 前缀的 64 字节数据，**不是可以播放或已经解码的生成视频**。

## 2. 准备已存在的公共 API 任务

使用此前公共 API 返回的任务 ID，以及该任务所属用户的 API 密钥。密钥只放在进程环境变量 `SEEDANCE_API_KEY` 中，不写进命令参数、源码或检查点文件。在你控制的机器运行，不放到浏览器前端。客户端只向 `https://minimaxh3.studio/api/v1/tasks/{id}` 发送密钥。

## 3. 指定保存目录，继续查询同一个任务

```sh
node client.mjs --task YOUR_EXISTING_API_TASK_ID --out ./saved-video
```

上述命令假设你已安全设置环境变量，不要把真实密钥粘贴进去。输出文件名为通过校验的任务 ID 加 `.mp4`。检查点只存任务 ID、状态与最终文件校验信息，不存密钥、原始响应或签名媒体 URL。再次运行相同命令会继续查询原任务；若本地完成文件已存在，只有尺寸和 SHA-256 与检查点一致才能复用。

## 4. 明确允许真实的托管媒体来源

默认只允许 `https://minimaxh3.studio` 下载来源。若任务返回的托管地址位于其他来源，先根据任务响应与存储配置核对其准确 HTTPS 来源，再显式加入：

```sh
node client.mjs --task YOUR_EXISTING_API_TASK_ID --out ./saved-video --media-origin https://YOUR_VERIFIED_MEDIA_HOST
```

下载请求不带 API 密钥。重定向、URL 内用户名密码、未允许的来源、非 MP4 Content-Type 都会被拒绝。允许一个来源不代表该来源的每个 URL 都是安全且有效的视频。签名地址可以有查询参数，仅在内存中使用，不写入检查点。

## 5. 限制等待和下载，核对落盘文件

默认总期限 10 分钟，最多 120 次任务请求，单次请求最多 30 秒，处理中每 5 秒查询一次，媒体最大 256 MiB。429 与 503 在这些限制内重试；数字或 HTTP 日期形式的 `Retry-After` 最多等待 60 秒。401、404 或 `failed` 会退出，不创建替代任务。媒体流停滞也受请求超时约束。

```sh
node client.mjs --task YOUR_EXISTING_API_TASK_ID --out ./saved-video --timeout-ms 300000 --max-bytes 52428800
```

下载先写入独占临时文件，检查尺寸、类型与 MP4 前缀，再计算 SHA-256，不覆盖已有目标文件。如果你有独立可信的校验值，可以增加 `--sha256 YOUR_TRUSTED_64_CHARACTER_LOWERCASE_SHA256`。客户端自己计算的哈希只能证明本地字节一致，不能证明模型来源、解码质量或内容正确。真实视频还需单独播放与检查。

## 6. 根据错误决定下一步

| 现象 | 处理方式 |
|---|---|
| `not_found` / `unauthorized` | 检查任务 ID、公共 API 地址、密钥所属用户和权限，不自动重新生成。 |
| `poll_limit_exceeded` / `deadline_exceeded` | 保留检查点，核对服务状态后继续查询相同任务。 |
| `task_failed_*` | 查看真实错误，另行核对账单状态；本客户端不承诺或执行退款。 |
| `unapproved_output_url` | 核对托管媒体来源后再改允许列表。 |
| `download_too_large`、`checksum_mismatch`、`invalid_mp4_prefix` | 核对预期尺寸、格式与独立校验值；失败的临时媒体会清理。 |
| `output_exists` | 检查现有文件与检查点；不相关时使用新的目录。客户端拒绝覆盖。 |

## 验收与证据边界

- 测试流量只有 localhost GET；媒体请求不带 Authorization。
- 检查点指向原任务，不含密钥和交付 URL。
- 完成文件的字节数、SHA-256 与检查点一致。
- 失败、用户不符、限流、超时、路径/软链接、来源、重定向、尺寸和哈希错误均不会提交新任务。
- 本次测试没有验证线上凭据、线上任务可见性、提供商完成情况、视频解码、生成质量、结算/退款或搜索流量。

历史关键词证据支持 API 集成主题家族，并没有证明本页具体 slug 的搜索量。
