Seedance API 的限流是公布的,两个数字而不是一个。doubao-seedance-2-5-260628 挂着 最大 RPM: 企业用户: 600 个人用户: 180 和 最大并发: 企业用户: 10 个人用户: 3。两列共用同一个限定词:非刚性保障,受平台负载/调用方式影响,详见文档。离线推理 暂不支持。API 总览讲调用形态。
官方公布的限流数字
数字写在方舟模型列表里,列头是 在线推理限流;每格都是官方原文,
| 模型 ID | 最大 RPM | 最大并发 | 离线推理限流 |
|---|---|---|---|
doubao-seedance-2-5-260628 | 企业用户 600 / 个人用户 180 | 企业用户 10 / 个人用户 3 | 暂不支持 |
doubao-seedance-2-0-260128 | 非 4k:600 / 180;4k:15 / 15 | 非 4k:10 / 3;4k:1 / 1 | 暂不支持 |
doubao-seedance-2-0-fast-260128 | 企业用户 600 / 个人用户 180 | 企业用户 10 / 个人用户 3 | 暂不支持 |
doubao-seedance-2-0-mini-260615 | 企业用户 600 / 个人用户 180 | 企业用户 10 / 个人用户 3 | 暂不支持 |
搜这个关键词,会先撞上四套互相打架的第三方表:30 requests per 60 seconds per account、Generation 100/min、每分鐘請求: 20–60、Requests per minute 60。四家都注明是自己的数字,没有一家是方舟的端点参考里是请求侧本身。
curl -X POST https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedance-2-5-260628",
"content": [
{ "type": "text", "text": "A workshop at dawn, hands assembling a clock movement." }
],
"ratio": "16:9",
"duration": 5
}'
并发与 RPM 是两个独立额度

两个数字的行为不一样,混为一谈是常见的规划错误。
RPM 数每分钟的提交次数。一个视频任务要一次请求创建,之后每轮询一次又是一次请求,紧凑的轮询循环本身就是请求制造机。并发数的是同一时刻在飞的任务数,一条 Seedance 任务却占着槽位数分钟。
把额度换算成在飞任务
这个差别改变你要观测的指标。10 个并发配 600 RPM 意味着限流不是瓶颈,自己任务的耗时才是。一次生成三分钟,10 个槽位每分钟大约只能吐 3 条,剩下 590 次请求都是花出去的轮询。
import json
import os
import threading
from concurrent.futures import ThreadPoolExecutor
import requests
ARK = "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks"
BUDGET = 10 # 最大并发: 企业用户: 10 个人用户: 3
slots = threading.Semaphore(BUDGET)
def run(payload, api_key):
with slots: # one slot held for the whole generation, released on exit
created = requests.post(
ARK,
headers={"Authorization": f"Bearer {api_key}"},
json=payload,
timeout=60,
)
created.raise_for_status()
task_id = created.json()["id"]
while True:
polled = requests.get(
f"{ARK}/{task_id}",
headers={"Authorization": f"Bearer {api_key}"},
timeout=60,
)
polled.raise_for_status()
body = polled.json()
if body["status"] in {"succeeded", "failed", "expired", "cancelled"}:
return task_id, body["status"]
with ThreadPoolExecutor(max_workers=BUDGET) as pool:
futures = [pool.submit(run, {"model": "doubao-seedance-2-5-260628",
"content": [{"type": "text", "text": "A workshop at dawn."}],
"ratio": "16:9", "duration": 5}, os.environ["ARK_API_KEY"])
for _ in range(40)]
for future in futures:
print(*future.result())
curl -s -X GET \
"https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks?page_num=1&page_size=100&filter.status=running" \
-H "Authorization: Bearer $ARK_API_KEY" | jq '.items | length'
额度按账号算,不按 Key 算
官方写得很直白:每个账号(含主账号下的所有子账号,合并计算)。主账号下面每个子账号,都在同一个天花板下取额度。
所以「每个 Key 一份额度」是幻觉。两个服务各按 10 并发调优,合起来就是要 20 个。限流得挡在所有服务都能看到的地方:一个队列加一个派发器,或共享存储里的计数器。
为什么还有余额就被限流
方舟在常见问题里给了答案,这是整个话题里最有用的一句:方舟对于模型限流的逻辑使用的是预扣机制,来保障您已提交的请求的完成率。即在收到请求时会根据输入和输出长度预扣除本时间窗口的 TPM 配额。
先对窗口预扣。请求在跑之前就按输入和预期输出长度扣掉额度。同一窗口连提几条长任务,就可能在面板还显示余量时被拒,那点余量已被预扣、还没消耗。官方给的理由是稳定性:不预扣,一波长请求会把已提交的任务全部饿死。
被限流时的退避写法
麻烦在于方舟没有公布限流契约:没有文档化的状态码,也没有重试响应头。下面这段脚本记录真实收到的东西,而不是假定某个码。
import random
import time
import requests
ARK = "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks"
def submit(payload, api_key, attempts=6):
"""Submit one task. Backs off on any non-2xx and keeps the first body seen."""
for attempt in range(attempts):
response = requests.post(
ARK,
headers={"Authorization": f"Bearer {api_key}"},
json=payload,
timeout=60,
)
if response.ok:
return response.json()
# Ark does not publish which code means throttled, so log it rather
# than hardcoding a guess.
print("status", response.status_code, response.text[:200])
delay = min(2**attempt, 60) * (0.5 + random.random())
time.sleep(delay)
raise RuntimeError("gave up after repeated non-2xx responses")
这段里没有 Retry-After,是故意的。那是第三方网关的做法,不是方舟文档。
分辨率会改变额度
2.0 系列那一行按输出分辨率拆成两档:非 4k 档与上表一致,4k 档掉到 最大 RPM 企业用户:15 个人用户:15、最大并发 企业用户:1 个人用户:1。
2.0 的 4K 那一行
并发为 1 意味着 4k 档完全串行:第一条没跑完,第二条没地方去。拿 10 槽位的模型去排一批 4k,速率差 40 倍,并发差 10 倍。
2.5 只公布一组数字,没有分辨率分档,不要把 2.0 的 4K 数字搬过来。分辨率会不会改变 2.5 的天花板,官方没说。
官方没有公布什么
本次核查中官方没有公布:
- 请求被限流时返回的 HTTP 状态码。本次读到的官方页面里没有
429,第三方的429处理是网关自己的做法。 - 任何重试响应头,包括
Retry-After和X-RateLimit-*这一族。 - 各接口的 QPS 上限。此前被引用的页面已是无关内容,本次读到的官方页面也没有这些数字。
- 分辨率是否会改变 2.5 的天花板,以及队列深度、等待时长与成功率保证。
- 免费额度。
两条已公布的细节容易漏掉。天花板是非刚性目标,官方写的是 非刚性保障,那些数字表达的是意图而不是承诺。提额路径很明确:如需提升,请联系客户经理或者提交 工单。
常见问题
Seedance 每分钟允许多少次请求? 模型列表写的是 最大 RPM: 企业用户: 600 个人用户: 180。
同时能跑多少条任务? 最大并发: 企业用户: 10 个人用户: 3;2.0 的 4k 档只有 1。
轮询算不算在限额里? 官方给的是请求速率,轮询就是请求。不留意的话,轮询循环会吃掉大部分请求预算。
限额是按 Key 还是按账号? 按账号:每个账号(含主账号下的所有子账号,合并计算)。服务拆到不同 Key 上,仍共用一个天花板。
被限流时返回什么错误? 官方没有公布。别在假定某个 429 上分支,把真实响应记下来;想知道一波突发要花多少钱,看价格公式,不是错误日志。
给队列定容量之前,把模型列表再核一遍。