FLUX.2 按百万像素计价、用 credits 结算,而承载这些数字的两个官方页面,列法并不一样。鉴权只有一个 x-key 头。剩下的全在四条取整规则上——定价脚注把它们写出来了,但没有任何一个官方页面把它们拼成一个算例。

下面每个数字都留在它来自的那一页旁边,没公布的地方就写没公布。

FLUX.2 请求按什么计费

定价文档把换算写得直白:1 credit 等于 $0.01 USD,API 与 Playground 同价。图像这条线上它补了一句,FLUX.2 用按百万像素计价,所以成本随输出分辨率变化,而不是一次调用一个固定价。

决定账单的只有三个输入。输出尺寸决定收多少个百万像素,档位决定每个百万像素的单价,参考图各算各的。

官方费率表,逐页对照

bfl.ai/pricing 把每档拆成首个百万像素、之后每个百万像素、每张参考图三列。文档站的定价页每一项只给一个「起」字价。

端点路径档位首个 MP之后每个 MP每张参考图
/v1/flux-2-maxFLUX.2 [max]$0.07$0.03$0.03/MP
/v1/flux-2-proFLUX.2 [pro]$0.03$0.015$0.015/MP
/v1/flux-2-flexFLUX.2 [flex]$0.05$0.05$0.05/MP
/v1/flux-2-klein-4bFLUX.2 [klein] 4B$0.014$0.001$0.001/MP
/v1/flux-2-klein-9bFLUX.2 [klein] 9B$0.015$0.002$0.002/MP

只有一个档位两家对不上:文档定价页写 [flex] 每百万像素 $0.05 起,和定价页一致,而模型总览写的是 $0.06。引用时把页面和列名一起带上。

FLUX.2 [dev] 是故意不在表里的:仅本地、开放权重、非商用、不提供托管 API,也就没有可计费的端点。

决定总额的四条取整规则

四条脚注会改变最终数字,而且是叠加的。

  • 一个百万像素是 1024×1024 像素,所以除数取 1,048,576,不是 1,000,000。
  • 分辨率向上取整到下一个整百万像素,参考图与生成图分别取整。
  • 所有操作的输出上限都是 4 MP,超过 4 MP 的图会被压到 4 MP。
  • 传多张参考图时,每张超过 1 MP 的图被压到 1 MP,并且每张参考图都按 1 MP 计费,与请求的输出尺寸无关。单张参考图不一样:不超过 4 MP 时按原分辨率处理。

第二条最贵。一张 1440×2048 的输出有 2,949,120 个像素,也就是 2.81 个百万像素,按 3 收。

Black Forest Labs 官方示例:雪豹、小熊猫、熊猫、白色犬与企鹅被安排在一摞电视上,共享同一套布光
Black Forest Labs

第四条两头都咬。四张参考图挂在 [max] 上是 4 × $0.03,而一张 4 MP 参考图同样是 $0.12——单张保分辨率,多张则被统一压成每张一个百万像素。两次请求的完整账单把它从头走了一遍。

发请求之前先把钱算出来

下面这段估算代码按顺序套用那四条规则。它是纯算术,离线能跑,不花一分钱。

# 费率照抄 bfl.ai/pricing 图片页,单位是每百万像素的美元
RATES = {
    "flux-2-max":      {"first": 0.07,  "next": 0.03,  "ref": 0.03},
    "flux-2-pro":      {"first": 0.03,  "next": 0.015, "ref": 0.015},
    "flux-2-flex":     {"first": 0.05,  "next": 0.05,  "ref": 0.05},
    "flux-2-klein-4b": {"first": 0.014, "next": 0.001, "ref": 0.001},
    "flux-2-klein-9b": {"first": 0.015, "next": 0.002, "ref": 0.002},
}
MP = 1024 * 1024          # 官方定义:1 MP = 1024 x 1024 像素
CREDIT = 0.01             # 1 credit = $0.01 USD


def billed_megapixels(width, height):
    """向上取整到整百万像素;超过 4 MP 的输出会被压缩。"""
    pixels = min(width * height, 4 * MP)
    return -(-pixels // MP)


def cost(model, width, height, references=0):
    rate = RATES[model]
    output = billed_megapixels(width, height)
    usd = rate["first"] + max(output - 1, 0) * rate["next"]
    usd += references * rate["ref"]        # 多张参考图:每张算 1 MP
    return round(usd, 4), round(usd / CREDIT)


for job in [("flux-2-pro", 1440, 2048, 0), ("flux-2-max", 1024, 1024, 4)]:
    usd, credits = cost(*job)
    print(job, "->", f"${usd:.3f}", f"({credits} credits)")

跑出来的结果是 flux-2-pro 1440x2048 要 $0.060(6 credits),flux-2-max 1024x1024 带四张参考图要 $0.190(19 credits)。

这段估算代码逐行在做什么

billed_megapixels 先按 4 MP 封顶再向上取整,这个顺序是脚注推出来的:封顶是一次尺寸压缩,取整发生在它之后。-(-pixels // MP) 是整数除法向上取整,不会因为浮点误差悄悄少算一个百万像素。参考图的费用是直接乘出来的。把 RATES 放进配置,费率会变。

用同一份任务打真实 API

提交是一次 POST,返回的是待轮询的作业,不是图片;下载必须在同一次运行里完成,因为签名地址只活十分钟。

# 需要 curl 与 jq。先设好 BFL_API_KEY,密钥来自 dashboard.bfl.ai。
BASE="https://api.bfl.ai/v1"

curl -s -X POST "${BASE}/flux-2-pro-preview" \
  -H "x-key: ${BFL_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"A ceramic espresso cup on a walnut counter, oblique morning light.","width":1440,"height":2048}' \
  > submit.json

polling_url=$(jq -r .polling_url submit.json)

while true; do
  curl -s -H "x-key: ${BFL_API_KEY}" "${polling_url}" > poll.json
  status=$(jq -r .status poll.json)
  if [ "$status" = "Ready" ]; then break; fi
  if [ "$status" = "Error" ] || [ "$status" = "Failed" ]; then echo "generation failed"; exit 1; fi
  sleep 0.5
done

curl -sL -o flux-2-pro.png "$(jq -r .result.sample poll.json)"

Python 客户端做的是同一件事,只是把失败分支写明白了——预算出问题通常先在这里冒头。

# pip install requests
import os, time, requests

BASE = "https://api.bfl.ai/v1"
HEADERS = {"x-key": os.environ["BFL_API_KEY"], "Content-Type": "application/json"}

r = requests.post(
    f"{BASE}/flux-2-pro-preview",
    headers=HEADERS,
    json={"prompt": "A ceramic espresso cup on a walnut counter.",
          "width": 1440, "height": 2048},
)
r.raise_for_status()
job = r.json()

deadline = time.time() + 120
while time.time() < deadline:
    time.sleep(0.5)
    poll = requests.get(job["polling_url"], headers=HEADERS).json()
    if poll["status"] == "Ready":
        print(poll["result"]["sample"])   # 签名地址,有效期十分钟
        break
    if poll["status"] in ("Error", "Failed"):
        raise SystemExit(poll)

402 与 429 对预算意味着什么

两个状态码该进成本讨论。余额不足返回 402;API 允许 24 个并发任务,超过返回 429,flux-kontext-max 只有 6 个。把 worker 池开到 24 以上不会让请求失败,它让队列在时间上变贵;而批处理中途吃到一个 402,会留下一半付过钱、一半没做完的任务。

输出尺寸如何改变账单

取整和 4 MP 上限会互相作用,把常见尺寸在同一档上排一行价,是最省事的看法。

# 取整规则与 4 MP 上限对一次 FLUX.2 [pro] 任务的影响
# 费率:首个百万像素 $0.03,之后每个 $0.015
sizes = [(1024, 1024), (1440, 2048), (1920, 1080), (3840, 2160)]
for w, h in sizes:
    px = min(w * h, 4 * 1024 * 1024)          # 超过 4 MP 的输出会被压到 4 MP
    mp = -(-px // (1024 * 1024))              # 向上取整到整百万像素
    usd = 0.03 + max(mp - 1, 0) * 0.015
    print(f"{w}x{h}  {w * h / 1048576:5.2f} raw MP -> {mp} billed MP -> ${usd:.3f}")

这段输出值得读两遍:1024×1024 收 1 MP、$0.030;1440×2048 收 3 MP、$0.060;1920×1080 收 2 MP、$0.045;3840×2160 收 4 MP、$0.075。最后一行是上限在起作用——请求了 7.91 个百万像素,交付和计费都按 4 个算。至于少重抽几次让预算更耐用,FLUX.2 提示词指南讲的是那一半。

批量、编辑与微调端点

有三处已公布的细节会改变规模化之后的估算。

批量请求把基础价乘以张数。定价页给的例子是 FLUX.2 [pro] 批量四张:单张 $0.03 起,四张 $0.12 起。那是乘法,不是量价折扣。

图像编辑是两个官方页面开始不可互换的地方。文档表格把 [pro] 的图像编辑写成 $0.045 起,而 bfl.ai/pricing 把 [pro] 的参考图写成每百万像素 $0.015。不同的列在量不同的东西。

微调端点在公开测试期内按基础端点的费率计费。官方给的例子是 flux-2-klein-9b-kv-finetuned,与同分辨率的 flux-2-klein-9b 同价。页面补了一句,测试期结束后可能变。

定价页仍未公布的东西

  • 没有免费 API 额度、注册赠送或试用额度。快速开始流程从注册直接走到买 credits,自动充值是 $5 阈值、目标值至少高于阈值 $10,那是充值规则,不是购买下限。
  • 没有按国家拆分的价格,欧洲与美国两个端点之间也没有价差。
  • 没有成功率或基准分,所以「每张可用图的成本」无法从官方公布的东西推出来。
  • 商用开放权重各档没有单价。授权页只列了 Builder、Platform、Professional、Enterprise 与每月出图量,每张卡片都指向 Contact Sales。

常见问题

FLUX.2 API 有免费档吗? 没有公布免费 API 额度。免费那一条路是开放权重,它是授权,不是配额。

输出越大一定越贵吗? 不是。超过 4 MP 会被压到 4 MP,所以 4 MP 的任务和 8 MP 的任务同价。上限以下由整百万像素取整决定。

参考图怎么影响价格? 多张参考图的任务里,每张都按 1 MP 计费,与输出尺寸无关,所以 [max] 上四张参考图加 $0.12。单张不超过 4 MP 时保原分辨率,按原分辨率计费。

为什么 [pro] 编辑会有两个价? 两个官方页面用了不同的列:文档表格写 $0.045,定价页写每百万像素 $0.015 的参考图费率。引用时把两页都写上。

把费率表放进配置,批处理之前跑一次估算,把 402 和 429 当成成本信号而不是网络错误。请求本身的机制在 FLUX.2 API 接入指南里,同一套费率在浏览器里的样子写在 FLUX 使用教程