mcpField
V
vidu-video

vidu-video

github.com/calesthio创意与媒体219102 次安装15 周前更新
代码仓库

关于 vidu-video

用于规划 Vidu Open Platform API 视频生成集成的技能,帮助制作团队选择端点与模型、组织参考素材和音频,并在执行前审核请求。

主要功能

  1. 01按生成模式选择端点与模型
  2. 02支持文本、图像、首尾帧及参考视频模式
  3. 03命名主体与多帧工作流
  4. 04按端点配置音频控制
  5. 05试运行规划与审批检查点

适用场景

  1. 01根据文本提示生成视频片段
  2. 02让首帧动画过渡至目标帧
  3. 03使用命名主体生成对话视频
  4. 04提交前规划并审核视频请求

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/calesthio/generative-media-skills --skill vidu-video

安装后在 Claude Code 中输入/vidu-video确认已加载。

附带文件EVAL.md

详细介绍

Vidu 视频

使用此技能为 Vidu Open Platform API 设计生产请求或集成。默认进行试运行规划。未经操作员批准确切的提供方、端点、模型、输入、请求摘要、最高费用、存储目标和披露计划,绝不提交付费生成、上传私人媒体、取消任务或下载结果。

本文档已根据第一方公开文档于 2026-07-10 核实。模型、价格、接受的字段、政策和可用性都可能变化;执行前请立即重新打开链接中的端点和定价页面。

区分不同产品

  • Open Platform API: https://api.vidu.com、API 密钥、组织级限额、异步任务和 API 点数。本文介绍的是这一产品。
  • Vidu 消费者产品: https://www.vidu.com 及其订阅/套餐点数。不要假设其点数、功能、水印行为或条款适用于 API。
  • Vidu-S1 (Beta): 一款独立的交互式数字人产品,使用 HTTP 会话设置、AliRTC 媒体和 WebSocket 控制。它不是 Q3/Q2 视频片段模型。其公开页面目前将“1 分钟至 2 小时”的营销说法与 600 秒的会话上限混在一起。其定价部分另称每 2 秒消耗 3 个 S1 点数,列出的点数单价为 0.03125,每 6 秒扣费,按 2 秒间隔取整,并要求至少 45 个点数才能创建会话。未经书面确认,不要按视频片段 API 的 $0.005 点数价格重新计算这些数据。
  • S1 文档冲突: 第 3 步称,浏览器 WebSocket 身份验证应放在 URL 查询参数中,因为浏览器无法设置自定义标头;但页面的“重要说明”称必须放在授权标头中。此问题尚未解决。实施前请向 Vidu 确认当前传输方式,切勿将 bearer URL 放入日志/分析工具/引用来源中,也不要仅凭示例推断安全的浏览器设计。
  • 中国主机: S1 页面记录了中国区使用 api.vidu.cn,国际版使用 api.vidu.com。本文记录的常规视频片段端点使用 api.vidu.com;不要据此推断计算资源的驻留地。

先选择模式,再选择模型

端点约定比系列名称更权威。某个模型可能存在,但不一定支持所有模式。

需求端点当前适合生产环境的选项重要限制
仅提示词POST /ent/v2/text2videoviduq3-turbo、viduq3-pro;仅在有明确兼容性需求时使用 Q2/Q1Q3:1–16 秒,540p/720p/1080p;宽高比 16:9、9:16、3:4、4:3、1:1
动画化一张起始图像POST /ent/v2/img2videoQ3 pro-fast/turbo/pro;Q2 pro-fast/pro/turbo;Q1;Vidu 2.0必须恰好一张图像;URL 或数据 URL;PNG/JPEG/JPG/WebP;宽高比严格介于 1:4–4:1 之间;≤50 MB;整个 POST 正文 ≤20 MB
衔接确切的起始图像和结束图像POST /ent/v2/start-end2videoQ3 turbo/pro;Q2 pro-fast/pro/turbo;Q1/classic;Vidu 2.0必须恰好两张有序图像;它们的宽高比之比必须为 0.8–1.25;Q3 为 1–16 秒;Q2 端点文档记录为 1–8 秒
命名实体/对话POST /ent/v2/reference2video,subjects 格式页面接受列表中包括 Q3 turbo、Q3、Q2、Q1、Vidu 2.0图像/文本主体项目总数 ≤7;每个主体最多 3 张图像;使用 @name 引用;Q3 时长为 3–16 秒
未命名参考图像同一端点,images 格式Q3 mix/turbo/Q3、Q2 pro/Q2、Q1、Vidu 2.0通常为 1–7 张图像;同时提供视频时,Q2-pro 允许 1–4 张图像
参考视频/编辑同一端点,videos 格式仅 viduq2-pro最多一个 8 秒视频或两个 5 秒视频;MP4/AVI/MOV;每个 ≤100 MB;解码后的 base64 <20 MB
多关键帧连贯性POST /ent/v2/multiframe仅 viduq2-pro、viduq2-turbo关键帧有序;每个片段时长为 2–7 秒;540p/720p/1080p;其帧/片段计数和定价说明存在歧义,请核实当前页面
当前系列概览
  • Q3 pro: 注重质量的提示词/图像/首尾帧生成,24 fps,1–16 s,540p/720p/1080p,可选直接生成视听内容。
  • Q3 turbo: 更便宜、速度更快的 Q3 选项,适用于提示词/图像/首尾帧和参考生成。除非需求说明有充分理由选择 pro,否则先用它测试初始动态效果。
  • Q3 pro-fast: 文档说明仅适用于图生视频,720p/1080p,1–16 s。名称中的“fast”并不意味着它在所有设置下都比 turbo 便宜。
  • Q3 mix: 仅支持直接使用 images 进行参考生视频;720p/1080p。定价表写的是 3–16 s,而端点说明写的是 1–16 s。在 Vidu 解决这一冲突之前,请采用安全的交集范围,3–16 s。目前不支持命名实体 subjects 形式或非高峰时段选项。
  • Q3(未限定): 支持同步音频的参考生视频模型。请勿擅自将其替换为 Q3 pro:它们是参考端点上可接受的不同标识符。
  • Q2 pro: 在需要实际参考视频、视频编辑/替换或 Q2 多帧时使用。Q2 turbo/pro-fast 适用于文档所述的图像/首尾帧/多帧用途。Q2 和 Q3 的参数不能互换。
  • Q1/classic 和 Vidu 2.0: 较旧的兼容选项,时长或分辨率固定或范围较窄。公开文档未公布停用日期;请称其为较旧的选项,而非已弃用选项。

公开的 Model Map 更新落后于部分端点页面:例如,它没有列出所有较新的 Q3 参考标识符。发生冲突时,请按以下优先级处理:端点明确列出的可接受值、当前的 Pricing page,然后是 model map/更新通知。如果这些信息仍有冲突,请在登录后的控制台中确认,或联系 Vidu 支持。

音频因端点和模型而异

  • 在 Q3 生成中,audio: true 表示请求生成同步语音/音效;参考 subjects 形式还支持 audio_type(all、speech_only、sound-effect_only)以及每个主体的 voice_id。
  • Q3 不使用 bgm;请勿同时设置两者并假定它们会混合。文档说明,voice_id 在 Q3 图生视频中无效。
  • 不同页面和形式的默认值有所不同。请明确设置 audio。测试视觉动态效果时设为 false;对已批准的对话,请使用命名主体、准确的引用台词和 audio_type。
  • Q2 的音频定价和可用性有所不同;当前定价页面规定,启用音频的 Q2 图像/参考任务会额外增加 15 credits。
  • Vidu 的文本转音频、TTS、语音克隆、口型同步和数字人 API 是独立功能。请勿将这些功能的字段发送到视频端点。

构建模型可使用的参考资料

端点契约中的事实:

  • 主体图像至少为 128×128,宽高比须在 1:4–4:1 范围内,格式须为 PNG/JPEG/JPG/WebP。每个命名主体最多接受三张图像。
  • Q3 mix 不支持命名实体。Q2-pro 是列出的模型中唯一接受媒体列表形式参考视频的模型。
  • 在提示词中,通过 @name 调用 subjects[].name。auto_subjects 是一项独立的智能实体库选项;除非明确知道选中了哪些库资源,否则不要启用。

生产启发式做法,不是提供方保证:

  1. 为每个人物/物体指定唯一且稳定的名称,并提供 2–3 个清晰视图,确保服装、年龄、材质和光线保持一致。避免使用群体照片作为身份参考。
  2. 将身份和必须保持不变的特征置于动作之前:@Mara, red linen coat, short black bob; coat and face remain unchanged.
  3. 按主体 → 动作 → 环境 → 摄像机 → 光线 → 音频的顺序描述单个镜头。过多剪辑或同时发生的动作会增加身份漂移。
  4. 使用起始/结束帧指定几何形状或姿势端点;使用主体参考指定身份;使用多帧功能构建刻意编排的序列。不要用提示词正文代替适当的控制模式。
  5. 使用固定种子,以 540p/720p 和较短时长进行测试。确认动作和身份后,再为 1080p 或更长片段付费。种子有助于比较,但不能保证模型更新后逐位复现。

在构建请求前准备输入:

  • 构建规范输入清单,包含逻辑资源 ID、已批准实际字节的 SHA-256、字节数、检测到的媒体类型、相关尺寸/时长、权利/同意记录以及获准使用的定位符。URL 只是定位符;对 URL 进行哈希无法证明 Vidu 会获取哪些字节。拒绝可变或无法哈希的源内容。
  • 如果集成会在哈希或暂存时解析用户 URL,则只允许 HTTPS;拒绝包含用户信息、片段、环回/私有/链路本地/元数据目的地、DNS 重绑定或未经批准端口的 URL;限制重定向次数并重新验证每一跳;强制执行时间和字节数限制。向 Vidu 发送已批准的只读暂存 URL,而不是转发任意用户 URL。
  • 将签名源 URL 的权限限定为单个对象,并设为所需的最短有效期。不要在日志和审批页面中显示查询字符串。不要暴露存储桶前缀、列出对象的权限或可重复使用的写入凭据。
  • 单独的图像上传流程是一项涉及后果的三步写入操作(创建链接、PUT、完成),目前文档规定图像大小限制低于 10 MB,与生成页面的 50 MB 文件限制和 20 MB 请求正文限制不同。请另行获取批准,上传前验证字节,记录返回的 ETag/URI,并且不要根据示例中的存储头推断保留或删除 SLA。
完整示例 1 — 命名对话主体

**意图和限制:**在六秒的雨中集市对话镜头中,让一位演员和一件精心设计的物品保持可辨识。由于提示词使用 @name 命名实体,请采用 subjects 形式;使用 Q3 Turbo、普通模式、720p,并设置明确的视听控制,以低成本测试身份表现。这仅用于展示架构;未经明确批准,请勿运行。

{
  "model": "viduq3-turbo",
  "auto_subjects": false,
  "subjects": [
    {
      "name": "Mara",
      "images": [
        "https://assets.example.test/mara-front.jpg",
        "https://assets.example.test/mara-three-quarter.jpg"
      ],
      "voice_id": "APPROVED_VOICE_ID"
    },
    {
      "name": "OrchidDrone",
      "images": ["https://assets.example.test/orchid-drone.png"]
    }
  ],
  "prompt": "@Mara walks beside @OrchidDrone through a rainy market. Their designs remain unchanged. One continuous medium tracking shot. @Mara says: 'We leave before sunrise.' Rain and footsteps only after the line.",
  "duration": 6,
  "resolution": "720p",
  "aspect_ratio": "16:9",
  "audio": true,
  "audio_type": "all",
  "seed": 18427,
  "off_peak": false,
  "payload": "job-20260710-shot-014"
}

**预期报价和结果:**按当前普通 Q3 Turbo 参考费率,6 × 10 = 60 个 API 点数,即 $0.30(税前)。预期结果为一个连续跟拍镜头,包含已批准的台词和环境音;但不保证身份准确或逐字还原台词。

**审核与修正:**如果出现面部/物体漂移、未经批准的声音、措辞改变、多余音乐或剪辑,请拒绝。先简化动作/摄像机设置,并使用相同的短设置重新测试;仅当需求不包含雨声/脚步声时才使用 speech_only,且每次更改请求后都要获取新的摘要并重新审批。

完整示例 2 — 固定起始帧和结束帧

意图和约束: 将一帧已清理的纸鸟画面转换为第二帧已清理的飞行画面,同时锁定背景和摄像机。由于两个端点的构图都很重要,因此应使用起始帧/结束帧模式。Q3 Pro、5 秒、1080p、无声、普通模式是经批准的高质量变体。

{
  "model": "viduq3-pro",
  "images": [
    "https://assets.example.test/shot-08-start.png",
    "https://assets.example.test/shot-08-end.png"
  ],
  "prompt": "The paper bird unfolds into flight while the locked camera remains still; preserve the cream background and cobalt ink texture.",
  "duration": 5,
  "resolution": "1080p",
  "audio": false,
  "seed": 9081,
  "off_peak": false,
  "payload": "job-20260710-shot-008"
}

预期报价和结果: 5 × 24 = 120 个 API 积分,税前 $0.60。预期画面会向提供的结束帧插值,而非实现精确的几何变形。

审核和修复: 如果出现结束帧突变、拓扑断裂、摄像机移动或背景重设计,则应拒绝。应先提高两个源帧的兼容性,再延长时长;更便宜的 Q3 Turbo 720p 动态测试是有意义的变体,但需要新的请求和批准。

完整示例 3 — 未命名的产品参考图

意图和约束: 使用三个已清理的产品视图,在五秒的旋转过程中保持一盏未命名台灯的特征一致。使用直接的 images 形式和 Q3 Mix,因为不支持命名的 subjects。五秒处于文档所述的 3–16 秒定价范围内,也符合端点说明中更宽泛的 1–16 秒范围。

{
  "model": "viduq3-mix",
  "images": [
    "https://assets.example.test/product-front.png",
    "https://assets.example.test/product-side.png",
    "https://assets.example.test/product-detail.png"
  ],
  "prompt": "The same brass desk lamp rotates slowly on a dark walnut table, one continuous product shot, no redesign, no text or logos added.",
  "duration": 5,
  "resolution": "720p",
  "aspect_ratio": "16:9",
  "seed": 22109,
  "off_peak": false,
  "payload": "job-20260710-product-003"
}

预期报价和结果: 5 × 24 = 120 个 API 积分,税前 $0.60。Q3 Mix 没有列出非高峰费率。媒体列表请求架构目前未记录 audio 请求字段,尽管模型描述提到了视听输出,因此不要自行添加该字段或承诺无声;请检查返回的流,并在音频状态至关重要时向 Vidu 确认。

审核和修复: 如果出现产品重设计、添加文字/Logo、细节缺失、多镜头剪辑或意外音频,则应拒绝。添加更多图片之前,先提高参考图的一致性或调整裁剪。较低成本的变体是使用 720p 的 Q3 Turbo 参考模式;更换模型需要新的报价、摘要和批准。

价格和批准

API 积分当前每个 $0.005,适用税费另计。2025-11-03,Vidu 将数值面额乘以 10,但实际价值不变;请忽略调整前的积分示例。

当前选定的普通/非高峰模式每生成一秒的费率:

模型/模式540p720p1080p
Q3 pro 提示词/图像/起始帧-结束帧9 / 5 个积分20 / 1024 / 12
Q3 turbo 提示词/图像/起始帧-结束帧7 / 411 / 613 / 7
Q3 pro-fast 图像—20 / 1025 / 13
Q3 mix 参考图—24 / 无非高峰费率29 / 无非高峰费率
Q3 turbo 参考图4 / 210 / 513 / 7
Q3 参考图7 / 412 / 615 / 7

示例:Q3 turbo 文本生成视频,5 秒,720p,普通模式 = 11 × 5 = 55 个积分,即税前 $0.275。Q3 pro,5 秒,1080p,普通模式 = 24 × 5 = 120 个积分,即 $0.60。

off_peak: true 价格更低,但可能需要最多 48 小时;未完成的任务会自动取消并退款。兼容性取决于具体情况:参考文档称 Q3 可在启用音频时使用非高峰模式,而 Q2/Q1/Vidu 2.0 要求 audio 为 false;Q3 mix 没有非高峰价格。批准前请确认对应的具体费率行。

批准记录必须包含:

provider=Vidu Open Platform API
endpoint=/ent/v2/text2video
model=viduq3-turbo
mode=normal (off_peak=false)
duration=5s resolution=720p aspect=16:9 audio=false
input_manifest_sha256=<hash of canonical prompt/source-byte hashes, byte counts, media facts, and logical IDs; URLs are locators only>
request_sha256=<hash of canonical final JSON body>
execution_manifest_sha256=<hash binding method, URL, non-secret key ID, input/request hashes, pricing date, expected/max charge, call count, retries, and destination>
pricing_verified_on=<UTC date rechecked against pricing page/console>
expected=55 API credits / USD 0.275 before tax
max_authorized_credits=55
max_authorized_usd=<operator ceiling>
allowed_calls=1; retries=0; destination=<approved path/bucket>

输入清单摘要必须涵盖源文件字节和媒体信息,而不仅仅是定位符字符串。执行清单摘要是批准令牌:更改端点、API 密钥身份、请求正文、源文件、价格、上限、调用次数、重试策略或目标位置,都会使批准失效。

如果定价页面或控制台报价超过任一上限,请在提交前停止。如果唯一一次获准的创建请求返回了不同的积分费用,请保存任务 ID 并记录计费异常状态,不要再调用生成或取消操作,并与 Vidu 核对收据。不要将一般预算解读为对其他模型、重试、升频、提示词推荐(is_rec 当前会额外增加 10 个积分)或 Q2 音频附加费的授权。

先试运行,再发起一次调用的示例

此标准库 Python 示例专门针对上述 55 积分请求编写。默认模式会打印规范请求和审批封套,不会发起网络调用,也不会写入状态。审批前,请使用真实且非机密的密钥 ID、目标地址、上限、价格核验日期和新的客户端请求 ID 重新运行试运行。执行需要提供完全匹配的执行清单摘要,并在唯一一次 POST 前声明请求正文摘要。由于 Vidu 未说明幂等键,传输后的任何异常都会导致状态变为 UNKNOWN;脚本绝不会重试。如果多个主机或进程可能提交请求,请使用事务型数据存储,而不要采用此处展示的本地文件方式。

import datetime, hashlib, json, os, pathlib, sys, urllib.error, urllib.request
from decimal import Decimal

MODE = os.getenv("VIDU_MODE", "dry-run")
client_id = os.getenv("VIDU_CLIENT_REQUEST_ID", "dryrun-example")
endpoint = "https://api.vidu.com/ent/v2/text2video"
key_id = os.getenv("VIDU_KEY_ID", "UNBOUND")
destination = os.getenv("VIDU_DESTINATION", "UNSET")
pricing_verified_on = os.getenv("VIDU_PRICING_VERIFIED_ON", "UNVERIFIED")
body = {
    "model": "viduq3-turbo",
    "prompt": "A cobalt paper bird unfolds and glides across a cream studio background, one locked medium shot, preserve its ink texture.",
    "duration": 5,
    "resolution": "720p",
    "aspect_ratio": "16:9",
    "audio": False,
    "seed": 18427,
    "off_peak": False,
    "payload": client_id,
}
wire = json.dumps(body, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
digest = hashlib.sha256(wire).hexdigest()
input_manifest = {"kind": "text-only", "prompt_sha256": hashlib.sha256(body["prompt"].encode("utf-8")).hexdigest()}
input_digest = hashlib.sha256(json.dumps(input_manifest, sort_keys=True, separators=(",", ":")).encode("utf-8")).hexdigest()
expected_credits = 55
expected_usd = Decimal("0.275")
max_authorized_credits = int(os.getenv("VIDU_MAX_CREDITS", str(expected_credits)))
max_authorized_usd = Decimal(os.getenv("VIDU_MAX_USD", str(expected_usd)))
approval_manifest = {
    "provider": "Vidu Open Platform API", "method": "POST", "url": endpoint,
    "key_id": key_id, "input_manifest_sha256": input_digest, "request_sha256": digest,
    "pricing_verified_on": pricing_verified_on, "expected_credits": expected_credits,
    "expected_usd_before_tax": str(expected_usd), "max_authorized_credits": max_authorized_credits,
    "max_authorized_usd": str(max_authorized_usd),
    "allowed_calls": 1, "retries": 0, "destination": destination,
}
approval_wire = json.dumps(approval_manifest, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
approval_digest = hashlib.sha256(approval_wire).hexdigest()
print(json.dumps({"mode": MODE, "execution_manifest_sha256": approval_digest,
                  "approval_manifest": approval_manifest, "input_manifest": input_manifest,
                  "body": body}, indent=2, ensure_ascii=False))
if MODE == "dry-run":
    raise SystemExit(0)
if MODE != "execute":
    raise SystemExit("VIDU_MODE must be dry-run or execute")
if client_id == "dryrun-example":
    raise SystemExit("Set a fresh VIDU_CLIENT_REQUEST_ID")
if key_id == "UNBOUND" or destination == "UNSET":
    raise SystemExit("Bind the non-secret key ID and destination before approval")
try:
    verified_date = datetime.date.fromisoformat(pricing_verified_on)
except ValueError:
    raise SystemExit("Set VIDU_PRICING_VERIFIED_ON to an ISO date")
if verified_date != datetime.datetime.now(datetime.timezone.utc).date():
    raise SystemExit("Pricing must be revalidated on the UTC submission date")
if os.environ.get("VIDU_APPROVED_MANIFEST_SHA256") != approval_digest:
    raise SystemExit("Exact execution manifest was not approved")
if max_authorized_credits < expected_credits or max_authorized_usd < expected_usd:
    raise SystemExit("Approved ceiling is below expected cost")
api_key = os.environ.get("VIDU_API_KEY", "")
if not api_key:
    raise SystemExit("VIDU_API_KEY is required")

state_dir = pathlib.Path(os.getenv("VIDU_STATE_DIR", ".vidu-state")).resolve()
state_dir.mkdir(parents=True, exist_ok=True)
state_path = state_dir / f"{digest}.json"
def replace_state(value):
    temp = state_path.with_suffix(f".tmp-{os.getpid()}")
    with open(temp, "x", encoding="utf-8") as f:
        json.dump(value, f)
        f.flush(); os.fsync(f.fileno())
    os.replace(temp, state_path)
try:
    fd = os.open(state_path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
except FileExistsError:
    raise SystemExit("Digest already claimed; refusing a duplicate POST")
with os.fdopen(fd, "w", encoding="utf-8") as f:
    json.dump({"state": "PREPARED", "request_sha256": digest,
               "execution_manifest_sha256": approval_digest, "client_request_id": client_id}, f)
    f.flush(); os.fsync(f.fileno())

req = urllib.request.Request(
    endpoint, data=wire, method="POST",
    headers={"Authorization": f"Token {api_key}", "Content-Type": "application/json"})
try:
    with urllib.request.urlopen(req, timeout=45) as resp:
        raw = resp.read(1024 * 1024 + 1)
        if len(raw) > 1024 * 1024:
            raise RuntimeError("response exceeds 1 MiB")
        if resp.status not in (200, 201):
            raise RuntimeError(f"unexpected HTTP {resp.status}")
        result = json.loads(raw)
        task_id = result.get("task_id")
        if not isinstance(task_id, str) or not task_id:
            raise RuntimeError("successful response lacks task_id")
        charged_credits = result.get("credits")
        if not isinstance(charged_credits, int) or isinstance(charged_credits, bool):
            raise RuntimeError("successful response lacks an integer credits receipt")
except Exception as exc:
    replace_state({"state": "UNKNOWN", "request_sha256": digest,
        "execution_manifest_sha256": approval_digest,
        "client_request_id": client_id, "error_type": type(exc).__name__})
    raise SystemExit("POST outcome is UNKNOWN; do not retry. Reconcile in Vidu console/support.") from exc
final_state = "SUBMITTED" if charged_credits == expected_credits and charged_credits <= max_authorized_credits else "SUBMITTED_BILLING_EXCEPTION"
replace_state({"state": final_state, "request_sha256": digest,
    "execution_manifest_sha256": approval_digest,
    "client_request_id": client_id, "task_id": task_id, "charged_credits": charged_credits})
print(json.dumps({"task_id": task_id, "state": final_state,
                  "next": f"GET /ent/v2/tasks/{task_id}/creations"}))
if final_state != "SUBMITTED":
    raise SystemExit("Task was created with a credit variance; do not submit or cancel anything else")

任务中会回显本地的 payload,但文档未说明它可用作可搜索的 Task List 过滤条件。创建结果不明确时,请根据准确的提交时间、模型、提示词、时长、分辨率、密钥和本地客户端 ID,对照控制台/任务历史记录;必要时联系 Vidu 支持。在确认原请求未创建之前,不要提交替代请求;除非操作员明确批准重复风险和费用。

安全地处理异步任务

  1. 持久化保存 task_id、规范请求、摘要、API 密钥标识符(非密钥本身)、预期上限和创建响应。
  2. 使用有界指数退避和抖动轮询 GET /ent/v2/tasks/{id}/creations。状态包括 created、queueing、processing、success、failed。不要将客户端超时视为任务失败。
  3. 公布的默认值是每个组织同时运行五个任务,而非每个密钥五个。额外任务会大致按创建顺序排队;负载较高时,服务运行的任务数可能低于上限。429 也表示请求过于频繁/系统限流,因此读取操作应退避。不要仅因提交已被接受就向队列大量提交任务。
  4. 成功的任务会返回已扣除的 credits 和 creations[].{id,url,cover_url}。失败的任务会返回 err_code;请保存结构化错误中的跟踪 ID。策略限制不是可以规避的提示词问题。
  5. 取消是会产生实际影响的 POST 请求,发送至 /ent/v2/tasks/{id}/cancel;任务进入不可取消状态后,请求可能失败。取得针对该任务的授权,然后确认任务已进入终止状态/退款已处理,不要假设 {} 就能证明已撤销扣费。

回调是可选的。Vidu 会对失败的回调投递重试三次,因此处理程序必须具备幂等性。接受正文前,请验证 X-HMAC-ALGORITHM=hmac-sha256、访问密钥 vidu、Date 的时效性,以及完全匹配且顺序正确的签名标头列表。重新构造:

METHOD + "\n" + URI_PATH + "\n" + RAW_QUERY + "\n" + "vidu" + "\n" + DATE + "\n"
+ each "HeaderName:HeaderValue\n" in X-HMAC-SIGNED-HEADERS order
signature = base64(HMAC-SHA256(callback TokenSecret, signing_string))

使用恒定时间比较,保留短期的 (access_key, nonce) 重放缓存,拒绝过期的 Date,限制原始正文的大小,仅在签名验证后解析,并且要求任务 ID 已知、状态转换符合架构定义后,才接受事件。确认事件后,先持久化保存原始事件摘要和结果状态,再发送确认。由于回调投递不保证恰好一次,仍应通过轮询进行恢复。使用 Vidu 指定的回调凭据作为应用的 TokenSecret;不要猜测任意 bearer 密钥都可以互换。

接管并验证

创建 URL 和成片 URL 仅在 24 小时内有效。成功后,立即使用下载器将其复制到获批的目标位置。该下载器必须强制使用 HTTPS、遵循获批的主机和重定向策略、在每一跳解析公共 IP、设置超时和字节数上限,并在流式传输时计算哈希。将文件写入固定目标根目录下新创建的隔离文件;拒绝路径遍历、符号链接/重解析点逃逸、覆盖,以及内容类型/字节签名不匹配的文件。切勿记录签名查询字符串。

对于每个片段:

  • 保留 Vidu 任务/创建 ID、最终请求、扣除的积分、已脱敏的 URL、接收时间、SHA-256、字节数,以及来源/披露元数据;
  • 要求视频内容类型符合预期,然后使用 ffprobe 验证容器、编解码器、实际宽度/高度、fps、时长和是否存在音频流;
  • 执行完整解码,而不只是元数据探测;拒绝 HTML/错误响应、截断的媒体、时长/分辨率异常,以及意外的可执行文件/存档内容;
  • 检查每个帧区间是否存在身份漂移、额外的肢体/物体、不安全的文字/标志、剪切、闪烁,以及起始/结束是否符合要求;检查音频中的语音是否准确、是否有不需要的声音或音乐,以及是否清晰可懂;
  • 将失败的文件隔离。不要覆盖先前已验收的文件。将源生成内容与任何编辑/升频版本分开保存。

权利、隐私、披露与未知事项

  • 获取每张脸、每种声音、每个商标、受版权保护的作品、机密文件和个人数据字段的书面权利授权与同意。不得制作具有欺骗性的冒充内容、未经同意的亲密内容、骚扰、欺诈或违禁内容。
  • API 条款要求运营方告知终端用户、取得必要同意、尽量减少个人数据、进行人工审核、避免仅依赖输出结果,并且不得将涉及个人的输出用于具有重大影响的决策或法律决策。条款还禁止移除、伪造或遮盖用于区分深度合成输出的标记,并禁止将其冒充为人工制作的内容。保留 Vidu 的来源/深度合成标记,并添加适当的可见披露。
  • Vidu 表示,其可能会监控或审核输入/输出,以便运营服务和执行政策。其隐私政策涵盖用户内容,允许由服务提供商处理,规定的是基于用途而非固定期限的保留,并称个人数据可能存储/传输至位于新加坡的服务器。这并不能证明所有生成计算都在新加坡进行。
  • 公开文档未提供通用的 API 不用于训练承诺、适用于所有输入/输出的固定删除 SLA、完整的计算区域地图、输出内容的所有权归属、模型 EOL 日期或幂等键。文档公布了最多五个并发任务,但没有统一适用的每分钟请求数。上传前,须在已签署的条款中明确受监管数据、机密信息、数据驻留、所有权、赔偿、DPA、删除或训练方面的要求。
  • Vidu 的 2024 年技术报告介绍了历史上的 U-ViT/扩散模型 Vidu 系统,以及最初的 1080p/16 s 声明。该报告早于 Q3 发布;不得用它来断言 Q3 的架构、安全性、训练数据或基准性能。

排查问题,避免盲目花费

症状检查项安全操作
401/403请求头是否准确写为 Authorization: Token …;密钥/账户权限修复身份验证;切勿打印密钥
400 FieldInvalid端点对应的模型、时长、分辨率、宽高比、请求体大小根据该端点重新验证;对新的摘要执行试运行
400 ModelUnavailable标识符已过期或暂时不可用停止操作;不要悄悄更换模型
429 QuotaExceeded组织并发任务数是否达到 5 个,或是否触及自定义配额等待排队/运行中的任务完成;如有需要,请求调整限额
429 TooManyRequests/SystemThrottling轮询/提交频率使用带随机抖动的退避策略;遵循服务端的任何指引
AuditSubmitIllegal / CreationPolicyViolation输入/输出内容审核停止操作并检查权利/安全问题;不要通过混淆内容来规避审核
长时间处于 queueing 状态并发限制或非高峰时段模式报告模式和等待时长;非高峰时段模式的窗口为 48 小时
成功但 URL 无法使用24 小时链接已过期或发生不安全的重定向检查任务历史记录;如果未能取得生成内容,请联系支持人员
音频错误/无音频Q3 的 audio、参考内容的 audio_type、语音映射;Q3 会忽略 bgm修正架构,重新计价,并在再次生成前获得新的批准

主要来源

评论

支持 Markdown