GPT-Image 2.6 Flare ve Sunburst yayındaGörsel başına $0.025 ile başlar

Python ile Midjourney API: görsel üretme ve kaydetme

Görevi oluşturun, bitene kadar sorgulayın ve tek bir 2x2 PNG ızgarası kaydedin; anahtar ve gövde POST'tan önce diskte olur.

Kiki, OmniaKey COO8 dk okuma
Bu sayfada

Bu örnek, OmniaKey'in üçüncü taraf Midjourney API'sini Python'dan üç adımda çağırır: görevi oluştur, bitene kadar durumunu sorgula ve imzalı dosya URL'sinden PNG'yi indir. 12 Kasım 2026'daki entegrasyon testi 2048x2048 bir görseli 197,1 saniyede döndürdü ve bu görsel dört adaydan oluşan 2x2 bir ızgaradır. Aşağıdaki betik bir durum dosyası ekler; böylece zaman aşımı veya başarısız indirme ikinci bir ücretli görev oluşturmaz.

Kısa yanıt

  • POST https://api.omniakey.com/v1/media/tasks isteğini Idempotency-Key ile gönderin, ardından GET /v1/media/tasks/{id} ile durumu sorgulayın ve assets[0].url adresini indirin.
  • Bir görev dört görsel içeren tek bir PNG ızgarası döndürür; dört ayrı dosya değil.
  • Bu API'deki Midjourney yalnızca metinden görsele çalışır: düzenleme, referans görsel, blend, upscale, vary, kaydırma ve sürüm seçimi yok.
  • Anahtar OmniaKey'den gelir ve Midjourney aboneliğinden ayrıdır. POST'tan önce gövdeyi ve idempotency anahtarını kaydedin, API isteği kabul edince görev kimliğini ekleyin ve daha sonra devam etmek için durum dosyasını saklayın. Yerel zaman aşımı sunucudaki görevi iptal etmez.

Bu Python örneği hangi API'yi kullanıyor?

Örnek, OmniaKey'in Midjourney için sunduğu üçüncü taraf API'yi çağırır. OmniaKey Midjourney değildir ve OmniaKey anahtarı kendi bakiyesi olan ayrı bir hesaptır. Midjourney web sitesindeki abonelik ayrı bir üründür ve OmniaKey anahtarı oluşturmaz.

Midjourney model sayfası, OmniaKey tarafındaki modeli ve güncel ücreti gösterir. Geri kalan bölümler bu entegrasyonu ve görevlerin yaşam döngüsünü anlatır.

Neye ihtiyacınız var?

Üç şey gerekir:

  1. OMNIAKEY_API_KEY olarak dışa aktarılmış bir OmniaKey API anahtarı.
  2. Python 3. Betik yalnızca standart kitaplığı kullanır, SDK kurmanız gerekmez.
  3. Bu anahtar/hesap için midjourney erişimi. Model anahtarın listesinde yoksa oluşturma çağrısını çalıştırmadan önce hesap erişimini kontrol edin.
bash
export OMNIAKEY_API_KEY="your-key"
python3 midjourney_grid.py

Anahtarı betiğin ve günlüklerin dışında tutun. Kod anahtarı ortamdan bir kez okur.

İstek gövdesi ve parametreler

Midjourney bir prompt ve üç parametre alır. Bot türü OmniaKey tarafında önceden ayarlıdır, bu yüzden gövde model sürümünü ve botType alanını atlayabilir.

AlanDeğerNot
input.promptMetinİstediğiniz sahne
parameters.aspectRatio1:1Ayrıca 16:9, 9:16, 3:2, 2:3
parameters.quality"1"Belgeler "1" dizesini kullanır
parameters.n11 olmalı

Biçimi piksel boyutuyla değil aspectRatio ile belirleyin. Alan camelCase'dir: aspectRatio, asla aspect_ratio. Listelenen beş değerden birini kullanın.

Örnek prompt için gövde şöyle görünür:

json
{
  "model": "midjourney",
  "type": "image",
  "operation": "generate",
  "input": {
    "prompt": "A small red paper boat floating on a quiet blue lake at sunrise, cinematic lighting, elegant composition, no text"
  },
  "parameters": {"aspectRatio": "1:1", "quality": "1", "n": 1}
}

Midjourney API için Python kodu

Bunu midjourney_grid.py olarak kaydedip çalıştırın. İlk çalıştırma POST'tan önce midjourney-task.json dosyasını yazar, OmniaKey isteği kabul edince görev kimliğini ekler.

python
import hashlib
import json
import os
import sys
import time
import urllib.error
import urllib.request
import uuid
from pathlib import Path

API = "https://api.omniakey.com/v1"
KEY = os.environ["OMNIAKEY_API_KEY"]
STATE = Path("midjourney-task.json")
OUT = Path("midjourney-grid.png")
PROMPT = ("A small red paper boat floating on a quiet blue lake at sunrise, "
          "cinematic lighting, elegant composition, no text")


def save(state):
    tmp = STATE.with_suffix(".tmp")
    tmp.write_text(json.dumps(state, indent=2))
    tmp.replace(STATE)


def read_json(response):
    raw = response.read()
    try:
        return json.loads(raw)
    except ValueError:
        return {"raw": raw[:300].decode("utf-8", "replace")}


def call(method, path, body=None, headers=None):
    data = json.dumps(body).encode() if body is not None else None
    req = urllib.request.Request(
        API + path, data=data, method=method,
        headers={"Authorization": f"Bearer {KEY}", **(headers or {})})
    if body is not None:
        req.add_header("Content-Type", "application/json")
    try:
        with urllib.request.urlopen(req, timeout=60) as response:
            return response.status, read_json(response)
    except urllib.error.HTTPError as error:
        return error.code, read_json(error)
    except (urllib.error.URLError, TimeoutError) as error:
        return None, {"error": str(error)}


def main():
    state = json.loads(STATE.read_text()) if STATE.exists() else None
    if state is None:
        body = {
            "model": "midjourney", "type": "image", "operation": "generate",
            "input": {"prompt": PROMPT},
            "parameters": {"aspectRatio": "1:1", "quality": "1", "n": 1},
        }
        state = {"idempotency_key": str(uuid.uuid4()), "body": body,
                 "task_id": None, "status": "creating"}
        save(state)  # no API key here; write before POST
    elif state["body"]["input"]["prompt"] != PROMPT:
        sys.exit("The state file holds a different prompt. Move it aside to start a new job.")

    if OUT.exists() and state.get("status") == "downloaded":
        saved_sha = state.get("download_sha")
        if not saved_sha or hashlib.sha256(OUT.read_bytes()).hexdigest() == saved_sha:
            print("already saved", OUT)
            return

    if not state["task_id"]:
        code, task = call("POST", "/media/tasks", state["body"],
                          {"Idempotency-Key": state["idempotency_key"]})
        if code is None:
            sys.exit(f"Create not confirmed: {task['error']}. Rerun to retry the same key and body.")
        if code == 409:
            sys.exit("409 idempotency_key_reused: same key, different body. Restore the saved body.")
        if code == 503:
            sys.exit("503 no_available_channel: check model access for this key/account; "
                     "contact support with the request id if it persists.")
        if code not in (200, 202) or "id" not in task:
            sys.exit(f"Create failed: HTTP {code} {task}")
        state.update(task_id=task["id"], status=task["status"])
        save(state)

    deadline = time.monotonic() + 900
    while True:
        code, task = call("GET", f"/media/tasks/{state['task_id']}")
        if code is None:
            sys.exit(f"Polling stopped: {task['error']}. The job is still saved; rerun this script.")
        if code != 200 or "status" not in task:
            sys.exit(f"Poll failed: HTTP {code} {task}")
        state["status"] = task["status"]
        save(state)
        if task["status"] in ("failed", "canceled"):
            sys.exit(f"Job {task['status']}: {task.get('error')}")
        if task["status"] == "succeeded":
            break
        if time.monotonic() > deadline:
            sys.exit(f"Still {task['status']} after 900 s. Rerun with the same state file.")
        time.sleep(min(8, 2 + task.get("progress", {}).get("percent", 0) // 20))

    asset = task["assets"][0]
    if asset.get("mime_type") != "image/png":
        sys.exit(f"Expected a PNG grid, got {asset.get('mime_type')}")
    try:
        with urllib.request.urlopen(asset["url"], timeout=120) as response:
            data = response.read()  # signed URL: no Authorization header
    except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as error:
        sys.exit(f"Download failed: {error}. Rerun to get a fresh signed URL and retry.")
    digest = hashlib.sha256(data).hexdigest()
    if asset.get("sha256") and digest != asset["sha256"]:
        sys.exit("SHA-256 mismatch. Rerun to download the asset again.")
    part = OUT.with_suffix(".part")
    part.write_bytes(data)
    part.replace(OUT)
    state.update(status="downloaded", download_sha=digest)
    save(state)
    print("saved", OUT, len(data), "bytes")


if __name__ == "__main__":
    main()

İstek ve yanıt biçimleri 12 Kasım'daki entegrasyon testinden gelir; yeniden başlatma durumu burada eklenen kısımdır ve yaşam döngüsü dalları sahte yanıtlarla çevrimdışı kontrol edildi.

Durum dosyası devam etmek için gerekeni saklar: JSON gövdesini ve idempotency anahtarı olarak kullanılan UUID'yi. API anahtarı tutmaz. POST'tan önce yazıldığı için kopan bir bağlantı, kurtarma için iki değeri de diskte bırakır.

Oluşturma çağrısı iki başarı kodu döndürebilir. 202 yeni bir görevi kabul eder. 200, OmniaKey'in aynı anahtarı ve aynı gövdeyi daha önce gördüğünü ve özgün görevi döndürdüğünü gösterir; o görevi sorgulamaya devam edin. Aynı gövdeyi ve anahtarı yalnızca bağlantı hatasından sonra oluşturma sonucu bilinmiyorsa yeniden gönderin. Belgeler değişen gövde için 409 idempotency_key_reused listeler.

Sorgu döngüsünü status ile yönetin. Yüzde yaklaşık bir değerdir ve görev çalışırken 0'da kalabilir. succeeded, failed veya canceled durumunda durun. OmniaKey'in medya görevleri yaşam döngüsü belgeleri (12 Kasım 2026'da kontrol edildi) bu durumları açıklar.

Sorgu sınırı yereldir. Süre dolduğunda görev hâlâ çalışıyor veya kuyruktadır; aynı betiği yeniden çalıştırmak kayıtlı görev kimliğini okur ve sorgulamaya devam eder. Yerel zaman aşımı iptal değildir. İptal için ayrı bir endpoint vardır.

Dönen Midjourney görsel ızgarası

Başarılı bir görevin tek dosyası vardır: bir PNG ızgarası. Aşağıdaki, 12 Kasım 2026 entegrasyon testinden alınan örnektir:

Gün doğumunda mavi su üzerinde dört kırmızı katlanmış kâğıt kayık, sıcak yansıyan ışıkla 2x2 ızgara halinde
12 Kasım 2026 entegrasyon testi örneği: bir midjourney görevi, bir 2048x2048 PNG, dört aday, oluşturmadan indirmeye 197,1 saniye. İndirilen baytlar görevin SHA-256 değeriyle eşleşti.

Aşağıdaki yanıt kısaltılmıştır: URL gizlenmiştir ve expires_at geçmiş bir değerdir. İhtiyacınız olan dosya alanlarını ekler:

json
{
  "id": "task_DbCWJPfPL1jyhSD38IihNHiiFQao8hjV",
  "status": "succeeded",
  "progress": {"percent": 100, "stage": "completed"},
  "assets": [
    {
      "kind": "image",
      "mime_type": "image/png",
      "width": 2048,
      "height": 2048,
      "byte_size": 5834301,
      "sha256": "f503cef038d15fa150b36b5fe7c41874febad3aa1167698d790781e47a4a10b9",
      "expires_at": "2026-11-12T04:16:41Z",
      "url": "https://…redacted-signed-url…"
    }
  ]
}

2048 değerini sabitlemek yerine width ve height alanlarını dosyadan okuyun. 2048x2048 kare ve 197,1 saniye tek bir örnektir; onları böyle ele alın. Dört aday tek bir PNG'yi paylaşır, uygulamanız ayrı görseller istiyorsa ızgarayı indirdikten sonra bölün.

url imzalıdır ve kısa ömürlüdür, yaklaşık bir saat. Görev kaydı ve görsel, OmniaKey'in görsel API belgelerine göre (12 Kasım 2026'da kontrol edildi) oluşturmadan sonra 24 saat saklanır. URL'nin süresi dolmadan indirin. Süresi dolduysa yeni imzalı URL için görev kimliğini tekrar sorgulayın.

Dosya URL'sini normal bir GET ile ve Authorization başlığı olmadan indirin. İmza URL'nin içindedir. Betik ayrıca indirilen baytları görevin sha256 değeriyle karşılaştırır; böylece kesik bir dosya, iyi kopyanızın üzerine yazılmadan önce yakalanır.

Zaman aşımı veya başarısız indirmeden sonra yeniden çalıştırma

Aynı komutu yeniden çalıştırın ve görevi koruyun. Betik midjourney-task.json dosyasını okur ve en kısa güvenli yolu seçer:

  • Oluşturma doğrulanmadı: aynı gövdeyi aynı idempotency anahtarıyla yeniden POST eder.
  • Görev kimliği var ve görev hâlâ çalışıyor: mevcut kimliği sorgular.
  • Görev başarılı ama PNG yok: yeni imzalı URL için bir kez sorgular ve yeniden indirir.
  • PNG zaten kayıtlı ve kaydedilen SHA-256 ile eşleşiyor: başka istek olmadan çıkar. Bozuk dosya yeniden sorgulanır ve indirilir.

Bu, 24 saatlik saklama penceresi içinde çalışır. Aynı anahtar farklı bir prompt veya parametreyle 409 verir. Betik, promptu artık eşleşmeyen durum dosyasını reddeder; parametreleri değiştirirseniz dosyayı başka bir yere taşıyın.

Hatalar ve çözümler

Aşağıdaki hatalar API'nin görev ve idempotency kurallarından gelir. Nedeni düzeltin, uygunsa aynı durum dosyasıyla yeniden çalıştırın.

YanıtKodNe yapmalı
400missing_idempotency_keyBaşlığı ekleyin; 255 karakterin altında tutun
409idempotency_key_reusedÖzgün gövdeyi gönderin veya yeni anahtarla yeni bir görev başlatın
503no_available_channelBu anahtar/hesap için erişimi kontrol edin; sürerse destekle iletişime geçin
failederror.code, error.messageGörev hatasını okuyun; başarısız görevler iade edilir
canceled—Görev durdu; hâlâ gerekiyorsa yeni bir tane oluşturun

503 no_available_channel, bir anahtarın model izni olmadığı anlamına gelmez. Bu grupta kullanılan bir anahtarla iki gönderim 503 döndürdü ve hiç görev oluşturmadı; ayrı bir anahtar aynı gün daha erken bir entegrasyon testinde başarılı oldu. Neden bilinmiyor: anahtar/hesap kullanılabilirliği veya üst akış kanalı kullanılabilirliği olabilir. midjourney modelinin mevcut anahtarınız/hesabınız için kullanılabilir olduğunu doğrulayın. 503 sürerse yanıt gövdesini ve istek kimliğini desteğe gönderin.

Oluşturmada 200, özgün görevin aynen döndürülmesidir. Yalnızca failed ve canceled terminal hatalardır; betiği durdurmak görevi çalışır bırakır.

Maliyet ve ne zaman başka bir görsel API'si kullanmalı

OmniaKey başarılı görev başına bir kez ücret alır; başarısız veya iptal edilen görevler otomatik iade edilir. Güncel ücret Midjourney model sayfasında; toplu bir işi planlamadan önce kontrol edin.

Midjourney, tek ızgarada dört varyasyon arasında seçim yapmak için uygundur. Bu entegrasyon şu anda metinden görsele ızgarayı döndürür; çağrı başına tek görsel veya kaynak sahneyi koruyan bir düzenleme için GPT Image 2.5 API ya da Nano Banana Pro API sayfasına bakın.

Kod yazmak yerine prompt girmeyi tercih ederseniz AI Image Generator görsel modellerini tarayıcıda çalıştırır.

Sık sorulan sorular

Bu API'yi kullanmak için Midjourney aboneliği gerekli mi?

Hayır. Anahtar OmniaKey'den gelir ve çağrılar OmniaKey'in üçüncü taraf API'sine gider. OmniaKey Midjourney değildir; Midjourney web sitesindeki abonelik ayrı bir üründür ve OmniaKey anahtarı oluşturmaz.

Bir Midjourney görevi neden dört görseli tek dosyada döndürür?

Midjourney dört adayı tek bir PNG olarak 2x2 ızgarada döndürür. Dördü bu dosyayı paylaşır ve bu entegrasyonda upscale ile vary yoktur; ayrı dosyalar gerekiyorsa indirdikten sonra ızgarayı kendiniz bölün.

409 idempotency_key_reused ne anlama gelir?

OmniaKey'in zaten bildiği bir idempotency anahtarı gönderdiniz ama istek gövdesi değişti. Özgün gövdeyi gönderin veya yeni anahtarla yeni bir görev başlatın. Aynı anahtarı farklı bir promptla kullanmak yaygın nedendir.

Sorgulama sırasında betiğim zaman aşımına uğrarsa ne olur?

Görev çalışmaya devam eder. Görev kimliği midjourney-task.json içindedir; aynı betiği yeniden çalıştırmak o kimliği sorgular veya tamamlanan dosyayı indirir. Yerel zaman aşımı görevi ve ücreti olduğu gibi bırakır.

Bu makaledeki modeller

Midjourney APIPythongörsel API'si2x2 ızgaraAPI eğitimi

İlgili makaleler

Son makaleler

Popüler kılavuzlar