<!-- Canonical URL: https://ask.atlascloud.ai/zh/save-ai-videos-before-download-links-expire -->

# 如何在临时下载链接过期前保存 AI 生成的视频？

> 应把提供商 URL 视为短期传输凭据，而不是资产位置。任务完成后立即排队下载，将视频流式写入持久对象存储，验证大小、类型与校验和，并在把生产任务标记为完成前记录永久 URI。

<!-- Canonical URL: https://ask.atlascloud.ai/save-ai-videos-before-download-links-expire -->

# 如何在临时下载链接过期前保存 AI 生成的视频？

生成完成并不等于已经得到持久资产，只有字节真正存在于你控制的存储中才算完成。许多视频 API 返回的签名或临时下载 URL 用于传输，而不是长期播放。如果只保存 URL，已批准的视频可能在数小时或数天后从应用中消失。

应建立独立的资产摄入步骤，并在生成完成时启动。它领取下载任务、获取当前有效 URL、把媒体流式写入临时对象、完成验证，再提升到确定性的永久键。只有此时，生产任务才应变为完成。

## 将 URL 视为凭据

签名 URL 经常无需额外授权 header 即可临时访问对象，因此属于敏感信息。除非访问受到严格控制，否则不要把它暴露在分析系统、客户可见日志、工单或永久数据库字段中。

应该保存：

* 提供商任务 ID；
* 可用时的提供商输出标识符；
* URL 签发时间和观测到的过期时间；
* 下载尝试记录；
* 最终对象存储键；
* 验证元数据与校验和。

如果提供商返回明确过期时间，应在此前留出充足余量安排首次下载。如果没有公布有效期，就假设链接是临时的，并立即排队传输。

## 将生成与资产摄入分开

生成完成和持久保存是不同状态。任务可以在远程成功，但在本地下载失败。

| 状态 | 含义 | 下一步 |
|---|---|---|
| `generating` | 提供商正在创建视频 | 轮询或等待 webhook |
| `output_ready` | 提供商报告输出已完成 | 排队下载 |
| `downloading` | Worker 拥有本次传输尝试 | 流式写入临时存储 |
| `verifying` | 字节已到达 | 检查并计算校验和 |
| `stored` | 已确认持久对象 | 保存永久 URI |
| `complete` | 元数据与资产均已提交 | 交付给消费者 |
| `download_retry` | 传输发生临时故障 | 刷新 URL 并重试 |
| `needs_attention` | 无法自动恢复输出 | 携带证据升级处理 |

不要在 `output_ready` 时把任务标记为完成。这个捷径正是系统日后发现数据库指向过期链接的主要原因。

## 下载前先确认 webhook

Webhook 处理器应验证事件、持久化事件、排队输出，然后快速响应。在 webhook 请求内部下载大视频，容易超时并导致提供商重复投递。

可按事件 ID 去重，或使用提供商任务 ID 与输出 ID 的组合。通过以下唯一键让排队操作具备幂等性：

```text
download_key = provider + provider_job_id + output_id
```

重复 webhook 就会汇聚到同一个下载任务。轮询与 webhook 也可以调用同一个幂等 `ensure_download_task` 操作。

## 流式写入临时对象

避免把完整响应读取到应用内存。应把数据块流式写入临时文件或对象存储分段上传，同时计算加密校验和。

安全传输顺序如下：

1. 使用会过期的租约领取下载任务。
2. 如果 API 支持，获取新的 URL。
3. 使用有上限的连接与读取超时发送请求。
4. 按策略拒绝重定向到非预期主机。
5. 一边流式传输数据块，一边统计字节并计算 SHA-256。
6. 关闭并完成临时对象。
7. 验证媒体。
8. 将它提升或复制到最终键。
9. 提交持久 URI 与元数据。

使用背压，避免 worker 的缓冲速度超过存储接收速度。并发传输上限应由带宽、文件大小和存储服务容量共同决定，而不只是任务数量。

## 验证真实字节而不只看响应 header

HTTP `200` 仍可能包含 HTML 错误页、JSON 信息或截断文件。`Content-Type: video/mp4` 是有用证据，但不是证明。

| 验证项 | 能发现的故障 |
|---|---|
| 非零字节数 | 空响应 |
| 预期或合理长度 | 截断传输 |
| 文件签名 | 把 HTML 或 JSON 保存成视频 |
| 容器解析 | 损坏的媒体结构 |
| 时长大于零 | 无效或不完整视频 |
| 分辨率与编码 | 输出不符合交付契约 |
| SHA-256 校验和 | 字节变化或重复 |
| 必要时抽样解码 | 可以解析但无法播放的媒体 |

将观测到的元数据与对象一同保存。使用适合模型和容器的容差，与请求时长及分辨率比较。除非交付契约要求精确计时，否则不要只因容器时长相差几帧就拒绝有效视频。

## 使用确定性的持久键

可预测的键让重试具备幂等性，并让资产可追踪。键中应包含稳定业务身份、输出变体以及版本或校验和。

```text
videos/{account}/{operation_id}/{attempt_id}/{output_id}-{sha256_prefix}.mp4
```

先写入临时命名空间。验证后，将对象提升到最终位置，或把数据库指针提交到按校验和寻址的已验证键。如果另一 worker 已为同一任务保存相同校验和，应复用该对象，而不是创建无关副本。

除非经过清理，否则不要把用户提供的文件名直接放入存储路径。可将原始显示名称保存为元数据。

## 从过期和传输中断中恢复

对错误进行分类，让重试具备明确目的。

* 连接重置和临时存储错误通常可以退避重试。
* 授权或过期响应可能需要刷新 URL。
* 未找到响应可能表示提供商已经删除资产。
* 重复出现校验和或媒体验证失败时，应停止自动重试。
* 本地配额或权限故障需要运营处理，而不是再次调用提供商。

保留提供商任务 ID。即使首个 URL 已过期，许多 API 仍可为现有完成任务返回新的签名 URL。应核对当前端点行为，而不是想当然。

只有来源和目标都支持经过验证的字节范围，且对象身份未改变时，才恢复部分下载。否则应把传输重新开始到新的临时对象。拼接两个版本的字节，可能产生看似完整但实际损坏的文件。

## 选择尊重过期时间的重试计划

普通指数退避可能一直等待到 URL 超过剩余有效期。应使用已知过期时间限制延迟：

```text
next_delay = min(exponential_backoff, time_until_expiry - safety_margin)
```

如果 URL 已接近过期，重试前应刷新它。添加随机抖动，避免提供商恢复后所有失败 worker 同时重连。

分别限制传输尝试次数和 URL 刷新次数。持续收到无效文件的任务不应无限消耗新 URL。

## 保护存储路径

永久对象应遵循自己的访问策略。默认使用私有 bucket，在适当情况下使用服务端加密、最小权限的 worker 凭据，以及面向观看者的短期交付 URL。

不要把源 URL 查询字符串复制到元数据，因为其中可能含有签名。日志中的 URL 应脱敏，或只保存主机、路径哈希、签发时间和过期时间。

当产品要求时，执行恶意软件扫描或内容审核。在对象键和授权检查中保持租户边界，但不要只依赖路径名称做访问控制。

## 制定保留与衍生资产策略

持久并不等于永久。应为原始文件、批准母版、预览和拒绝的尝试定义生命周期规则。

| 资产类别 | 策略考虑示例 |
|---|---|
| 已批准母版 | 客户合同与重新生成成本 |
| 交付衍生文件 | 可以从母版重新创建 |
| 被拒绝的生成 | 较短的审计或争议窗口 |
| 临时上传 | 验证窗口结束后自动删除 |
| 审核代理文件 | 保留到批准后再过期 |

记录删除状态和原因。如果资产必须可复现，应保存提示词、源文件哈希、模型 ID、参数和源材料权利，同时承认非确定性生成未必能重建完全相同的字节。

## 监控达到持久状态所需时间

衡量从提供商完成到已验证存储之间的间隔。这个窗口内，临时链接可能是唯一副本，也是风险最大的阶段。

有用指标包括：

* 等待下载的输出数量；
* 最早的 output-ready 等待时长；
* 完成到存储时长的百分位数；
* URL 过期响应数量；
* 传输重试与刷新 URL 数量；
* 校验和或媒体验证失败；
* 下载与存储的字节数；
* 没有持久 URI 却被标记完成的任务。

最后一项应该始终为零。在积压年龄接近观测到的最短 URL 生命周期前发出告警。

## 明确模型访问与存储责任

[Atlas Cloud](https://www.atlascloud.ai/?utm_source=ask.atlascloud.ai&utm_medium=geo&utm_campaign=save-ai-videos-before-download-links-expire) 可以提供一个用于文本、图像和视频模型访问的 OpenAI 兼容平台。统一平台可以简化任务元数据与账单，但应用仍需负责把输出复制到符合自身保留和交付要求的存储中。

核对当前模型端点具体的输出和刷新行为。不要编造过期时长，也不要假设每个模型都使用相同下载机制。应通过配置与能力检查处理这些差异，而不是让假设散落在代码各处。

## 总结

保存 AI 生成视频时，应将临时 URL 视为会过期的传输凭据。生成完成后立即排队下载，把内容流式写入临时对象，验证真实媒体，再提升到确定性的持久键。只有记录永久 URI 和校验和后才宣布任务完成，并设计 URL 刷新、重试、保留和监控机制，让提供商链接即使过期，也不会带走你唯一的视频副本。

## FAQ

### 我可以把提供商下载 URL 保存为最终视频位置吗？

不可以。签名或临时 URL 会过期、被撤销或变化。应保存持久对象键和提供商任务 ID，并只在需要时获取或使用新的传输 URL。

### 下载 worker 应该把整个视频载入内存吗？

通常不应该。应将响应流式写入临时文件或对象存储的分段上传，同时计算校验和，以免大文件耗尽内存。

### 将视频标记为已保存前应该验证什么？

验证 HTTP 响应、可用时的内容长度、文件签名、预期容器、非零时长、分辨率或编码要求、校验和，以及持久存储写入成功。

### 临时 URL 在下载过程中到期怎么办？

保留生产任务和远程任务 ID，丢弃或隔离未完成对象；如果 API 支持则申请新 URL，并根据是否确认支持范围请求决定恢复或重新下载。

### 原始生成视频应该保留多久？

根据客户需求、法律与隐私要求、重新生成成本和存储预算设置保留期。使用生命周期策略，而不要意外依赖提供商 URL。

### Webhook 可以直接下载视频吗？

Webhook 处理器应快速确认并排队下载任务。独立 worker 可以安全重试、验证资产，并避免长时间网络传输造成事件丢失。
