6 points par GN⁺ 2023-08-15 | 1 commentaires | Partager sur WhatsApp
  • Les URL de fichiers YouTube peuvent être obtenues via l’API /youtubei/v1/player, mais si on les télécharge telles quelles, la vitesse devient extrêmement lente à cause de limitations de téléchargement non officielles
  • Depuis mi-2021, le paramètre de requête n ajouté aux URL doit être transformé par un algorithme JavaScript de base.js ; en cas d’échec, YouTube limite silencieusement le débit
  • Même lorsque n est correctement traité, le temps de téléchargement est ajusté en fonction de la durée et de la taille de la vidéo ; dans l’exemple, une vidéo de 1,5 Go se télécharge à environ 4,0 Mo/s
  • En découpant le fichier en morceaux de 10 Mo avec l’en-tête HTTP Range et en les récupérant via de nouvelles connexions, chaque morceau peut être téléchargé rapidement avant que la limitation ne s’applique
  • Le fichier final doit être assemblé avec ffmpeg à partir des flux vidéo et audio fournis séparément ; yt-dlp, VLC media player, NewPipe et node-ytdl-core utilisent aussi des techniques similaires

Flux pour obtenir l’URL d’un fichier YouTube

  • L’URL réelle du fichier média peut être récupérée en appelant l’endpoint /youtubei/v1/player
  • Cette API renvoie le titre, la description, la miniature et les informations de formats de la vidéo ; dans la liste des formats, on peut choisir l’URL du fichier correspondant à la qualité voulue
    • L’ID de vidéo d’exemple est aqz-KE-bpKQ
    • Le corps de la requête contient des valeurs comme videoId, context.client.clientName et context.client.clientVersion
    • Les autres valeurs de l’objet context sont des préconditions vérifiées par l’API ; on trouve les valeurs acceptées en observant les requêtes d’un navigateur web
  • Si l’on utilise directement adaptiveFormats[0].url reçu de l’API, le téléchargement devient si lent qu’il est pratiquement bloqué
    • Dans l’exemple, un fichier de 1,5 Go s’affiche à environ 66,7 ko/s
    • Le débit est généralement limité à 40 à 70 ko/s
    • Télécharger entièrement une vidéo de 10 minutes peut prendre environ 6 h 30

La première limitation créée par le paramètre n

  • Depuis mi-2021, YouTube inclut un paramètre de requête n dans la plupart des URL de fichiers
  • Cette valeur doit être transformée par un algorithme JavaScript présent dans base.js, distribué avec la page web
  • YouTube utilise la valeur n comme un challenge permettant de distinguer les clients officiels
    • Si n est absent ou n’est pas correctement transformé, une limitation de vitesse est appliquée silencieusement au téléchargement
  • L’algorithme de transformation est obfusqué et change souvent ; l’approche consistant à le rétroconcevoir à chaque fois n’est donc pas pratique
  • L’implémentation d’exemple télécharge le base.js de la version actuelle du lecteur, extrait le code de transformation de n, puis l’exécute avec la valeur n d’origine
    • Trouver l’URL de base.js dans la page d’intégration YouTube
    • Extraire par expression régulière le nom de la fonction de challenge et son corps
    • Exécuter la fonction de transformation avec vm.runInNewContext de Node.js
    • Remplacer le paramètre n de l’URL par la valeur transformée

La limitation de débit qui subsiste après la transformation de n

  • Lorsque le paramètre n est correctement transformé, la limitation initiale extrême disparaît, mais YouTube applique toujours une limitation de téléchargement variable
  • Le niveau de limitation dépend de la taille et de la durée de la vidéo, et le temps de téléchargement est ajusté pour correspondre à environ la moitié de la durée de la vidéo
  • Pour un service de streaming, servir systématiquement les fichiers médias aussi vite que possible pourrait représenter un important gaspillage de bande passante
  • Dans l’exemple de téléchargement, un fichier de 1,5 Go est récupéré à environ 4,0 Mo/s

Télécharger rapidement de petits morceaux avec HTTP Range

  • Le cœur de la méthode de contournement consiste à découper le fichier en plusieurs petites plages à télécharger avec l’en-tête HTTP Range
  • L’en-tête Range indique, pour chaque requête, la portion du fichier à recevoir
    • Exemple : Range: bytes=2000-3000
  • Le code d’exemple traite le fichier média en segments de 10 Mo
    • Supprimer le fichier de sortie existant
    • Calculer la prochaine plage de 10 Mo à partir du nombre d’octets déjà reçus
    • Ajouter l’en-tête Range à chaque requête et recevoir la réponse avec responseType: 'stream'
    • Ajouter les données reçues à la fin du fichier
    • Afficher la progression, la taille totale et le débit par segment
  • Cette méthode fonctionne parce qu’il faut un certain temps avant que les règles de limitation ne s’appliquent, et que de petits segments peuvent être récupérés très rapidement via une nouvelle connexion
  • Dans la sortie de test, les vitesses suivantes apparaissent pour un fichier de 1464,99 Mo
    • À 0,68 % : 46,73 Mo/s
    • À 1,37 % : 60,98 Mo/s
    • À 2,05 % : 71,94 Mo/s
    • À 6,14 % : 104,17 Mo/s
  • Certains téléchargements utilisaient presque entièrement une connexion à 1 Gb/s, et le débit moyen se situait généralement entre 50 et 70 Mo/s, soit 400 à 560 Mb/s

Fusion vidéo-audio et implémentations existantes

  • YouTube distribue les canaux vidéo et audio sous forme de fichiers séparés
  • Avec cette structure, les vidéos HD ou UHD peuvent réutiliser le même fichier audio, ce qui économise de l’espace de stockage
  • Certaines vidéos proposent aussi des canaux audio différents selon la langue
  • À l’étape finale, ffmpeg fusionne le fichier vidéo et le fichier audio en un seul fichier
    • -c copy copie les flux sans réencodage
    • -map 0:v:0 sélectionne le flux vidéo de la première entrée
    • -map 1:a:0 sélectionne le flux audio de la seconde entrée
    • Après la fusion, les fichiers temporaires vidéo et audio sont supprimés
  • Le code complet de l’exemple est fourni sous forme de youtube-download.js
  • Plusieurs projets utilisent des techniques similaires pour contourner les limitations de YouTube

1 commentaires

 
GN⁺ 2023-08-15
Avis sur Hacker News
  • D’après ce que j’ai vu dans les discussions du dépôt yt-dlp, cette limitation pouvait être contournée non pas avec l’en-tête HTTP Range, mais simplement en ajoutant un paramètre de requête range=xxx
    Même en définissant la plage sur l’ensemble du fichier, on retrouvait la vitesse maximale et, si ma mémoire est bonne, YouTube a déjà levé cette limitation
    Référence : https://github.com/yt-dlp/yt-dlp/issues/6400

  • Je n’ai pas essayé avec YouTube, mais il m’est déjà arrivé de récupérer des vidéos de sites de streaming plus louches avec les outils de développement web
    La plupart utilisent une protection qui, quand on ouvre les outils de développement, crée une instruction debugger impossible à ignorer et exécute du code très consommateur de CPU — probablement une boucle infinie ou un mineur de cryptomonnaie — afin de bloquer la vidéo
    Le plus important, c’est que ce code efface aussi les informations de requêtes réseau, ce qui rend difficile l’analyse du trafic déjà envoyé, et l’option « conserver les journaux » de Firefox devrait vraiment conserver les journaux
    Ce n’est pas une défense parfaite, donc au final il n’y a aucune vidéo que je n’ai pas pu récupérer, mais j’aimerais voir une ressource qui explique plus en profondeur le fonctionnement de cette technique

    • Il y a quelque temps, un billet expliquait précisément comment éviter ce genre de méthode, et la solution était aussi simple qu’efficace : reconstruire le navigateur en changeant le nom du mot-clé debugger
      C’était à en rire
      https://news.ycombinator.com/item?id=36961445
    • Pour contourner ce genre de techniques anti-débogage, Anti-Anti-Debug [0] peut valoir le coup
      C’est une petite extension que j’avais bricolée en quelques heures pour des raisons similaires
      0 : https://chrome.google.com/webstore/detail/anti-anti-debug/mn...
    • Le simple fait qu’une page puisse savoir si les outils de développement sont ouverts me semble être un gros défaut côté navigateur
      Une page web ne devrait absolument jamais pouvoir déterminer si les outils de développement sont ouverts, et ça me paraît faisable à implémenter correctement
    • Une méthode qui fonctionne parfois dans Firefox consiste à faire Maj+clic droit sur la vidéo → This FrameOpen Frame in New Tab
      Dans le nouvel onglet, les outils de développement fonctionnent
    • Si une page essaie de détecter les outils de développement du navigateur, j’aurais tendance à commencer par utiliser Wireshark pour analyser le trafic
  • À l’étape finale, il faudra payer en WorldCoin pour continuer à regarder l’écran, et ce WorldCoin non échangeable ne pourra probablement être gagné qu’en regardant des publicités
    Un petit Orb intégré à l’écran surveillera tout ça, et vous ne pensiez quand même pas que c’était vraiment pour le revenu de base
    Le problème du revenu de base a été résolu depuis longtemps avec les comptes bancaires et la connaissance client (KYC)

    • Aucun rapport avec les yeux ?
  • Je me demande si des gens rencontrent ces temps-ci des problèmes de limitation de débit avec yt-dlp
    Je regarde toujours YouTube avec mpv, qui utilise yt-dlp en interne, et depuis la semaine dernière la situation s’est fortement dégradée
    Au début, ça démarre aussi vite que la limite que j’ai fixée, 500 kB/s, mais au bout d’un moment, en 3 secondes de téléchargement je ne récupère qu’une seconde de lecture, donc il faut mettre en file d’attente un bon moment avant de lancer la lecture
    J’utilise la version git de yt-dlp, mais je n’ai pas vu d’issue à ce sujet

    • mpv utilise yt-dlp uniquement pour obtenir l’URL de la vidéo, puis transmet cette URL à ffmpeg
      ffmpeg n’implémente pas le contournement lié à l’en-tête Range, donc il se retrouve soumis à la limitation de débit
      On peut faire en sorte que yt-dlp télécharge directement et envoie le flux à mpv via un pipe pour le lire depuis l’entrée standard, mais la recherche vers une partie pas encore téléchargée ne fonctionne plus
      Il y a beaucoup d’issues à ce sujet dans le suivi de tickets de mpv
  • YouTube change constamment de petits éléments dans ce processus
    J’avais autrefois créé un outil interne de montage pour les vidéos YouTube qui avait besoin de fichiers MP4, et environ une fois par mois, l’éditeur cassait à cause de changements de YouTube ; il fallait alors passer au débogueur pour voir ce qui avait changé et s’adapter

  • C’est un détour, mais je me demande si c’est une illusion que la vidéo paraisse très légèrement meilleure quand on la regarde sur YouTube
    Je télécharge des vidéos que j’aime regarder pour les lire dans VLC ou Infuse d’Apple TV, et je peux vérifier avec les « nerd stats » de l’app YouTube que je regarde le même flux vidéo/audio
    Pourtant, YouTube semble appliquer un filtre très subtil qui rend les artefacts de compression en blocs plus doux
    Ce n’est pas un renforcement des contours ; j’ai plutôt l’impression qu’il repère les zones de variation de couleur sans contours et rend les artefacts en blocs moins visibles
    C’est peut-être une illusion, mais sur YouTube l’image paraît plus vivante et plus solide, tandis que sur la vidéo téléchargée on voit des artefacts et de légers tremblements très subtils mais perceptibles dans les arrière-plans ou les ombres, si bien que même une vidéo en 1440p semble avoir une qualité finale inférieure
    La différence audio est aussi nette : sur YouTube, le volume est globalement uniforme, alors que sur la vidéo téléchargée il faut augmenter le volume, ce qui est pénible
    J’aimerais que VLC ou Infuse appliquent eux aussi un traitement qui rende la vidéo plus agréable à regarder comme YouTube ; cela ressemble moins à un filtre de couleur ou de netteté qu’à un traitement du type nivellement audio, destiné à rendre l’expérience cohérente entre les chaînes

    • Pour l’audio, je peux répondre
      La plupart des sites de streaming comme YouTube et Spotify utilisent quelque chose appelé ReplayGain
      C’est une balise qui calcule le volume moyen d’une vidéo ou d’un morceau, et elle est calculée au moment de l’upload
      Le client YouTube officiel utilise cette balise à la lecture pour ajuster le volume, mais lors du téléchargement la balise peut être absente, ou bien MKV peut ne pas prendre en charge les balises ReplayGain par défaut
    • Le filtre de mise à l’échelle utilisé par le lecteur et la méthode de mise à l’échelle de la chrominance influencent la netteté
      Si vous lisez un flux à sa résolution native en plein écran, la différence devrait disparaître sur les contours en noir et blanc
      Selon le système d’exploitation, vous pouvez tester la différence en basculant rapidement entre deux applications plein écran, et l’ISO 29170-2 recommande 5 Hz
      Les variations de couleur peuvent venir d’un échec de traitement de l’espace colorimétrique de la vidéo ou du profil du moniteur ; dans ce cas, les captures d’écran peuvent ne pas correspondre à l’affichage réel de l’application
      Les micro-saccades peuvent être des pertes d’images, et si vous voyez de la pixellisation sur les bords d’objets colorés, il s’agit probablement d’un upscaling de chrominance au plus proche voisin
    • Une vidéo YouTube contient plusieurs flux vidéo, audio et multiplexés
      Le flux choisi par le navigateur et celui choisi par défaut par youtube-dl ou ses forks peuvent être différents
      À une époque, le meilleur flux multiplexé était choisi par défaut pendant un moment, mais les meilleurs flux audio et vidéo séparés offrent une qualité supérieure
    • Les lecteurs comme VLC peuvent faire mieux, et vous pouvez aussi créer vous-même les corrections souhaitées en GLSL
      J’aime particulièrement le pack de shaders anime4k : il est basé sur l’apprentissage automatique, mais il tourne en temps réel dans mpv et devrait aussi fonctionner dans VLC
      Comme son nom l’indique, il est optimisé pour l’animation, mais sa réduction du bruit et du flou est correcte, et il rend souvent les contenus YouTube plus agréables à regarder ; l’étape de restauration gère assez bien les artefacts de compression
      Cela dit, il est très orienté animation, donc il ne fonctionne pas toujours bien et peut même dégrader l’image
      https://github.com/bloc97/Anime4K/releases
    • Le pipeline vidéo du navigateur peut être différent de celui utilisé par VLC
      Vous pouvez comparer en créant un simple document HTML contenant un élément video pointant vers un fichier local
  • Je suis surpris chaque fois que YT déploie encore une demi-mesure contre les downloaders
    GOOG possède aussi Widevine ; je me demande pourquoi ils ne l’utilisent pas

    • La version logicielle de Widevine serait complètement cassée en très peu de temps, au point d’être contournée même par une extension de téléchargement en un clic
      Cela ne changerait rien pour l’utilisateur, et YouTube n’aurait que la charge d’exploitation de Widevine en plus
      Avec la version matérielle, il pourrait y avoir beaucoup de problèmes sur les appareils non pris en charge
    • YouTube ne semble pas vraiment se soucier du piratage de contenus ni de l’utilisation de clients tiers en soi
      Ce qui les préoccupe, c’est le gaspillage de bande passante
      Sur les sites de streaming vidéo financés par la publicité, le coût de bande passante est généralement supérieur aux revenus, mais Google dispose d’une bande passante suffisamment bon marché pour pouvoir faire pression sur les FAI afin d’obtenir du peering gratuit, ce qui rend tout juste le modèle viable
      Ce type de limitation de débit vise à laisser la majeure partie de la bande passante aux vrais utilisateurs, plutôt qu’aux gens qui aspirent tous les contenus
    • S’ils n’utilisent pas Widevine, c’est parce que l’étape de déchiffrement supplémentaire ralentit le tout, qu’elle force un décodage vidéo logiciel donc plus lent, et que les navigateurs web ne prennent en charge que la forme la plus faible de Widevine, peu efficace
      Ce ne serait pas très efficace pour atteindre l’objectif, tout en risquant fortement de pousser une part importante des utilisateurs hors de la plateforme
    • La raison principale est que cela réduirait un peu l’efficacité du cache CDN, ce qui coûterait de l’argent, et qu’il faudrait exploiter un système supplémentaire de gestion des clés
      À l’échelle de YouTube, ils veulent réduire ce genre de systèmes autant que possible
      Cela ferait aussi de Widevine Level 3 une très grosse cible d’attaque
      Au final, c’est une équation financière : l’argent perdu à cause du blocage des pubs ne suffit pas encore à justifier d’actionner l’interrupteur Widevine, mais il suffit pour prendre des mesures plus faibles, et il y aura aussi la pression des maisons de disques ; il est donc possible que ce soit déployé plus largement dans les prochaines années
      Si je devais prédire, ils commenceraient par les vidéos contenant de la musique de labels ou des extraits de studios détectés par Content ID, et pourraient fournir aux autres créateurs une balise optionnelle
      Ces vidéos sont plus utiles à la monétisation et ne feraient pas perdre d’un coup tous les avantages du CDN
    • Google veut probablement freiner les clients tiers tout en permettant aux gens d’archiver
      Prendre discrètement ce genre de demi-mesures est la solution parfaite, et la seule, pour atteindre cet objectif
  • Je me suis toujours demandé comment YouTube distribuait ses vidéos
    Même quand Internet était catastrophique, ça fonctionnait bien ; en Amérique du Sud, toutes les plateformes ne tournent pas correctement, mais YouTube est la plateforme vidéo la plus fluide
    Ce qui s’en rapproche le plus, c’est Netflix, mais il reste quand même loin derrière

    • Ils placent des serveurs de cache dans le réseau du FAI, près de chez vous
      Le FAI y gagne aussi, donc il l’autorise
      Le goulot d’étranglement d’un FAI est la connexion entre son propre réseau et le backbone Internet plus large, et les serveurs de cache des grands CDN enlèvent une grosse charge à ce goulot
      Documentation sur une configuration similaire chez Netflix : https://openconnect.netflix.com/
  • Avez-vous déjà essayé de télécharger directement une vidéo depuis YouTube ?
    Le faire manuellement, sans dépendre de youtube-dl, yt-dlp ou de sites de ce genre, est bien plus compliqué qu’on ne l’imagine

    • Il y a très longtemps, j’avais travaillé sur un script Perl qui faisait ça : https://www.perlmonks.org/?node_id=636777
      Le problème avec ce genre de scripts, évidemment, c’est qu’il faut constamment suivre les changements que YouTube apporte pour empêcher le téléchargement des vidéos
    • Je procède en injectant directement un script utilisateur
      À voir WEI, c’est une méthode qui utilise mon USER AGENT, ce qui pourrait ne pas durer longtemps
      Plutôt que d’essayer de réimplémenter la signature, le décodage de n et la fonction de limitation de débit, je repère player.js avec match(/(?:player\/([a-zA-Z0-9_-]+)\/)?(?:html5player|(?:www|player(?:_ias)?))[-\.]([^/]+?)(?:(?:\/html5player(?:-new)?)?|(?:\/[a-z]{2,3}_[A-Z]{2})?\/base)\.js/), puis je greppe les fonctions concernées à l’intérieur et je les appelle directement
      Du point de vue de YouTube, on pourrait dire que sa propre fonction de DRM ouvre pour moi un lien .mp4, donc cela paraît 100 % normal
    • Vous voulez dire appuyer sur le bouton « Download » et payer Premium ?
  • Techniquement, tout cela est intéressant, mais éthiquement, si l’on ne pense pas seulement « va te faire voir, Google », il semble raisonnable de s’arrêter à la première optimisation, c’est-à-dire réussir le vrai contrôle de navigateur et obtenir la vitesse d’un navigateur normal
    À ce niveau-là, on ne gaspille pas plus les ressources de YouTube qu’un utilisateur de navigateur avec bloqueur de pubs
    Utiliser tout le débit en Gb/s sans rien payer donne l’impression de tenter la chance de l’ensemble des utilisateurs de bloqueurs de pubs
    Bien sûr, au bout du compte, cela peut aussi être « va te faire voir, Google »

    • Techniquement, tout le monde paie le coût de sa connexion réseau
      Je n’irais pas jusqu’à dire qu’attaquer YouTube au débit maximal est contraire à l’éthique, mais je ne reprocherais pas non plus à YouTube de prendre des mesures pour l’empêcher
      J’utilise une extension de navigateur qui affiche les images de réseaux sociaux en taille originale au survol de la souris, et Instagram m’a affiché un avertissement d’activité anormale avec menace de verrouillage du compte
      J’ai vérifié si l’extension faisait du scraping en arrière-plan, mais elle ne semblait pas poser de problème ; Meta détecte probablement une séquence de requêtes différente de celle du client standard et l’interprète comme du scraping de données
      C’est une succession de mesures et de contre-mesures, et YouTube mettra aussi en place ses propres contre-mesures, auxquelles les scrapers répondront à nouveau ; mais comme une consommation légitime ne va pas plus vite que 2× la vitesse de lecture dans le client officiel, il devrait finir par être possible de limiter les téléchargements à ce niveau
      Malgré tout, je pense que le téléchargement en lui-même ne devrait pas être restreint
      Les contenus sont déjà protégés par la loi, et la plupart des gens téléchargent des vidéos pour des raisons légitimes, comme l’archivage, l’analyse ou la réalisation de vidéos de critique
      Le contenu YouTube n’est pas créé dans le vide ; une fois publié, il crée l’environnement dans lequel de nouvelles vidéos peuvent être produites, et c’est pourquoi cette liberté de création est importante
    • Je ne sais pas très bien à quel point c’est abusif
      Au final, on ne fait que recevoir la même quantité de données en moins de temps : on utilise donc plus de bande passante, mais on disparaît plus vite
      Le cas d’usage d’un navigateur classique semble optimisé pour la situation courante où l’on ne regarde pas la vidéo jusqu’au bout
      Si l’objectif est dès le départ de tout regarder et de l’archiver, il est difficile de dire que l’on consomme davantage de bande passante de Google ; il peut seulement y avoir davantage de surcoût à cause du nombre de connexions
    • Les entreprises n’ont pas d’éthique, seulement des intérêts
      Il est naturel que je me comporte de façon similaire
    • On parle des ressources de YouTube et de Gb/s, mais dans la plupart des cas la vidéo est servie depuis le réseau du même FAI
      C’est parce que YouTube dispose de caches chez presque tous les FAI et points d’échange Internet du monde, et c’est peut-être le plus grand CDN jamais construit
      Par exemple, l’URL YouTube de l’auteur de l’article pointe vers le FAI canadien Videotron
      https://bgp.he.net/dns/rr1---sn-8qu-t0aee.googlevideo.com
    • Techniquement, on devrait pouvoir télécharger les vidéos, et cela ne devrait pas être bloqué
      Ne serait-ce que pour conserver des preuves si quelqu’un diffuse des propos haineux ou m’insulte, moi ou ma famille
      On pourrait filmer l’écran avec un caméscope, mais cela ressemble à une solution de l’âge de pierre
      Par exemple, dans un navigateur sur Mac, Netflix empêche de prendre des captures d’écran, ce qui nous prive même de la création de mèmes, pourtant relevant de l’usage équitable