Cara Menggunakan Z-Image-Turbo API di WaveSpeed (Panduan Langkah demi Langkah)

Cara Menggunakan Z-Image-Turbo API di WaveSpeed (Panduan Langkah demi Langkah)

Hal kecil yang membawa saya ke sini. Saya Dora. Hari itu, saya membutuhkan foto produk yang bersih untuk variasi landing page, dan alat gambar biasaku terasa lebih berat dari tugas tersebut. Saya terus mendengar tentang Z-Image-Turbo​ ​​​API​. Bukan jenis penyebutan yang ramai, lebih seperti muncul diam-diam di changelog dan catatan engineering. Jadi saya mencobanya.

Saya menggunakannya selama seminggu di akhir Januari 2026, sebagian besar untuk menghasilkan visual pemasaran sederhana dan beberapa tekstur konsep untuk prototipe. Tidak ada yang rumit. Saya ingin melihat di mana tempat yang cocok tanpa mengerjakan ulang stack saya. Berikut apa yang membantu, apa yang tidak, dan bagaimana saya menyambungkannya tanpa membuat berantakan.

Prasyarat

Buat Akun WaveSpeed

Saya mulai dengan membuat akun WaveSpeed. Alurnya sederhana: email, kata sandi, verifikasi. Tidak ada kejutan. Saya menyukai bahwa dashboard tidak mencoba menjual apa pun sebelum saya bisa menguji.

Dapatkan Kunci API Anda

Setelah mendaftar, saya pergi ke bagian developer dan membuat kunci. Saya melabelnya untuk proyek tes saya dan menyimpannya di file .env lokal saya. Satu catatan kecil: saya membuat kunci kedua untuk staging nanti. Menjaga kunci dalam cakupan per environment menyelamatkan saya dari menebak panggilan mana yang mengenai paket berbayar saya.

Dasar-dasar API

Struktur URL Endpoint

Saya menggunakan satu endpoint generate untuk sebagian besar kasus. Polanya terlihat seperti ini:

  • Base: api.wavespeed.ai
  • Path dengan versi: /v1
  • Path produk: /z-image-turbo
  • Aksi: /generate

Jadi URL khas terlihat seperti /v1/z-image-turbo/generate. Saya menghindari hardcoding versi karena mereka berubah. Saya memasukkan base dan versi ke config sehingga saya dapat memperbaruinya nanti tanpa menulis ulang panggilan.

Pengaturan Header Autentikasi

Autentikasi adalah token Bearer standar. Yang membantu adalah menjaga pengaturan header terpusat:

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

Saya menguji dengan timeout kecil (10 detik) terlebih dahulu, kemudian menaikkannya. Ketika layanan sedang beban tinggi, pembuatan gambar dapat memakan waktu lebih lama dari panggilan REST biasa. Lebih baik merencanakan daripada mencoba lagi secara agresif dan mencapai batas laju.

Parameter Inti Dijelaskan

prompt, Menulis Prompt yang Efektif

Saya bukan penyair prompt. Yang bekerja di sini adalah bahasa sederhana, literal dan satu isyarat gaya yang jelas. Untuk foto produk, saya menemukan struktur yang stabil:

  • Subjek: “a matte black wireless earbud on a white seamless background”
  • Sudut atau lensa: “45-degree angle, soft studio lighting”
  • Isyarat konteks: “minimal shadow, no reflections”

Saya menghindari menumpuk gaya (“cinematic, moody, editorial, glossy”) karena gambar melayang. Prompt singkat dan biasa memberikan hasil yang lebih dapat diprediksi.

Dua pass membantu saya iterate:

  • Pass pertama: prompt luas untuk melihat komposisi.
  • Pass kedua: tambahkan kendala hanya di mana diperlukan (panjang bayangan, tekstur latar belakang).

size, Resolusi yang Didukung (256-1536)

Saya paling sering menggunakan ukuran persegi dan potret. API menerima nilai umum dari 256 hingga 1536. Saya berpegang pada 512 untuk pratinjau cepat dan 1024 untuk aset final. 1536 menghasilkan detail bagus tetapi memerlukan lebih banyak waktu dan token. Jika Anda membuat banyak varian, mulai dari kecil dan upscale atau jalankan kembali prompt pilihan dengan ukuran lebih tinggi.

seed, Kontrol Reproduksibilitas

Seed penting lebih dari yang saya harapkan. Ketika saya menemukan tampilan yang saya sukai, saya menyimpan seed sehingga saya bisa hanya menyesuaikan satu variabel (seperti kepadatan latar belakang) tanpa melayang terlalu jauh. Jika saya mengubah prompt banyak, saya menghapus seed untuk menghindari melawan bias model sebelumnya. Dalam praktik: saya mencatat prompt, ukuran, dan seed per ID gambar. Itu membuat re-render membosankan, dalam cara yang baik.

output_format, JPEG vs PNG vs WebP

  • JPEG: ringan dan cepat. Bagus untuk pratinjau dan aset web tanpa transparansi.
  • PNG: ​lossless, lebih besar. Saya menggunakannya untuk overlay UI atau ketika saya membutuhkan tepi yang bersih.
  • WebP: ​pertengahan yang solid. Lebih kecil dari PNG, lebih bersih dari JPEG agresif.

Ketika saya membuat batch, saya mengatur pratinjau ke JPEG dan final ke PNG atau WebP tergantung target. Mencampur format dalam satu run dimungkinkan, tetapi saya menjaganya konsisten per pekerjaan untuk mengurangi pembukuan.

Contoh Kode

Awal Cepat cURL Inilah jalur terpendek yang saya gunakan untuk pemeriksaan sanitas endpoint. Saya menyukai memulai dengan cURL karena membuat pesan kesalahan jelas.

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

Jika mode sync diaktifkan dan didukung untuk permintaan Anda, respons mengembalikan data gambar biner atau bidang base64 (tergantung header dan pengaturan server). Saya menyimpannya langsung ke file selama tes.

Implementasi Python Saya menjaga versi Python sederhana. Requests, timeout, dan pemeriksaan kesalahan dasar.

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")

Contoh JavaScript/Node.js Di Node, saya lebih suka fetch dengan AbortController untuk timeout.

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

Mode Async vs Sync

enable_sync_mode Dijelaskan

Ketika enable_sync_mode benar, gambar kecil (512–1024) sering tiba dalam satu tembakan. Itu bagus untuk pratinjau dan satu kali. Tetapi mode sync habis waktu di bawah beban berat atau ukuran yang lebih besar. Ketika saya mencapai tepi itu, API mengembalikan ID pekerjaan alih-alih gambar.

Polling untuk Hasil

Async membutuhkan detik untuk disiapkan, kemudian itu baik-baik saja. Alurnya:

  • POST permintaan generate dengan enable_sync_mode diatur ke false (atau tinggalkan saja).
  • Terima job_id dalam JSON.
  • Poll endpoint status setiap 1–2 detik dengan exponential backoff.
  • Ketika status selesai, unduh gambar dari URL yang disediakan.

Saya membatasi polling pada ~30 detik sebelum gagal dengan baik. Dalam produksi, saya akan beralih ke webhook jika layanan menawarkannya. Polling bekerja, tetapi bukan hal yang romantis.

Penanganan Kesalahan

Kode Kesalahan Umum

Yang saya lihat selama tes:

  • 400: bidang buruk (ukuran di luar jangkauan, format tidak diketahui). Perbaiki payload Anda.
  • 401: token Bearer hilang atau tidak valid. Periksa header dan cakupan kunci.
  • 404: jalur endpoint salah atau pekerjaan tidak ditemukan (biasanya typo).
  • 429: batas laju. Mundur dan coba lagi nanti.
  • 500/503: masalah layanan sementara. Coba lagi dengan jitter.

Saya mencatat badan respons karena mereka sering membawa petunjuk dalam bahasa biasa, membantu ketika ukuran atau seed ditolak.

Praktik Terbaik Batas Laju

Saya menggunakan token bucket di klien, dengan antrian pendek. Jika API mengembalikan 429, saya mundur secara eksponensial dan menambahkan jitter acak (50–200ms) untuk menghindari kawanan guntur. Juga, batch permintaan (lihat di bawah) mengurangi burst puncak.

Tips Produksi

Pola Pemrosesan Batch

Menghasilkan satu gambar per permintaan terasa sederhana, tetapi itu membuang overhead. Saya pindah ke ukuran batch kecil (3–5 prompt masing-masing) dan mendapat throughput lebih stabil. Saya menulis hasil ke folder bertanggal dengan file manifest.json yang menyimpan prompt, ukuran, seed, dan jalur output. Manifest itu terbukti berguna ketika stakeholder berkata, “Bisakah kita melakukan hal yang sama, tetapi dengan cahaya yang lebih hangat?” Saya hanya menyesuaikan seed atau mengubah prompt dan menjalankan ulang.

Optimasi Biaya

Tiga hal penting:

  • Disiplin ukuran: pratinjau di 512, finalisasi di 1024 hanya bila diperlukan. 1536 hanya untuk penggunaan berat crop.
  • Pas format: JPEG untuk pratinjau: WebP untuk sebagian besar build web: PNG ketika transparansi tidak dapat dinegosiasikan.
  • Penghentian awal: jika frame pertama terlihat salah, saya membatalkan pekerjaan alih-alih menunggu. Itu menghemat sen, yang bertambah.

Satu catatan praktis lagi: saya membatasi total pengeluaran harian dalam skrip saya. Tidak glamor, tetapi itu melindungi saya dari loop yang melarikan diri.

Beberapa pengamatan penutup. Z-Image-Turbo API tidak terasa magis. Mungkin itulah mengapa saya menyukainya. Itu stabil setelah saya menetapkan guardrail: seed tetap untuk reproduksibilitas, batch kecil, timeout konservatif. Mode sync bagus untuk pratinjau: async masuk akal untuk segalanya. Jika Anda sudah berenang di alat AI, yang satu ini tidak akan berteriak untuk perhatian. Itu akan duduk diam di pipeline dan melakukan pekerjaannya.

Saya masih penasaran tentang bagaimana cara menangani prompt yang bising dengan resolusi lebih tinggi. Itu adalah tes untuk hari lain.