再開可能なアップロード

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/*)または application/octet-stream の MIME タイプのファイルをアップロードできます。

次の例は、動画のアップロードを再開可能なセッションを開始する方法を示しています。このリクエストは 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 サーバーは 200OK)HTTP ステータス コードを返します。レスポンスには、再開可能セッションの 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 201Created)レスポンス コードを返します。レスポンスの本文は、作成した video リソースです。

  • アップロードは成功しませんでしたが、再開できます。

    次のいずれかのケースでは、アップロードは再開可能です。

    • アプリケーションと API サーバーの間の接続が失われたためにリクエストが中断した場合。このケースでは API レスポンスを受け取りません。

    • API レスポンスでは、次のいずれかの 5xx レスポンス コードを指定します。これらのレスポンス コードのいずれかを受け取った後にアップロードを再開する場合は、コードで指数バックオフ戦略を使用する必要があります。

      • 500Internal Server Error
      • 502Bad Gateway
      • 503Service Unavailable
      • 504Gateway 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 308Resume 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.2Range ヘッダーの説明をご覧ください)。

    したがって、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 2,048)を送信していることを示します。

下記は、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 サーバーは 308Resume Incomplete)レスポンスを返します。レスポンスの形式は、上記のステップ 4.2: API レスポンスを処理するで説明したものと同じです。

API レスポンスの Range ヘッダーで返された上限値を使用して、次のチャンクの開始位置を決定します。ステップ 4.3: アップロードを再開するで説明されているように、引き続き PUT リクエストを送信して、ファイル全体のアップロードが完了するまで後続のファイル チャンクをアップロードします。

ファイル全体がアップロードされると、サーバーは 201 HTTP レスポンス コード(Created)で応答し、新しく作成された動画リソースのリクエストされた部分を返します。

リクエストが中断された場合や、アプリケーションで 5xx レスポンス コードを受信した場合は、ステップ 4 の手順に沿ってアップロードを完了してください。ただし、残りのファイルをアップロードするのではなく、アップロードを再開するポイントからチャンクのアップロードを続けます。ファイル アップロードをどこから再開するかを判別するには、必ずアップロード ステータスを確認してください。前のリクエストで送信されたバイトがすべてサーバーに受信された(あるいはまったく受信されていない)と仮定することはできません。

注: アップロードされたチャンクの間にアクティブ アップロードのステータスをリクエストすることもできます(ステータスを取得する前にアップロードを中断する必要はありません)。