Görseller Nasıl Otomatik Üretilir: Şablon, Job ve Webhook
Bu sorunun çoğu cevabı, bir metin kutusunun ekran görüntüsü. Prompt yaz, butona bas, bekle, indir, tekrarla. Bu otomasyon değil. Bu, sizin elinizle daha hızlı çalışmanız.
Otomatik demek, döngüde insan yok demek. Bir veri satırı geliyor, bir görsel çıkıyor, kimse olup bitmesini izlemiyor. Bunun için dört parça gerekiyor: içinde delikler olan bir prompt şablonu, delikleri dolduracak veri, işi bloklamadan kabul eden bir kuyruk ve sonucu koyacak kalıcı bir yer. Bunun ortasında API'yi biz çalıştırıyoruz; dolayısıyla insanların kurduğu pipeline'ları da lansmandan üç hafta sonra sessizce kırılanları da görüyoruz.

Kimsenin önce söylemediği kısım: artık ucuz
Rakamla başlayın, çünkü neyi kurmaya razı olduğunuzu o değiştiriyor.
Nano Banana 2 Lite üzerinden bin görsel $23.80 tutuyor. Yani 1.000 × $0.0238; 26 Ağustos 2026'daki fiyatımızla. Yüz bin ürün çekimi — gerçek bir katalog, her SKU, her renk varyantı — $2,380.
Aralarında seçim yapacağınız katmanlarda aynı hacimler:
| Görsel | Nano Banana 2 Lite | Nano Banana 2 | Nano Banana Pro |
|---|---|---|---|
| 100 | $2.38 | $4.00 | $7.50 |
| 1.000 | $23.80 | $40.00 | $75.00 |
| 10.000 | $238.00 | $400.00 | $750.00 |
| 100.000 | $2,380.00 | $4,000.00 | $7,500.00 |
Fiyatlar ve ürün koşulları zamanla değişebilir; satın alma kararı öncesinde güncel fiyatları kontrol edin. Google Batch veya Flex fiyatlandırması, zamanlama, kapasite ve işleme koşulları farklı olduğu için standart on-demand API request'iyle birebir eşdeğer değildir ve bu tabloya dahil edilmemiştir. Bu karşılaştırma belirli bir kullanım senaryosuna aittir; E2X'in her koşulda "dünyanın en ucuzu" olduğu iddia edilmemektedir.
Görsel üretimini nasıl otomatikleştireceğini soran insanların çoğu, bunu sessizce "denemesi bile fazla pahalı" diye fiyatlamış oluyor. Bu $23.80'lik bir soru. Kurun şu şeyi.
Adım 1: prompt yazmayı bırakın, şablon yazmaya başlayın
Bir kez yazdığınız prompt bir cümledir. Bir makinenin on bin kez çalıştırdığı prompt, slot'ları olan bir şablondur ve bütün iş bu farkta.
Kural şu: değişen her şey bir slot'a, aynı kalması gereken her şey sabit metne gider. Bu sınırı yanlış çizerseniz set kayar — görsellerin yarısı beyazda, yarısı gride kalır; çünkü "arka plan" değişken tarafa sızmıştır.
TEMPLATE = (
"{colour} renkli bir {product_name} ürününün stüdyo çekimi, "
"düz sıcak gri bir fon üzerinde ortalanmış, sol üstten yumuşak yönlü "
"ana ışık, sığ alan derinliği, editoryal katalog stili, "
"metin yok, logo yok, insan yok"
)
İki slot. Işık, fon, kadraj ve dışlamalar donduruldu. 400 görselin 400 kaza yerine tek bir çekim gibi görünmesini sağlayan şey, o donmuş yarı.
Değişken yarının dışında tutmanız gereken dört şey var: mecra, ışık yönü, arka plan ve olumsuz talimatlar. Görsel kimliğiniz bunlar. Satır başına oynuyorlarsa, kimliğiniz yok demektir.

Prompt zanaatının kendisi ayrı bir yazının konusu. Otomasyon açısından önemli olan şekil: sabit çerçeve, adlandırılmış delikler, sürpriz yok.
Adım 2: asıl ürün veri
Şablon önemsiz. İş verinin içinde ve genelde veri zaten elinizde.
- Bir ürün katalog tablosu. SKU başına bir satır; isim, renk, malzeme, kategori sütunları.
- Blog yazılarının bir CMS export'u; başlık ve konu, makale başına bir header görselinin slot'ları oluyor.
- Uygulama veritabanınızdaki satırlar — kullanıcı tarafından oluşturulan ilanlar, etkinlik sayfaları, tarifler.
- Bir reklam varyantı tablosu: altı başlık çarpı dört arka plan yirmi dört görsel eder ve bunu kimse elle brief'lemiyor.
Kaynak ne olursa olsun, API'ye dokunmadan önce onu bir sözlük listesine normalize edin ve her satırda sabit bir ID tutun. Sonuçları kayıtlarla eşleştirmek için gerekiyor ve atlamanın acısı tam olarak bir webhook tetiklendiğinde çıkıyor.
Adım 3: gönderin, beklemeyin
API'miz bilerek asenkron. Bir job POST ediyorsunuz, anında bir job ID alıyorsunuz ve üretim bizim tarafımızda oluyor.
curl -X POST https://api.e2x.ai/v1/jobs/submit \
-H "Authorization: Bearer $E2X_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/nano-banana-2-lite/text-to-image",
"input": {
"prompt": "Mat siyah renkli bir ceviz masa lambasının stüdyo çekimi...",
"aspect_ratio": "1:1"
},
"webhookUrl": "https://your-app.example.com/hooks/e2x"
}'
Bir tabloyu job'lara çeviren gezgin kabaca otuz satır. Bir CSV okuyor, şablonu satır başına biçimlendiriyor, gönderiyor ve hiçbir şey öksüz kalmasın diye job ID'yi satır ID'sinin karşısına yazıyor.
import csv
import os
import time
import requests
API = "https://api.e2x.ai/v1"
HEADERS = {
"Authorization": f"Bearer {os.environ['E2X_API_KEY']}",
"Content-Type": "application/json",
}
TEMPLATE = (
"{colour} renkli bir {product_name} ürününün stüdyo çekimi, "
"düz sıcak gri bir fon üzerinde ortalanmış, sol üstten yumuşak yönlü "
"ana ışık, sığ alan derinliği, editoryal katalog stili, "
"metin yok, logo yok, insan yok"
)
MAX_IMAGES = 500 # sert tavan, maliyet bölümüne bakın
UNIT_COST = 0.0238 # Nano Banana 2 Lite, 26 Ağustos 2026'da kontrol edildi
def submit(row):
body = {
"model": "google/nano-banana-2-lite/text-to-image",
"input": {
"prompt": TEMPLATE.format(**row),
"aspect_ratio": "1:1",
},
"webhookUrl": "https://your-app.example.com/hooks/e2x",
}
for attempt in range(4):
r = requests.post(f"{API}/jobs/submit", json=body, headers=HEADERS, timeout=30)
if r.status_code < 300:
return r.json()["data"]["jobId"]
if r.status_code == 429 or r.status_code >= 500:
time.sleep(2 ** attempt)
continue
raise RuntimeError(f"row {row['id']} rejected: {r.status_code} {r.text}")
raise RuntimeError(f"row {row['id']} still failing after 4 attempts")
with open("catalog.csv") as fh:
rows = list(csv.DictReader(fh))[:MAX_IMAGES]
print(f"submitting {len(rows)} jobs, budget ${len(rows) * UNIT_COST:.2f}")
submitted = {}
for row in rows:
try:
submitted[row["id"]] = submit(row)
except RuntimeError as err:
print(f"skipped: {err}")
print(f"{len(submitted)}/{len(rows)} accepted")
O döngünün yapmadığı şeye dikkat edin: bir satır patladığında durmuyor. 212. satırında renk alanı boş olan 500'lük bir batch size 499 görsel ve loglanmış bir atlama vermeli; gece üçte bir stack trace ve sıfır görsel değil.
Slug göründüğünden önemli. google/nano-banana-2-lite/text-to-image capability ekini taşıyor; Nano Banana 2'nin metin slug'ı ise eksiz, çıplak google/nano-banana-2. Tahmin etmek, aksi hâlde bitmiş görünen bir pipeline'da size 404 ödetiyor. Her model parametre listesini makine tarafından okunabilir bir spec dosyasında yayımlıyor.
Adım 4: polling yerine webhook ve sebebi
Poll edebilirsiniz. GET /v1/jobs/{JOB_ID} size pending, processing, completed, failed ya da cancelled döndürüyor ve tek seferlik bir script için bu gayet iyi.
Bir pipeline için yanlış tercih ve sebebi zarafet değil. Polling, süreç ömrünüzü batch'teki en yavaş job'a bağlıyor. Bir Lite üretimi bizim tarafımızda kabaca 60 saniye sürüyor. 500 tane gönderin ve poller'ın, kuyruk ne kadar sürerse o kadar hayatta kalıp state tutması gerekir — bir deploy boyunca, bir container yeniden başlatması boyunca, hangi serverless platformdaysanız oradaki 15 dakikalık timeout boyunca. Öldüğünde de, hangi job'ların havada olduğuna dair tek kaydı elinde tutarak ölür.
Webhook bunu tersine çeviriyor. Gönderiyor ve çıkıyorsunuz. Sonra tamamlanmış bir job'la bir POST geliyor ve siz tam olarak o tek job'ı, state tutmadan işliyorsunuz.
// Express handler. Idempotent: aynı jobId iki kez gelebilir.
app.post("/hooks/e2x", express.json(), async (req, res) => {
res.status(200).end(); // önce onayla, işi sonra yap
const job = req.body.data;
if (job.status !== "completed") {
await markFailed(job.jobId, job.error?.message ?? "unknown");
return;
}
const already = await findAsset(job.jobId);
if (already) return;
await storeImage(job.jobId, job.outputs[0].url);
});
Bir script'i elle çalıştırıp izlerken poll edin. Kimse izlemiyorken webhook'u alın — otomasyonun tanımı da zaten bu.
Adım 5: çıktı URL'i geçici ve pipeline'lar böyle kırılıyor
Asıl mesele bu. Geri kalan her şeyi göz gezdirerek geçecekseniz, bu bölümü iki kez okuyun.
data.outputs[0].url bir teslimat URL'i, depolama değil. Şu anda çalışıyor. Sonsuza kadar çalışmayacak. Onu kalıcı sanan her şey — bir product_image_url sütunu, bir CMS alanı, müşteriye e-postayla gönderilen bir link — staging'de düzgün render oluyor ve iki hafta sonra kırık görsel ikonları gösteriyor.
Arıza kötü, çünkü gecikmeli. Yazma anında hiçbir şey hata vermiyor. Testler geçiyor. Batch 500 başarı raporluyor. Sonra görseller en eski kayıtlardan başlayarak kaybolmaya başlıyor ve biri fark ettiğinde onları bütün job'ı yeniden çalıştırmadan yeniden üretemiyorsunuz — çünkü prompt'lar da hiç kaydedilmemişti.
Byte'ları indirin. Kendi bucket'ınıza koyun. Kendi URL'inizi saklayın.

import requests
import boto3
s3 = boto3.client("s3")
def store_image(job_id, row_id, source_url):
img = requests.get(source_url, timeout=60)
img.raise_for_status()
key = f"products/{row_id}.jpg"
s3.put_object(
Bucket="my-assets",
Key=key,
Body=img.content,
ContentType=img.headers.get("content-type", "image/jpeg"),
)
return f"https://cdn.example.com/{key}"
Hazır oradayken prompt'u görselin yanına kaydedin. Tek bir metin sütunu ve "o varyantı yeniden üret" ile "baştan başla" arasındaki fark tam olarak bu.
Birinci günden edinmeye değer iki alışkanlık daha. İndirmenin bir hata sayfası değil, görsel byte'ları döndürdüğünü kontrol edin; çünkü içinde HTML olan bir 200 de bucket'ınıza gayet keyifle yazılır. Ve depolamayı bizim job ID'mize değil, kendi satır ID'nize göre anahtarlayın; böylece bir yeniden üretim doğru nesnenin üstüne yazar, onu öksüz bırakmaz.
Adım 6: hacimde gerçekte ne bozuluyor
Küçük batch'ler her şeyi gizliyor. Birkaç yüzü geçtiğinizde ortaya çıkanlar şunlar.
Kısmi batch'ler normaldir. Büyük her koşunun bir kısmı patlıyor — bir içerik filtresine takılan prompt, bozuk bir satır, geçici bir upstream hatası. 500'de 497'yi başarı durumu sayın ve kendinize yalnızca o üç satırı yeniden çalıştıran tek komutluk bir yol bırakın.
Yeniden denemelerin bir harcama tavanı olmalı. Tavansız bir retry döngüsü, fatura kesen bir bug'dır. Atış başına $0.0238 zararsız geliyor; ta ki takılmış bir döngü onu kırk bin kez çalıştırana kadar. Kodun içine sert bir sayaç koyun — yukarıdaki MAX_IMAGES satırı buradaki en ucuz sigorta.
Idempotency opsiyonel değil. Webhook'lar birden fazla kez teslim edilebiliyor. Tek bir job ID üzerinde iki kez çalıştırılması güvenli olmayan bir handler size mükerrer varlıklar ve mükerrer satırlar veriyor ve bunu en yoğun haftada öğreniyorsunuz.
Maliyetlerin aylık faturaya değil, canlı bir sayaca ihtiyacı var. API'mizde parasal değerler mikro-cent olarak dönüyor — 1.000.000, $1 ediyor. Onları batch başına toplayın ve batch kapandığında toplamı loglayın. Her gece "412 görsel, $9.81" raporlayan bir pipeline, kimsenin denetlemek zorunda kalmadığı bir pipeline'dır.
Aspect ratio varsayılanları sizi şaşırtacak. Lite varsayılan olarak 1:1 veriyor, Nano Banana 2 ve Pro ise 9:16. Onu şablonda sabitleyin, yoksa kataloğunuzun yarısı sessizce portreye döner.
Watermark dosyayla birlikte geziyor. Google, görsel modellerinin ürettiği her şeye SynthID basıyor. Görünmez, bir flag değil ve pipeline'ınızın byte'lara sonradan yaptığı her şeyden sağ çıkıyor. Sizin tarafta marka ya da hukuktan kim sorumluysa, yapay zekâ üretimi varlıkları pipeline var olmadan önce onaylamalı; o bir bucket'a 20.000 nesne yazdıktan sonra değil.

Pipeline'ı hangi modele yöneltmeli
Varsayılanınız Nano Banana 2 Lite olsun ve ancak somut bir şey sizi zorladığında oradan ayrılın.
Bu bir kaçamak değil, aritmetik. $0.0238'le görsel üreten en ucuz şey o; yerini aldığı orijinal Nano Banana'dan tam bir kuşak daha yeni ve pipeline hacimlerinde fiyat farkı, finansın baktığı tek rakama dönüşerek birikiyor. Ayrıca başka hiçbir şeyde olmayan dört aspect ratio taşıyor — 1:4, 4:1, 1:8 ve 8:1 — çıktı banner ve dikey şeritse tam olarak istediğiniz şey. Tek tuhaflığı: resolution parametresi hiç yok ve bir tane göndermek sessizce yok sayılan bir işlem değil, hata.
Şu dört durumda oradan başka yere yönlendirin, başka türlü değil:
- 1K üstü çıktı. Lite yalnızca 1K. Nano Banana 2 $0.04 tabanla 4K'ya uzanıyor; 2K ×1,5 ve 4K ×2.
- Görselin içinde okunaklı metin. Fiyatlı ürün kartları, yerelleştirilmiş infografikler. Bu, $0.075'le Nano Banana Pro'da yaşıyor; orada 1K ile 2K aynı fiyat — 2K'yı alın, bedava.
- Şeffaf arka planlar. Kesimler ve sticker sayfaları
background: transparentistiyor ve bunu tek çağrıda yapan tek model GPT Image 2. 1K'da ham katalog rakamını değil, $0.0525'i bütçeleyin —qualityher katmanda 7 ile çarpıyor. - Birçok kare boyunca aynı yüz ya da aynı şişe. Bu bir hacim problemi değil, referans görsel problemi; tutarlılık üzerine kendi yazısı var.
Karışık iş yükleri için asıl kütleyi Lite'ta çalıştırın ve metin ya da sadakat gerektiren %2'yi verinizdeki bir sütuna göre Pro'ya dallandırın. Tek pipeline, iki model, Pro fiyatı yalnızca bir şey kazandırdığı yerde.
Submit ve poll kontratının parametre parametre anlatımı için Nano Banana Pro API eğitimine, katman katman dökümü için model karşılaştırmasına bakın. İkisi de bir modeli çoktan seçmiş olduğunuzu varsayıyor. Seçmediyseniz, text-to-image modelleri fiyatlarıyla birlikte listeli ve katalog video tarafını da ekliyor.
Sırasıyla, bütünü
Slot'lu şablon. Sabit ID'li veri. Sert bir tavan altında job olarak gönderim. Webhook alma. Byte'ları kendi depolamanıza indirme. Hataları ve harcamayı loglama. Altı adım, hiçbiri zor değil ve atlanan hep beşinci adım oluyor.
Sıkça sorulan sorular
Görsel otomatik nasıl üretilir?
Prompt'unuzu adlandırılmış slot'ları olan bir şablon olarak yazın, o slot'ları ürün kataloğu ya da CSV gibi bir veri kaynağından doldurun ve doldurulmuş her prompt'u bir görsel API'sine asenkron job olarak gönderin. Sonucu poll ederek değil webhook'la alın, sonra görsel byte'larını kendi depolamanıza indirin. O döngüdeki hiçbir şeyin insana ihtiyacı yok; işi hızlı el emeği olmaktan çıkarıp otomatik yapan da bu.
1.000 görseli otomatik üretmek ne kadar tutar?
26 Ağustos 2026'daki E2X fiyatlarıyla Nano Banana 2 Lite üzerinden 1.000 görsel $23.80, çünkü her request $0.0238. Aynı hacim Nano Banana 2'de $40.00, Nano Banana Pro'da $75.00. Daha yüksek çözünürlükler bunun üstüne çarpan biniyor, ama standart 1K çıktı için hesabın tamamı görsel başına rakam.
Görsel üretme job'ları için webhook mu kullanmalıyım, polling mi?
Gözetimsiz çalışan her şey için webhook kullanın. Polling, süreç ömrünüzü batch'teki en yavaş job'a bağlıyor; dolayısıyla bir deploy ya da bir serverless timeout, poller'ı hangi job'ların hâlâ çalıştığına dair tek kaydı elinde tutarken öldürüyor. Webhook ise gönderip çıkmanıza, sonra tamamlanan her job'ı state tutmadan işlemenize izin veriyor. Çalışmasını izlediğiniz bir script için polling gayet iyi.
Ürettiğim görseller neden bir süre sonra yüklenmiyor?
Çünkü görseli değil, API'nin çıktı URL'ini sakladınız. O URL depolama değil, geçici teslimat; dolayısıyla onu tutan bir sütun önce doğru render oluyor, sonra kırılıyor. Job tamamlanır tamamlanmaz byte'ları indirin, kendi bucket'ınıza yazın, kendi URL'inizi saklayın. Bir görsel pipeline'ının kırık hâlde yayına çıkmasının en yaygın yolu bu.
Otomatik bir görsel pipeline'ının varsayılanı hangi model olmalı?
Görsel başına $0.0238'le Nano Banana 2 Lite. Kataloğumuzdaki en ucuz görsel modeli ve orijinal Nano Banana'dan bir kuşak daha yeni; batch hacimlerinde de fiyat diğer bütün değerlendirmelere baskın çıkıyor. Nano Banana 2'ye yalnızca 1K üstü çıktı için, Nano Banana Pro'ya yalnızca okunaklı görsel içi metin için, GPT Image 2'ye yalnızca şeffaf arka plan için geçin.
Bir batch'teki bazı görseller patlarsa ne olur?
Her zaman bir kısmı patlayacak ve pipeline bunu ölümcül değil, normal saymalı. Reddedilen bir satırdan sonra göndermeye devam edin, patlayan ID'leri hatalarıyla loglayın ve yalnızca hataları çalıştıran bir retry yolu kurun. Her denemesi gerçek bir ücret olduğu için retry sayısını sınırlayın.