Precaptura de vídeo en la caché con Compute
No hay peor sensación que ponerse a ver esa serie cuyo estreno llevas tanto tiempo esperando y que el vídeo tarde en cargar. Para que todos los espectadores disfruten de la mejor experiencia posible, los editores de contenido deberían plantearse usar la precaptura de vídeo.
¿Por qué conviene preparar la caché?
En el caso del contenido de vídeo que no se ha reproducido durante un tiempo, o que se reproduce por primera vez, el tiempo hasta el primer byte (TTFB) puede aumentar considerablemente si la petición del reproductor tiene que ir hasta el servidor de origen en cada uno de los fragmentos de vídeo. Si los editores saben que tendrán un público numeroso a determinada hora, lo ideal es tener todos los objetos de vídeo en la caché del edge para distribuirlo rápidamente en cualquier región geográfica.
Pensemos, por ejemplo, en el último episodio de «Juego de Tronos» de HBO, una de las series más populares de los últimos años. Millones de fans estaban esperando el momento en que estaría disponible: el domingo a las 20:00. HBO sabía que un público masivo y disperso geográficamente le daría al botón de reproducir exactamente a esa hora. Al ser un vídeo nuevo, se produciría un fallo de caché, y todas las peticiones de los espectadores volverían al servidor de origen, lo que retrasaría la reproducción del vídeo y reduciría el rendimiento y, por lo tanto, la satisfacción de los clientes.
Para evitarlo, HBO implementó la precaptura de todos los objetos de vídeo, o al menos de los primeros segundos, para que pudiera reproducirse de inmediato.
Dificultades de la preparación
Para preparar la caché, se solía acceder a cada nodo de caché y se ejecutaba un script para obtener todos los objetos de vídeo, o se utilizaba una VPN para iniciar un servidor cliente en cada zona geográfica y pedir los objetos de vídeo del lado del cliente. Sin embargo, esto presentaba algunos inconvenientes:
Es un proceso lento y difícil de gestionar. Necesitas mucha información de la red interna sobre la CDN con la que estás trabajando. Además, debes saber cómo acceder a cada uno de los POP o, en el caso del lado del cliente, cómo se enrutará cada zona geográfica hacia los POP.
Puede ser que estés utilizando un valioso espacio de caché de la CDN para contenido que nadie ve. Es lo que ocurriría si prepararas todos los POP de todo el mundo, pero el contenido solo se reprodujera en Norteamérica: los demás POP tendrían objetos de vídeo que nunca llegarían a ningún cliente.
Preparación con Compute
Antes de Compute, teníamos limitaciones con respecto a lo que podíamos hacer frente a una petición. VCL no tenía la capacidad de leer ni manipular la petición o el cuerpo de respuesta, y también había aspectos mejorables en cuanto a las peticiones asíncronas.
Compute elimina estas limitaciones y nos abre un mundo de posibilidades en cuestión de distribución de vídeo, como la preparación de la caché o la precaptura eficientes.
Primero, la petición de manifiesto
Antes de nada, demos un repaso rápido a la distribución de vídeo en streaming:
El vídeo se distribuye de forma gradual en pequeñas partes. Un reproductor del lado del cliente pide un archivo llamado «manifiesto», que tiene URL a otros objetos de vídeo que el reproductor comenzará a pedir a medida que los necesite tanto para almacenarlos en búfer como para reproducirlos.
A continuación encontrarás un manifiesto de una lista de reproducción truncada para una versión 720p de «Big Buck Bunny» que muestra las primeras tres URL relativas (son las que tienen la extensión .ts).
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:13
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:12.500000,
buck_720p_0000.ts
#EXTINF:7.666667,
buck_720p_0001.ts
#EXTINF:11.466667,
buck_720p_0002.ts
#EXTINF:12.300000,
buck_720p_0003.ts
El reproductor pediría cada uno de estos segmentos de vídeo uno por uno. En una situación normal sin precaptura, con una caché en frío, la petición debería ir al servidor de origen en cada uno de los segmentos. Pues bien, esto puede hacerse mucho mejor.
Como he dicho anteriormente, Compute tiene la capacidad de leer el cuerpo de la petición. Esto nos permite escribir una aplicación simple que se ejecuta en el edge para preparar la caché. Cuando el reproductor solicita el manifiesto, puede pasar la petición al servidor de origen. Sin embargo, cuando se devuelve la respuesta, el reproductor analiza el manifiesto y obtiene las primeras N URL de los objetos de vídeo. Luego puede enviar el manifiesto de vuelta al cliente. El siguiente fragmento de código es un ejemplo de ello:
match m3u8_rs::parse_playlist_res(new_resp.take_body_bytes().as_slice()) {
Ok(Playlist::MasterPlaylist(_pl)) => println!("Master playlist"),
Ok(Playlist::MediaPlaylist(pl)) => {
println!("Media Playlist. Path = {}", path_str);
send_media_segments_requests_async(&pl, req_url)?;
}
Err(_e) => fastly::error::bail!("Invalid manifest"),
}
// I got what I needed so return the beresp in a Result
Ok(beresp)
}
El reproductor encuentra los primeros N segmentos de vídeo, envía la petición de forma asíncrona e ignora la respuesta. Esto sucede muy rápido, por lo que el manifiesto vuelve al reproductor casi sin latencia adicional. No nos importan las respuestas a las peticiones de segmento de vídeo: solo queremos traerlas a la caché de la CDN. Para cuando el reproductor comienza a solicitar los segmentos de vídeo, ya deberían encontrarse en la caché.
CMCD-NOR
Uno de los estándares en los que trabaja la Consumer Technology Association (CTA) es el estándar CMCD (Common Media Client Data). Se trata de una especificación abierta que define información adicional para analizar, supervisar y optimizar la distribución de contenido en streaming, y que proporciona una mayor visibilidad de la calidad del servicio y un mejor rendimiento de la distribución. No te pierdas el artículo que publicaremos con un debate más extenso sobre este tema.
Uno de los elementos del estándar CMCD es la petición del objeto siguiente (NOR). Se trata de una cadena que puede pasarse como un parámetro de consulta o en un encabezado, y que representa la URL relativa del objeto siguiente que se va a pedir. Esta aplicación de Compute funciona de manera similar a la anterior, pero en vez de buscar el siguiente objeto en el manifiesto, lo hace en la consulta o los encabezados:
match req.get_header("cmcd-request") {
Some(cmcd) => {
let cmcd = cmcd.to_str().unwrap().to_string();
send_nor_request(cmcd, &req);
}
None => {
// We looked for a cmcd-request header and it wasn't there so let's see if it's in the
// query parameters.
if let Ok(q) = req.get_query() {
let qs_map: HashMap<String, String> = q;
if qs_map.contains_key("CMCD") {
let cmd = qs_map.get("CMCD").unwrap();
send_nor_request(cmd.to_string(), &req);
}
};
}
}
Aquí estamos buscando la petición NOR en los encabezados y, si no está allí, buscamos en los parámetros de consulta. Si la encontramos en alguna de esas ubicaciones, la enviamos a la función send_nor_request que analiza la URL de la petición y luego la envía de forma asíncrona.
Inteligencia de última generación
Los flujos de trabajo anteriores son los más evidentes y fáciles de implementar en producción. Pero Compute es tan versátil y potente que permite hacer mucho más que eso. Por ejemplo:
Evitar la precaptura de los créditos: sabemos que la audiencia baja al final del vídeo y que los usuarios no suelen leer los créditos. Por eso, no tiene sentido precapturar ese contenido en concreto. Podemos optimizar la aplicación para que detecte cuándo comienzan los créditos según una marca de tiempo, una etiqueta u otros metadatos, y detener la precaptura en ese momento.
Implementar la precaptura inteligente basada en patrones de uso: otra opción es optimizar la precaptura mediante inteligencia artificial o aprendizaje automático. Por ejemplo, podrías utilizar inteligencia artificial para identificar las horas en las que el vídeo tiene más espectadores y solo implementar la precaptura entonces.
Resumen
Al utilizar Compute para preparar la caché, no solo aprovechas una red sólida distribuida a nivel global, sino que también resuelves las dificultades tradicionalmente asociadas a la precaptura.