Seedance 2.5 首尾帧实测:尾帧误差 5.4,2.0 Mini 是 35.9

把首尾两张图一起发给 Seedance 2.5,它真的落在你指定的尾帧上:480p 尾帧误差 5.4,2.0 Mini 是 35.9。传 aspect_ratio 会直接 400,480p 按 $0.11/秒计费。

Seedance 2.5 首尾帧实测:尾帧误差 5.4,2.0 Mini 是 35.9

Seedance 2.5 把尾帧当成目的地,而不是提示。 给它一个镜头的首尾两端,它会真的落在你要的那一端 —— 这正是 2.0 Mini 做不到的事。

接口:      POST /v1/videos  ->  202 + polling_url
字段:      frame_images[],每个元素带 frame_type first_frame / last_frame
画幅规则:  2.5 的帧任务传 aspect_ratio 直接 400。不传,或者传 adaptive。
2.0 一样吗:不一样。2.0-mini 接受 frame_images + aspect_ratio。
尾帧误差(0-255 平均绝对差,越小越接近):
            Seedance 2.5 720p     2.0
            Seedance 2.5 480p     5.4
            Seedance 2.0 Mini    35.9
            两张无关图片          39.0(天花板)
计费:      480p $0.11/秒,720p $0.24/秒,走文生视频那一行
实测:      2026-08-24,每种配置一段 5 秒片

最后更新 2026-08-24。下面每个数字都来自当天通过 ofox 发出的 POST /v1/videos。视频模型路由会变,把校验表抄进自己代码之前,请重跑一遍那四个错误用例。

首帧和尾帧怎么传

frame_images 里两个元素,各自打上 frame_type 没有模式开关,接口从请求体推断这是图生视频。

import base64, json, requests

def data_uri(path):
    return "data:image/jpeg;base64," + base64.b64encode(open(path, "rb").read()).decode()

body = {
    "model": "bytedance/seedance-2.5",
    "prompt": "The woman stops walking on the rain-slicked street, turns toward the "
              "camera, and the shot pushes in to her face. Hand-painted 2D animation style.",
    "duration": 5,
    "resolution": "480p",
    # 这里故意不传 aspect_ratio,原因见下一节
    "frame_images": [
        {"type": "image_url", "image_url": {"url": data_uri("wide.jpg")},  "frame_type": "first_frame"},
        {"type": "image_url", "image_url": {"url": data_uri("close.jpg")}, "frame_type": "last_frame"},
    ],
}

r = requests.post("https://api.ofox.io/v1/videos", json=body,
                  headers={"Authorization": "Bearer YOUR_OFOX_API_KEY"})
print(r.status_code, r.json())   # 202 {'id': ..., 'status': 'queued', 'polling_url': ...}

data URI 是通的,这件事比听上去重要:你不用先搭一个公网图床,就能把首尾帧功能测完。之后轮询 polling_url 到终态即可,而轮询本身有一堆坑,写循环之前值得先读一遍。

prompt 在这里仍然干活。它不是夹在两张固定图片中间的装饰品:它决定中间这段发生什么,以及要用掉几个运镜。

它真的会落在尾帧上吗

会,而且和 2.0 Mini 的差距一点也不微妙。 同样两张图、同样 prompt、同样时长、同一天。

输入帧与输出帧对照网格:Seedance 2.5 同时复现了指定的开场街景和指定的收尾特写,而 Seedance 2.0 Mini 的结尾落在了完全不同的人物上

为了给它一个数字,我们从每段片子里取出第 0 帧和最后一帧,把帧和源图都缩到 256x144,然后算每通道平均绝对差(0-255 量纲)。数值越小越接近。

运行首帧误差尾帧误差计费
Seedance 2.5,720p1.82.0$1.20
Seedance 2.5,1080p1.83.1$2.40
Seedance 2.5,480p3.05.4$0.55
Seedance 2.0 Mini,480p9.535.9$0.10
Seedance 2.0 Mini,480p,不传 ratio9.637.1$0.10
参照:两张无关图片38.639.0不适用

先看最后一行。两张毫无关系的图片,分数大约是 39。Mini 的尾帧是 35.9,也就是说它自己挑了个地方结束:雨天的色调还在,人物换了,取景也换了。首帧则是另一回事,两个模型都抓得很牢 —— 这和我们在 2.0 上看到的老行为一致:首帧被尊重,尾帧会飘

在此基础上建东西之前有两条提醒。每种配置只跑了一次,不是分布,所以请把排序当作结论,把小数点当作单个样本。另外这个差异指标是刻意粗糙的:一个构图正确但早了两帧的结尾也会被它扣分。而这种粗糙恰恰让 35.9 更有说服力 —— 这么钝的指标都能测出接近「无关」的数值,说明差得是真的远。

为什么 2.5 的帧任务传 aspect_ratio 会 400

因为画幅是从首帧图片推导出来的,所以传它是错误,而不是冗余。

POST /v1/videos  {model: bytedance/seedance-2.5, resolution: 480p,
                  aspect_ratio: "16:9", frame_images: [first, last]}

400 invalid_request
"The parameter ratio specified in the request is not valid. For first-frame or
 first-last-frame generation, the output ratio follows the first-frame image."

容易踩的地方在于:我们的首帧图正好是 1280x720,传的 16:9 完全正确,照样被拒。API 不是在拿你的值和图片比对,它是在这个模式下根本不接受这个值

由此推出三件事,全部是实测而非推断:

请求结果
2.5 + frame_images + aspect_ratio: "16:9"400,ratio not valid
2.5 + frame_images + aspect_ratio: "adaptive"202,输出 854x480
2.5 + frame_images,不传该字段202,720p 下输出 1280x720
2.5 纯文生视频 + aspect_ratio: "16:9",无帧202
2.0 Mini + frame_images + aspect_ratio: "16:9"202,输出 864x496

所以这个限制专属于 2.5 的帧类任务。它不是关于视频生成的规则,不是关于整个模型的规则,也不是网关加的规则。在 Seedance 2.0 上跑了几个月的代码,会在有人把模型 ID 改成 2.5 的那天开始返回 400,而错误信息谈论的是一个没人动过的参数。

字节自己是写清楚了的。Seedance 2.5 提示词指南把任务分成锁定和非锁定两类,把「编辑、首尾帧、续写」放进锁定组,并说明锁定意味着「输出视频的画幅,有时还包括时长,是被锁死的」。同一页还有一句正好解释了我们的 2.0 结果:「Seedance 2.0 不作这个区分。」

frame_images 的校验还会拒绝什么

四种形状,全部在请求发往上游之前拦下。 每个都在一秒左右返回,不花钱。

你发的东西HTTP信息
两个元素都是 first_frame400frame_images: at most one first_frame and one last_frame
只有 last_frame400frame_images: last_frame requires a first_frame
frame_type: "start_frame"400frame_images[0]: frame_type must be first_frame or last_frame
frame_imagesinput_references 同时出现400frame_images and input_references are mutually exclusive

注意第三条里带了下标路径。当你在循环里批量生成请求体时,frame_images[0] 直接告诉你该看哪个元素 —— 这比多数视频 API 给的多。

终端会话:向 ofox 视频接口发出的五个请求依次被拒,各自返回不同错误码的 HTTP 400,最后是 ffprobe 输出,显示 480p 和 720p 片子是 h264、1080p 那段是 hevc

五个拒绝全部是对 Seedance 2.5 的真实调用。底部的 ffprobe 那段是三段成功跑出来的片子,1080p 的编码变化就在那里。

第二条规则最值得围着它做设计:没有「只给尾帧」这个模式,所以想让片子结束在某张已知图片上的产线,必须同时决定它从哪开始。如果你只在乎结尾,就先生成一张说得通的开场静帧,然后两张一起传。

图生视频一段片子到底多少钱

按对应分辨率的文生视频那一行计费。 模型页按分辨率和模式列价,没有图生视频这一行,所以很自然会担心自己落到「其他组合」的 $0.568/秒 上。不会。

分辨率模型页文生视频价我们 5 秒帧任务实际计费折算
480p$0.11/秒$0.55$0.11/秒
720p$0.24/秒$1.20$0.24/秒
1080p$0.48/秒$2.40$0.48/秒

三个分辨率,三次精确吻合。文件分别是 854x480、1280x720、1920x1080,都是 24 fps,带 32 kHz 的 AAC 音轨。时长落在 5.04 秒而不是正好 5 秒,所以计费请读 usage.video_seconds,不要用自己的算术。

作为对比,同样的请求在 bytedance/seedance-2.0-mini 的 480p 上计费 $0.10。这也是 Mini 仍然适合走量的原因:便宜五倍半,而且在没人盯着尾帧的活儿上,这个差距无所谓。反过来说,在这个任务上,差距是看得见的。

Seedance 2.5 支持哪些分辨率

问价格表,别问文字描述。 模型页当前的文字摘要写着 480p 或 720p,而同一页的价格表列出了文生视频和视频生视频的 1080p 行,我们的 1080p 首尾帧任务也真的跑完了。

来源说法
模型页文字480p 或 720p,默认 720p
模型页价格表有 480p / 720p / 1080p 三行,1080p 文生视频 $0.48/秒
真实 API,1080p 首尾帧接受,176.2 秒完成,计费 $2.40

一个资费档刚开放的那几周,这种自相矛盾很常见,而分辨率字段恰好是最便宜的验证对象:发一个请求,看状态码。被拒是即时的,而且免费。

1080p 上还有一件页面上没写的事:文件回来是 HEVC,而 480p 和 720p 的输出是 H.264。如果你要用流复制拼接,或者直接丢给浏览器播,混编码的一批素材会咬人。按文件查编码,别按模型猜。

时长是两代之间变化的另一个轴:2.5 支持 4 到 30 秒,2.0 那条线到 15 秒为止。而 30 秒的片子在 prompt 里大概需要十个动作节拍,否则模型会把一个瞬间抻满十秒。这个节奏问题我们在 2.5 提示词指南里写过,剩下的能力差异在 2.5 与 2.0 的对比里。

怎么不开两个控制台就比较两个视频模型

这篇文章里的对比只需要一件麻烦事:拿同一个请求体去打 seedance-2.5seedance-2.0-mini,其他什么都不改。两个模型 ID,一把 key,一种接口形状。原生对接的话,那是两个厂商控制台、两个余额、两套请求 schema —— 到这一步,多数人就改成「拿一个模型和自己对另一个模型的印象比一比」,然后管它叫评测。

这里的两个模型都答在同一个 POST /v1/videos 上,因为视频接口与模型无关;两次运行之间的差异就只有 model 字段。我们用的是 ofox 的视频接口,任何能在不同厂商之间保持请求形状稳定的网关都能干同样的活。信任一次跨模型对比之前要检查的点是:网关有没有在中途把字段规范化掉。如果 aspect_ratio 在 2.5 和 2.0 上表现完全一致,那才是异味。它没有一致,这正是字段原样送达每个模型的证据。

参考资料

常见问题

怎么给 Seedance 2.5 传首帧和尾帧?
在 POST /v1/videos 的 frame_images 数组里放两个元素,每个元素带 image_url 和 frame_type(first_frame 或 last_frame)。模式由请求体推断,没有 mode 参数要设。图片可以是公网 URL,也可以是 data URI —— base64 data URI 是通的,省掉了为测试搭图床这一步。
Seedance 2.5 真的会落在你给的尾帧上吗?
会,而且很接近。我们把输出的最后一帧和请求的尾帧做对比,480p 的平均绝对像素误差是 5.4,720p 是 2.0(0-255 量纲)。同样的请求在 Seedance 2.0 Mini 上是 35.9,而两张毫不相干的图片的基线是 39.0。在 Mini 上尾帧是建议,在 2.5 上尾帧是目标。
为什么 Seedance 2.5 的首尾帧任务传 aspect_ratio 会 400?
因为输出画幅取自首帧图片,所以这个字段是被拒绝而不是被忽略。错误信息写着:首帧或首尾帧生成时,输出画幅跟随首帧图片。即使你传的比例和图片完全一致也照样报错。要么不传 aspect_ratio,要么传 adaptive。
Seedance 2.0 也有这个限制吗?
没有。完全相同的请求体(frame_images 加 aspect_ratio 16:9)在 bytedance/seedance-2.0-mini 上被接受,返回了 864x496 的片子。这个限制属于 2.5 的锁定任务类型,不是「带帧生成」的通用规则 —— 所以在 2.0 上跑了几个月的代码,会在有人把模型 ID 改成 2.5 的那天开始 400。
可以只传尾帧吗?
不行,会返回 400:last_frame requires a first_frame。也不能传两个首帧,那是 400:at most one first_frame and one last_frame。这两条都在请求发往上游之前校验,所以不花钱,大约一秒就返回。
Seedance 2.5 的图生视频怎么计费?
按对应分辨率的文生视频档计费,不是「其他组合」那一行。我们的 5 秒 480p 任务计费 $0.55,720p 计费 $1.20,正好等于模型页上的 $0.11/秒 和 $0.24/秒。失败任务 usage 为 null,不计费。
Seedance 2.5 支持 1080p 吗?
模型页的价格表里文生视频和视频生视频都有 1080p 行,我们的 1080p 首尾帧任务也跑完了:176.2 秒,计费 $2.40,正好是 $0.48/秒 的文生视频价。但同一个页面的文字描述仍然写着 480p 或 720p。以价格表和一次真实请求为准。
输出带声音吗?
默认带。我们拉回来的每一段片子都有 32 kHz 的 AAC 音轨,视频是 24 fps 的 H.264。如果你后面要拼接,这点很重要:音频参数也必须一致,否则 ffmpeg concat 的流复制会拒绝工作。