チュートリアル
HiAPI API で muse-image-1.0/image-to-image を呼び出す方法:curl、Python と実際に動作するリクエスト例
image-to-image リクエストが実際に送信するもの
最初のコードを書く前に、image-to-image 呼び出しが何を期待しているのかを把握しておくと役立ちます。プロンプトが唯一のクリエイティブな入力である純粋な text-to-image リクエストとは異なり、muse-image-1.0/image-to-image はソース画像と、それをどう変換するかの指示が必要です。
最低限、リクエストペイロードには以下が含まれます:
model:識別子muse-image-1.0/image-to-image。image:編集したいソース画像。通常は base64 エンコード文字列または公開アクセス可能な URL として送信されますが、エンドポイントが受け付ける形式によります。モデルの入力 schema を確認して、正確なフィールド名と形式を確かめてください。prompt:行いたい編集のテキスト記述。何を変更し、何を保持するのかを具体的に述べてください。- strength や guidance などのオプションパラメータ(モデルが公開している場合)を使うと、出力がソース画像からどれだけ乖離するかを制御できます。正確なパラメータセットはモデルごとに異なるため、当然と決めつけず API リファレンスで確認してください。
重要な心構えの転換はこうです:ゼロから生成するのではなく、出発点と方向性を提供するのです。"make it better" のような曖昧なプロンプトは、モデルに自由を与えすぎるため予測不能な結果を生みます。一方、"replace the sky with a sunset and keep the buildings unchanged" のようなプロンプトはモデルに明確な制約を与えます。
さらに、画像の制約——サポートされる形式、最大サイズ、ファイルサイズ——を事前に確認してください。ソース画像が 12 MB の PNG なら、リクエストが受け付けられる前にダウンサンプリングするか JPEG に変換する必要があるかもしれません。送信前に画像を適切に処理しておけば、往復のやり取りと混乱を招くエラーメッセージを一つ省けます。
ソース画像と明確な編集プロンプトが揃えば、最初の呼び出しを行う準備ができます。
curl で最初のリクエストを送信する
統合を検証する最速の方法は、ターミナルから直接リクエストを送信することです。正確なエンドポイントパスとペイロード schema はモデルの API リファレンスで定義されています。以下の例は一般的な形を示しているので、現在の仕様に合わせて調整してください。
curl -X POST https://api.hiapi.ai/v1/images/edits \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "muse-image-1.0/image-to-image",
"image": "https://your-bucket.example.com/source.jpg",
"prompt": "replace the sky with a warm sunset, keep the buildings unchanged",
"strength": 0.6
}'
$HIAPI_API_KEY はキーを直接貼り付けるのではなく、環境変数で置き換えてください。ツールが対応していればシェルセッションでキーをエクスポートし、コマンド履歴に残らないようにしましょう。
返されるレスポンスにはジョブ識別子が含まれます。画像編集は計算負荷が高いため、API は通常、同じレスポンスで完成した画像を返しません。代わりにジョブ ID とステータスを受け取ります。その ID を保存してください——次のステップで結果をポーリングするのに使います。
呼び出しが失敗した場合は、エラーレスポンスボディを注意深く読んでください。400 は通常、ペイロードの形式エラーまたはサポートされていない画像形式を示します。401 はキーが欠落しているか誤っていることを示します。429 はリクエストを送信しすぎていることを示します。これらの問題はターミナル段階で修正する方が、完全なアプリケーションでデバッグするよりはるかに簡単です。
同じリクエストを Python で実装する
curl 呼び出しが成功したら、それを小さな Python 関数に変換しましょう。requests を使えば、依存が少なく移植しやすい例になります。
import os
import requests
HIAPI_API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = "https://api.hiapi.ai/v1/images/edits"
def submit_edit(image_url: str, prompt: str, strength: float = 0.6) -> str:
payload = {
"model": "muse-image-1.0/image-to-image",
"image": image_url,
"prompt": prompt,
"strength": strength,
}
headers = {
"Authorization": f"Bearer {HIAPI_API_KEY}",
"Content-Type": "application/json",
}
response = requests.post(BASE_URL, json=payload, headers=headers, timeout=30)
response.raise_for_status()
data = response.json()
return data["id"]
この関数についてのいくつかの注意点:
timeoutパラメータは、ネットワークが停滞したときにスクリプトが無限にハングするのを防ぎます。送信呼び出しには 30 秒で十分ですが、必要に応じて調整してください。raise_for_status()は HTTP エラーを例外に変換するので、一箇所で捕捉できます。- ジョブ ID だけを返すことで、関数は責務に集中できます。ポーリングロジックは別の関数に置くべきです。
ソース画像を URL ではなくバイトとして送信したい場合は、ファイルを読み込んで base64 エンコードし、その結果を image フィールドに入れてください。切り替える前に、ドキュメントで期待される形式を確認してください。これら二つのエンコーディングは常に相互交換可能とは限りません。
この関数は意図的に最小限に保っています。実際のサービスではログ、リトライ処理、型検証を追加するでしょうが、コアとなるリクエストパターンはここで見たとおりです。
非同期ジョブを処理し結果をポーリングする
画像編集には時間がかかります——通常は数秒から数十秒で、プロンプトと解像度によります。API はリクエストを受け付け、ジョブ ID を返し、バックグラウンドで処理を行います。あなたの仕事は、ステータスが終状態に達するまで繰り返し確認することです。
ポーリングは単純に聞こえますが、100 ミリ秒ごとに発火する素朴なループはクォータを浪費し、レート制限を引き起こす可能性があります。合理的な間隔とリトライ上限を使いましょう:
import time
import requests
def poll_job(job_id: str, interval: float = 2.0, max_attempts: int = 30) -> dict:
url = f"https://api.hiapi.ai/v1/jobs/{job_id}"
headers = {"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"}
for attempt in range(max_attempts):
response = requests.get(url, headers=headers, timeout=15)
response.raise_for_status()
data = response.json()
status = data["status"]
if status == "succeeded":
return data
if status == "failed":
raise RuntimeError(data.get("error", "job failed"))
time.sleep(interval)
raise TimeoutError(f"job {job_id} did not finish after {max_attempts} attempts")
2 秒の間隔は合理的な出発点です。ジョブが通常 5 秒以内に完了するなら、最初はより頻繁にポーリングし、その後徐々にバックオフしてもよいでしょう。通常より長くかかるなら、ポーリング頻度を下げて不要な呼び出しを避けましょう。
リトライ上限はセーフティネットです。これがないと、スタックしたジョブが無限にループする可能性があります。上限に達したら明確なエラーを投げ、呼び出し元が操作がタイムアウトしたことを認識できるようにし、静かにハングしないようにします。
本番環境では、ポーリングをバックグラウンド worker やキューに移すことを検討してください。そうすれば、リクエスト処理スレッドが画像のレンダリング完了を待ってブロックされることがなくなります。
出力画像をダウンロードして保存する
ジョブが succeeded 状態に達すると、レスポンスには 1 枚以上の出力画像が含まれ、通常は URL として提供されます。次のステップは画像をダウンロードして永続的に保存することです。
def download_image(result: dict, dest_path: str) -> None:
image_url = result["output"][0]["url"]
response = requests.get(image_url, timeout=30)
response.raise_for_status()
with open(dest_path, "wb") as f:
f.write(response.content)
いくつかの実務上の考慮点:
- 出力 URL は一時的な場合があります。短命なリソースとして扱い、URL だけを唯一の参照として保存するのではなく、速やかにダウンロードしてください。
- ファイルはバイナリモードで書き込みます。画像レスポンスはテキストではないので、
"w"で開くとデータが破損します。 - 成功を宣言する前に、ファイルが空でないことを検証してください。ゼロバイトのダウンロードは通常、URL が期限切れか、リクエストがブロックされたことを意味します。
ローカルスクリプト以外のあらゆる場面では、一度ディスクに保存するのではなく、ダウンロードを直接ストレージプロバイダにストリーミングしてください。ほとんどのオブジェクトストレージ SDK はファイルライクオブジェクトやバイトストリームを受け付けるので、中間ファイルなしで response.raw や response.content をアップロード呼び出しにパイプできます。
最後に、ジョブ ID を保存したオブジェクトと一緒に記録してください。後で出力が破損した場合や、特定の編集を再現する必要がある場合、ジョブ ID と元の入力があれば、送信した内容を追跡できます。
よくある失敗ポイントとその修正方法
統合の問題のほとんどは少数のカテゴリに分類されます。以下に各種類の診断方法を示します。
ジョブ作成前にリクエストが拒否される
送信時の 400 エラーは通常、ペイロードの誤りを示します。model が正確に muse-image-1.0/image-to-image であるか、image がアクセス可能か base64 エンコードが正しいか、prompt が非空文字列かを確認してください。画像が URL なら、公開アクセス可能であることを確認してください——プライベートバケットや期限切れの署名付き URL は検証を通過しません。
ジョブが処理中に失敗する
ポーリングが failed 状態を返したら、レスポンスボディのエラーメッセージを読んでください。よくある原因には、画像が大きすぎる、プロンプトがコンテンツポリシーに違反している、パラメータ値が許容範囲外などがあります。原因を切り分けるために、画像サイズを縮小しプロンプトを簡素化してください。
ポーリングがタイムアウトする
終状態に達しないままリトライ上限に達した場合、ジョブが実際により多くの時間を必要としているか、スタックしている可能性があります。まず max_attempts を増やし、API リファレンスで典型的な処理時間を確認してください。ジョブが継続的にタイムアウトするなら、ソース画像が異常に大きくないか確認してください。単純にリトライ上限を削除しないでください——有界リトライは静かな無限ループを防ぎます。
レート制限
429 レスポンスはリクエストを送信しすぎていることを意味します。バックオフし、retry-after ヘッダがあれば従い、同時送信をずらしてください。画像のバッチを処理しているなら、一度にすべて送信するのではなく、順次処理するか、より小さい並列度の制限を使ってください。
出力が欠落または切り詰められている
ジョブは成功したのにダウンロードしたファイルが空の場合、ポーリングとダウンロードの間に出力 URL が期限切れになった可能性があります。成功後すぐにダウンロードしてください。画像が破損している場合は、バイナリモードで書き込んでおり、ストリームにテキストエンコーディングを適用していないことを確認してください。
リクエストペイロード、ジョブ ID、ステータス遷移を記録しておくと、デバッグが容易になります。これら三つの情報があれば、ほぼすべての失敗を根本原因まで追跡できます。
リクエストの形、curl と Python のパターン、ポーリングロジック、ダウンロード手順が揃えば、HiAPI API で muse-image-1.0/image-to-image を使う実用的なパイプラインが完成します。ターミナルの例から始め、スクリプトに移し、正常系が安定してからリトライとログを追加してください。
関連記事
すべての記事を見る →-
チュートリアル
HiAPI API で hailuo-2.3-fast/image-to-video を呼び出す方法:curl と Python の実践
高速・低コストな画像から動画へのティアにおける最初の実行可能なリクエスト — モデル ID から MP4 のダウンロードまで
-
チュートリアル
HiAPI APIでhailuo-2.3/text-to-videoを呼び出す方法:curl、Python、実行可能なリクエスト例
-
チュートリアル
HiAPI で Kandinsky 6.0 Pro のテキストto動画を使用する:curl と Python チュートリアル
リクエスト優先の実践デモ:プロンプトから動画クリップへの呼び出しを構築し、リクエストを送信し、完了状態をポーリングし、結果をダウンロードする