Files
BSN-Chatsystem/docs/nanobanana-skill.md
Hermes Agent 30433806cc
Quality Gate / 🛡️ Lint + Type Check + Tests (push) Failing after 13m35s
docs: NanoBanana Skill — echte API-Response-Felder (successFlag, resultImageUrl) + Cloudflare-Workaround
2026-06-22 22:27:04 +02:00

252 lines
7.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: nanobanana-image-gen
description: Bilder per NanoBanana API generieren — Text-to-Image + Image-to-Image (Brettspiel-Cover + Prompt) für BSN-News-Artikel
version: 1.0.0
category: creative
metadata:
hermes:
tags: [nanobanana, image-generation, bsn, article-images, midjourney-alternative]
base_url: https://api.nanobananaapi.ai
token_env: NANOBANANA_API_KEY
docs: https://docs.nanobananaapi.ai
---
# NanoBanana Image Generation — BSN News
> **API:** https://api.nanobananaapi.ai
> **Docs:** https://docs.nanobananaapi.ai
> **Auth:** `Authorization: Bearer <API_KEY>` (in `~/.hermes/profiles/cody/.env` als `NANOBANANA_API_KEY`)
> **Modelle:** NanoBanana AI (Basis), NanoBanana 2 (empfohlen), NanoBanana Pro
---
## API-Referenz
### POST /api/v1/nanobanana/generate-2 (empfohlen)
```json
{
"prompt": "Text-Prompt (max 20.000 Zeichen)",
"imageUrls": ["https://...brettspiel-cover.jpg"], // [] für Text-to-Image
"aspectRatio": "16:9", // 1:1|1:4|2:3|3:2|3:4|4:3|4:5|5:4|9:16|16:9|21:9|auto
"resolution": "2K", // 1K|2K|4K
"googleSearch": false, // Web-Grounding für Akkuratesse
"outputFormat": "jpg", // png|jpg
"callBackUrl": "" // Optional, für async
}
```
**Response:** `{"code": 200, "msg": "success", "data": {"taskId": "abc123"}}`
### GET /api/v1/nanobanana/record-info?taskId=abc123
**Response (fertig):**
```json
{
"code": 200,
"data": {
"taskId": "abc123",
"successFlag": 1,
"completeTime": "2026-06-23 04:26:02",
"response": {
"resultImageUrl": "https://tempfile.aiquickdraw.com/workers/images/image_xxx.jpg",
"originImageUrl": null
},
"operationType": "nano-banana-2_2k",
"createTime": "2026-06-23 04:25:26"
}
}
```
**Status-Prüfung:** `data.successFlag`: `1` = fertig, `0`/`null` = noch in Arbeit, `2` = fehlgeschlagen.
**Bild-URL:** `data.response.resultImageUrl` — das fertige Bild.
**Original (bei Image-to-Image):** `data.response.originImageUrl`.
### POST /api/v1/nanobanana/generate (Basis-Modell)
```json
{
"prompt": "...",
"type": "TEXTTOIAMGE", // TEXTTOIAMGE|IMAGETOIAMGE
"numImages": 1, // 1-4
"imageUrls": [],
"callBackUrl": ""
}
```
---
## BSN-Use-Cases
### ⚡ Standard-Format für ALLE BSN-Bilder
| Parameter | Wert |
|---|---|
| Auflösung | 1920 × 1080 px |
| DPI | 72 (Web-Standard) |
| Format | JPG |
| API-Mapping | `resolution: "2K"` + `aspectRatio: "16:9"` |
> **Wichtig:** Die API garantiert keine exakten Pixelmaße. Mit `2K + 16:9` kommt ca. 1920×1080 heraus. Bei Abweichungen → Post-Processing mit Pillow (s.u.).
### 1. Artikel-Header-Bild aus Prompt
```bash
curl -s -X POST "https://api.nanobananaapi.ai/api/v1/nanobanana/generate-2" \
-H "Authorization: Bearer *** get bsn/nanobanana-key)" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Professional board game photography of Catan, hexagonal tiles, wooden pieces, warm lighting, 4K product shot style",
"aspectRatio": "16:9",
"resolution": "2K",
"imageUrls": [],
"outputFormat": "jpg"
}'
```
### 2. Brettspiel-Cover veredeln (Image-to-Image)
```bash
curl -s -X POST "https://api.nanobananaapi.ai/api/v1/nanobanana/generate-2" \
-H "Authorization: Bearer *** get bsn/nanobanana-key)" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Transform this board game cover into a cinematic movie poster style, dramatic lighting, epic composition, keep the game title and theme",
"imageUrls": ["https://example.com/catan-cover.jpg"],
"aspectRatio": "16:9",
"resolution": "2K",
"outputFormat": "jpg"
}'
```
### 3. Post-Processing: Exakt 1920×1080 + 72 DPI
```python
from PIL import Image
def normalize_bsn_image(path: str) -> str:
"""Bringt Bild auf exakt 1920×1080, 72 DPI, JPG."""
img = Image.open(path)
img = img.convert("RGB") # Falls PNG/RGBA
img = img.resize((1920, 1080), Image.LANCZOS)
img.save(path, "JPEG", quality=92, dpi=(72, 72))
return path
```
### 4. Polling bis zum Ergebnis (Python)
```python
import time, requests, json, subprocess
API_KEY=subpro..."], capture_output=True, text=True).stdout.strip()
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0" # ⚠️ Pflicht! Cloudflare blockt ohne Browser-UA
}
# Task starten
resp = requests.post(
"https://api.nanobananaapi.ai/api/v1/nanobanana/generate-2",
headers=HEADERS,
json={
"prompt": prompt,
"imageUrls": image_urls if image_urls else [],
"aspectRatio": aspect_ratio,
"resolution": resolution,
"outputFormat": output_format,
},
timeout=30
).json()
if resp.get("code") != 200:
raise Exception(f"API-Fehler: {resp}")
task_id = resp["data"]["taskId"]
print(f"Task gestartet: {task_id}")
# Pollen
for i in range(30): # max 5 Minuten
time.sleep(10)
r = requests.get(
f"https://api.nanobananaapi.ai/api/v1/nanobanana/record-info?taskId={task_id}",
headers=HEADERS,
timeout=15
).json()
data = r.get("data", {})
success = data.get("successFlag")
if success == 1:
url = data["response"]["resultImageUrl"]
print(f"✅ Fertig nach {(i+1)*10}s: {url}")
return url, data["response"].get("originImageUrl")
elif success == 2:
raise Exception(f"Generation fehlgeschlagen: {data.get('errorMessage')}")
print(f" Poll {i+1}: noch in Arbeit...")
raise TimeoutError("Timeout nach 5 Minuten")
```
---
## Prompt-Engineering für Brettspiele
### Gute Prompts (funktionieren):
- `"Professional product photography of [SPIELNAME] board game, box art, cinematic lighting, 4K resolution, clean background"`
- `"A family playing [SPIELNAME] at a wooden table, warm candlelight, cozy atmosphere, lifestyle photography"`
- `"Transform this board game cover into a [STIL] style poster, keep title and key art elements"`
### Aspect-Ratio-Guide:
| Zweck | Ratio | Entspricht |
|---|---|---|
| **Header-Bild (News)** ⭐ | **16:9** | **1920×1080 px** |
| Thumbnail | 1:1 | Quadratisch |
| Instagram/Story | 9:16 | Hochformat |
| Cover-Reproduktion | 2:3 | Standard-Brettspiel-Box |
| Breitformat-Banner | 21:9 | Ultrawide
### Styles für Brettspiel-Bilder:
- `product shot style` — clean, wie Amazon-Produktbilder
- `lifestyle photography` — Menschen spielen am Tisch
- `cinematic movie poster` — dramatisch, episch
- `flat lay top-down` — von oben, alle Komponenten sichtbar
- `watercolor illustration` — künstlerisch, handgemalt
---
## API-Key-Management
Der API-Key wird als Secret via `bsn-secrets` gespeichert:
```bash
echo "nb_api_key..." | bsn-secrets set bsn/nanobanana-key
```
Abruf: `bsn-secrets get bsn/nanobanana-key`
**Key beziehen:** https://nanobananaapi.ai/api-key
---
## Kosten
- Credit-basiertes System — vor Nutzung Credits prüfen:
```bash
curl -s "https://api.nanobananaapi.ai/api/v1/common/account-credits" \
-H "Authorization: Bearer $(bsn-secrets get bsn/nanobanana-key)"
```
## Pitfalls
- **⛔ Cloudflare-Block:** API blockt Requests ohne `User-Agent: Mozilla/5.0` → IMMER Browser-UA mitschicken
- **Task ist asynchron** — `POST` gibt sofort `taskId` zurück, Ergebnis nach 30-60s via GET
- **Status-Feld heißt `successFlag`** (nicht `status`): `1` = fertig, `0`/`null` = pending, `2` = failed
- **Bild-URL:** `data.response.resultImageUrl` (nicht `data.imageUrls`)
- **NICHT blockierend warten** — Pollen mit 10s Intervallen, max 30 Versuche
- **`imageUrls: []` für Text-to-Image** — Leeres Array, nicht weglassen
- **Prompt-Länge max 20K** bei generate-2
- **Aspect-Ratio als String** `"16:9"` — nicht als Float
- **Keine exakten Pixel-Garantien** — API liefert ~1920×1080 bei 2K+16:9. Immer mit `normalize_bsn_image()` nachbearbeiten
- **DPI wird von API nicht gesetzt** — `PIL.Image.save(dpi=(72,72))` behebt das