diff --git a/docs/nanobanana-skill.md b/docs/nanobanana-skill.md new file mode 100644 index 0000000..f657d36 --- /dev/null +++ b/docs/nanobanana-skill.md @@ -0,0 +1,190 @@ +--- +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 ` (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": { + "status": "SUCCESS", + "imageUrls": ["https://cdn.nanobananaapi.ai/result/abc123_0.jpg"], + "prompt": "...", + "taskId": "abc123" + } +} +``` + +**Status-Werte:** `PENDING` → warten, `SUCCESS` → fertig, `FAILED` → Fehler + +### POST /api/v1/nanobanana/generate (Basis-Modell) + +```json +{ + "prompt": "...", + "type": "TEXTTOIAMGE", // TEXTTOIAMGE|IMAGETOIAMGE + "numImages": 1, // 1-4 + "imageUrls": [], + "callBackUrl": "" +} +``` + +--- + +## BSN-Use-Cases + +### 1. Artikel-Header-Bild aus Prompt + +```bash +curl -s -X POST "https://api.nanobananaapi.ai/api/v1/nanobanana/generate-2" \ + -H "Authorization: Bearer $(bsn-secrets 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 $(bsn-secrets 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": "2:3", + "resolution": "2K", + "outputFormat": "jpg" + }' +``` + +### 3. Polling bis zum Ergebnis (Python) + +```python +import time, requests, json + +API_KEY = subprocess.run(["bsn-secrets","get","bsn/nanobanana-key"], capture_output=True, text=True).stdout.strip() +HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"} + +# 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, +}).json() + +task_id = resp["data"]["taskId"] + +# Pollen +for _ 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).json() + if r["data"]["status"] == "SUCCESS": + return r["data"]["imageUrls"] + elif r["data"]["status"] == "FAILED": + raise Exception("Generation failed") + +raise TimeoutError("Timeout after 5 minutes") +``` + +--- + +## 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 | +|---|---| +| Header-Bild (News) | 16:9 | +| Thumbnail | 1:1 | +| Instagram/Story | 9:16 | +| Cover-Reproduktion | 2:3 (Standard-Brettspiel-Box) | +| Breitformat-Banner | 21:9 | + +### 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 + +- **Task ist asynchron** — `POST` gibt sofort `taskId` zurück, Ergebnis erst nach 10-60s via GET +- **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, weniger bei generate +- **Aspect-Ratio als String** `"16:9"` — nicht als Float +- **Status-Check:** Immer `r["data"]["status"]` prüfen — nicht `r["code"]`