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

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

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

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

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

Примечание. Вы также можете просмотреть серию запросов на возобновление загрузки или любую другую операцию API, используя одну из клиентских библиотек Google API с включенным ведением журнала 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 в примере соответствует категории видео. Список поддерживаемых категорий можно получить с помощью метода videoCategories.list API.

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
      • 502 Bad 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 .

    Таким образом, если последний байт в заголовке Range999999 , первый байт в запросе на возобновление загрузки должен быть байтом 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, чтобы завершить загрузку. Однако вместо того, чтобы пытаться загрузить остальную часть файла, просто продолжайте загрузку фрагментов с того места, где вы возобновляете загрузку. Обязательно используйте проверку статуса загрузки, чтобы определить, где возобновить загрузку файла. Не предполагайте, что сервер получил все (или ни одного) байты, отправленные в предыдущем запросе.

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