Google API 用の再開可能アップロード プロトコルを使用して、動画のアップロードの信頼性を向上させることができます。このプロトコルを使用すると、ネットワークの中断などの通信障害が発生しても後でアップロードの操作を再開することができるので、ネットワーク障害時の時間と帯域幅の節約につながります。
再開可能アップロードが特に有効なケースは次のとおりです。
- 大きなファイルを転送する場合。
- ネットワーク中断の可能性が高い場合。
- 携帯端末などの低帯域幅な端末、またはインターネット接続が不安定な端末からアップロードする場合。
このガイドでは、再開可能アップロード プロセスを使用して動画をアップロードするためにアプリケーションが作成する一連の HTTP リクエストについて説明します。Google APIs Client Library では一部で再開可能アップロードのネイティブ サポートを提供していますが、このガイドは主にライブラリを利用できないデベロッパーを対象としています。実際、YouTube Data API - 動画のアップロードガイドでは、Python 用 Google API クライアント ライブラリを使用して、再開可能なアップロード プロセスで動画をアップロードする方法について説明しています。
注: HTTP ロギングを有効化して Google API Client Library を使用することで、再開可能アップロードなどの API 操作のために作成された一連のリクエストを確認できます。たとえば、Python の HTTP トレースを有効にするには、httplib2
ライブラリを使用します。
httplib2.debuglevel = 4
ステップ 1 - 再開可能セッションを開始する
再開可能な動画アップロードを開始するには、次の URL に POST リクエストを送信します。URL で、part
パラメータ値をリクエストに適した値に設定します。パラメータ値は、設定するプロパティを含む部分を識別します。また、API レスポンスに含める部分も識別します。リクエスト URL のパラメータ値は URL エンコードする必要があります。
https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=PARTS
リクエストの本文を video
リソースに設定します。さらに、次の HTTP リクエスト ヘッダーも設定します。
Authorization
- リクエストの認可トークン。Content-Length
- リクエストの本文で指定されたバイト数。チャンク形式転送エンコードを使用している場合は、このヘッダーを指定する必要はありません。Content-Type
- 値をapplication/json; charset=UTF-8
に設定します。X-Upload-Content-Length
- 後続のリクエストでアップロードされるバイト数。値として、アップロードするファイルのサイズを設定します。x-upload-content-type
- アップロードするファイルの MIME タイプ。動画の MIME タイプ(video/*
)または MIME タイプapplication/octet-stream
のファイルをアップロードできます。
次の例は、動画のアップロードに再開可能なセッションを開始する方法を示しています。このリクエストは、video
リソースの snippet
部分と status
部分のプロパティを設定し(取得します)、リソースの contentdetails
部分のプロパティも取得します。
post /upload/youtube/v3/videos?uploadType=resumable&part=parts http/1.1 host: www.googleapis.com authorization: bearer auth_token content-length: content_length content-type: application/json; charset=utf-8 x-upload-content-length: x_upload_content_length X-Upload-Content-Type: X_UPLOAD_CONTENT_TYPE video resource
次の例は、認証トークンを除くすべての値が入力された POST リクエストを示しています。例の categoryId
値は動画カテゴリに対応しています。サポートされているカテゴリのリストは、API の videoCategories.list
メソッドを使用して取得できます。
POST /upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails HTTP/1.1 Host: www.googleapis.com Authorization: Bearer AUTH_TOKEN Content-Length: 278 Content-Type: application/json; charset=UTF-8 X-Upload-Content-Length: 3000000 X-Upload-Content-Type: video/* { "snippet": { "title": "My video title", "description": "This is a description of my video", "tags": ["cool", "video", "more keywords"], "categoryId": 22 }, "status": { "privacyStatus": "public", "embeddable": True, "license": "youtube" } }
ステップ 2 - 再開可能セッション URI を保存する
リクエストが成功すると、API サーバーは HTTP ステータス コード 200
(OK
)のレスポンスを返します。レスポンスには、再開可能なセッションの URI を指定する Location
HTTP ヘッダーが含まれます。これは動画ファイルのアップロードに使用する URI です。
以下は、ステップ 1 でのリクエストに対する API レスポンスの例です。
HTTP/1.1 200 OK Location: https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&upload_id=xa298sd_f&part=snippet,status,contentDetails Content-Length: 0
手順 3 - 動画ファイルをアップロードする
API レスポンスからセッション URI を抽出したら、その場所に実際の動画ファイルのコンテンツをアップロードする必要があります。リクエストのボディは、アップロードする動画のバイナリ ファイル コンテンツです。以下はリクエストの形式を示す例です。
PUT UPLOAD_URL HTTP/1.1 Authorization: Bearer AUTH_TOKEN Content-Length: CONTENT_LENGTH Content-Type: CONTENT_TYPE BINARY_FILE_DATA
リクエストは、次の HTTP リクエスト ヘッダーを設定します。
Authorization
- リクエストの認可トークン。Content-Length
- アップロードするファイルのサイズ。この値は、ステップ 1 のX-Upload-Content-Length
HTTP リクエスト ヘッダーの値と同じにする必要があります。Content-Type
- アップロードするファイルの MIME タイプ。この値は、ステップ 1 のX-Upload-Content-Type
HTTP リクエスト ヘッダーの値と同じにする必要があります。
ステップ 4 - アップロード プロセスを完了する
リクエストの結果は、次のいずれかのシナリオとなります。
-
アップロードが完了しました。
API サーバーは HTTP
201
(Created
)レスポンス コードで応答します。レスポンスの本文は、作成したvideo
リソースです。 -
アップロードは完了しなかったが、再開できる。
次のいずれかのケースでは、アップロードは再開可能です。
-
アプリケーションと API サーバーの間の接続が失われたためにリクエストが中断した場合。このケースでは API レスポンスを受け取りません。
-
API レスポンスには、次のいずれかの
5xx
レスポンス コードが指定されます。これらのレスポンス コードを受け取った後にアップロードを再開する場合は、コードで指数バックオフ戦略を使用する必要があります。500
~Internal Server Error
502
~Bad Gateway
503
~Service Unavailable
504
~Gateway Timeout
アップロードを再開するには、下記のアップロード ステータスを確認するとアップロードを再開するの説明をご覧ください。再開可能セッション URI の存続期間は有限で、最終的には期限切れとなります。このため、セッション URI を取得したら即座に再開可能アップロードを開始し、中断が発生したら速やかにアップロードを再開することをおすすめします。
-
-
アップロードが完全に失敗しました。
アップロードが失敗すると、レスポンスには失敗の原因を説明するエラー レスポンスが含まれます。アップロードが恒久的に失敗した場合、API レスポンスには、上記以外の
4xx
レスポンス コードまたは5xx
レスポンス コードが含まれます。有効期限が切れたセッション URI を使用してリクエストを送信すると、サーバーから
404
HTTP レスポンス コード(Not Found
)が返されます。この場合は、再開可能な新しいアップロードを開始して新しいセッション URI を取得し、新しい URI を使用してアップロードを最初からやり直す必要があります。
ステップ 4.1: アップロード ステータスを確認する
中断された再開可能なアップロードのステータスを確認するには、手順 2 で取得し、手順 3 でも使用したアップロード URL に空の PUT リクエストを送信します。リクエストで、Content-Range
ヘッダーの値を bytes */CONTENT_LENGTH
に設定します。ここで、CONTENT_LENGTH はアップロードするファイルのサイズです。
PUT UPLOAD_URL HTTP/1.1 Authorization: Bearer AUTH_TOKEN Content-Length: 0 Content-Range: bytes */CONTENT_LENGTH
ステップ 4.2: API レスポンスを処理する
アップロードが既に完了している場合、成功したか失敗したかにかかわらず、API はアップロードが最初に完了したときに送信したものと同じレスポンスを返します。
ただし、アップロードが中断された場合や、まだ進行中の場合は、API レスポンスに HTTP 308
(Resume Incomplete
)レスポンス コードが含まれます。レスポンスの Range
ヘッダーには、すでに正常にアップロードされたファイルのバイト数を指定します。
- このヘッダー値は
0
から始まります。たとえば、ヘッダー値が0-999999
の場合、ファイルの先頭から1,000,000
バイトがアップロードされたことを示します。 - まだ何もアップロードされていない場合、API レスポンスには
Range
ヘッダーが含まれません。
以下は、再開可能アップロードでの API レスポンスの形式を示すサンプル レスポンスです。
308 Resume Incomplete Content-Length: 0 Range: bytes=0-999999
API レスポンスに Retry-After
ヘッダーも含まれている場合は、そのヘッダーの値を使用して、アップロードを再開するタイミングを決定します。
ステップ 4.3: アップロードを再開する
アップロードを再開するには、ステップ 2 で取得されたアップロード URL にもう一度 PUT
リクエストを送ります。リクエスト ボディには、動画ファイル中のアップロード未完了部分のバイナリ コードを設定します。
PUT UPLOAD_URL HTTP/1.1 Authorization: Bearer AUTH_TOKEN Content-Length: REMAINING_CONTENT_LENGTH Content-Range: bytes FIRST_BYTE-LAST_BYTE/TOTAL_CONTENT_LENGTH PARTIAL_BINARY_FILE_DATA
設定する必要がある HTTP リクエスト ヘッダーは次のとおりです。
-
Authorization
- リクエストの認可トークン。 -
Content-Length
- まだアップロードされていないコンテンツのサイズ(バイト単位)。ファイルの残りの部分をアップロードする場合は、TOTAL_CONTENT_LENGTH
値からFIRST_BYTE
値を減算してこの値を計算できます。どちらの値もContent-Range
ヘッダーで使用されます。 -
Content-Range
- アップロードするファイルの部分。このヘッダー値は 3 つの値で構成されます。-
FIRST_BYTE
– 何バイト目からアップロードを再開するかを示す数値的指標(0 から開始)。この値は、前の手順で取得したRange
ヘッダーの 2 番目の数値より 1 大きい値です。上の例では、Range
ヘッダーの値は0-999999
であるため、その後の再開されたアップロードの最初のバイトは1000000
になります。 -
LAST_BYTE
– アップロードするバイナリ ファイルが何バイト目で終わるかを示す数値的指標(0 から開始)。通常、これはファイル内の最後のバイトです。 たとえば、ファイルサイズが3000000
バイトの場合、ファイル内の最後のバイトは2999999
になります。 -
TOTAL_CONTENT_LENGTH
– 動画ファイルの合計サイズ(バイト単位)。この値は、元のアップロード リクエストで指定されたContent-Length
ヘッダーと同じです。
注: 不連続なバイナリ ファイル ブロックをアップロードすることはできません。不連続なブロックをアップロードしようとすると、残りのバイナリ コンテンツは一切アップロードされません。
そのため、再開したアップロードでアップロードされる最初のバイトは、YouTube に正常にアップロードされた最後のバイトの次のバイトである必要があります。(ステップ 4.2 のRange
ヘッダーの説明をご覧ください)。
したがって、Range
ヘッダーの最後のバイトが999999
の場合、アップロードを再開するリクエストの最初のバイトはバイト 1000000 にする必要があります。(いずれの数値も 0 からカウントされます)。バイト 999999 以下(バイトが重複)またはバイト 1000001 以上(バイトがスキップされる)からアップロードを再開しようとすると、バイナリ コンテンツはアップロードされません。 -
チャンクでファイルをアップロードする
ファイル全体をアップロードしてネットワークが中断した場合にアップロードを再開するのではなく、アプリケーションでファイルをチャンクに分割し、一連のリクエストを送信してチャンクを順番にアップロードすることもできます。この方法が必要になることはほとんどありません。また、多くのリクエストが必要でパフォーマンスに影響を与えるため、実際にはおすすめできません。ただし、非常に不安定なネットワーク上で進捗状況を示す指標を見ようとしている場合には役立ちます。
ファイルをチャンクでアップロードする方法についての説明は、上記の 4 つのステップとほぼ同じです。ただし、ファイルのアップロードを開始するリクエスト(上記のステップ 3)とアップロードを再開するリクエスト(上記のステップ 4.3)の両方で、ファイルがチャンクでアップロードされている場合、Content-Length
ヘッダー値と Content-Range
ヘッダー値が異なります。
-
Content-Length
ヘッダー値は、リクエストが送信するチャンクのサイズを指定します。チャンク サイズに関する次の制限に注意してください。-
チャンクサイズは 256 KB の倍数にする必要があります。(ファイル全体のサイズが 256 KB の倍数でない場合があるため、この制限は最後のチャンクには適用されません)。チャンクのサイズは大きいほど効率的です。
-
アップロード シーケンスのすべてのリクエストのチャンク サイズは等しくなければなりません。ただし、最後のチャンクのサイズを指定する最後のリクエストについては例外です。
-
-
Content-Range
ヘッダーには、リクエストでアップロードするファイルのバイト数を指定します。この値を設定する際は、ステップ 4.3 のContent-Range
ヘッダーを設定する手順が適用されます。たとえば、値が
bytes 0-524287/2000000
の場合、リクエストは 2,000,000 バイトのファイルの先頭 524,288 バイト(256 x 2048)を送信します。
下記は、2,000,000 バイトのファイルをチャンクでアップロードする一連のリクエストの中の最初のリクエストの形式を示す例です。
PUT UPLOAD_URL HTTP/1.1 Authorization: Bearer AUTH_TOKEN Content-Length: 524888 Content-Type: video/* Content-Range: bytes 0-524287/2000000 {bytes 0-524287}
最後のリクエスト以外のリクエストが成功すると、API サーバーは 308
(Resume Incomplete
)レスポンスを返します。レスポンスの形式は、上記のステップ 4.2: API レスポンスを処理するで説明したものと同じです。
API レスポンスの Range
ヘッダーで返された上限値を使用して、次のチャンクの開始位置を決定します。ステップ 4.3: アップロードを再開するで説明されているように、PUT
リクエストを送信し続け、ファイル全体がアップロードされるまで後続のファイル チャンクをアップロードします。
ファイル全体がアップロードされると、サーバーは 201
HTTP レスポンス コード(Created
)で応答し、新しく作成された動画リソースの要求された部分を返します。
リクエストが中断された場合や、アプリが 5xx
レスポンス コードを受信した場合は、ステップ 4 の手順に沿ってアップロードを完了します。ただし、残りのファイルをアップロードするのではなく、アップロードを再開するポイントからチャンクのアップロードを続けます。ファイル アップロードをどこから再開するかを判別するには、必ずアップロード ステータスを確認してください。前のリクエストで送信されたバイトがすべてサーバーに受信された(あるいはまったく受信されていない)と仮定することはできません。
注: アップロードされたチャンクの間にアクティブ アップロードのステータスをリクエストすることもできます(ステータスを取得する前にアップロードを中断する必要はありません)。