6 puntos por GN⁺ 2023-08-15 | 1 comentarios | Compartir por WhatsApp
  • La URL del archivo de YouTube puede obtenerse mediante la API /youtubei/v1/player, pero si se descarga tal cual, la velocidad se vuelve extremadamente lenta por una limitación de descarga no oficial
  • El parámetro de consulta n que se agrega a la URL desde mediados de 2021 debe transformarse con el algoritmo JavaScript de base.js; si falla, YouTube limita la velocidad de forma silenciosa
  • Incluso procesando correctamente n, el tiempo de descarga se ajusta según la duración y el tamaño del video; en el ejemplo, un video de 1.5GB se descarga a unos 4.0MB/s
  • Si se divide el archivo en fragmentos de 10MB con el encabezado HTTP Range y se descargan en conexiones nuevas, cada fragmento puede obtenerse rápido antes de que se aplique la limitación
  • El archivo final requiere combinar los flujos de video y audio por separado con ffmpeg, y yt-dlp, VLC media player, NewPipe y node-ytdl-core también usan técnicas similares

Flujo para obtener la URL del archivo de YouTube

  • La URL real del archivo multimedia puede obtenerse llamando al endpoint /youtubei/v1/player
  • Esta API devuelve el título del video, la descripción, la miniatura y la información de formatos; en la lista de formatos se puede elegir la URL del archivo con la calidad deseada
    • El ID del video de ejemplo es aqz-KE-bpKQ
    • El cuerpo de la solicitud incluye valores como videoId, context.client.clientName y context.client.clientVersion
    • Los demás valores del objeto context son precondiciones que la API valida, y los valores permitidos pueden encontrarse observando solicitudes del navegador web
  • Si se usa directamente adaptiveFormats[0].url recibido de la API, la descarga se vuelve prácticamente inutilizable por lo lenta
    • En el ejemplo, un archivo de 1.5GB aparece descargándose a 66.7kB/s
    • La velocidad suele quedar limitada a 40~70kB/s
    • Descargar por completo un video de 10 minutos puede tomar unas 6 horas y 30 minutos

La primera limitación creada por el parámetro n

  • Desde mediados de 2021, YouTube incluye el parámetro de consulta n en la mayoría de las URL de archivos
  • Ese valor debe transformarse con un algoritmo JavaScript dentro de base.js, distribuido junto con la página web
  • YouTube usa el valor n como una especie de desafío para distinguir clientes oficiales
    • Si n no existe o no se transforma correctamente, se aplica silenciosamente una limitación de velocidad de descarga
  • Como el algoritmo de transformación está ofuscado y cambia con frecuencia, no resulta práctico hacer ingeniería inversa de su contenido cada vez
  • La implementación de ejemplo descarga base.js de la versión actual del reproductor, extrae el código de transformación de n y luego lo ejecuta con el valor original de n
    • Encuentra la URL de base.js en la página de inserción de YouTube
    • Extrae con expresiones regulares el nombre de la función de desafío y el cuerpo de la función
    • Ejecuta la función de transformación con vm.runInNewContext de Node.js
    • Sustituye el parámetro n de la URL por el valor transformado

La limitación de velocidad que sigue existiendo después de transformar n

  • Si el parámetro n se transforma correctamente, desaparece la limitación extrema inicial, pero YouTube sigue aplicando una limitación de descarga variable
  • El grado de la limitación cambia según el tamaño y la duración del video, y se ajusta para que el tiempo de descarga sea aproximadamente la mitad de la duración del video
  • Si el archivo multimedia se entregara siempre a la mayor velocidad posible, para un servicio de streaming eso podría implicar un gran desperdicio de ancho de banda
  • En la descarga de ejemplo, el archivo de 1.5GB se recibe a unos 4.0MB/s

Recibir fragmentos pequeños rápidamente con HTTP Range

  • La clave del método de evasión es dividir el archivo en varios tramos pequeños para descargarlos usando el encabezado HTTP Range
  • El encabezado Range especifica qué tramo del archivo se recibirá en cada solicitud
    • Ejemplo: Range: bytes=2000-3000
  • El código de ejemplo procesa el archivo multimedia en segmentos de 10MB
    • Elimina el archivo de salida existente
    • Calcula el siguiente tramo de 10MB según la cantidad de bytes ya recibidos
    • Envía el encabezado Range en cada solicitud y recibe la respuesta con responseType: 'stream'
    • Escribe los datos recibidos al final del archivo
    • Muestra el progreso, el tamaño total y la velocidad por segmento
  • Esto funciona porque las reglas de limitación tardan un tiempo en aplicarse, y los segmentos pequeños pueden descargarse muy rápido en conexiones nuevas
  • En la salida de prueba, para un archivo de 1464.99MB se observaron las siguientes velocidades
    • En 0.68%: 46.73MB/s
    • En 1.37%: 60.98MB/s
    • En 2.05%: 71.94MB/s
    • En 6.14%: 104.17MB/s
  • Algunas descargas casi aprovecharon por completo una conexión de 1Gb/s, y la velocidad promedio solía quedar entre 50~70MB/s, es decir, 400~560Mb/s

Combinación de video y audio, e implementaciones existentes

  • YouTube distribuye los canales de video y audio en archivos separados
  • Esta estructura permite reutilizar el mismo archivo de audio para videos HD o UHD, ahorrando espacio de almacenamiento
  • Algunos videos también ofrecen distintos canales de audio según el idioma
  • En la etapa final, ffmpeg combina el archivo de video y el archivo de audio en uno solo
    • Con -c copy copia los flujos sin recodificación
    • Con -map 0:v:0 selecciona el flujo de video de la primera entrada
    • Con -map 1:a:0 selecciona el flujo de audio de la segunda entrada
    • Después de la combinación, elimina los archivos temporales de video y audio
  • El código de ejemplo completo está disponible en youtube-download.js
  • Varios proyectos usan técnicas parecidas para eludir las limitaciones de YouTube

1 comentarios

 
GN⁺ 2023-08-15
Opiniones en Hacker News
  • Por lo que vi en las discusiones del repositorio de yt-dlp, esta restricción se podía evadir simplemente agregando el parámetro de consulta range=xxx, no el encabezado HTTP Range.
    Incluso si se definía el rango como el archivo completo, volvía a alcanzar la velocidad máxima y, si no recuerdo mal, YouTube ya levantó esa restricción.
    Referencia: https://github.com/yt-dlp/yt-dlp/issues/6400

  • No lo probé con YouTube, pero alguna vez descargué videos de sitios de streaming más sospechosos usando las herramientas de desarrollo web.
    La mayoría usa una protección que, al abrir las herramientas de desarrollo, crea una instrucción debugger imposible de saltar y ejecuta código que consume mucho CPU, probablemente un bucle infinito o un minero de criptomonedas, para detener el video.
    Lo más importante es que ese código también borra la información de las solicitudes de red, lo que dificulta analizar el tráfico enviado hasta ese momento, y “conservar registros” de Firefox de verdad debería conservar los registros.
    No es una defensa perfecta, así que al final no hubo ningún video que no pudiera descargar, pero me gustaría ver algún material que explique más a fondo cómo funciona este comportamiento.

    • Hace poco se publicó un artículo que evitaba exactamente este método, y la solución era simple pero efectiva: recompilar el navegador cambiando el nombre de la palabra clave debugger.
      Me dio risa.
      https://news.ycombinator.com/item?id=36961445
    • Para esquivar esas técnicas de anti-debugging, vale la pena probar Anti-Anti-Debug [0].
      Es una extensión sencilla que hice hace tiempo en unas pocas horas por motivos similares.
      0: https://chrome.google.com/webstore/detail/anti-anti-debug/mn...
    • El solo hecho de que se pueda saber si las herramientas de desarrollo están abiertas me parece una falla importante del lado del navegador.
      Una página web nunca debería poder averiguar si las herramientas de desarrollo están abiertas, y parece algo que se podría implementar correctamente.
    • Un método que a veces funciona en Firefox es hacer shift+clic derecho sobre el video → This FrameOpen Frame in New Tab.
      En la pestaña nueva, las herramientas de desarrollo funcionan.
    • Si es una página que intenta detectar las herramientas de desarrollo del navegador, para analizar el tráfico lo primero que se me ocurre usar es Wireshark.
  • En la etapa final, para seguir viendo la pantalla habrá que pagar con WorldCoin, y parece que esas WorldCoin no transferibles solo se podrán ganar viendo anuncios.
    Un pequeño Orb integrado en la pantalla vigilará esto, y no me digas que de verdad creían que esto era para un ingreso básico.
    El problema del ingreso básico se resolvió hace mucho con cuentas bancarias y verificación de identidad (KYC).

    • ¿No tiene nada que ver con los ojos?
  • Me pregunto si últimamente hay gente con problemas de limitación de velocidad en yt-dlp.
    Siempre veo YouTube con mpv, que internamente usa yt-dlp, y desde la semana pasada está funcionando muy mal.
    Al principio arranca tan rápido como el límite que puse, 500 kB/s, pero al poco rato en 3 segundos de descarga solo recibe 1 segundo de reproducción, así que tengo que dejarlo en cola un buen rato antes de reproducir.
    Estoy usando la versión git de yt-dlp, pero no vi ningún issue relacionado.

    • mpv solo obtiene la URL del video con yt-dlp y le pasa esa URL a ffmpeg.
      ffmpeg no implementa el workaround relacionado con el encabezado Range, así que cae en la limitación de velocidad.
      Se puede hacer que yt-dlp descargue directamente y lo pase por pipe a mpv para reproducir desde la entrada estándar, pero se rompe la búsqueda hacia partes que aún no se descargaron.
      Hay muchos issues sobre este problema en el tracker de mpv.
  • YouTube sigue cambiando pequeños detalles en este proceso.
    Hace tiempo hice una herramienta interna de edición para videos de YouTube que necesitaba archivos MP4, y más o menos una vez al mes el editor se rompía por algún cambio de YouTube, así que tenía que revisar en el debugger qué había cambiado y ajustarlo.

  • Es un desvío del tema, pero me pregunto si es una ilusión que los videos se vean apenas un poco mejor en YouTube
    Descargo los videos que me gusta ver y los miro en VLC o en Infuse de AppleTV, y con las “nerd stats” de la app de YouTube puedo confirmar que estoy viendo el mismo stream de video/audio
    Pero parece que YouTube aplica un filtro muy sutil que hace que los artefactos de compresión en bloques se vean más suaves
    No es que realce los bordes; se siente más bien como si detectara áreas con cambios de color sin bordes y hiciera que los artefactos en bloques fueran menos notorios
    Puede ser una ilusión, pero en YouTube la imagen se ve más viva y sólida, mientras que en el video descargado se ven artefactos y un ligero temblor muy sutiles pero perceptibles en fondos o sombras, así que incluso un video 1440p termina viéndose con menor calidad final
    El audio también tiene una diferencia clara: en YouTube el volumen suele ser uniforme, mientras que en el video descargado tengo que subir el volumen, lo cual resulta incómodo
    Me gustaría que VLC o Infuse también aplicaran algún procesamiento para hacer que el video se vea mejor, como YouTube; parece más bien algo como nivelación de audio para que la experiencia sea consistente entre canales, no tanto un filtro de color o nitidez

    • Sobre el audio sí puedo responder
      La mayoría de los sitios de streaming como YouTube y Spotify usan algo llamado ReplayGain
      Es una etiqueta que calcula el volumen promedio de un video o una canción, y se calcula al momento de la subida
      El cliente oficial de YouTube usa esa etiqueta durante la reproducción para ajustar el volumen, pero al descargar puede que la etiqueta se pierda, o que MKV no admita etiquetas ReplayGain de forma predeterminada
    • Los filtros de escalado que usa el reproductor y la forma en que escala la crominancia afectan la nitidez
      Si reproduces un stream en resolución nativa a pantalla completa, la diferencia debería desaparecer en los bordes en blanco y negro
      Según el sistema operativo, puedes probar la diferencia alternando rápidamente entre dos apps en pantalla completa; ISO 29170-2 recomienda 5 Hz
      Los cambios de color pueden venir del espacio de color del video o de un fallo en el manejo del perfil del monitor, y en ese caso las capturas de pantalla podrían verse distintas a la imagen real de la app
      El temblor puede ser pérdida de frames, y si se ve pixelación en los bordes de objetos de color, probablemente sea escalado de crominancia por vecino más cercano
    • Un solo video de YouTube tiene varios streams de video, audio e integrados
      El stream que elige el navegador puede ser distinto del que elige por defecto youtube-dl o alguno de sus forks
      Antes, durante un tiempo, se elegía por defecto el mejor stream integrado, pero los mejores streams separados de audio y video tienen mayor calidad
    • Reproductores como VLC pueden hacerlo mejor, y con GLSL incluso puedes crear tú mismo las correcciones que quieras
      En particular me gusta el paquete de shaders anime4k; está basado en machine learning, pero corre en tiempo real en mpv y creo que también podría funcionar en VLC
      Como su nombre indica, está ajustado para animación, pero su reducción de ruido y de desenfoque son bastante buenas, así que muchas veces mejora el contenido de YouTube, y la etapa de restauración maneja bastante bien los artefactos de compresión
      Eso sí, está demasiado ajustado para animación, así que no siempre funciona bien e incluso puede empeorar la imagen
      https://github.com/bloc97/Anime4K/releases
    • La pipeline de video del navegador puede ser distinta de la que usa VLC
      Puedes compararlo creando un documento HTML simple con un elemento video que apunte a un archivo local
  • Me sorprende cada vez que YT despliega otra medida a medias contra los descargadores
    GOOG también tiene Widevine, así que me pregunto por qué no lo usa

    • La versión de software de Widevine quedaría completamente rota en muy poco tiempo, y hasta un add-on de descarga de un clic podría saltársela
      Para el usuario no cambiaría nada, y YouTube solo cargaría con el costo operativo de Widevine
      Si usaran la versión basada en hardware, podrían aparecer muchos problemas en dispositivos no compatibles
    • YouTube no parece preocuparse demasiado por la piratería de contenido ni por el uso de clientes de terceros en sí
      Lo que le preocupa es el desperdicio de ancho de banda
      En los sitios de streaming de video basados en publicidad, normalmente el costo de ancho de banda supera los ingresos, y Google apenas logra que el modelo funcione porque consiguió ancho de banda barato al punto de poder presionar a los ISP para obtener peering gratuito
      Estos límites de velocidad son una medida para dejar la mayor parte del ancho de banda a los usuarios reales, no a quienes scrapean todo el contenido
    • La razón por la que no usan Widevine es que agrega una etapa de descifrado y eso lo hace más lento, fuerza la decodificación de video por software y por eso es lento, y los navegadores web solo admiten la forma más débil de Widevine, que es poco efectiva
      No sería muy eficaz para lograr el objetivo y, además, probablemente empujaría a muchos usuarios fuera de la plataforma
    • La razón principal es que reduciría un poco la eficiencia de la caché del CDN, lo que cuesta dinero, y además habría que operar un sistema adicional de gestión de claves
      A la escala de YouTube, quieren reducir este tipo de sistemas al mínimo
      También convertiría a Widevine Level 3 en un objetivo de ataque enorme
      Al final es una ecuación financiera: el dinero que pierden por bloqueo de anuncios todavía no basta para activar el interruptor de Widevine, pero sí para aplicar medidas más débiles, y también debe haber presión de las discográficas, así que es probable que en unos años se despliegue más ampliamente
      Si tuviera que predecir, al principio empezaría con videos que contengan música de sellos o clips de estudios detectados por Content ID, y podrían ofrecer a otros creadores una etiqueta opcional
      Esos videos son más útiles para monetizar y no perderían de golpe las ventajas del CDN
    • Es probable que Google quiera desalentar los clientes de terceros, pero permitir que la gente archive contenido
      Tomar discretamente este tipo de medidas a medias es la solución perfecta y única para lograr ese objetivo
  • Siempre me dio curiosidad cómo distribuye YouTube los videos
    Incluso cuando internet anda mal, funciona bien; y en Sudamérica no todas las plataformas funcionan bien, pero YouTube es la plataforma de video más fluida
    Lo más cercano es Netflix, pero aun así se queda bastante atrás

    • Tienen servidores de caché desplegados dentro de la red del ISP cerca de tu casa
      Al ISP también le conviene, así que lo permite
      El cuello de botella del ISP es la conexión desde su propia red hacia el backbone más amplio de internet, y los servidores de caché de los grandes CDN alivian buena parte de esa carga en ese cuello de botella
      Documentación de una configuración similar de Netflix: https://openconnect.netflix.com/
  • ¿Alguna vez descargaste un video directamente desde YouTube?
    Si lo hacés manualmente, sin depender de youtube-dl, yt-dlp ni de esos sitios web, es mucho más complicado de lo que parece

    • Hace mucho tiempo trabajé en un script de Perl que hacía eso: https://www.perlmonks.org/?node_id=636777
      Claro que el problema con este tipo de scripts es que hay que seguir persiguiendo los cambios que YouTube hace para impedir la descarga de videos
    • Lo manejo inyectando directamente un script de usuario
      Viendo WEI, es una forma de usar mi USER AGENT que quizá no dure mucho
      En vez de intentar reimplementar la firma, la decodificación de n y la función de limitación de velocidad, busco player.js con match(/(?:player\/([a-zA-Z0-9_-]+)\/)?(?:html5player|(?:www|player(?:_ias)?))[-\.]([^/]+?)(?:(?:\/html5player(?:-new)?)?|(?:\/[a-z]{2,3}_[A-Z]{2})?\/base)\.js/), luego hago grep de las funciones relevantes dentro de ese archivo y las llamo directamente
      Desde el punto de vista de YouTube, se podría decir que se ve 100% normal, porque su propia función de DRM me está abriendo el enlace .mp4
    • ¿Te referís a apretar el botón “Download” y pagar Premium?
  • Técnicamente todo es interesante, pero si desde lo ético uno no está pensando solo en “que se joda Google”, parece razonable detenerse en la primera optimización: es decir, pasar la verificación de navegador real y obtener velocidad de navegador normal
    Con eso no se desperdician más recursos de YouTube que con un usuario de navegador con bloqueador de anuncios
    Usar toda la velocidad de Gb/s sin pagar nada se siente como tentar la suerte de todos los usuarios con bloqueador de anuncios
    Aunque, claro, al final quizá también sea un “que se joda Google”

    • Técnicamente, todos pagamos el costo de la conexión de red
      No diría que golpear YouTube a máxima velocidad sea inmoral, pero tampoco culparía a YouTube si toma medidas para bloquearlo
      Uso una extensión de navegador que muestra las imágenes de redes sociales en tamaño original al pasarles el mouse, e Instagram me mostró una advertencia de actividad anormal y amenazó con bloquearme la cuenta
      Revisé si la extensión estaba haciendo scraping en segundo plano, pero no parecía haber nada raro; probablemente Meta ve un orden de solicitudes distinto al del cliente estándar y lo interpreta como scraping de datos
      Es una repetición de medidas y contramedidas, y YouTube también implementará sus propias contramedidas para que los scrapers vuelvan a responder, pero como el consumo legítimo en el cliente oficial nunca debería superar 2 veces la velocidad de reproducción, algún día podrán limitar las descargas a algo así
      Aun así, creo que la descarga en sí no debería limitarse
      El contenido ya está protegido por la ley, y la mayoría descarga videos por motivos razonables, como archivarlos, analizarlos o crear videos de reseña
      El contenido de YouTube no se crea en el vacío y, una vez publicado, genera el entorno para que se creen nuevos videos, por eso esta libertad creativa es importante
    • No estoy seguro de hasta qué punto esto es abuso
      Al final solo se recibe la misma cantidad de datos en menos tiempo, así que usa más ancho de banda, pero desaparece más rápido
      El caso de uso de un navegador normal parece estar ajustado para la situación común en la que no se mira el video hasta el final
      Si desde el principio la intención es verlo completo y guardarlo, no es fácil decir que consuma más ancho de banda de Google; aunque por la cantidad de conexiones sí puede haber más overhead
    • Las empresas no tienen ética, solo intereses
      Es natural que yo actúe de forma parecida
    • Se habla de recursos de YouTube y de Gb/s, pero en la mayoría de los casos el video se sirve dentro de la misma red del ISP
      Eso se debe a que YouTube tiene cachés en casi todos los ISP y puntos de intercambio de Internet del mundo, y quizá sea la CDN más grande jamás construida
      Por ejemplo, la URL de YouTube del autor apunta al ISP canadiense Videotron
      https://bgp.he.net/dns/rr1---sn-8qu-t0aee.googlevideo.com
    • Técnicamente debería ser posible descargar videos, y no debería bloquearse
      Aunque sea para conservar evidencia de que alguien difundió discurso de odio o me insultó a mí y a mi familia
      También podría filmar la pantalla con una videocámara, pero suena como una solución de la Edad de Piedra
      Por ejemplo, en un navegador de Mac no se pueden tomar capturas de pantalla de Netflix, así que incluso la creación de memes, que entra dentro del uso justo, nos fue arrebatada