如何在 WaveSpeed 上使用 Z-Image-Turbo API(分步指南)

如何在 WaveSpeed 上使用 Z-Image-Turbo API(分步指南)

一件小事把我带到了这里。我是 Dora。那天,我需要为登陆页面变体生成一张干净的产品照片,而我通常使用的图像工具对这个任务来说显得太复杂了。我一直听到关于 Z-Image-Turbo​ ​​​API​ 的声音。不是那种大声宣传,而是它悄悄地出现在更新日志和工程笔记中。所以我试了试。

我在 2026 年 1 月下旬的一周内使用了它,主要是生成一些简单的营销视觉效果和一个原型的几个概念纹理。没什么特别的。我想看看它在哪里适用,而不需要重新调整我的技术栈。以下是哪些有帮助,哪些没有,以及我如何在不造成混乱的情况下集成它。

前置条件

创建 WaveSpeed 账户

我首先 创建了一个 WaveSpeed 账户。流程很简单:电子邮件、密码、验证。没有惊喜。我喜欢仪表板在我测试之前没有尝试向我销售任何东西。

获取您的 API 密钥

注册后,我进入开发者部分并生成了一个密钥。我为我的测试项目标记了它,并将其存储在我的本地 .env 文件中。有一个小提示:我后来为登陆环境创建了第二个密钥。按环境限制密钥范围让我避免了猜测哪些调用是在我的付费计划中进行的。

API 基础知识

端点 URL 结构

在大多数情况下,我使用单一生成端点。模式看起来像这样:

  • 基础:api.wavespeed.ai
  • 版本化路径:/v1
  • 产品路径:/z-image-turbo
  • 操作:/generate

所以一个典型的 URL 看起来像 /v1/z-image-turbo/generate。我避免硬编码版本,因为它们会改变。我将基础和版本放入配置中,这样我以后可以更新它,而无需重写调用。

身份验证标头设置

身份验证是标准的 Bearer 令牌。有帮助的是将标头设置集中在一起:

  • Authorization: Bearer YOUR_API_KEY
  • Content-Type: application/json

我先用很小的超时(10 秒)进行了测试,然后提高了它。当服务负载很重时,图像生成可能比典型的 REST 调用花费更长时间。最好提前计划,而不是积极地重试并触发速率限制。

核心参数解释

prompt,撰写有效提示

我不是提示诗人。这里有效的是简单、直白的语言和一个清晰的风格提示。对于产品照片,我发现了一个稳定的结构:

  • 主题:“一个哑光黑色无线耳塞放在白色无缝背景上”
  • 角度或镜头:“45 度角,柔和的工作室照明”
  • 背景线索:“最小阴影,无反射”

我避免了堆叠风格(“电影感、阴沉、社论、有光泽”),因为图像往往会漂移。简短、朴素的提示给了更可预测的结果。

两次通过帮助我迭代:

  • 第一次通过:广泛的提示以查看构图。
  • 第二次通过:仅在需要的地方添加约束(阴影长度、背景纹理)。

size,支持的分辨率 (256-1536)

我最常使用正方形和纵向尺寸。API 接受从 256 到 1536 的常见值。我坚持使用 512 进行快速预览,使用 1024 进行最终资产。1536 产生了很好的细节,但花费了更多的时间和令牌。如果您生成许多变体,请从小开始并放大或在更高的大小下重新运行选定的提示。

seed,可重现性控制

种子比我预期的更重要。当我找到喜欢的外观时,我保存了种子,所以我只能改变一个变量(比如背景密度),而不会偏离太远。如果我改变了很多提示,我清除了种子以避免与模型的早期偏见作斗争。在实践中:我为每个图像 ID 记录了提示、大小和种子。这使得重新渲染变得乏味,以一种好的方式。

output_format,JPEG vs PNG vs WebP

  • JPEG: 轻巧快速。适合预览和没有透明度的网页资产。
  • PNG: 无损,较大。当我需要 UI 叠加或干净边缘时使用它。
  • WebP: 一个很好的中间地带。比 PNG 小,比积极的 JPEG 干净。

当我在批处理时,我将预览设置为 JPEG,最终设置为 PNG 或 WebP,具体取决于目标。在一次运行中混合格式是可能的,但我为了减少记录保存而保持一致。

代码示例

cURL 快速开始这是我用来进行理智检查端点的最短路径。我喜欢从 cURL 开始,因为它使错误消息显而易见。

Bash

curl -X POST https://api.wavespeed.ai/v1/z-image-turbo/generate \
  -H "Authorization: Bearer $WAVESPEED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "a matte black wireless earbud on a white seamless background, soft studio lighting",
    "size": 1024,
    "seed": 12345,
    "output_format": "webp",
    "enable_sync_mode": true
  }' \
  --output preview.webp

如果为您的请求启用并支持同步模式,响应返回二进制图像数据或 base64 字段(取决于标头和服务器设置)。在测试期间我直接将其保存到文件。

Python 实现我保持 Python 版本简单。请求、超时和基本错误检查。

Python

import os
import requests
import base64

API_KEY = os.getenv("WAVESPEED_API_KEY")
URL = "https://api.wavespeed.ai/v1/z-image-turbo/generate"

payload = {
    "prompt": "cozy reading nook by a window, soft morning light, minimalist",
    "size": 1024,
    "output_format": "png",
    "enable_sync_mode": True,
}

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

resp = requests.post(URL, json=payload, headers=headers, timeout=30)
resp.raise_for_status()

# Some deployments return JSON with base64. Others return binary directly.
content_type = resp.headers.get("Content-Type", "")
if "application/json" in content_type:
    data = resp.json()
    img_b64 = data.get("image_base64")
    if not img_b64:
        raise RuntimeError("No image in response")
    with open("output.png", "wb") as f:
        f.write(base64.b64decode(img_b64))
else:
    with open("output.png", "wb") as f:
        f.write(resp.content)

print("Saved output.png")

JavaScript/Node.js 示例在 Node 中,我更喜欢使用 AbortController 的 fetch 来处理超时。

JavaScript

import fetch from 'node-fetch';
import { writeFileSync } from 'fs';

const API_KEY = process.env.WAVESPEED_API_KEY;
const URL = "https://api.wavespeed.ai/v1/z-image-turbo/generate";

const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000);

const payload = {
  prompt: "abstract paper texture, soft fibers, off-white, subtle grain",
  size: 512,
  output_format: "jpeg",
  enable_sync_mode: true,
};

try {
  const resp = await fetch(URL, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(payload),
    signal: controller.signal,
  });

  if (!resp.ok) {
    throw new Error(`${resp.status} ${resp.statusText}`);
  }

  const buffer = Buffer.from(await resp.arrayBuffer());
  writeFileSync("out.jpg", buffer);
  console.log("Saved out.jpg");
} catch (err) {
  console.error("Request failed:", err.message);
} finally {
  clearTimeout(timeoutId);
}

异步与同步模式

enable_sync_mode 解释

当 enable_sync_mode 为真时,小图像(512–1024)通常一次到达。这对于预览和一次性很好。但同步模式在负载很重或更大的尺寸下会超时。当我碰到了这个边界,API 返回了一个作业 ID 而不是一个图像。

轮询结果

异步花了一秒钟来装配,然后就很好了。流程:

  • 发送一个生成请求,enable_sync_mode 设置为 false(或只是省略它)。
  • 在 JSON 中收到 job_id。
  • 每 1-2 秒用指数退避轮询一次状态端点。
  • 当状态完成时,从提供的 URL 下载图像。

我将轮询限制在约 30 秒,然后优雅地失败。在生产中,如果服务提供 webhook,我会切换到 webhook。轮询有效,但它不浪漫。

错误处理

常见错误代码

我在测试期间看到了什么:

  • 400:一个坏字段(大小超出范围、未知格式)。修复你的有效负载。
  • 401:缺少或无效的 Bearer 令牌。检查标头和密钥范围。
  • 404:错误的端点路径或找不到作业(通常是拼写错误)。
  • 429:速率限制。退后并稍后重试。
  • 500/503:临时服务问题。使用抖动重试。

我记录了响应体,因为它们经常包含纯文本提示,当大小或种子被拒绝时很有帮助。

速率限制最佳实践

我在客户端使用了令牌桶,带有一个短队列。如果 API 返回 429,我指数级退避并添加随机抖动(50–200ms)以避免雷鸣般的羊群。另外,批处理请求(见下文)减少了峰值突发。

生产提示

批处理模式

每个请求生成一个图像感觉很简单,但它浪费了开销。我改进到一个小批量大小(每个 3-5 个提示),获得了更稳定的吞吐量。我将结果写入带日期的文件夹,其中包含 manifest.json 文件,该文件保存了提示、大小、种子和输出路径。该清单在利益相关者说”我们能做得一样,但带有更温暖的光吗?“时派上了用场。我只是提高了种子或调整了提示并重新运行。

成本优化

三件事很重要:

  • 大小规则:在 512 处预览,仅在需要时在 1024 处完成。1536 仅用于裁剪繁重的使用。
  • 格式适应:JPEG 用于预览:WebP 用于大多数网络构建:当透明度不可协商时使用 PNG。
  • 早期停止:如果前几帧看起来不对,我会取消作业而不是等待。它节省了美分,但累加起来。

还有一个更实际的注意事项:我在脚本中限制了总每日支出。这不是很光彩,但它保护我免受了一个失控的循环。

一些结束观察。Z-Image-Turbo API 没有感觉魔法。这可能就是我喜欢它的原因。一旦我设置了护栏,它就很稳定:用于可重现性的固定种子、小批量、保守的超时。同步模式对于预览很好:异步对其他一切都有意义。如果你已经在 AI 工具中游泳,这个不会大声喊叫以引起注意。它会静静地坐在管道中并做它的工作。

我仍然很好奇它如何在更高分辨率下处理嘈杂的提示。那是另一天的测试。