コンテンツにスキップ

マルチモーダル入力

マルチモーダル入力により、モデルはテキストだけでなく、画像や音声などの他の形式のコンテンツも処理できます。RouteAPIは /v1/chat/completions(OpenAI形式)と /v1/messages(Claude形式)の両方でマルチモーダルコンテンツの受け渡しをサポートし、異なるアップストリームプロトコル間のフォーマット変換を自動的に処理します。

サポートされるモダリティタイプ

Section titled “サポートされるモダリティタイプ”
モダリティタイプ説明
画像(Vision)PNG、JPEG、WebP、GIFなどの形式で、画像理解、OCR、チャート分析に使用
音声(Audio)一部のモデルが音声入力をサポートし、音声理解、文字起こしなどのシーンに使用
動画(Video)一部のモデルが動画フレーム入力をサポートし、動画をキーフレームシーケンスに分割

現在、画像入力のサポートが最も広く、ほぼすべての主流の視覚モデルがサポートしています。音声と動画の入力は、特定のモデルの機能に依存します。

以下のモデルが画像入力をサポートしています(完全なリストではありません):

モデルシリーズ代表的なモデルID
OpenAI GPT-4 Visiongpt-4o, gpt-4-turbo, gpt-5.5
Claude Visionclaude-sonnet-4-5, claude-opus-4-5
Gemini Visiongemini-2.0-flash, gemini-2.5-pro
Azure OpenAIazure-gpt-4o

まずモデルリストエンドポイントでモデルがアカウントで利用可能か確認してください:

Terminal window
curl https://api.routeapi.ai/v1/models \
-H "Authorization: Bearer $ROUTEAPI_KEY"

このエンドポイントは画像入力能力を示すフィールドを返しません。ビジョン入力をサポートするかどうかは、プロバイダーのドキュメントまたは画像を含む実際のリクエスト1回を基準としてください。

形式MIME Type説明
PNGimage/png可逆圧縮形式、スクリーンショットやチャートに適している
JPEGimage/jpeg非可逆圧縮、写真に適している
WebPimage/webpモダンな形式、サイズが小さく品質が高い
GIFimage/gif非アニメーション形式(最初のフレームのみ使用)

モデルによって画像サイズの制限は異なりますが、一般的な推奨事項:

制限項目推奨値説明
単一画像サイズ< 20 MB超大型画像は処理時間とコストを増加させる
画像解像度長辺 ≤ 2048px高解像度は自動的にスケーリングまたはチャンク処理される
Base64エンコード後< 32 MB総リクエストサイズはアップストリームサービスの制限を受ける

アップロード前に画像を圧縮し、可読性を保証しながら解像度を下げることをお勧めします。これにより、転送時間を短縮し、トークンコストも削減できます。

画像はトークンに変換されて課金されます。高解像度画像が消費するトークン数はテキストよりもはるかに多くなります:

  • 低解像度モード(OpenAIの detail: "low" など):固定で約85トークン/画像。
  • 高解像度モード(detail: "high" など):画像サイズに応じてチャンク化され、2048×2048の画像は800-1500トークンを消費する可能性があります。

本番環境では、実際のニーズに応じて解像度モードを選択することをお勧めします。細かい認識が不要な場合は low モードを優先してください。

画像には2つの受け渡し方法があります:URLとBase64エンコード。

公開アクセス可能な画像URLを渡し、アップストリームモデルサービスに取得させます:

利点:

  • リクエストサイズが小さく、アップロード帯域幅を使用しない。
  • すでにCDNでホストされている画像に適している。

欠点:

  • 画像は公開アクセス可能でなければならず、アップストリームサービスのIPがアクセスできる必要がある。
  • 画像の読み込みに失敗した場合(ネットワーク問題、認証、期限切れリンク)、リクエストがエラーになる。

適用シーン:すでに公開画像ホスト、CDNでホストされている画像で、一時的なアップロードが不要な場合。

画像をバイナリデータとして読み取り、Base64でエンコードしてリクエストに直接埋め込みます:

利点:

  • 公開アクセス可能なURLが不要で、プライベート画像に適している。
  • リクエストが自己完結型で、外部サービスの可用性に依存しない。

欠点:

  • Base64エンコードによりデータサイズが約33%増加する。
  • リクエストサイズが大きく、アップロードに時間がかかる。

適用シーン:ユーザーがアップロードしたプライベート画像、ローカルファイル、一時的なスクリーンショットなど、公開URLがない場合。

比較項目URL方式Base64方式
リクエストサイズ小(URL文字列のみ)大(Base64エンコード後は元ファイルの約1.33倍)
アップロード速度速い遅い
画像アクセシビリティ公開アクセス可能である必要がある要件なし、プライベート画像可
外部依存画像サーバーとアップストリームフェッチに依存外部依存なし
適用シーン公開画像ホスト、CDNユーザーアップロード、ローカルファイル

/v1/chat/completions では、画像は content 配列を通じて渡され、各要素はコンテンツブロックであり、type でテキストと画像を区別します。

content は文字列(プレーンテキスト)または配列(マルチモーダル)にできます:

{
"role": "user",
"content": [
{ "type": "text", "text": "この画像には何がありますか?" },
{
"type": "image_url",
"image_url": {
"url": "https://example.com/image.jpg"
}
}
]
}

image_url コンテンツブロックのフィールド:

フィールドタイプ必須説明
typestringはい"image_url" に固定
image_url.urlstringはい画像URLまたはBase64 Data URI
image_url.detailstringいいえ解像度モード: "low", "high", "auto"(デフォルト)

detail は画像処理の解像度とコストを制御します:

値動作トークン消費
"low"低解像度モード、画像を固定サイズに縮小(例:512×512)固定で約85トークン
"high"高解像度モード、画像をチャンクで処理し、詳細を保持チャンク数に応じて、通常数百から数千トークン
"auto"モデルが自動選択(デフォルト)モデルの戦略に依存

コスト差の例:

  • 簡単なスクリーンショットを "low" で処理すると85トークンのみ(約¥0.0001)。
  • 同じ画像を "high" で処理すると800トークンを消費(約¥0.001)。

小さな文字や詳細を認識する必要がないシーン(「これは何の動物か」「インターフェースのテーマカラーは何か」など)では、"low" で十分です。OCR、チャート数値の読み取り、小さなオブジェクトの認識が必要な場合のみ "high" を使用してください。

{
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/320px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg",
"detail": "high"
}
},
{ "type": "text", "text": "この画像の内容を説明してください" }
]
}
]
}

Base64はData URI形式を使用する必要があります:data:<mime_type>;base64,<encoded_data>。

{
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
}
},
{ "type": "text", "text": "この画像にはどんなテキストがありますか?" }
]
}
]
}

Base64文字列は非常に長くなる可能性があり、上記の例は切り詰められています。実際の使用では、完全なエンコードは数百KBから数MBになる可能性があります。

/v1/messages では、画像は content 配列の image タイプブロックを通じて渡され、構造はOpenAI形式と明らかに異なります。

{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": "/9j/4AAQSkZJRgABAQEAYABgAAD..."
}
},
{ "type": "text", "text": "この画像を説明してください" }
]
}

source フィールドは画像ソースを指定し、2つの方法があります:

フィールドタイプ必須説明
typestringはい"base64" に固定
media_typestringはいMIMEタイプ、例:image/jpeg, image/png
datastringはいBase64エンコードされた画像データ(data: プレフィックスなし)

Claude形式のBase64は Data URIプレフィックスが不要で、エンコード文字列を直接渡すことに注意してください。

{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
}
}
フィールドタイプ必須説明
typestringはい"url" に固定
urlstringはい公開アクセス可能な画像URL
{
"type": "image",
"source": {
"type": "url",
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/320px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
}
}
{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "url",
"url": "https://upload.wikimedia.org/wikipedia/commons/a/a7/Camponotus_flavomarginatus_ant.jpg"
}
},
{ "type": "text", "text": "これは何の昆虫ですか?" }
]
}
]
}

Geminiのネイティブ形式は content ではなく parts 配列を使用し、構造がかなり異なります。RouteAPIは内部で変換を処理するため、OpenAIまたはClaude形式でGeminiモデルを呼び出す際、ネイティブ形式の詳細を気にする必要はありません。以下は参考のみです。

{
"contents": [
{
"role": "user",
"parts": [
{ "text": "この画像を説明してください" },
{
"inlineData": {
"mimeType": "image/jpeg",
"data": "/9j/4AAQSkZJRg..."
}
}
]
}
]
}
フィールド説明
inlineData.mimeTypeMIMEタイプ
inlineData.dataBase64エンコードデータ

GeminiはファイルURIを通じてGoogleサービスにアップロード済みのファイルを参照することもサポートしています:

{
"fileData": {
"mimeType": "image/jpeg",
"fileUri": "gs://bucket-name/path/to/image.jpg"
}
}

実際の使用では、RouteAPIを通じてGeminiモデルを呼び出す際、OpenAIまたはClaude形式を使用すれば、RouteAPIが自動的に変換します。

すべての主流の視覚モデルは、1回のリクエストで複数の画像を渡すことをサポートしています。

content / parts 配列に複数の画像ブロックを配置します:

OpenAI形式:

{
"role": "user",
"content": [
{ "type": "text", "text": "これら2つの画像の違いを比較してください" },
{
"type": "image_url",
"image_url": { "url": "https://example.com/image1.jpg" }
},
{
"type": "image_url",
"image_url": { "url": "https://example.com/image2.jpg" }
}
]
}

Claude形式:

{
"role": "user",
"content": [
{ "type": "text", "text": "これら2つの画像の類似点と相違点は何ですか?" },
{
"type": "image",
"source": { "type": "url", "url": "https://example.com/before.jpg" }
},
{
"type": "image",
"source": { "type": "url", "url": "https://example.com/after.jpg" }
}
]
}

モデルは配列の順序で画像を理解します。テキストで「最初の画像」「2番目の画像」と指定すると、モデルは出現順序で対応します。説明テキストをすべての画像の前または後に配置し、間に挿入しないことをお勧めします。これにより意味がより明確になります:

{
"content": [
{ "type": "text", "text": "最初はユーザーインターフェースのスクリーンショット、2番目はデザイン案です。両者の違いを比較し、修正提案を提供してください。" },
{ "type": "image_url", "image_url": { "url": "..." } },
{ "type": "image_url", "image_url": { "url": "..." } }
]
}

テキストと画像を交互に配置して、段階的な説明を行うこともできます:

{
"content": [
{ "type": "text", "text": "これは元のインターフェースです:" },
{ "type": "image_url", "image_url": { "url": "https://example.com/old.jpg" } },
{ "type": "text", "text": "これは改善後のインターフェースです:" },
{ "type": "image_url", "image_url": { "url": "https://example.com/new.jpg" } },
{ "type": "text", "text": "改善点を要約してください。" }
]
}

実際の効果は、モデルのコンテンツブロック順序の理解能力に依存しますが、主流の視覚モデルは通常正しく処理できます。

一部のモデルは音声入力をサポートし、音声理解、文字起こし、感情分析などのシーンに使用されます。現在のサポート度は画像ほど広くありません。

特定のモデルに依存し、一般的な形式には以下が含まれます:

  • WAV(audio/wav)
  • MP3(audio/mpeg)
  • OGG(audio/ogg)
  • FLAC(audio/flac)

画像と同様に、音声もURLとBase64の2つの方法をサポートしています。OpenAI形式の例(モデルがサポートしていると仮定):

{
"role": "user",
"content": [
{
"type": "input_audio",
"input_audio": {
"data": "<base64-encoded-audio>",
"format": "wav"
}
},
{ "type": "text", "text": "この音声を文字起こしし、要点を要約してください" }
]
}

実際のフィールド名と構造はモデルプロトコルに依存します。使用前に選択したモデルのドキュメントを参照するか、モデルリストエンドポイントで supports_audio_input フィールドを確認してください。

以下の例は、curl、Python、Node.jsの3つの言語で画像理解のエンドツーエンド実装を示しています。

画像を与えて、モデルにその内容を説明させます。

curl(OpenAI形式、URL方式):

Terminal window
curl https://api.routeapi.ai/v1/chat/completions \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/320px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
}
},
{ "type": "text", "text": "この画像の内容と雰囲気を詳しく説明してください" }
]
}
]
}'

Python(OpenAI SDK、Base64方式):

import base64
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ROUTEAPI_KEY"],
base_url="https://api.routeapi.ai/v1",
)
# ローカル画像を読み取りBase64にエンコード
with open("image.jpg", "rb") as f:
image_data = base64.b64encode(f.read()).decode("utf-8")
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{image_data}"
},
},
{"type": "text", "text": "この画像には何がありますか?"},
],
}
],
)
print(response.choices[0].message.content)

Node.js(openaiパッケージ、URL方式):

import OpenAI from 'openai';
const client = new OpenAI({
apiKey: process.env.ROUTEAPI_KEY,
baseURL: 'https://api.routeapi.ai/v1',
});
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{
type: 'image_url',
image_url: {
url: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/320px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg',
},
},
{ type: 'text', text: 'この画像のテーマを一文で要約してください' },
],
},
],
});
console.log(response.choices[0].message.content);

チャートのスクリーンショットをアップロードし、モデルにデータを読み取って分析させます:

Python(Claude形式、Base64):

import base64
import os
from anthropic import Anthropic
client = Anthropic(
api_key=os.environ["ROUTEAPI_KEY"],
base_url="https://api.routeapi.ai",
)
with open("chart.png", "rb") as f:
image_data = base64.b64encode(f.read()).decode("utf-8")
message = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": image_data,
},
},
{
"type": "text",
"text": "このチャートはどのようなトレンドを示していますか?主要なデータポイントを抽出し、分析を提供してください。",
},
],
}
],
)
print(message.content[0].text)

スクリーンショットや写真からテキストコンテンツを抽出します:

curl(OpenAI形式、高解像度):

Terminal window
curl https://api.routeapi.ai/v1/chat/completions \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "https://example.com/document.jpg",
"detail": "high"
}
},
{
"type": "text",
"text": "画像内のすべてのテキストを抽出し、元の形式と構造を維持してください"
}
]
}
]
}'

OCRシーンでは、認識精度を保証するために "detail": "high" を使用することをお勧めします。特に小さな文字や密集したテキストの場合。

2つ以上の画像の違いを比較します:

Python(OpenAI形式、複数画像):

from openai import OpenAI
import os
client = OpenAI(
api_key=os.environ["ROUTEAPI_KEY"],
base_url="https://api.routeapi.ai/v1",
)
response = client.chat.completions.create(
model="gpt-5.5",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": "以下の2つの画像を比較し、それらの間の5つの主要な違いを見つけてください:",
},
{
"type": "image_url",
"image_url": {"url": "https://example.com/before.jpg"},
},
{
"type": "image_url",
"image_url": {"url": "https://example.com/after.jpg"},
},
],
}
],
)
print(response.choices[0].message.content)

複数ターンの対話で画像とテキストを混合します:

from openai import OpenAI
import os
client = OpenAI(
api_key=os.environ["ROUTEAPI_KEY"],
base_url="https://api.routeapi.ai/v1",
)
messages = [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {"url": "https://example.com/product.jpg"},
},
{"type": "text", "text": "この製品の主な特徴は何ですか?"},
],
}
]
response = client.chat.completions.create(model="gpt-4o", messages=messages)
messages.append(response.choices[0].message)
print("第1ターン:", response.choices[0].message.content)
# 続けて質問(プレーンテキスト)
messages.append({"role": "user", "content": "どのようなユーザー層に適していますか?"})
response = client.chat.completions.create(model="gpt-4o", messages=messages)
print("第2ターン:", response.choices[0].message.content)

画像は最初のターンで一度渡すだけで、後続のターンではモデルが画像の内容を覚えています(コンテキストウィンドウ内)。再度アップロードする必要はありません。

アップロード前に必要な最適化を行うことで、コストを削減し、応答速度を向上させることができます:

最適化項目推奨
サイズ長辺を2048px以内に抑える。より多くの詳細を認識する必要がない限り
形式スクリーンショットやチャートにはPNG、写真にはJPEG、究極の圧縮にはWebP
圧縮JPEG品質80-90%で十分。視覚的な差は小さいがサイズは大幅に削減
トリミング無関係な領域(大きな空白、透かし、枠線など)を削除し、重要なコンテンツのみを保持

トークンを節約するために画像を認識できないレベルまで圧縮しないでください。モデルが認識できなければ、かえって無駄になります。

マルチモーダル入力のコストは主に画像から発生します:

シーン典型的なトークン消費コスト見積もり(GPT-4o)
低解像度画像(detail: "low")~85トークン¥0.0001
高解像度小画像(500×500、detail: "high")~200トークン¥0.0003
高解像度大画像(2000×2000、detail: "high")~800トークン¥0.0012
複数の高解像度画像(5枚、detail: "high")~4000トークン¥0.006

具体的な料金は選択したモデルに依存します。上記は例のみです。本番環境での推奨事項:

  1. デフォルトで detail: "auto" または "low" を使用し、モデルまたはユーザーのニーズに解像度を決定させる。
  2. 細かい認識が明確に必要な場合(OCR、チャートデータ、小さなオブジェクト検出)のみ "high" を使用。
  3. 各リクエストのトークン使用量(レスポンスの usage フィールド)を記録し、コスト異常を特定。

マルチモーダル入力は追加の失敗ポイントを導入し、対象を絞った処理が必要です:

サポートされていない画像形式

Section titled “サポートされていない画像形式”
{
"error": {
"message": "Unsupported image format",
"type": "invalid_request_error"
}
}

解決策:MIMEタイプが正しいことを確認するか、PNG/JPEGに変換してください。

{
"error": {
"message": "Image size exceeds limit",
"type": "invalid_request_error"
}
}

解決策:画像を圧縮するか解像度を下げて再試行してください。

{
"error": {
"message": "Failed to fetch image from URL",
"type": "invalid_request_error"
}
}

解決策:

  • URLが公開アクセス可能で、認証が不要であることを確認。
  • アップストリームサービスのIPがそのURLにアクセスできるかテスト(ファイアウォール、地域制限)。
  • Base64方式に切り替えて、外部サービスへの依存を回避。
{
"error": {
"message": "Invalid base64 encoding",
"type": "invalid_request_error"
}
}

解決策:Base64エンコードが完全で、形式が正しいか確認してください(OpenAI形式は data: プレフィックスが必要、Claude形式は不要)。

リスク保護措置
URL画像漏洩URLが指す画像に機密情報が含まれていないことを確認するか、認証付き一時リンクを使用
Base64サイズ攻撃ユーザーがアップロードする画像のサイズ上限を制限(例:20MB)、超大リクエストを防止
インジェクション攻撃ユーザーがアップロードした画像URLをシステムコマンドやSQLに直接連結しない
モデルの幻覚画像理解結果が不正確な可能性があり、高リスクシーン(医療、法律、金融)では人間の確認が必要
  • 視覚能力、サポートされる画像形式、最大画像数は選択したモデルに依存します。本番環境前にテストして確認してください。
  • detail パラメータはOpenAI形式でのみ意味があり、Claude形式には対応するパラメータがありません。
  • 異なるモデルは解像度の処理戦略が異なり、同じ画像でも異なるモデルでのトークン消費が大きく異なる可能性があります。
  • ストリーミングレスポンスでは、画像コンテンツの処理結果は通常、ストリームの早期または後期に一度に返され、文字ごとにストリーミング出力されることはありません。
  • 各リクエストのrequest ID、モデルID、ステータスコード、トークン使用量を記録し、コストと品質の問題をトラブルシューティングしやすくします。詳細はエラーとデバッグを参照してください。