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

7.7 KiB
Raw Permalink Blame History

name, description, version, category, metadata
name description version category metadata
nanobanana-image-gen Bilder per NanoBanana API generieren — Text-to-Image + Image-to-Image (Brettspiel-Cover + Prompt) für BSN-News-Artikel 1.0.0 creative
hermes
tags base_url token_env docs
nanobanana
image-generation
bsn
article-images
midjourney-alternative
https://api.nanobananaapi.ai NANOBANANA_API_KEY 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)

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

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

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

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)

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

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)

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:

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:
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 asynchronPOST 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 gesetztPIL.Image.save(dpi=(72,72)) behebt das