Veo 3.1、Sora 2 与可灵 3 应按带版本的生产服务比较,而不是排一个永久不变的名次。真正有用的问题不是“哪个 Demo 最惊艳”,而是“在当前工作负载、策略、时延、版权与成本预算下,哪个已核验的服务界面能产出最多合格成片”。
本文提供一套可复现的三平台选型方法:把官方能力与实测质量分开,在美学评分前执行硬性发布门禁,并用每条合格成片总成本替代标价。需要与厂商无关的通用协议,可阅读 AI 视频评测协议。各平台 API 接入不属于本文范围,因为每个服务界面都需要单独核验当前契约与运营边界。
核心要点
- 比较具体产品界面与模型版本,不比较抽象品牌名。
- 官方文档只能证明能力边界,不能证明你的场景中谁质量最好。
- 使用语义相同的测试样本,保留各平台实际请求,并对评审隐藏来源。
- 先执行版权、策略、身份与事实硬门禁,再计算质量分。
- 同时统计通过率、失败原因、p50/p95 时延和每条合格成片成本。
- 用可替换适配器隔离供应商,因为访问、限制、模型和策略都会变化。
- 保存生成与评审证据,但不能因此无限期留存敏感素材。
排名之前先定义比较对象
有效对比必须明确被测服务。“Sora”“Veo”“可灵”可能分别指消费端应用、云模型、预览部署、合作方 API 或模型家族;它们暴露的输入、限制、审核、留存、价格和地域可用性可能完全不同。
生成第一条视频前,先固定以下身份:
| 字段 | 为什么必须记录 |
|---|---|
| 提供方与产品界面 | 消费端、第一方 API、云市场和聚合 API 是不同契约 |
| 模型或部署 ID | 同一模型家族可能包含质量、速度和预览版本 |
| 地域与账号等级 | 可用能力、数据处理、配额和策略可能不同 |
| 请求 Schema | 时长、比例、分辨率、参考素材、音频与编辑能力由它决定 |
| 有效 Prompt | 平台改写或安全转换可能改变实际指令 |
| 策略与条款版本 | 肖像、知识产权和商业使用边界可能变化 |
| 测试时间与输出哈希 | 结果需要可复核的证据边界 |
不要根据输出反推私有架构。一次逼真的碰撞不能证明服务内部存在物理引擎;声画同步也不能证明音频一定与视频联合生成。只比较可观察行为,只有厂商公开技术资料时才描述内部机制。
官方来源能证明什么
官方来源可以建立能力快照,不能替代质量排行榜。下表刻意保留了每份来源的适用边界。
| 候选服务界面 | 已公开能力 | 重要边界 |
|---|---|---|
| Microsoft Foundry 上的 Sora 2 | 预览文档描述文生视频、图生视频、已生成视频再编辑、音频输出、Remix 与异步任务 | 必须在目标 Azure 账号中核验预览状态、地域、部署名、安全措施和 API 行为 |
| Google AI Studio 中的 Veo 3.1 | Google 列出 Veo 3.1 系列的文本、图片和视频输入、原生音频、720p/1080p/有条件 4K,以及满足条件时的 4/6/8 秒选项 | 不同模型版本和条件不同;营销页最大值不代表每个端点和请求都支持 |
| 可灵 3.0 | 快手发布资料描述文本、图片、音频和视频输入,文生/图生/参考生视频与视频内编辑,原生多语言音频、多镜头控制和最长 15 秒 | 发布公告不是 API Schema 或当前账号权益;实施前必须核验真实产品或 API 界面 |
因此,比较必须依次回答三个问题:
- 目标能力是否写入具体服务界面的正式资料?
- 目标账号、地域与套餐是否真的启用?
- 它能否通过团队自己的工作负载测试?
前两关不通过属于“不可用”,不是质量得分为零。不要把不可用候选塞进质量排名,也不要用营销页面替代账号实测。
按工作负载建立候选集
不同平台因公开能力不同而进入候选集。下表是待验证假设,不是赢家结论。
| 工作负载要求 | 值得测试的候选 | 试验前必须核验 |
|---|---|---|
| 输入已有视频或局部 Remix | Sora 2 Foundry 界面或 Veo 3.1 | 接受的媒体类型、编辑语义、输出限制与预览状态 |
| 带原生音频的短镜头 | Veo 3.1 或可灵 3.0 | 对话语言、音频控制、时长、分辨率与审核 |
| 参考人物、商品或场景 | Veo 3.1 或可灵 3.0 | 参考素材数量和类型、授权、留存与身份漂移 |
| 单次生成多镜头叙事 | 可灵 3.0 | 当前界面是否支持、镜头控制、时长与一致性 |
| 企业治理已标准化在 Azure | Microsoft Foundry 上的 Sora 2 | 地域、模型部署、身份、日志与内容过滤 |
| 有条件的 4K 交付 | Veo 3.1 | 精确模型、时长、输入、端点、配额和输出条件 |
如果候选无法满足地域、删除、版权、输出格式、时延上限或禁止内容策略等硬需求,应在创意测试前淘汰。漂亮样片无法补救不可用的服务契约。
建立代表真实生产的测试集
测试集必须覆盖团队准备发布的视频,也要覆盖最难和最危险的边界。反复使用几个电影感 Prompt,只能得到 Demo 排名,不能支持采购决策。
按失败机制分层设计:
| 测试层 | 示例要求 | 检查重点 |
|---|---|---|
| 主体身份 | 人物或商品经历运动和遮挡后保持一致 | 面部、服装、几何、颜色与再次出现 |
| 构图 | 指定物体数量和空间关系 | 缺失、复制、互换或位置错误 |
| 动作与物理 | 倾倒、碰撞、接触与关节运动 | 因果、穿模、重力与状态变化 |
| 文字与品牌 | 包装或画面必须出现指定文字 | 拼写、持续性、变形与违规表述 |
| 运镜 | 平移、环绕、推拉、变焦和切镜 | 运镜是否正确、主体运动与构图 |
| 音频 | 对话、环境音、音效或静音 | 口型、事件同步、语言、音色漂移和杂音 |
| 多镜头叙事 | 跨镜头按顺序完成动作 | 事件完成、身份、场景和时间逻辑 |
| 编辑或 Remix | 只修改一项并保持其余内容 | 编辑局部性与非预期漂移 |
| 安全边界 | 肖像、未成年人、公众人物和受监管声明 | 拒绝、放行、升级与人工复核 |
每个样本保留一份语义 Brief,再保存各平台的请求映射。如果一个 API 支持 Negative Prompt,另一个不支持,必须记录这个差异,不能悄悄给某个候选增加更丰富的指令。
每个样本需要重复生成,以暴露随机失败。评审前随机打乱顺序、去除平台元数据,并使用稳定匿名 ID。最终决策还应保留 Holdout 集,避免 Prompt 调优只适配测试集。
{
"fixture_id": "product-pour-07",
"semantic_brief_version": "sha256:brief...",
"required_events": ["打开瓶盖", "液体进入杯中", "标签始终可读"],
"hard_gates": ["版权", "策略", "事件顺序", "品牌文字"],
"graded_dimensions": ["画面质量", "运动", "身份", "音频"],
"provider_request_hash": "sha256:request...",
"output_hash": "sha256:video...",
"review_rubric_version": "video-rubric-v4"
}
文生视频术语页进一步解释了为什么帧数、帧率、时长、模型版本、有效 Prompt 和来源素材哈希属于生成身份,而不是可有可无的备注。
先执行硬门禁,再计算质量分
硬失败不能被漂亮画面平均掉。视频一旦违反肖像授权、遗漏必须出现的商品事实、改变主体身份或颠倒动作顺序,即使美学评分很高,也不具备发布资格。
按以下顺序评估:
- 可用性门禁:服务在目标地域、账号和部署契约下可访问。
- 策略与版权门禁:输入输出满足同意、许可、平台和内部策略。
- 任务门禁:必要实体、事件、文字、顺序和格式完整。
- 连续性门禁:需要保持的人物、物体状态与因果变化正确。
- 质量评分:评审画面、运动、运镜、音频和后期修复量。
- 运营门禁:时延、失败率、配额、删除和成本满足服务目标。
VBench 2.0 将人物真实性、可控性、创造性、物理和常识分开,而不是把视觉吸引力当作全部问题。MSVBench 也针对多镜头结果区分画面质量、故事与视频对齐、视频一致性和运动质量。生产量表可以借鉴这种拆分,再补充领域硬门禁和人工复核。
自动指标适合筛查和回归检测,但不能成为发布裁判。视觉语言模型可能遗漏品牌缺陷、误解事件或复制偏见。每个自动阈值都应对齐人工标注,并按样本类型持续监控分歧。
计算每条合格成片成本
真正有意义的成本分母是合格成片,不是生成秒数或订阅席位。
每条合格成片成本 =
(生成 + 重试 + 人工审核 + 后期修复 + 存储 + 分发)
/ 通过全部发布门禁的成片数
至少报告:
- 尝试任务数、完成数、策略拦截数、技术失败数与合格数;
- 首次通过率与最终通过率;
- 从排队到下载完成的 p50 和 p95 时延;
- 生成、审核、修复、存储与分发成本;
- 各测试层的失败原因;
- 样本量允许时的成本与时延置信区间。
策略拦截不属于模型质量失败,而是独立的策略结果,但它仍可能使某个服务无法承接合法工作负载。技术失败也不能从成本分子里删除,因为重试同样消耗时间,且通常产生费用。
使用 Go 汇总验收结果
下面的零依赖 Go 程序实现供应商无关的汇总层。示例观测值是合成数据,必须替换为团队自己的盲审记录。只有全部硬门禁通过且人工评分达到阈值,视频才算合格。
package main
import (
"fmt"
"math"
"sort"
)
type Observation struct {
Provider string
LatencySeconds float64
GenerationUSD float64
ReviewUSD float64
PromptPass bool
IdentityPass bool
SafetyPass bool
HumanScore float64
}
type Summary struct {
Provider string
Trials int
Accepted int
AcceptanceRate float64
P95LatencySeconds float64
CostPerApprovedShot float64
}
func isAccepted(item Observation, minimumHumanScore float64) bool {
return item.PromptPass &&
item.IdentityPass &&
item.SafetyPass &&
item.HumanScore >= minimumHumanScore
}
func percentile95(values []float64) float64 {
sorted := append([]float64(nil), values...)
sort.Float64s(sorted)
index := int(math.Ceil(0.95*float64(len(sorted)))) - 1
return sorted[index]
}
func summarize(provider string, items []Observation) (Summary, error) {
if len(items) == 0 {
return Summary{}, fmt.Errorf("%s has no observations", provider)
}
latencies := make([]float64, 0, len(items))
totalCost := 0.0
accepted := 0
for index, item := range items {
if item.Provider != provider {
return Summary{}, fmt.Errorf("row %d belongs to %s, not %s", index, item.Provider, provider)
}
if item.LatencySeconds <= 0 || item.GenerationUSD < 0 || item.ReviewUSD < 0 {
return Summary{}, fmt.Errorf("row %d has invalid latency or cost", index)
}
if item.HumanScore < 1 || item.HumanScore > 5 {
return Summary{}, fmt.Errorf("row %d has a human score outside 1..5", index)
}
latencies = append(latencies, item.LatencySeconds)
totalCost += item.GenerationUSD + item.ReviewUSD
if isAccepted(item, 4) {
accepted++
}
}
costPerApproved := math.Inf(1)
if accepted > 0 {
costPerApproved = totalCost / float64(accepted)
}
return Summary{
Provider: provider,
Trials: len(items),
Accepted: accepted,
AcceptanceRate: float64(accepted) / float64(len(items)),
P95LatencySeconds: percentile95(latencies),
CostPerApprovedShot: costPerApproved,
}, nil
}
func main() {
data := map[string][]Observation{
"candidate-a": {
{Provider: "candidate-a", LatencySeconds: 72, GenerationUSD: 1.2, ReviewUSD: 0.3, PromptPass: true, IdentityPass: true, SafetyPass: true, HumanScore: 4.3},
{Provider: "candidate-a", LatencySeconds: 95, GenerationUSD: 1.2, ReviewUSD: 0.3, PromptPass: true, IdentityPass: false, SafetyPass: true, HumanScore: 4.4},
{Provider: "candidate-a", LatencySeconds: 80, GenerationUSD: 1.2, ReviewUSD: 0.3, PromptPass: true, IdentityPass: true, SafetyPass: true, HumanScore: 4.1},
},
"candidate-b": {
{Provider: "candidate-b", LatencySeconds: 60, GenerationUSD: 0.9, ReviewUSD: 0.4, PromptPass: true, IdentityPass: true, SafetyPass: true, HumanScore: 4.0},
{Provider: "candidate-b", LatencySeconds: 110, GenerationUSD: 0.9, ReviewUSD: 0.4, PromptPass: false, IdentityPass: true, SafetyPass: true, HumanScore: 4.6},
{Provider: "candidate-b", LatencySeconds: 75, GenerationUSD: 0.9, ReviewUSD: 0.4, PromptPass: true, IdentityPass: true, SafetyPass: false, HumanScore: 4.8},
},
}
providers := make([]string, 0, len(data))
for provider := range data {
providers = append(providers, provider)
}
sort.Strings(providers)
for _, provider := range providers {
summary, err := summarize(provider, data[provider])
if err != nil {
panic(err)
}
fmt.Printf(
"%s trials=%d accepted=%d rate=%.1f%% p95=%.0fs cost/approved=$%.2f\n",
summary.Provider,
summary.Trials,
summary.Accepted,
summary.AcceptanceRate*100,
summary.P95LatencySeconds,
summary.CostPerApprovedShot,
)
}
}
预期输出:
candidate-a trials=3 accepted=2 rate=66.7% p95=95s cost/approved=$2.25
candidate-b trials=3 accepted=1 rate=33.3% p95=110s cost/approved=$3.90
这组样例没有替 Veo、Sora 或可灵选赢家。它只展示了为什么较低生成价格仍可能产生更高的合格成片成本,也说明加权质量均分不能挽救硬门禁失败。
设计生产控制平面
多供应商系统应把平台细节隔离在适配器后面,同时集中管理身份、策略、证据与状态转换。
统一使用 submitted、queued、running、succeeded、failed、cancelled、expired 和 downloaded 等显式状态。将平台状态映射进统一词表时,仍要保留原始响应。
每个任务都应:
- 根据 Brief 和尝试身份生成幂等键;
- 设置截止时间与重试预算,禁止无限轮询;
- 区分可重试传输错误、策略拒绝和非法输入;
- 平台支持回调时校验签名;
- 流式写入有容量上限的存储,并校验媒体类型、大小、时长和哈希;
- 保留原始任务 ID、模型或部署 ID;
- 按留存策略删除临时参考素材与输出。
Fallback 不是天然安全的。把遭拒绝的肖像或机密参考图转发给另一家服务,可能绕过原始策略并扩大数据暴露。切换供应商前必须重新执行版权、隐私、地域和策略检查。
用失败分类指导修复
把失败分类,才能把评审结果转化为工程动作:
| 失败 | 优先干预 | 不能得出的结论 |
|---|---|---|
| 缺少必需物体 | 简化绑定、增加参考图或拆分镜头 | 模型在所有任务上都弱 |
| 遮挡后身份变化 | 增加身份样本、缩短镜头或使用参考素材 | 首帧相似即可证明连续性 |
| 事件顺序错误 | 拆成镜头、使用分镜并逐个校验转换 | 运动流畅即可证明叙事正确 |
| 商品文字变形 | 后期叠加已核验文字,或直接拒绝 | 超分辨率可以修复语义文字 |
| 音频与动作错位 | 独立执行音频门禁、重试或后期同步 | 原生音频一定可以直接发布 |
| 策略表现变化 | 固定界面与策略版本,增加升级路径 | 一次成功就保证长期可用 |
| 成本突然升高 | 检查重试、排队失败、审核与修复 | 标价可以预测交付成本 |
| C2PA 信息丢失 | 测试导出、编辑、转码与平台接入 | Manifest 能经受所有转换 |
诊断时一次只改变一个变量。Prompt、参考素材、画幅、时长、模型版本和供应商不能在同一轮同时变化,否则无法归因。
治理版权、隐私与内容来源
视频生成流程处理的不只是 Prompt。人物脸部、声音、商品设计、脚本、地点素材、客户数据和未公开广告资产都可能受到版权或保密约束。
提交前记录:
- 每份输入由谁拥有或授权;
- 被摄者是否同意目标用途;
- 服务商是否保留或使用输入输出;
- 处理地域和批准的数据路径;
- 目标平台的内容与广告限制;
- 删除、事件处置与法律留置要求。
C2PA Content Credentials 2.2可以把签名且可检测篡改的来源声明绑定到媒体,但不能证明每条声明真实、画面事件真实发生,也不能保证下游平台保留 Manifest。团队必须校验信任链,并测试每次编辑、转码、上传与下载。AI 水印术语页解释了可见标签、元数据、来源 Manifest 与统计水印为何是不同机制。
涉及具体法域的标识和证据要求时,应参考 AI 合规工程指南。法律适用性必须由具备资质的人员判断,供应商功能表不能替代法律意见。
作出选型决定
选择能通过工作负载门禁的最小供应商组合。单一镜头类型可能只需一个供应商;只有实测证明能力互补时,多供应商路由才有价值。
| 决策 | 必须提供的证据 |
|---|---|
| 选择一个供应商 | 通过全部硬需求,且 Holdout 集置信边界仍可接受 |
| 按镜头类型路由 | 分类器稳定、样本足够,且合格成片成本更低或通过率更高 |
| 保留备用供应商 | 备用路径独立通过版权、策略、质量与运营门禁 |
| 延迟采用 | 访问、删除、证据、质量或成本仍未核验 |
| 替换供应商 | 新候选在同一版本化测试中胜出,且迁移约束可控 |
在业务方明确权重和硬门禁前,不要把无关质量维度相加成一个总分。建议必须附完整评分卡、样本数、拒绝原因、置信区间和未解决风险。
发布与重新评测门禁
生产发布至少应包含:
- 精确服务界面、模型 ID、地域、请求 Schema 与来源版本组成的签名比较清单。
- 版本化测试集、平台请求映射、输出哈希和匿名评审记录。
- 硬门禁结果与失败原因,不能只提供综合得分。
- 按工作负载分层的通过率、p50/p95 时延与每条合格成片成本。
- 版权、隐私、审核、留存、删除与来源证据。
- 配额、超时、重试、Fallback、事件响应与回滚方案。
- 模型、API、策略、价格、地域、条款或工作负载变化后的重评触发器。
正式放量前先运行 Canary。将线上结果与评测基线对比,硬门禁失败率、成本或时延超出批准边界时自动停止路由。
常见问题
Veo 3.1、Sora 2 和可灵 3 哪个更好?
现有公开证据不能支持一个通用赢家。先核验具体服务界面的可用性和能力,再用代表性测试集比较。参考商品镜头、对话、多镜头叙事和严格企业治理可能分别得到不同结果。
官方参数能证明哪个模型画质最好吗?
不能。参数只能说明支持的控制项与限制,无法预测模型在你的主体、Prompt、语言、品牌和策略下能否通过验收。官方资料用于建立候选集,最终质量结论必须来自匿名盲测。
团队应该如何比较价格?
计算每条合格成片总成本,把失败和拦截任务、重复生成、人工审核、修复、后期、存储与分发全部计入。同时报告通过率和时延,因为便宜的单次尝试可能因大量拒绝而变成昂贵交付。
VBench 或视觉语言模型裁判足够吗?
不够。评测基准有助于扩展覆盖面,自动裁判可以筛查大量结果,但生产验收还包括叙事意图、身份、事实、品牌、版权与安全。每种关键工作负载都要用匿名人工判断校准自动指标。
什么样的对比可以复现?
可复现对比需要保留语义 Brief、平台实际请求、来源素材哈希、产品界面与模型身份、生成参数、输出、评审量表、逐条判断、成本输入和来源版本。另一位评审者应能解释每个通过结果,并重新计算全部指标。