WaveSpeed上でZ-Image-Turbo APIを使う方法 (ステップバイステップガイド)

WaveSpeed上でZ-Image-Turbo APIを使う方法 (ステップバイステップガイド)

I’ll translate this article to Japanese now.

Z-Image-Turbo APIチュートリアル:ちょっとしたことがきっかけでした。私はドラ(Dora)です。その日、ランディングページのバリエーションの為にクリーンな商品ショットが必要でした。いつもの画像ツールではこのタスクには重すぎるように感じました。Z-Image-Turbo​ ​​​API​ についての話をずっと聞いていました。大きな宣伝ではなく、むしろ静かにチェンジログやエンジニアリングノートに現れるような話です。そこで試してみることにしました。

2026年1月下旬の1週間にわたってこれを使用しました。主にシンプルなマーケティングビジュアルやプロトタイプ用のコンセプトテクスチャを生成するためです。何も凝ったことはしていません。スタックを再構築することなく、どこに適合するかを確認したかったのです。ここに、役に立ったこと、役に立たなかったこと、そしてメスを入れることなくどのように配線したかを記載します。

前提条件

WaveSpeedアカウントの作成

WaveSpeedアカウントを作成することから始めました。フローは基本的でした:メール、パスワード、確認。驚きはありません。テストする前に何かを売ろうとしないダッシュボードが好きです。

APIキーを取得

サインアップ後、デベロッパーセクションに移動してキーを生成しました。テストプロジェクト用にラベルを付けて、ローカルの.envファイルに保存しました。小さな注記:後でステージング用の2番目のキーを作成しました。キーを環境ごとに分割しておくことで、どの呼び出しが有料プランに当たっているかを推測することなく済みました。

APIの基本

エンドポイントURLの構造

ほとんどのケースでは単一の生成エンドポイントを使用しました。パターンは次のようになっていました:

  • ベース:api.wavespeed.ai
  • バージョン付きパス:/v1
  • プロダクトパス:/z-image-turbo
  • アクション:/generate

したがって、一般的なURLは/v1/z-image-turbo/generateのようになっていました。バージョンを変更される可能性があるため、ハードコーディングしていません。ベースとバージョンをconfigに含めて、後で呼び出しを書き直すことなくバージョンを上げることができるようにしました。

認証ヘッダーのセットアップ

認証は標準的なBearerトークンでした。役立ったのは、ヘッダーのセットアップを一元化しておくことです:

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

最初は短いタイムアウト(10秒)でテストしてから、それを上げました。サービスが負荷を受けている場合、画像生成は一般的なREST呼び出しよりも長くかかることがあります。積極的に再試行してレート制限に達するよりも、計画しておく方が良いでしょう。

コアパラメータの説明

プロンプト、効果的なプロンプトの作成

私はプロンプト詩人ではありません。ここで役に立ったのは、シンプルで文字通りの言語と1つの明確なスタイルの手がかりでした。商品ショットの場合、安定した構造が見つかりました:

  • 主体:「白いシームレスな背景の上のマットブラックのワイヤレスイヤバド」
  • 角度またはレンズ:「45度の角度、柔らかいスタジオライティング」
  • コンテキストの手がかり:「最小限の影、反射なし」

スタイルをスタッキング(「シネマティック、ムーディー、エディトリアル、光沢のある」)していません。画像が漂流したからです。短くてシンプルなプロンプトは、より予測可能な結果をもたらしました。

2つのパスが反復を助けてくれました:

  • 最初のパス:構図を確認する為のブロードプロンプト。
  • 2番目のパス:必要な場所にのみ制約を追加します(影の長さ、背景のテクスチャ)。

サイズ、サポートされている解像度(256-1536)

ほとんどの場合、正方形とポートレートサイズを使用しました。APIはアップから1536までの一般的な値を受け入れました。クイックプレビューは512、最終アセットは1024を使用しました。1536では素敵なディテールが生成されましたが、より多くの時間とトークンがかかりました。多くのバリエーションを生成する場合は、小さく始めて、選択したプロンプトをより高いサイズでアップスケールまたは再実行してください。

シード、再現性の制御

シードは予想していた以上に重要でした。好きな見た目を見つけたときに、背景密度など1つの変数だけを調整できるようにシードを保存しました。プロンプトを大きく変更した場合は、モデルの初期のバイアスと戦わないようにシードをクリアしました。実際には:プロンプト、サイズ、シードを画像IDごとにログに記録しました。退屈な再レンダリングになったのはいい意味です。

出力形式、JPEGとPNGとWebP

  • **JPEG:**軽くて高速。プレビューと透明性なしのウェブアセットに最適。
  • **PNG:**ロスレス、より大きい。UIオーバーレイまたはクリーンなエッジが必要な場合に使用しました。
  • **WebP:**バランスの取れた中間地点。PNGより小さく、攻撃的なJPEGより清潔。

バッチ処理を実行していた場合、プレビューをJPEGに設定し、目的に応じて最終をPNGまたはWebPに設定しました。1つの実行で形式を混ぜることは可能ですが、記帳を減らすために実行ごとに一貫性を保ちました。

コード例

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);
}

非同期 vs 同期モード

enable_sync_modeの説明

enable_sync_modeがtrueの場合、小さな画像(512–1024)はしばしば一度に到着しました。それはプレビューと1回の操作に良かったです。しかし同期モードは高負荷またはより大きなサイズではタイムアウトします。そのエッジに当たると、APIは画像の代わりにジョブIDを返しました。

結果のポーリング

非同期は配線に少し時間がかかり、その後は問題ありませんでした。流れ:

  • enable_sync_modeをfalseに設定してgenerate要求をPOSTします(またはそれを省略するだけです)。
  • JSON内のjob_idを受け取ります。
  • ステータスエンドポイントを1~2秒ごとに指数バックオフでポーリングします。
  • ステータスが終了した場合、提供されたURLから画像をダウンロードします。

~30秒でのポーリングをキャップしてから、優雅に失敗しました。本番環境では、サービスが提供する場合、ウェブフックにシフトします。ポーリングは機能していますが、ロマンチックではありません。

エラーハンドリング

一般的なエラーコード

テスト中に見たもの:

  • 400:悪いフィールド(範囲外のサイズ、不明な形式)。ペイロードを修正してください。
  • 401:Bearer トークンが不足しているか無効です。ヘッダーとキースコープを確認してください。
  • 404:エンドポイントパスが間違っているか、ジョブが見つかりません(通常はタイプミスです)。
  • 429:レート制限。戻ってから後で再試行してください。
  • 500/503:一時的なサービスの問題。ジッターを使用して再試行します。

応答本文をログに記録しました。理由としては、サイズまたはシードが拒否されたときに役立つプレーンテキストのヒントを含むことが多いからです。

レート制限のベストプラクティス

クライアント上にトークンバケットを使用し、短いキューを使用しました。APIが429を返した場合、指数関数的にバックオフして、ランダムジッター(50–200ミリ秒)を追加して、雷の群れを避けました。また、リクエストをバッチ処理(下記を参照)すると、ピークバーストが減少しました。

プロダクションのヒント

バッチ処理パターン

リクエストごとに1つの画像を生成するのは簡単に見えましたが、オーバーヘッドが無駄でした。小さいバッチサイズ(3~5プロンプトずつ)に移動して、より安定したスループットが得られました。結果をプロンプト、サイズ、シード、出力パスを保存したmanifest.jsonファイルを含む日付付きフォルダーに書き込みました。その結果、ステークホルダーが「同じですが、より温かい光で行うことができますか?」と言ったときに、その結果が役立つことがわかりました。シードをバンプするか、プロンプトを調整して再実行しました。

コスト最適化

3つのことが重要でした:

  • サイズ規律:512でプレビュー、必要な場合のみ1024で最終化。1536のみ切り取り構文を多用する場合。
  • フォーマットフィット:プレビュー用JPEG:ほとんどのウェブビルド用WebP:透明度が非交渉の場合PNGが必要です。
  • 早期停止:最初のフレームが間違って見えた場合、待つ代わりにジョブをキャンセルしました。それはペニーを節約しました。

もう1つの実用的な注記:スクリプトの1日の総支出をキャップしました。派手ではありませんが、実行ループを保護してくれました。

いくつかの終わりの観察。Z-Image-Turbo APIは魔法のようには感じませんでした。おそらくそれが私が好きな理由です。ガードレールを設定したら安定していました:再現性の為の固定シード、小さなバッチ、保守的なタイムアウト。同期モードはプレビューに良かった:非同期は他のすべてに理にかなっていました。あなたがすでにAIツールで泳いでいるなら、このツールは注意を求めて叫びません。パイプラインで静かに座って、その仕事をします。

より高い解像度でノイズの多いプロンプトをどのように処理するかについて、私はまだ好奇心が強いです。それは別の日のためのテストです。