Cargas reanudables

Utilizando el protocolo de carga reanudable para las API de Google, puedes subir videos de forma más segura. Este protocolo permite reanudar una operación de carga después de una interrupción de la red u otra falla de transmisión, ahorrando tiempo y ancho de banda en caso de fallas de la red.

El uso de cargas reanudables es especialmente útil en los siguientes casos:

  • Al transferir archivos grandes.
  • Si hay una alta probabilidad de interrupción de la red.
  • Si las cargas se originan desde un dispositivo con poco ancho de banda o con una conexión a Internet inestable, como un dispositivo móvil.

Esta guía explica la secuencia de solicitudes HTTP que hace una aplicación para subir videos mediante un proceso de carga reanudable. Esta guía está destinada principalmente para programadores que no pueden utilizar las bibliotecas cliente de la API de Google, algunas de las cuales proporcionan asistencia nativa para las cargas reanudables. La guía API de datos de YouTube: Cómo subir un video explica cómo utilizar la biblioteca cliente de la API de Google para Python para subir un video con un proceso de carga reanudable.

Nota: También puedes ver la serie de solicitudes que se hacen para la carga reanudable o cualquier otra operación de la API utilizando una de las bibliotecas cliente de la API de Google con acceso HTTPS activado. Por ejemplo, puedes usar la biblioteca httplib2 para activar el rastreo HTTP para Python:

httplib2.debuglevel = 4

Paso 1 - Iniciar una sesión reanudable

Para iniciar una subida de video reanudable, envía una solicitud POST a la siguiente URL. En la dirección URL, establezca el valor del parámetro part en el valor adecuado para su solicitud. Recuerde que el valor del parámetro identifica las partes que contienen propiedades que está configurando. También identifica las partes que desea la respuesta del API a incude. Los valores de parámetros en la URL deben estar codificado como dirección URL.

https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=PARTS

Ajusta el cuerpo de la solicitud a un recurso de video. También debes definir los siguientes encabezados de la solicitud HTTP:

  • Authorization – El token de autorización de la solicitud.
  • Content-Length – La cantidad de bytes que se proporcionan en el cuerpo de la solicitud. Ten en cuenta que no es necesario proporcionar este encabezado si utilizas la codificación de transferencia en bloques.
  • Content-Type – Establece el valor en application/json; charset=UTF-8.
  • X-Upload-Content-Length – La cantidad de bytes que se cargarán en las siguientes solicitudes. Establece este valor para que coincida con el tamaño del archivo que deseas subir.
  • x-upload-content-type – El tipo MIME del archivo que estás subiendo. Puedes cargar archivos con cualquier tipo MIME de video (video/*) o con un tipo MIME de application/octet-stream.

El siguiente ejemplo muestra cómo iniciar una sesión reanudable para subir un video. La solicitud establece (y recupera) las propiedades de las partes snippet y status del recurso de video y también recupera las propiedades de la parte contentDetails del recurso.

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

El siguiente ejemplo muestra una solicitud POST en la que se han completado todos estos valores, excepto el token de autenticación. El valor categoryId de este ejemplo corresponde a una categoría de video. La lista de categorías admitidas se puede recuperar con el método videoCategories.list de la 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"
  }
}

Paso 2 - Guardar el URI de la sesión reanudable

Si la solicitud se realiza correctamente, el servidor de la API responde con un código de estado HTTP 200 (OK). La respuesta incluye un encabezado HTTP Location que especifica el URI de la sesión reanudable. Este es el URI que se utiliza para subir el archivo de video.

El siguiente ejemplo muestra una respuesta de la API a la solicitud del paso 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

Paso 3 - Subir el archivo de video

Después de extraer el URI de la sesión de la respuesta de la API, debes subir el contenido del archivo de video en cuestión a esta ubicación. El cuerpo de la solicitud es el contenido de archivo binario del video que deseas subir. El siguiente ejemplo muestra el formato de la solicitud.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: CONTENT_LENGTH
Content-Type: CONTENT_TYPE

BINARY_FILE_DATA

La solicitud establece los siguientes encabezados de la solicitud HTTP:

  • Authorization – El token de autorización de la solicitud.
  • Content-Length – El tamaño del archivo que deseas cargar. Este valor debe ser igual al del encabezado de la solicitud HTTP X-Upload-Content-Length del paso 1.
  • Content-Type – El tipo MIME del archivo que deseas cargar. Este valor debe ser igual al del encabezado de la solicitud HTTP X-Upload-Content-Type del paso 1.

Paso 4 - Completar el proceso de carga

La solicitud puede conducir a uno de los siguientes escenarios:

  • La carga se realiza correctamente.

    El servidor de la API genera un código de respuesta HTTP 201 (Created). El cuerpo de la respuesta es el recurso de video que se creó.

  • La carga no se realiza correctamente, pero se puede reanudar.

    Deberías poder reanudar la carga en uno de los siguientes casos:

    • La solicitud se interrumpió debido a que se perdió la conexión entre la aplicación y el servidor de la API. En este caso, no recibirás una respuesta de la API.

    • La respuesta de la API especifica uno de los siguientes códigos de respuesta 5xx. El código debe utilizar una estrategia de retirada exponencial al reanudar las cargas después de recibir cualquiera de estos códigos de respuesta.

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

    Para reanudar una carga, sigue las instrucciones que aparecen a continuación para comprobar el estado de la carga y reanudar una carga. Recuerda que cada URI de sesión tiene una duración limitada y expirará en algún momento. Por esta razón, te recomendamos empezar una carga reanudable en cuanto obtengas el URI de la sesión y reanudar una carga interrumpida poco después de que se produzca la interrupción.

  • La carga falla en forma permanente.

    Para una carga que falla, la respuesta contiene una respuesta de error que ayuda a explicar la causa de la falla. Para una carga que falla en forma permanente, la respuesta de la API incluye un código de respuesta 4xx o un código de respuesta 5xx distinto de los que se detallaron previamente.

    Si envías una solicitud con un URI de sesión caducada, el servidor muestra un código de respuesta HTTP 404 (Not Found). En este caso, se debe iniciar una nueva carga reanudable, obtener un nuevo URI de sesión y comenzar la carga desde el principio con el nuevo URI.

Paso 4.1: Comprobar el estado de una carga

Para comprobar el estado de una carga reanudable interrumpida, envía una solicitud PUT vacía a la URL de carga que recuperaste en el paso 2 y que también se usa en el paso 3. En la solicitud, establece el valor del encabezado Content-Range en bytes */CONTENT_LENGTH, donde CONTENT_LENGTH es el tamaño del archivo que deseas cargar.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: 0
Content-Range: bytes */CONTENT_LENGTH

Paso 4.2: Procesar la respuesta de la API

Si la carga ya finalizó, independientemente de si se realizó correctamente o falló, la API muestra la misma respuesta que envió cuando la carga finalizó originalmente.

Sin embargo, si la carga se interrumpió o todavía está en curso, la respuesta de la API tendrá un código de respuesta HTTP 308 (Resume Incomplete). En la respuesta, el encabezado Range detalla cuántos bytes del archivo ya se cargaron correctamente.

  • El valor del encabezado está indexado desde {{{0/}/}/}. Por lo tanto, un valor del encabezado de 0-999999 indica que se cargó el primer 1.000.000 de bytes del archivo.
  • Si todavía no se carga nada, la respuesta de la API no incluirá el encabezado Range.

La respuesta de muestra que aparece a continuación muestra el formato de la respuesta de la API para una carga reanudable:

308 Resume Incomplete
Content-Length: 0
Range: bytes=0-999999

Si la respuesta de la API incluye también el encabezado Retry-After, se debe utilizar el valor del encabezado para determinar cuándo es recomendable intentar reanudar la carga.

Paso 4.3: Reanudar la carga

Para reanudar la carga, envía otra solicitud PUT a la URL de carga que se capturó en el paso 2. Establece el cuerpo de la solicitud en el código binario de la parte del archivo de video que todavía no se ha subido.

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

Debes establecer los siguientes encabezados de la solicitud HTTP:

  • Authorization – El token de autorización de la solicitud.

  • Content-Length – El tamaño, en bytes, del contenido que todavía no se carga. Si vas a cargar la parte restante de un archivo, puedes calcular este valor al restar el valor de FIRST_BYTE del valor de TOTAL_CONTENT_LENGTH. Ambos valores se utilizan en el encabezado de Content-Range.

  • Content-Range – La parte del archivo que deseas subir. El valor del encabezado se compone de tres valores:

    • FIRST_BYTE – El índice numérico con base 0 del número del byte desde el cual se reanuda la carga. Este valor es un número mayor que el segundo número del encabezado Range que se recuperó en el paso anterior. En el ejemplo anterior, el valor del encabezado Range era 0-999999, de modo que el primer byte de la próxima carga que se reanuda sería 1000000.

    • LAST_BYTE – El índice numérico con base 0 del último byte del archivo binario que estás subiendo. Habitualmente, este es el último byte del archivo. De este modo, si el tamaño del archivo fuese de 3000000 bytes, el último byte del archivo sería el número 2999999.

    • TOTAL_CONTENT_LENGTH – El tamaño total del video, en bytes. Este valor es el mismo que el del encabezado Content-Length que se especificó en la solicitud de carga original.

    Nota: No puedes cargar un bloque no continuo del archivo binario. Si intentas subir un bloque no continuo, el contenido binario restante no se carga en absoluto.

    Por lo tanto, el primer byte que se sube en una carga reanudada debe ser el siguiente byte después del último byte que se subió correctamente a YouTube. (Consulta el análisis del encabezado Range en el paso 4.2.

    Entonces, si el último byte del encabezado Range es 999999, el primer byte de la solicitud para reanudar la carga debe ser el byte 1000000. (Ambos números usan un índice con base 0). Si intentas reanudar la carga desde el byte 999999 o menos (superponiendo los bytes) o desde el byte 1000001 o más (omitiendo bytes), el contenido binario no se carga en absoluto.

Cargar un archivo en bloques

En lugar de intentar cargar un archivo completo y reanudar la carga en caso de una interrupción de la red, la aplicación puede dividir el archivo en bloques y enviar una serie de solicitudes para subir los bloques en secuencia. Este enfoque rara vez es necesario y en realidad no se recomienda su uso. ya que requiere solicitudes adicionales, que tienen consecuencias en el rendimiento. Sin embargo, podría ser útil si intentas mostrar un indicador de avance en una red muy inestable.

Las instrucciones para cargar un archivo en bloques son prácticamente idénticas al proceso de cuatro pasos que se explicó anteriormente en esta guía. Sin embargo, las solicitudes para comenzar a subir un archivo de video (paso 3 anterior) y para reanudar una carga (paso 4.3 anterior) definen los valores del encabezado Content-Length y Content-Range de distinta forma cuando un archivo se sube en bloques.

  • El valor del encabezado Content-Length indica el tamaño del bloque que está enviando la solicitud. Ten en cuenta las siguientes restricciones en los tamaños del bloque:

    • El tamaño del bloque debe ser un múltiplo de 256 KB. (Esta restricción no se aplica al último bloque ya que el tamaño del archivo completo puede no ser un múltiplo de 256 KB). Recuerda que los bloques más grandes son más eficientes.

    • El tamaño del bloque debe ser el mismo para cada solicitud de la secuencia carga, excepto para la última solicitud, que especifica el tamaño del bloque final.

  • El encabezado Content-Range especifica los bytes del archivo que está cargando la solicitud. Las instrucciones para configurar el encabezado Content-Range que aparecen en el paso 4.3 se aplican al configurar este valor.

    Por ejemplo, un valor de bytes 0-524287/2000000 muestra que la solicitud está enviando los primeros 524288 bytes (256 x 2048) de un archivo de 2.000.000 de bytes.

El siguiente ejemplo muestra el formato de la primera de una serie de solicitudes que subirán un archivo de 2.000.000 bytes en bloques:

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}

Si se realiza correctamente una solicitud distinta de la solicitud final, el servidor de la API muestra una respuesta 308 (Resume Incomplete). El formato de la respuesta será el mismo que el descrito en el Paso 4.2: Procesar la respuesta de la API que aparece anteriormente.

Utiliza el valor superior que muestra el encabezado Range de la respuesta de la API para determinar dónde comenzar el próximo bloque. Continúa enviando solicitudes PUT, como se describe en el Paso 4.3: Reanudar la carga, para subir los siguientes bloques de archivos hasta que se cargue el archivo completo.

Cuando se carga el archivo completo, el servidor envía una respuesta con el código HTTP 201 (Created) y muestra las partes solicitadas del recurso de video creado recientemente.

Si se interrumpe cualquier solicitud, o si la aplicación recibe algún código de respuesta 5xx, se debe seguir el procedimiento que se explica en el paso 4 para finalizar la carga. Sin embargo, en lugar de intentar cargar el resto del archivo, solo debes continuar subiendo bloques desde el punto donde reanudas la carga. Asegúrate de comprobar el estado de la carga para determinar dónde reanudar la carga del archivo. No supongas que el servidor recibió todos (o ninguno) de los bytes de la solicitud anterior.

Nota: también puedes solicitar el estado de una carga activa entre bloques cargados. (No es necesario que la carga sufra una interrupción para que puedas recuperar su estado).