Seedream 5.5 API-Tutorial: Generierung, Bearbeitungen und Migration

Bilder mit der Seedream 5.5 API generieren und bearbeiten: Modell-ID, Aufgabenstatus, authentifizierte Downloads, asynchrones Polling und Fallstricke bei der Migration.

AIHubMix10 Min. Lesezeit
Seedream 5.5 API-Tutorial: Generierung, Bearbeitungen und Migration

Bei der Migration zu Seedream 5.5 geht es vor allem um einen Datei-Workflow, nicht nur um den Austausch des Modellnamens: ein Bild generieren, die zurückgegebene Aufgabe prüfen, das Bild speichern und anschließend die gespeicherten Bytes als Referenz für eine Bearbeitung senden.

Seedream 5.5 auf AIHubMix verwendet derzeit doubao-seedream-5-5 und POST /ai/v1/images/generations. In diesem Tutorial erstellen wir ein Produktbild für einen Keramikbecher und fordern anschließend eine reine Farbänderung an.

Umfang: Die Dokumentation wurde am 12. November 2026 geprüft. Der Code wurde nur lokal auf Syntax und offline auf Hilfsfunktionen geprüft; es wurde keine Generierungsanfrage ausgeführt. Daraus lassen sich keine Rückschlüsse auf Ausgabequalität, Bearbeitungstreue, Latenz oder tatsächliche Kosten ziehen.

1. Eine kleine, präzise Anfrage vorbereiten

Verwenden Sie Python 3.10+ mit requests. Installieren Sie in Bash die Abhängigkeit und geben Sie den Schlüssel ein, ohne seinen Wert im Shell-Verlauf zu speichern:

python3 -m pip install requests
read -r -s -p 'AIHubMix API key: ' AIHUBMIX_API_KEY
printf '\n'
export AIHUBMIX_API_KEY

In bereitgestelltem Code sollten Sie die Umgebungsvariable über Ihren Secret-Manager injizieren. Halten Sie den Schlüssel aus Quelldateien, Anfragebeispielen, Logs, Notebooks und browserseitigem Code heraus. Aktivieren Sie vor einem der beiden POST-Aufrufe die Aufgabenfunktion des Kontos wie im Leitfaden zu asynchronen Aufgaben beschrieben. Diese Voraussetzung gilt für native Medienaufgaben-Endpunkte unter /ai/v1, einschließlich synchronen Wartens; sie ist unabhängig davon, ob Sie die Ausführung im Hintergrund wählen.

Lesen Sie das aktuelle Schema des Modell-Endpunkts und wählen Sie den Eintrag anhand von path statt anhand seiner Position im Array aus. Die modellspezifischen Einschränkungen haben Vorrang vor einer gemeinsamen Parameterliste.

Einstellung Hier verwendeter Wert
Modell doubao-seedream-5-5
Route POST /ai/v1/images/generations
Body Flaches JSON
Größe 2048x2048
Bildanzahl n = 1
Dateiformat png
Antwortformat url

Das Schema erfordert model und einen nicht leeren prompt, beschränkt n auf 1 und führt png und jpeg als Ausgabeformate auf. Als Eingabe für image werden eine URL, Base64-Daten oder ein {url}-Objekt akzeptiert; images akzeptiert ein Array mit einem veröffentlichten Maximum von 14 Referenzen. Diese Grenze wurde hier nicht zur Laufzeit getestet. Dieses Beispiel verwendet eine Referenz und gibt die Standardgröße explizit an, ohne äußeres input-Objekt oder extra-Erweiterungen.

2. Bild generieren, Aufgabe prüfen und PNG speichern

Die Dokumentation zur einheitlichen Image-API definiert eine Aufgabenantwort mit id, object: image, model, status, output und error. Behandeln Sie sie nicht wie das Legacy-Format data[0].url.

Lesen Sie zuerst den kurzen Workflow; die vollständige Einrichtung und die Download-Hilfsfunktion finden Sie im eingeklappten Anhang weiter unten. Laden Sie vor der Ausführung dieser Beispiele den Codeblock aus dem Anhang einmal in dieselbe Python-Sitzung. Darin werden settings, api_json und collect definiert, ohne eine Bildanfrage abzusenden. Führen Sie dann die kurzen Codeblöcke der Reihe nach aus. Jeder POST ist eine separate kostenpflichtige Aktion. Führen Sie ihn nicht erneut aus, um eine fehlende Antwort oder einen fehlgeschlagenen Download zu beheben.

Bildanfrage einmal absenden

generation = {
    **settings,
    "prompt": "Product photograph of one matte blue ceramic mug on a cream tabletop, "
              "soft side lighting, plain warm-gray background, no text or logos.",
}
task = api_json("POST", IMAGES + "/generations", generation)

Aufgabe prüfen, dann PNG speichern

Wenn async weggelassen wird, wird synchron gewartet. Auch bei HTTP 200 kann status: failed zurückgegeben werden. Die Hilfsfunktion speichert die Aufgaben-ID, bevor sie den Status prüft: Nur bei completed wird der Download fortgesetzt; bei failed, cancelled und unbekannten Zuständen wird abgebrochen. Bei pending und in_progress muss die bestehende Aufgabe geprüft werden, nicht eine weitere Generierung gestartet werden.

collect(task, "mug-blue")

Dieser einzelne Aufruf verwendet den Schlüssel, mit dem die Aufgabe erstellt wurde, um die fertige Ausgabe abzurufen, prüft die PNG-Bytes und speichert mug-blue.png. Er versucht nicht automatisch erneut, die Aufgabe zu erstellen, und verweigert unerwartete Download-Hosts oder Weiterleitungen, bevor der Schlüssel weitergegeben wird. Die vollständige Implementierung steht im Anhang; das beschriebene Verhalten basiert auf der Dokumentation und ist kein verifiziertes Generierungsergebnis.

Laut Modellleitfaden sind Ausgabe-URLs ungefähr 30 Minuten gültig. Laden Sie die Datei zeitnah mit demselben Bearer-Header herunter und speichern Sie die Bytes selbst. expires_at: null ist keine Zusage dauerhafter Speicherung. Wenn b64_json ausgefüllt ist, dekodieren Sie die Daten, statt eine URL herunterzuladen.

3. Die lokale Datei bearbeiten, nicht ihre geschützte Download-URL

Prüfen Sie das gespeicherte Bild selbst, bevor Sie Geld für eine Bearbeitung ausgeben. Ein content_url, das Ihr authentifizierter Client herunterladen kann, ist nicht unbedingt eine öffentliche URL, auf die der Bildanbieter zugreifen kann. Laden Sie die lokale PNG-Datei als Data URI erneut hoch:

reference = Path("mug-blue.png").read_bytes()
if not reference.startswith(b"\x89PNG\r\n\x1a\n"):
    raise SystemExit("The editing reference must be the saved PNG.")
edit = {
    **settings,
    "prompt": "Change only the mug color from blue to forest green. Preserve the mug shape, "
              "camera angle, tabletop, background, lighting, and shadows.",
    "image": "data:image/png;base64," + base64.b64encode(reference).decode("ascii"),
}
task = api_json("POST", IMAGES + "/generations", edit)
collect(task, "mug-green")

Damit wird die Beibehaltung angefordert, aber nicht nachgewiesen, dass sie tatsächlich erfolgt ist. Prüfen Sie das Ergebnis, bevor Sie eine weitere kostenpflichtige Runde starten. Die gesamte JSON-Anfrage einschließlich Inline-Kodierung muss in 32 MiB passen; außerdem gelten modellspezifische Medienlimits. Eine tatsächlich öffentliche und für den Anbieter erreichbare Bild-URL ist eine weitere akzeptierte Eingabeoption.

4. Optional: asynchrones Warten und Wiederherstellung nach Unterbrechungen

Die in Abschnitt 1 genannte Voraussetzung für das Konto ist unabhängig vom Ausführungsmodus. 403 async_not_enabled bedeutet, dass die Aufgabenfunktion in der Konsole aktiviert werden muss. Nur die Ausführung im Hintergrund ist optional.

Wenn Sie die Generierung lieber im Hintergrund ausführen möchten, erstellen Sie dasselbe generation-Dictionary und verwenden Sie anschließend die beiden folgenden Zeilen anstelle sowohl der synchronen Zeile task = api_json(...) als auch des separaten Aufrufs von collect(...). Wählen Sie den Modus vor dem Absenden aus und führen Sie nicht beide Varianten aus:

task = api_json("POST", IMAGES + "/generations", {**generation, "async": True})
collect(task, "mug-blue", poll=True)

Die Hilfsfunktion fragt ungefähr alle 15 Sekunden GET /ai/v1/images/{id} ab, bis ein Endstatus erreicht ist. Das ist die dokumentierte Polling-Empfehlung, kein serverseitig erzwungenes Intervall. Webhooks erfordern async: true; ein Empfänger ist nicht Teil dieses Tutorials.

Wenn die Abholung abgebrochen wurde, laden Sie bei Bedarf nur den gemeinsamen Setup-/Hilfsfunktionsblock aus dem Anhang in einer neuen Sitzung erneut, nicht aber einen Erstellungsblock. Wenn eine ID gespeichert wurde, setzen Sie den Vorgang ohne POST fort:

task_id = Path("mug-blue.task-id").read_text(encoding="utf-8").strip()
task = api_json("GET", IMAGES + "/" + quote(task_id, safe=""))
collect(task, "mug-blue", poll=True)

Verwenden Sie für die Wiederherstellung der Bearbeitung den entsprechenden Präfix mug-green. Wenn die Antwort der Erstellung verschwunden ist, bevor eine ID gespeichert wurde, prüfen Sie stattdessen die letzten Aufgaben:

recent = api_json("GET", IMAGES + "?limit=20&order=desc")
for row in recent.get("data", []):
    print(row.get("id"), row.get("model"), row.get("status"), row.get("created_at"))

Stimmen Sie Modell und Erstellungszeit ab; wählen Sie nicht blind die neueste Aufgabe aus. Verwenden Sie bei Bedarf next_after als after-Cursor für die nächste Anfrage. Wenn die Zuordnung nicht eindeutig ist, wenden Sie sich an den Support, statt die Anfrage erneut abzusenden. Eine Liste ist eine Momentaufnahme; verwenden Sie für das Polling die Aufgabendetails. output_error in einer Zeile bedeutet, dass die Ausgabe nicht gelesen werden konnte, nicht, dass bei der Generierung nichts erzeugt wurde oder sich die Kosten geändert haben.

Verwenden Sie weiterhin den Schlüssel, mit dem die Aufgabe erstellt wurde. Insbesondere sind der Zugriff auf Aufgabenliste, -details und -inhalte der einheitlichen API nach Token isoliert: Ein anderer Schlüssel desselben Kontos kann diese Aufgaben nicht lesen. Eine lokale Unterbrechung beweist weder einen Fehlschlag noch, dass keine Kosten angefallen sind.

5. Migrationsfehler und aktuelle Fehler

Die Dokumentation zum Legacy-Doubao-Adapter führt ältere IDs unter /v1/models/doubao/<id>/predictions mit einem input-Wrapper auf. In der Übersicht ist 5.5 nicht aufgeführt. Verwenden Sie hier die auffindbare 5.5-Route und den flachen Body; ein Fehlschlag bei der Legacy-Generierung wurde nicht getestet. Übernehmen Sie die aktuelle ID mit Bindestrichen exakt, statt anzunehmen, dass eine Schreibweise mit Punkten ein Alias ist.

Übernehmen Sie nicht die Top-Level-Felder quality, background, aspect_ratio oder seed: Sie fehlen im aktuellen Schema dieses Modells. Die Launch-Ankündigung von ByteDance beschreibt eine native Ausgabe mit transparentem RGBA, aber das Gateway-Schema bietet weder background noch layer_decomposition. Nur PNG auszuwählen ist keine verifizierte Methode, um Transparenz zu erhalten.

Dies sind dokumentierte Fehler der einheitlichen Image-API, keine beobachteten Antworten von 5.5. Prüfen Sie den HTTP-Status getrennt vom Aufgabenstatus und verzweigen Sie anhand von code, nicht anhand des vollständigen Meldungstexts.

Wo Code Nächster Schritt
HTTP 400 schema_violation Schemafelder korrigieren
HTTP 400 capability_not_supported Nicht unterstützte Optionen entfernen
HTTP 504 sync_timeout Wiederherstellung versuchen; Support kontaktieren
HTTP 502 task_status_unavailable Nicht erneut absenden
HTTP 422 output_blocked Inhalt überarbeiten
HTTP 403 async_not_enabled Aufgabenfunktion aktivieren
Fehlgeschlagene Aufgabe result_delivery_failed Vorhandenes Ergebnis untersuchen

Zu HTTP 502 task_status_unavailable steht im Leitfaden:

Der Aufgabenstatus beim Modellanbieter konnte nicht bestätigt werden. Senden Sie die Anfrage nicht erneut. Wenden Sie sich mit der Aufgaben-ID oder Anfrage-ID an den Support.

Zu result_delivery_failed auf Aufgabenebene steht dort:

Das generierte Ergebnis konnte nicht zugestellt werden. Senden Sie die Anfrage nicht automatisch erneut. Wenden Sie sich mit der Aufgaben-ID an den Support.

Ein sync_timeout belegt nicht, dass die Ausführung nie stattgefunden hat. Bewahren Sie error.tid auf, verwenden Sie eine Aufgaben-ID nur, wenn tatsächlich eine zurückgegeben wurde, und bitten Sie den Support, unklare Ergebnisse zu klären. Bei einem behebbaren Downloadfehler wiederholen Sie den Abruf, nicht die Generierung. 410 artifact_expired ist etwas anderes: Dieses Artefakt kann nicht mehr abgerufen werden. Prüfen Sie zuerst die gespeicherten Dateien. Wenn Sie weiterhin einen Ersatz benötigen, autorisieren Sie bewusst eine neue kostenpflichtige Generierung. Bei 429 too_many_downloads prüfen Sie gespeicherte Kopien oder wenden Sie sich an den Support; bloßes Warten garantiert keinen erneuten Zugriff.

Laut Leitfaden entfällt die Generierungsgebühr bei output_blocked ausdrücklich auch dann, wenn dieser Fehler bei einer fehlgeschlagenen Aufgabe gemeldet wird. Übertragen Sie diese Ausnahme nicht auf alle fehlgeschlagenen oder moderierten Anfragen; für output_policy_violation gelten die bestehenden Abrechnungsregeln für Moderation.

6. Das Budget für den Workflow einplanen, nicht nur für eine Ausgabe

Der Launch-Bericht von Sina Technology nennt ungefähr CNY 0.28 für eine quadratische Bearbeitung in 2K, einschließlich Bild-Eingabe und -Ausgabe; Text-Token sind kostenlos. Das sind Angaben aus der Presse, keine verifizierte offizielle Preisliste und kein Preisangebot von AIHubMix.

Zur Veranschaulichung: Zwei kostenpflichtige Bearbeitungsrunden eines bestehenden Bildes, die jeweils diesem gerundeten Szenario entsprechen, kosten ungefähr 2 × CNY 0.28 = CNY 0.56. Die anfängliche Text-zu-Bild-Generierung, zusätzliche Referenzbilder, weitere Varianten und Wiederholungsversuche sind nicht enthalten. Dies ist keine gemessene Rechnung.

Für dieses Beispiel mit Generierung und anschließender Bearbeitung gilt Gesamtkosten = Gebühr für die anfängliche Generierung + Gebühr für die Bearbeitung mit Referenz. Aus den geprüften Seiten ließ sich kein vollständiger offizieller Tarif für 5.5 ermitteln. Dieses Tutorial nennt daher weder einen festen Gesamtpreis noch ein genaues Einsparungsverhältnis zwischen alter und neuer Version.

Vor dem Absenden:

  • Aktuelle ID, Route, flachen Body und Modellschema bestätigen.
  • Den Schlüssel in der Umgebung halten; Aufgaben-IDs zur Wiederherstellung aufbewahren.
  • Jeden POST als separate kostenpflichtige Aktion behandeln, niemals als Wiederholung eines Downloads.
  • Prüfen Sie vor der Bearbeitung den Aufgabenstatus und das gespeicherte Bild.
  • Laden Sie lokale Bytes mit dem richtigen MIME-Typ erneut hoch.
  • Stellen Sie den Status unsicherer Aufgaben fest, bevor Sie eine weitere Generierung in Betracht ziehen.

Beginnen Sie mit einem Bild und einer gezielten Bearbeitung; fügen Sie erst nach dem Prüfen der Dateien weitere Durchläufe hinzu.

Anhang: gemeinsame Einrichtung und Download-Hilfsfunktion

Überspringen Sie diesen Anhang, wenn Sie den Workflow lesen. Klappen Sie vor der Ausführung der kurzen Beispiele diesen Block auf und laden Sie ihn einmal in dieselbe Python-Sitzung. Er konfiguriert die Sitzung und definiert Funktionen, ohne ein Bild zu generieren. Um eine unterbrochene Aufgabe in einer neuen Sitzung wiederherzustellen, laden Sie nur diesen Block erneut – keinen Block zur Erstellung oder Bearbeitung.

Vollständige Hilfsfunktion aufklappen – vor den kurzen Beispielen einmal laden; keine Bildanfrage
import base64
import os
import time
from pathlib import Path
from urllib.parse import quote, urlsplit

import requests

BASE = "https://aihubmix.com"
IMAGES = "/ai/v1/images"
settings = {
    "model": "doubao-seedream-5-5",
    "size": "2048x2048",
    "n": 1,
    "output_format": "png",
    "response_format": "url",
}
client = requests.Session()
client.headers["Authorization"] = "Bearer " + os.environ["AIHUBMIX_API_KEY"]


def api_json(method, path, body=None):
    try:
        response = client.request(
            method, BASE + path, json=body,
            timeout=(15, 600), allow_redirects=False,
        )
    except requests.RequestException:
        raise SystemExit(
            "Connection interrupted. Recover the existing task before another POST."
        ) from None
    try:
        data = response.json()
    except ValueError:
        raise SystemExit(
            f"HTTP {response.status_code}: non-JSON response; recover before another POST."
        ) from None
    if not isinstance(data, dict):
        raise SystemExit("Unexpected response; recover before another POST.")
    if not 200 <= response.status_code < 300:
        error = data.get("error") or {}
        raise SystemExit(
            f"HTTP {response.status_code}: code={error.get('code')}, "
            f"tid={error.get('tid')}. No automatic generation retry."
        )
    return data


def collect(task, stem, poll=False):
    task_id = task.get("id")
    if not isinstance(task_id, str) or not task_id:
        raise SystemExit("No task ID returned. Recover from the task list; do not resubmit.")
    Path(stem + ".task-id").write_text(task_id + "\n", encoding="utf-8")
    while True:
        status = task.get("status")
        print("Task:", task_id, "status:", status)
        if status == "completed":
            break
        if status not in {"pending", "in_progress"}:
            error = task.get("error") or {}
            raise SystemExit(
                f"Stopped: status={status}, code={error.get('code')}; task={task_id}."
            )
        if not poll:
            raise SystemExit("Task still active. Query the saved ID; do not recreate it.")
        time.sleep(15)
        task = api_json("GET", IMAGES + "/" + quote(task_id, safe=""))

    output = task.get("output") or []
    if not output:
        raise SystemExit("Completed without readable output; investigate the saved task.")
    item = output[0]
    if item.get("b64_json"):
        image_bytes = base64.b64decode(item["b64_json"], validate=True)
    else:
        url = item.get("content_url")
        if not isinstance(url, str):
            raise SystemExit("Missing content_url; investigate the saved task.")
        parsed = urlsplit(url)
        if (parsed.scheme, parsed.netloc) != ("https", "aihubmix.com"):
            raise SystemExit("Unexpected download origin; key was not forwarded.")
        try:
            response = client.get(url, timeout=(15, 120), allow_redirects=False)
        except requests.RequestException:
            raise SystemExit("Download interrupted; recover this task, not a new generation.") from None
        if not 200 <= response.status_code < 300:
            try:
                detail = response.json()
            except ValueError:
                detail = {}
            error = detail.get("error", {}) if isinstance(detail, dict) else {}
            code = error.get("code") if isinstance(error, dict) else None
            if response.status_code == 410 or code == "artifact_expired":
                raise SystemExit("Artifact expired; retrieval cannot recover it. Check saved files first.")
            if code == "too_many_downloads":
                raise SystemExit("Download allowance exhausted; check saved files or contact support.")
            raise SystemExit(
                f"Download HTTP {response.status_code}, code={code}; "
                "inspect the saved task. Retry retrieval only if recoverable."
            )
        image_bytes = response.content
    if not image_bytes.startswith(b"\x89PNG\r\n\x1a\n"):
        raise SystemExit("Expected PNG bytes; stopped before saving or reusing the result.")
    destination = Path(stem + ".png")
    destination.write_bytes(image_bytes)
    print("Saved:", destination)
    return destination

Das Lese-Timeout von 600 Sekunden ist eine Entscheidung auf Client-Seite und keine Zusage zur Latenz des Dienstes. Die PNG-Prüfung entspricht dem in diesem Tutorial ausdrücklich gewählten Ausgabeformat; passen Sie sie an, wenn Sie JPEG wählen.

FAQ

Welche Modell-ID und welchen Endpunkt sollte Seedream 5.5 verwenden?
Verwenden Sie doubao-seedream-5-5 mit POST /ai/v1/images/generations und flachem JSON. Gehen Sie nicht davon aus, dass eine andere Schreibweise oder ein Legacy-Adapter gleichwertig ist.

Enthält dieses Tutorial getestete Generierungsergebnisse?
Nein. Der Code basiert auf der Dokumentation und wurde nur lokal auf Syntax sowie mit Offline-Prüfungen der Hilfsfunktionen überprüft. Es wurde weder eine Inferenzanfrage noch eine Messung der Bildqualität oder Latenz noch ein Abrechnungstest ausgeführt.

Ist Async erforderlich?
Nein; standardmäßig wird synchron gewartet. Für die Ausführung im Hintergrund wird der boolesche Wert async: true verwendet. Die Aktivierung der Aufgabenfunktion auf Kontoebene ist Voraussetzung für die nativen Medien-Aufgaben-Endpunkte, auch wenn synchron gewartet wird.

Bedeutet HTTP 200, dass die Bilderstellung erfolgreich war?
Nein. Prüfen Sie den Aufgabenstatus und den zugehörigen Fehler. Eine Aufgabe kann fehlgeschlagen sein, obwohl die HTTP-Anfrage erfolgreich war; laden Sie das Bild erst herunter, wenn die Aufgabe abgeschlossen ist.

Kann eine Ergebnis-Download-URL als Referenz für die nächste Bearbeitung dienen?
Gehen Sie nicht davon aus. Laden Sie das Bild mit dem Schlüssel herunter, mit dem es erstellt wurde, und kodieren Sie es anschließend als Data URI; alternativ können Sie eine tatsächlich öffentliche Bild-URL angeben.

Was sollte nach einem Timeout oder einer verlorenen Antwort geschehen?
Wiederholen Sie die Generierung nicht automatisch. Prüfen Sie die gespeicherte Aufgaben-ID oder rufen Sie sie mit dem Schlüssel, mit dem das Bild erstellt wurde, aus der Bildliste ab. Bewahren Sie die Anfrage-IDs auf und wenden Sie sich an den Support, wenn das Ergebnis unklar ist.

Garantiert die Wahl von PNG eine transparente Ausgabe oder eine Rechnung über CNY 0.28?
Weder noch. Das Schema bietet keine verifizierte Steuerung der Transparenz. CNY 0.28 ist ein in der Presse genannter ungefähres Beispiel für die Bearbeitung eines 2K-Bildes, kein Angebot von AIHubMix und kein Festpreis für Text-zu-Bild plus Bearbeitung.

Weiterlesen: die Seedream-5.5-Serie

Quellen

  1. Startankündigung von Seedream 5.5 — ByteDance Seed; Angaben des Anbieters zu den Funktionen.
  2. Aktuelles Schema des Seedream-5.5-Endpunkts — AIHubMix; Anfragefelder und modellspezifische Einschränkungen.
  3. Einheitliche API zur Bildgenerierung — AIHubMix; Aufgaben, Downloads und aktuelle Fehler.
  4. Leitfaden zum Seedream-5.5-Modell — AIHubMix; Modell-ID und kurzzeitig gültige authentifizierte Downloads. Verwenden Sie für routenspezifische Fehler das Dokument zur einheitlichen API.
  5. Berichterstattung zum Start von Seedream 5.5 — Sina Technology; ungefähres Kostenszenario für die Bildbearbeitung, kein offizieller Tarif.

Ein Gateway zu mehreren KI-Anbietern. Gebaut für den Produktiveinsatz.

AIHubMix besuchen