|

APIファイルアップロードをマスターする:multipart/form-data完全ガイドとSora 2実践例

APIでのファイルアップロードは、AI動画生成や画像処理などのインターフェースを呼び出す際、開発者が頻繁に遭遇する技術的ニーズです。本記事では、multipart/form-data エンコード方式の仕組みを体系的に解説し、Sora 2の「イメージ to ビデオ」APIを例に、APIファイルアップロードの核となるスキルを習得できるようサポートします。

コア・バリュー: 本記事を読み終える頃には、multipart/form-data の低レイヤーのメカニズムを完全に理解し、curl -F コマンドを使用したファイルアップロードを習得し、Sora 2 などの AI API における画像アップロード機能を自力で実装できるようになります。

api-file-upload-multipart-form-data-guide-ja 图示


API ファイルアップロードの核心知識

コードを詳しく見る前に、なぜ API でのファイルアップロードに特殊なエンコード方式が必要なのかを理解しておく必要があります。

なぜ multipart/form-data が必要なのか

API を介して通常のテキストデータを送信する場合、シンプルな application/x-www-form-urlencoded エンコードを使用できます。しかし、ファイルを扱う際、この方式には重大な問題があります。

エンコード形式 適用シーン ファイル処理能力 効率
application/x-www-form-urlencoded シンプルなキーと値のペア ❌ 不向き バイナリにURLエスケープが必要で効率が低い
application/json 構造化データ ⚠️ Base64 エンコードが必要 データサイズが33%増加
multipart/form-data ファイルアップロード ✅ ネイティブサポート エンコード不要、高効率

multipart/form-data は 1998 年の RFC 2388 標準で提案されたスキームで、HTTP プロトコルにおいてテキストとバイナリデータを混合して送信する際の問題を専門に解決するものです。

multipart/form-data の仕組み

multipart/form-data の核となる考え方は、一つの HTTP リクエストボディを複数の独立した「パート(parts)」に分割することです。各パートは独自の内容タイプ(Content-Type)を持つことができます。

api-file-upload-multipart-form-data-guide-ja 图示

データ構造の詳細解説

典型的な multipart/form-data リクエストは、以下の構造で構成されます。

POST /v1/videos HTTP/1.1
Host: api.apiyi.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxk

------WebKitFormBoundary7MA4YWxk
Content-Disposition: form-data; name="prompt"

She turns around and smiles
------WebKitFormBoundary7MA4YWxk
Content-Disposition: form-data; name="model"

sora-2-pro
------WebKitFormBoundary7MA4YWxk
Content-Disposition: form-data; name="input_reference"; filename="sample.jpeg"
Content-Type: image/jpeg

[二进制图片数据]
------WebKitFormBoundary7MA4YWxk--
コンポーネント 役割
Boundary 各データパートを区切るための一意の識別子 ----WebKitFormBoundary7MA4YWxk
Content-Disposition そのパートのメタデータを記述 form-data; name="prompt"
Content-Type そのパートの MIME タイプ image/jpeg
Body 実際のデータ内容 テキストまたはバイナリデータ

🎯 テクニカルポイント: Boundary は、リクエストボディ内に出現しない一意の文字列である必要があります。サーバーはこの boundary を使用して、各データパートを解析および分離します。


curl -F コマンド詳説:API ファイルアップロード実践

curl は最も頻繁に使用されるコマンドライン HTTP クライアントツールであり、その -F パラメータは multipart/form-data リクエスト専用に設計されています。

curl -F 基本構文

curl -F "フィールド名=値" URL
curl -F "ファイルフィールド=@ローカルファイルパス" URL
パラメータ形式 説明
-F "key=value" 通常のテキストフィールドを送信 -F "prompt=Hello"
-F "key=@file" ローカルファイルをアップロード -F "[email protected]"
-F "key=@file;type=mime" ファイルの MIME タイプを指定 -F "[email protected];type=image/jpeg"
-F "key=@file;filename=new.jpg" アップロードファイル名をカスタマイズ -F "[email protected];filename=upload.jpg"

curl -F と他のパラメータの違い

多くの開発者が -F-d-X POST の使い方を混同しがちです。

# ❌ 誤り: -d は x-www-form-urlencoded 用であり、ファイルアップロードには適していません
curl -X POST -d "[email protected]" https://api.example.com/upload

# ❌ 誤り: 手動で Content-Type を指定しながら -d を使用している
curl -X POST -H "Content-Type: multipart/form-data" -d "..." https://api.example.com/upload

# ✅ 正解: -F を使用して正しい Content-Type と boundary を自動設定する
curl -F "[email protected]" https://api.example.com/upload

技術解説: -F を使用すると、curl は自動的に以下の処理を行います:

  1. リクエストメソッドを POST に設定
  2. Content-Type: multipart/form-data を設定
  3. 一意の boundary を生成
  4. RFC 標準に従ってリクエストボディをフォーマット

Sora 2 API ファイルアップロード実践

Sora 2 は OpenAI が発表した動画生成モデルで、API を通じて参照画像をアップロードし、それを元に動画を生成することをサポートしています。これは multipart/form-data の典型的な活用シーンです。

Sora 2 イメージ to ビデオ API パラメータ

パラメータ 必須 説明
prompt string 動画の説明テキスト(プロンプト)
model string モデル選択: sora-2 または sora-2-pro
size string 解像度: 1280x720, 720x1280, 1024x1792, 1792x1024
seconds integer 時間: 4, 8, 12
input_reference file 参照画像、動画の最初のフレームとして使用

api-file-upload-multipart-form-data-guide-ja 图示

Sora 2 モデル比較

特性 sora-2 sora-2-pro
生成品質 良好 卓越
レンダリング速度 高速 低速
活用シーン プロトタイピング、コンセプト検証 プロダクションレベルの出力
価格 標準 高め
利用可能なプラットフォーム APIYI (apiyi.com), 公式 API APIYI (apiyi.com), 公式 API

Sora 2 ファイルアップロード完全版の例

以下は、curl を使用して Sora 2 API を呼び出し、画像から動画を生成する完全な例です。

curl -X POST "https://api.apiyi.com/v1/videos" \
  -H "Authorization: Bearer $APIYI_KEY" \
  -H "Content-Type: multipart/form-data" \
  -F prompt="She turns around and smiles, then slowly walks out of the frame." \
  -F model="sora-2-pro" \
  -F size="1280x720" \
  -F seconds="8" \
  -F input_reference="@sample_720p.jpeg;type=image/jpeg"

コマンド解説

パーツ 説明
curl -X POST POST リクエストメソッドを指定
"https://api.apiyi.com/v1/videos" APIYI Sora 2 動画生成エンドポイント
-H "Authorization: Bearer $APIYI_KEY" 環境変数を使用して API キーを渡す
-H "Content-Type: multipart/form-data" コンテンツタイプを宣言 (curl -F が自動的に追加します)
-F prompt="..." 動画の説明プロンプト
-F model="sora-2-pro" 高品質モデルを選択
-F size="1280x720" 横向き 720p 解像度
-F seconds="8" 8 秒間
-F input_reference="@sample_720p.jpeg;type=image/jpeg" 参照画像をアップロード

🚀 クイックスタート: Sora 2 API を素早くテストするには、APIYI (apiyi.com) プラットフォームの使用をお勧めします。このプラットフォームは、複雑な設定なしですぐに統合できる API インターフェースを提供しています。

画像アップロードの注意点

Sora 2 API で参照画像をアップロードする際は、以下の点に注意してください:

要件 説明
解像度の適合 画像の解像度は、ターゲット動画の size パラメータと一致している必要があります
サポート形式 image/jpeg, image/png, image/webp
ファイルサイズ 10MB 以下を推奨
画像品質 鮮明で構図の整った画像の方が、より良い生成結果が得られます

Python による multipart/form-data アップロードの実装

curl だけでなく、実際の開発ではプログラミング言語を使用してファイルアップロードを実装するのが一般的です。以下に Python での実装方法を紹介します。

シンプルな例

import requests

# 使用 APIYI 统一接口
url = "https://api.apiyi.com/v1/videos"
headers = {"Authorization": "Bearer YOUR_API_KEY"}

# 准备 multipart 数据
files = {
    "input_reference": ("sample.jpeg", open("sample_720p.jpeg", "rb"), "image/jpeg")
}
data = {
    "prompt": "She turns around and smiles, then slowly walks out of the frame.",
    "model": "sora-2-pro",
    "size": "1280x720",
    "seconds": "8"
}

response = requests.post(url, headers=headers, data=data, files=files)
print(response.json())
完全なコードを表示(エラー処理とポーリングを含む)
import requests
import time
import os

class Sora2Client:
    """Sora 2 API 客户端 - 支持 multipart/form-data 文件上传"""

    def __init__(self, api_key: str, base_url: str = "https://api.apiyi.com/v1"):
        self.api_key = api_key
        self.base_url = base_url
        self.headers = {"Authorization": f"Bearer {api_key}"}

    def create_video(
        self,
        prompt: str,
        model: str = "sora-2",
        size: str = "1280x720",
        seconds: int = 8,
        input_reference: str = None
    ) -> dict:
        """
        创建视频生成任务

        Args:
            prompt: 视频描述
            model: 模型选择 (sora-2 或 sora-2-pro)
            size: 分辨率
            seconds: 时长 (4, 8, 12)
            input_reference: 参考图片路径 (可选)

        Returns:
            任务信息字典
        """
        url = f"{self.base_url}/videos"

        data = {
            "prompt": prompt,
            "model": model,
            "size": size,
            "seconds": str(seconds)
        }

        files = None
        if input_reference and os.path.exists(input_reference):
            # 根据文件扩展名确定 MIME 类型
            ext = os.path.splitext(input_reference)[1].lower()
            mime_types = {
                ".jpg": "image/jpeg",
                ".jpeg": "image/jpeg",
                ".png": "image/png",
                ".webp": "image/webp"
            }
            mime_type = mime_types.get(ext, "application/octet-stream")

            files = {
                "input_reference": (
                    os.path.basename(input_reference),
                    open(input_reference, "rb"),
                    mime_type
                )
            }

        try:
            response = requests.post(
                url,
                headers=self.headers,
                data=data,
                files=files,
                timeout=30
            )
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            return {"error": str(e)}
        finally:
            if files and "input_reference" in files:
                files["input_reference"][1].close()

    def get_video_status(self, video_id: str) -> dict:
        """查询视频生成状态"""
        url = f"{self.base_url}/videos/{video_id}"
        response = requests.get(url, headers=self.headers, timeout=30)
        return response.json()

    def wait_for_completion(self, video_id: str, poll_interval: int = 10) -> dict:
        """轮询等待视频生成完成"""
        while True:
            status = self.get_video_status(video_id)
            if status.get("status") in ["completed", "failed"]:
                return status
            print(f"Status: {status.get('status')}... waiting {poll_interval}s")
            time.sleep(poll_interval)


# 使用示例
if __name__ == "__main__":
    client = Sora2Client(api_key=os.getenv("APIYI_KEY"))

    # 创建图生视频任务
    result = client.create_video(
        prompt="She turns around and smiles, then slowly walks out of the frame.",
        model="sora-2-pro",
        size="1280x720",
        seconds=8,
        input_reference="sample_720p.jpeg"
    )

    if "id" in result:
        print(f"Task created: {result['id']}")
        final_result = client.wait_for_completion(result["id"])
        print(f"Video URL: {final_result.get('video_url')}")
    else:
        print(f"Error: {result}")

アドバイス: APIYI(apiyi.com)で無料テストクレジットを取得し、画像から動画を作成する機能を素早く検証することをお勧めします。

requests ライブラリでの multipart 処理

Python の requests ライブラリで multipart/form-data を処理する際のポイントは以下の通りです。

パラメータ 用途 説明
data 通常のフォームフィールド 辞書形式: {"key": "value"}
files ファイルフィールド タプル形式: {"name": (filename, file_obj, content_type)}

⚠️ 注意: data パラメータと files パラメータを同時に使用する場合、requests が自動的に適切な Content-Type と boundary を設定するため、手動で指定する必要はありません。


JavaScript/Node.js による実装方法

ブラウザ環境 (FormData API)

const formData = new FormData();
formData.append('prompt', 'She turns around and smiles');
formData.append('model', 'sora-2-pro');
formData.append('size', '1280x720');
formData.append('seconds', '8');
formData.append('input_reference', fileInput.files[0]);

fetch('https://api.apiyi.com/v1/videos', {
    method: 'POST',
    headers: {
        'Authorization': 'Bearer YOUR_API_KEY'
        // 注意: 不要手动设置 Content-Type
    },
    body: formData
})
.then(response => response.json())
.then(data => console.log(data));

Node.js 環境

const FormData = require('form-data');
const fs = require('fs');
const axios = require('axios');

const form = new FormData();
form.append('prompt', 'She turns around and smiles');
form.append('model', 'sora-2-pro');
form.append('size', '1280x720');
form.append('seconds', '8');
form.append('input_reference', fs.createReadStream('sample_720p.jpeg'), {
    contentType: 'image/jpeg'
});

axios.post('https://api.apiyi.com/v1/videos', form, {
    headers: {
        ...form.getHeaders(),
        'Authorization': 'Bearer YOUR_API_KEY'
    }
})
.then(response => console.log(response.data));

💡 重要なヒント: ブラウザで FormData を使用する場合、Content-Type ヘッダーを手動で設定しないでください。ブラウザが自動的に適切な boundary パラメータを追加します。


multipart/form-data よくある問題のトラブルシューティング

アップロード失敗の主な原因

問題 症状 解決策
boundary の欠落 サーバーが 400 を返す Content-Type を手動で設定せず、ツールに自動生成させる
MIME タイプの誤り ファイルが拒否される ;type=image/jpeg を使用して明示的に指定する
ファイルパスの誤り ファイルが見つからない @ 以降のパスが正しいことを確認する(相対パス/絶対パスに対応)
解像度の不一致 Sora API エラー 画像の解像度は size パラメータと一致する必要がある
ファイルサイズが大きすぎる タイムアウトまたは拒否 画像を圧縮するか、チャンク(分割)アップロードを行う

デバッグのコツ

curl の -v パラメータを使用して、リクエスト全体を確認します。

curl -v -F "[email protected]" https://api.example.com/upload

これにより、以下が表示されます:

  • リクエストヘッダー(自動生成された Content-Type と boundary を含む)
  • リクエストボディの構造
  • サーバーのレスポンス

よくある質問

Q1: multipart/form-data と Base64 エンコード、どちらが良いですか?

multipart/form-data はファイルアップロードに適しています。Base64 エンコードはファイルサイズを約 33% 増加させ、ネットワーク転送時間やサーバーの処理負荷を増大させます。multipart/form-data はバイナリデータを直接転送するため、より効率的です。

ただし、特定のシナリオ(WebSocket や単一フィールドの JSON API など)では、Base64 が唯一の選択肢となる場合があります。APIYI apiyi.com プラットフォームを通じて API を呼び出す際は、multipart/form-data 方式を優先的に使用することで、より優れたパフォーマンスを体験できます。

Q2: なぜ私の curl -F アップロードは失敗するのですか?

主な原因は以下の通りです:

  1. ファイルパスの問題: @ 記号の後に正しいファイルパスが続いているか確認してください。
  2. 権限の問題: ファイルの読み取り権限を確認してください。
  3. MIME タイプ: 一部の API では、正しい content-type の指定が求められます。

まずは APIYI apiyi.com でテスト環境を利用してリクエスト形式を検証することをお勧めします。プラットフォームは詳細なエラー情報を提供し、問題の迅速な特定をサポートします。

Q3: Sora 2 API はどの画像フォーマットをサポートしていますか?

Sora 2 API は、input_reference 用に以下の画像フォーマットをサポートしています:

  • JPEG (.jpg, .jpeg) – 推奨、圧縮率が良い
  • PNG (.png) – 透過チャンネルをサポート
  • WebP (.webp) – モダンな形式、サイズが小さい

画像の解像度はターゲットビデオの size パラメータと一致する必要があります。例えば 1280x720 の解像度を使用する場合、参照画像も 1280×720 である必要があります。

Q4: 如何処理大容量ファイルのアップロード?

大容量ファイルのアップロードについては、以下を検討してください:

  1. チャンクアップロード: ファイルを小さなブロックに分割して順番にアップロードします。
  2. 圧縮の最適化: 品質を維持しつつファイルを圧縮します。
  3. レジューム機能(断点続伝): アップロード失敗後に中断した箇所から再開できるようにします。

multipart/form-data はストリーミング転送をサポートしており、サーバーは受信しながら処理できるため、大容量ファイルのシナリオに適しています。


まとめ

本記事では、APIファイルアップロードのコア技術である multipart/form-data について詳しく解説しました。

重要なポイントの振り返り:

要点 説明
エンコードの仕組み boundary(境界線)でマルチパートデータを区切り、各パートが独立した Content-Type を持ちます。
curl -F コマンド -F "key=value" でテキストを送信、-F "key=@file" でファイルをアップロードします。
Sora 2 の実践 input_reference パラメータで参照画像をアップロードします。解像度を合わせる必要があります。
多言語での実装 Python requests / JavaScript FormData
デバッグのテクニック curl -v を使用してリクエストの全容を確認します。

multipart/form-data をマスターすることは、AI API 開発における基礎的なスキルです。Sora 2 の動画生成、GPT-4 Vision の画像理解、あるいはその他のファイルアップロードを必要とする API であっても、その核心となる仕組みは共通しています。

APIYI (apiyi.com) を通じてファイルアップロード機能を素早く検証し、統一された API インターフェースと詳細なテクニカルサポートをぜひ体験してください。


著者: APIYI Team | 大規模言語モデル API の技術共有に特化
技術交流: apiyi.com にアクセスして、より多くの API 開発リソースを入手してください。

参考文献

  1. RFC 2388: multipart/form-data の標準仕様

    • リンク: tools.ietf.org/html/rfc2388
  2. curl 公式ドキュメント: Multipart Formposts

    • リンク: everything.curl.dev/http/post/multipart
  3. MDN Web Docs: FormData オブジェクトの使用

    • リンク: developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects
  4. OpenAI Sora API ドキュメント: Video Generation Guide

    • リンク: platform.openai.com/docs/guides/video-generation

類似投稿