Возобновляемые загрузки

Вы можете загружать видео более надежно, используя протокол возобновляемой загрузки для API Google. Этот протокол позволяет возобновить операцию загрузки после прерывания сети или другого сбоя передачи, экономя время и пропускную способность в случае сетевых сбоев.

Использование возобновляемых загрузок особенно полезно в любом из следующих случаев:

  • Вы передаете большие файлы.
  • Вероятность прерывания сети высока.
  • Загрузки происходят с устройства с низкой пропускной способностью или нестабильным подключением к Интернету, например с мобильного устройства.

В этом руководстве объясняется последовательность HTTP-запросов, которые приложение делает для загрузки видео с помощью возобновляемого процесса загрузки. Это руководство в первую очередь предназначено для разработчиков, которые не могут использовать клиентские библиотеки Google API , некоторые из которых обеспечивают встроенную поддержку возобновляемой загрузки. На самом деле, YouTube Data API — Руководство по загрузке видео объясняет, как использовать клиентскую библиотеку API Google для Python для загрузки видео с помощью возобновляемого процесса загрузки.

Примечание. Вы также можете просмотреть серию запросов на возобновляемую загрузку или любую другую операцию API, используя одну из клиентских библиотек API Google с включенным ведением журнала HTTPS. Например, чтобы включить трассировку HTTP для Python, используйте библиотеку httplib2 :

httplib2.debuglevel = 4

Шаг 1. Начните возобновляемый сеанс

Чтобы начать возобновляемую загрузку видео, отправьте запрос POST на следующий URL. В 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 .

в следующем примере показано, как инициировать возобновляемый сеанс для загрузки видео. запрос устанавливает (и будет извлекать) свойства в частях snippet и status video , а также извлекает свойства в части 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 ), а ответ будет включать HTTP-заголовок Location , который указывает URI для возобновляемого сеанса. Это URI, который вы будете использовать для загрузки видеофайла.

В приведенном ниже примере показан образец ответа API на запрос на шаге 1:

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 - Загрузите видеофайл

После извлечения URI сеанса из ответа API вам необходимо загрузить фактическое содержимое видеофайла в это место. Тело запроса представляет собой содержимое двоичного файла загружаемого видео. Пример ниже показывает формат запроса.

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 — размер загружаемого файла. Это значение должно совпадать со значением заголовка HTTP-запроса X-Upload-Content-Length на шаге 1.
  • Content-Type — тип MIME загружаемого файла. Это значение должно совпадать со значением заголовка HTTP-запроса X-Upload-Content-Type на шаге 1.

Шаг 4 - Завершите процесс загрузки

Ваш запрос приведет к одному из следующих сценариев:

  • Ваша загрузка прошла успешно.

    Сервер API отвечает кодом ответа HTTP 201 ( Created ). Тело ответа — это созданный вами video .

  • Ваша загрузка не удалась, но ее можно возобновить.

    Вы сможете возобновить загрузку в одном из следующих случаев:

    • Ваш запрос прерван, так как связь между вашим приложением и сервером API потеряна. В этом случае вы не получите ответ API.

    • В ответе API указан любой из следующих кодов ответа 5xx . Ваш код должен использовать экспоненциальную стратегию отсрочки при возобновлении загрузки после получения любого из этих кодов ответа.

      • 500Internal Server Error
      • 502Bad Gateway
      • 503Service Unavailable
      • 504Gateway Timeout

    Чтобы возобновить загрузку, следуйте приведенным ниже инструкциям по проверке статуса загрузки и возобновлению загрузки . Помните, что каждый URI возобновляемого сеанса имеет конечное время жизни и в конечном итоге истекает. По этой причине мы рекомендуем начать возобновляемую загрузку, как только вы получите URI сеанса, и возобновить прерванную загрузку вскоре после прерывания.

  • Ваша загрузка не удалась навсегда.

    В случае неудачной загрузки ответ содержит сообщение об ошибке , которое помогает объяснить причину сбоя. Если загрузка завершается с ошибкой, ответ API будет иметь код ответа 4xx или код ответа 5xx , отличный от перечисленных выше.

    Если вы отправляете запрос с URI сеанса с истекшим сроком действия, сервер возвращает код ответа HTTP 404 ( Not Found ). В этом случае вам нужно будет начать новую возобновляемую загрузку, получить новый URI сеанса и начать загрузку с самого начала, используя новый URI.

Шаг 4.1. Проверьте статус загрузки

Чтобы проверить состояние прерванной возобновляемой загрузки, отправьте пустой запрос PUT на URL-адрес загрузки, который вы получили на шаге 2, а также использовали на шаге 3. В своем запросе установите значение заголовка 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. Возобновите загрузку

Чтобы возобновить загрузку, отправьте еще один запрос PUT на URL-адрес загрузки, полученный на шаге 2. В теле запроса укажите двоичный код части видеофайла, которая еще не была загружена.

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 — размер в байтах контента, который еще не был загружен. Если вы загружаете оставшуюся часть файла, вы можете рассчитать это значение, вычитая значение FIRST_BYTE из значения TOTAL_CONTENT_LENGTH . Оба значения используются в заголовке Content-Range .

  • Content-Range — часть загружаемого файла. Значение заголовка состоит из трех значений:

    • FIRST_BYTE — числовой индекс номера байта, отсчитываемый от 0, с которого вы возобновляете загрузку. Это значение на одно число больше, чем второе число в заголовке Range , полученном на предыдущем шаге. В предыдущем примере значение заголовка Range было 0-999999 , поэтому первый байт в последующей возобновленной загрузке будет 1000000 .

    • LAST_BYTE — числовой индекс последнего байта загружаемого двоичного файла, начинающийся с 0. Обычно это последний байт в файле. Так, например, если размер файла был 3000000 байт, последним байтом в файле будет номер 2999999 .

    • TOTAL_CONTENT_LENGTH — общий размер видеофайла в байтах. Это значение совпадает с заголовком Content-Length , указанным в исходном запросе на загрузку .

    Примечание. Вы не можете загрузить непрерывный блок двоичного файла. Если вы попытаетесь загрузить непрерывный блок, оставшийся двоичный контент не будет загружен.

    Таким образом, первый байт, загружаемый при возобновленной загрузке, должен быть следующим байтом после последнего байта, который уже был успешно загружен на YouTube. (См. обсуждение заголовка Range на шаге 4.2 .

    Таким образом, если последний байт в заголовке Range равен 999999 , первым байтом в запросе на возобновление загрузки должен быть байт 1000000. (Оба числа используют индекс, начинающийся с 0.) Если вы попытаетесь возобновить загрузку с байта 999999 или меньше (перекрывающиеся байты) или байт 1000001 или выше (пропуская байты), ни одно двоичное содержимое не будет загружено.

Загрузить файл частями

Вместо того, чтобы пытаться загрузить файл целиком и возобновить загрузку в случае сбоя в сети, ваше приложение может разбить файл на фрагменты и отправить серию запросов на последовательную загрузку фрагментов. Этот подход редко бывает необходим и на самом деле не рекомендуется, поскольку он требует дополнительных запросов, которые влияют на производительность. Однако это может быть полезно, если вы пытаетесь отобразить индикатор выполнения в очень нестабильной сети.

Инструкции по загрузке файла фрагментами практически идентичны четырехэтапному процессу, описанному ранее в этом руководстве. Однако запросы на начало загрузки файла (шаг 3 выше) и на возобновление загрузки (шаг 4.3 выше) задают значения заголовков Content-Length и Content-Range по-разному, когда файл загружается фрагментами.

  • Значение заголовка Content-Length указывает размер фрагмента, отправляемого запросом. Обратите внимание на следующие ограничения на размеры фрагментов:

    • Размер фрагмента должен быть кратен 256 КБ. (Это ограничение не распространяется на последний фрагмент, поскольку размер всего файла не может быть кратным 256 КБ.) Помните, что более крупные фрагменты более эффективны.

    • Размер фрагмента должен быть одинаковым для каждого запроса в последовательности загрузки, за исключением последнего запроса, который определяет размер последнего фрагмента.

  • Заголовок Content-Range указывает количество байтов в файле, который загружает запрос. Инструкции по настройке заголовка Content-Range на шаге 4.3 применимы при установке этого значения.

    Например, значение bytes 0-524287/2000000 показывает, что запрос отправляет первые 524 288 байт (256 x 2048) в файле размером 2 000 000 байт.

В приведенном ниже примере показан формат первого из серии запросов, которые загружают файл размером 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 выше.

Используйте верхнее значение, возвращенное в заголовке Range ответа API, чтобы определить, с чего начать следующий фрагмент. Продолжайте отправлять запросы PUT , как описано в шаге 4.3: Возобновить загрузку , чтобы загружать последующие фрагменты файла, пока не будет загружен весь файл.

Когда весь файл загружен, сервер отвечает кодом ответа HTTP 201 ( Created ) и возвращает запрошенные части вновь созданного видеоресурса.

Если какой-либо запрос прерывается или ваше приложение получает какой-либо код ответа 5xx , выполните процедуру, описанную в шаге 4 , чтобы завершить загрузку. Однако вместо того, чтобы пытаться загрузить остальную часть файла, просто продолжайте загружать фрагменты с того места, где вы возобновляете загрузку. Обязательно используйте проверку статуса загрузки, чтобы определить, где возобновить загрузку файла. Не предполагайте, что сервер получил все (или ни одного) байты, отправленные в предыдущем запросе.

Примечание. Вы также можете запросить статус активной загрузки между загруженными чанками. (Загрузку не нужно прерывать, прежде чем вы сможете получить ее статус.)