HiAPI
Blog

Tutorial

Bilder mit der API freistellen: promptbasierte Bearbeitung

So ersetzen oder entfernen Sie Bildhintergründe mit Image-to-Image-Modellen auf hiapi – mit minimalem Code, Stapelverarbeitung und den Schema-Details, die die Produktfotografie exakt machen.

Aug 6, 2026
Bilder mit der API freistellen: promptbasierte Bearbeitung

Herkömmliche Werkzeuge zur Hintergrundentfernung bieten nur eine Operation: das Motiv ausschneiden und einen transparenten Bereich (oder eine Volltonfarbe) zurücklassen. Promptbasierte Hintergrundentfernung mit Image-to-Image-Modellen liefert dagegen in einem einzigen Aufruf sowohl das Freistellungsergebnis als auch den ersetzten Hintergrund – einen nahtlosen weißen Studiohintergrund, eine Alltagsszene oder eine reine Markenfarbe –, weil das Modell den Hintergrund pixelweise um das erhaltene Motiv herum neu generiert, statt nur eine Alpha-Maske zu berechnen.

Diese Anleitung zeigt genau, wie Sie das auf hiapi umsetzen: welche Image-to-Image-Modelle bei der Hintergrundentfernung wirklich stark sind, die Request-/Response-Struktur, an der Sie sich beim Programmieren orientieren müssen, und die Produktionsmuster (Callbacks, Wiederholungen, Fehlerbehandlung), mit denen Stapeljobs verhindern, dass Ihr Produktkatalog stillschweigend verunreinigt wird.

Voraussetzungen:

  • Ein hiapi-API-Schlüssel aus Ihrem Dashboard
  • Python 3.9+ mit installiertem requests (pip install requests)
  • Ihre Quellbilder werden unter einer öffentlichen URL gehostet – die hiapi-Task-API ruft Bilder per URL ab, nicht per Datei-Upload, daher funktionieren lokale Dateipfade nicht. Jeder Objektspeicher oder CDN eignet sich.

Wie Hintergrundentfernung als Image-to-Image-Task funktioniert

Jede Generierung auf hiapi – Bild, Video oder Audio – durchläuft denselben asynchronen Task-Lebenszyklus: Sie senden einen Task ab, erhalten eine taskId und rufen dann entweder die Ergebnisse ab (Polling) oder empfangen sie über eine Callback-URL. Die vollständige Vertragsbeschreibung finden Sie in der Referenz zur asynchronen Task-API; für die Hintergrundentfernung sind folgende Teile wichtig:

  1. POST /v1/tasks mit model + input (Ihr Prompt, die Quellbild-URL und die Ausgabeform) gibt {"code":200,"data":{"taskId":"tk-hiapi-..."}} zurück. Zu diesem Zeitpunkt gibt es noch kein status-Feld.
  2. GET /v1/tasks/{taskId} gibt data.status zurück, mit einem der Werte queued, handling, archiving, success, fail. Nur success und fail sind Endzustände.
  3. Im Status success ist data.output ein Array von {"url","type","expireAt"}. Die url ist ein signierter, kurzlebiger Link (expireAt ist ein Unix-Zeitstempel) – laden Sie ihn sofort herunter und speichern Sie nicht den Hotlink.

Verwenden Sie für das Modell den Image-to-Image-Endpunkt und lassen Sie den Prompt den ersetzten Hintergrund beschreiben, statt isoliert „Hintergrund entfernen“ zu sagen – diese Modelle reagieren weit besser auf konkrete Ziele als auf verneinende Anweisungen:

Remove the background completely and replace it with a seamless, pure white
studio background. Keep the subject's shape, edges, lighting, and colors
exactly unchanged. Do not add shadows, reflections, or any other objects
that were not in the original image.

Minimalbeispiel: ein Bild eingeben, Hintergrund ersetzen

seedream-5.0-lite/image-to-image ist die günstigste ausreichende Option für diesen Zweck – es akzeptiert prompt, image_urls, aspect_ratio und resolution (nur 2K oder 4K; dieser Endpunkt hat keine 1K-Stufe, und unbekannte Felder wie n oder seed werden direkt mit 400 abgelehnt).

import os
import time
import requests

API = "https://api.hiapi.ai/v1"
HEADERS = {
    "Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}",
    "Content-Type": "application/json",
}

BACKGROUND_PROMPT = (
    "Remove the background completely and replace it with a seamless, pure "
    "white studio background. Keep the subject's shape, edges, lighting, and "
    "colors exactly unchanged. Do not add shadows, reflections, or any other "
    "objects that were not in the original image."
)

def create_task(model: str, task_input: dict) -> str:
    resp = requests.post(f"{API}/tasks", headers=HEADERS,
                          json={"model": model, "input": task_input}, timeout=60)
    resp.raise_for_status()
    return resp.json()["data"]["taskId"]

def wait_task(task_id: str, timeout_s: int = 180, poll_s: int = 3) -> dict:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        resp = requests.get(f"{API}/tasks/{task_id}", headers=HEADERS, timeout=30)
        resp.raise_for_status()
        task = resp.json()["data"]
        if task["status"] == "success":
            return task
        if task["status"] == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task {task_id} failed: {err.get('code')} {err.get('message')}")
        time.sleep(poll_s)
    raise TimeoutError(f"task {task_id} still {task['status']} after {timeout_s}s")

task_id = create_task("seedream-5.0-lite/image-to-image", {
    "prompt": BACKGROUND_PROMPT,
    "image_urls": ["https://your-cdn.example.com/product-photo.jpg"],
    "aspect_ratio": "1:1",
    "resolution": "2K",
})
task = wait_task(task_id)
image_bytes = requests.get(task["output"][0]["url"], timeout=60).content

with open("product-no-bg.png", "wb") as f:
    f.write(image_bytes)

Das ist die gesamte Schleife: absenden, abfragen, herunterladen. Wenn Sie vor der Integration in eine Pipeline eine schnelle Validierung ohne Code wünschen, führt das AI Product Photo Lab dieselbe Art der Hintergrundersetzung im Browser aus.

Stapelverarbeitung eines Produktkatalogs

Echte Produktkataloge enthalten Dutzende oder Hunderte von Bildern, und die Task-API hat keinen nativen Stapel-Endpunkt – Sie müssen einzelne Task-Übermittlungen selbst aufteilen und sie parallel abfragen:

from concurrent.futures import ThreadPoolExecutor, as_completed

def remove_background(image_url: str, aspect_ratio: str = "1:1") -> str:
    task_id = create_task("seedream-5.0-lite/image-to-image", {
        "prompt": BACKGROUND_PROMPT,
        "image_urls": [image_url],
        "aspect_ratio": aspect_ratio,
        "resolution": "2K",
    })
    task = wait_task(task_id)
    return task["output"][0]["url"]

source_urls = [
    "https://your-cdn.example.com/sku-1001.jpg",
    "https://your-cdn.example.com/sku-1002.jpg",
    # ...
]

results = {}
with ThreadPoolExecutor(max_workers=5) as pool:
    futures = {pool.submit(remove_background, url): url for url in source_urls}
    for future in as_completed(futures):
        url = futures[future]
        try:
            results[url] = future.result()
        except Exception as exc:
            results[url] = None
            print(f"failed: {url}: {exc}")

Halten Sie max_workers maßvoll – zu häufiges Abfragen bei vielen parallelen Tasks verbraucht nur Ihr Anfragekontingent und beschleunigt die Generierung nicht, da die Wandzeit jedes Tasks hauptsächlich von der Modellinferenz bestimmt wird, nicht von Ihrer Abfragefrequenz.

Produktionshärtung: exakte Komposition, Callbacks, Idempotenz, Fehler

Exakte Produktkomposition beibehalten. Bei Katalogarbeiten können Sie es sich meist nicht leisten, dass das Modell das Bild neu komponiert oder das Motiv leicht beschneidet – ein in der Eingabe zentrierter Schuh muss auch in der Ausgabe zentriert bleiben. seedream-5.0-pro/image-to-image unterstützt einen aspect_ratio-Wert, den die Lite-Stufe nicht bietet: match_input_image, wodurch die Ausgabefläche auf die Abmessungen des Eingabebilds festgelegt wird, statt ein festes Seitenverhältnis zu erzwingen. Es akzeptiert außerdem bis zu 10 image_urls pro Aufruf und beschränkt resolution auf 1K/2K (eine andere Auflösungsmenge als bei Lite – gehen Sie nicht davon aus, dass die Schemas der seedream-Endpunkte einheitlich sind; jeder Endpunkt hat seine eigenen Enum-Werte). Für reine Hintergrundentfernungs- und -ersetzungsarbeiten, bei denen die Komposition exakt übereinstimmen muss, ist dies die Stufe der Wahl, zu höheren Kosten pro Bild – aktuelle Tarife finden Sie unter Preise.

Wenn Sie mehrere Quellperspektiven gleichzeitig referenzieren müssen (z. B. Vorder- und Seitenansicht desselben Produkts), statt ein Bild pro Aufruf zu verarbeiten, ist nano-banana-2 eine sinnvolle Alternative – es akzeptiert Referenzbilder über image_input (nicht image_urls), daneben kann resolution die Werte 1K/2K/4K annehmen.

Callbacks statt Polling verwenden. Für Stapeljobs jeder realistischen Größe sind Webhooks dem Polling vorzuziehen: Fügen Sie ein callback-Objekt als Geschwister von input hinzu – nicht darin verschachtelt, POST /v1/tasks lehnt diese Struktur ab:

task_input = {
    "prompt": BACKGROUND_PROMPT,
    "image_urls": [image_url],
    "aspect_ratio": "1:1",
    "resolution": "2K",
}
resp = requests.post(f"{API}/tasks", headers=HEADERS, json={
    "model": "seedream-5.0-lite/image-to-image",
    "input": task_input,
    "callback": {"url": "https://your-service.example.com/hooks/hiapi", "when": "final"},
}, timeout=60)

Nachdem ein Task einen Endzustand erreicht hat, sendet hiapi per POST dasselbe data-Objekt an Ihre Callback-URL, das auch GET /v1/tasks/{taskId} zurückgeben würde. Wenn Sie die Echtheit des Callbacks serverseitig prüfen möchten, lesen Sie den optionalen X-HiAPI-Signature-HMAC-Header in der Referenz zur asynchronen Task-API.

Idempotenz. Es gibt kein dokumentiertes idempotency_key-Feld bei POST /v1/tasks – bauen Sie Idempotenz auf Anwendungsebene auf. Verwenden Sie einen kleinen Speicher (eine Datenbankzeile, einen Redis-Schlüssel oder sogar eine lokale Datei für einmalige Skripte), als Schlüssel den Hash von (image_url, prompt, model), und prüfen Sie vor dem Absenden eines neuen Tasks, ob für diesen Schlüssel bereits eine taskId oder Ausgabe-URL gespeichert ist. Wenn Ihr Stapeljob mittendrin abstürzt und erneut ausgeführt wird, können Sie die doppelte Abrechnung bereits verarbeiteter Bilder überspringen, statt die Kosten stillschweigend zu erhöhen.

Fehlerbehandlung – drei verschiedene Formen, nicht gleich behandeln:

  • Anfragevalidierung (fehlerhafte Eingabe bei der Erstellung) – HTTP 400, flache Struktur: {"code":400,"error_code":"INVALID_REQUEST","message":"...","data":null}. Das bedeutet, Ihr input-Dictionary passt nicht zum Modellschema – prüfen Sie auf falsch geschriebene Feldnamen oder falsche Enum-Werte.
  • Authentifizierungsfehler – HTTP 401, anders verschachtelt: {"error":{"code":"permission_denied","message":"...","request_id":"...","type":"hiapi_error"}}. Der API-Schlüssel fehlt oder ist abgelaufen, nicht die Anfrage ist falsch – nicht wiederholen, Schlüssel korrigieren.
  • Task-Level-Fehler (Anfrage gültig, aber die Generierung selbst schlägt fehl) – zeigt sich beim Abfragen: data.status == "fail", data.error beschreibt den Grund. Dies ist wiederholbar; vorübergehende Upstream-Fehler können nach erneuter Übermittlung erfolgreich sein.
if task["status"] == "fail":
    err = task.get("error") or {}
    # log err["code"] / err["message"], then decide: retry, skip, or alert

Fassen Sie nicht alle drei in ein einziges except Exception zusammen – ein 401, das in einer Schleife wiederholt wird, verbraucht nur Ihr Rate-Limit und wird nie erfolgreich sein, während ein Task-Level-fail beim zweiten Versuch durchaus erfolgreich sein kann.

Nächste Schritte

Häufig gestellte Fragen

Wird der Hintergrund wirklich entfernt oder nur überdeckt? Funktional beides – das Modell generiert die gesamte Fläche um das erhaltene Motiv herum neu, sodass keine Restmaske oder ausgefranste Kanten zurückbleiben wie bei Kantenerkennungs-Freistellungswerkzeugen. Der Preis dafür ist, dass im Prompt ausdrücklich „alles andere unverändert lassen“ stehen muss, sonst stilisiert das Modell gerne auch das Motiv mit um.

Kann ich ein transparentes PNG statt eines Volltonhintergrunds erhalten? Fordern Sie es direkt im Prompt an (z. B. „Hintergrund durch transparent ersetzen“ oder „Motiv auf transparentem Hintergrund isolieren“) und verlangen Sie eine PNG-Ausgabe, wo das Modell das Feld output_format unterstützt – die Unterstützung variiert je nach Modell, prüfen Sie daher die Seite des jeweiligen Modells, bevor Sie es als gegeben annehmen.

Warum kommt mein Bild neu komponiert zurück, statt dem Original zu entsprechen? Wahrscheinlich verwenden Sie eine Stufe, deren aspect_ratio-Enum match_input_image nicht enthält – in den Lite-/4.5-Stufen wählen Sie ein festes Seitenverhältnis, das das Quellbild möglicherweise beschneidet oder mit Rändern auffüllt. Wechseln Sie zu seedream-5.0-pro/image-to-image und setzen Sie aspect_ratio auf match_input_image.

Wie viel kostet ein Bild? Die Preise variieren je nach Modell und Auflösungsstufe und ändern sich im Laufe der Zeit – sehen Sie unter Preise nach, statt Zahlen in Ihrem eigenen Code oder Ihrer Dokumentation fest zu kodieren.

Was, wenn meine Bild-URL noch nicht öffentlich ist? Die Task-API ruft Bilder serverseitig per URL ab, daher muss es ohne Authentifizierung erreichbar sein. Laden Sie es zuerst in einen öffentlichen Bucket oder einen CDN-Pfad hoch – signierte/private URLs oder localhost-Pfade schlagen bei der Task-Erstellung fehl oder (schlimmer) stillschweigend während der Verarbeitung.

Ähnliche Artikel

Alle Artikel ansehen →

Starte mit persistenten KI-Artefakten

Hol dir deinen API-Key und rufe Bild-, Video- und Audiomodelle über eine einzige task-basierte API auf.

API-Dokumentation lesen