6 pontos por GN⁺ 2023-08-15 | 1 comentários | Compartilhar no WhatsApp
  • A URL do arquivo do YouTube pode ser obtida pela API /youtubei/v1/player, mas, se for baixada diretamente, a velocidade fica extremamente lenta por causa de uma limitação não oficial de download
  • Desde meados de 2021, o parâmetro de consulta n anexado à URL precisa ser transformado pelo algoritmo JavaScript de base.js; se isso falhar, o YouTube limita silenciosamente a velocidade
  • Mesmo tratando n corretamente, o tempo de download é ajustado de acordo com a duração e o tamanho do vídeo; no exemplo, um vídeo de 1,5GB é baixado a cerca de 4,0MB/s
  • Ao dividir o arquivo em blocos de 10MB com o cabeçalho HTTP Range, cada bloco pode ser obtido rapidamente em uma nova conexão antes que a limitação entre em ação
  • O arquivo final precisa unir os streams separados de vídeo e áudio com ffmpeg; yt-dlp, VLC media player, NewPipe e node-ytdl-core também usam técnicas semelhantes

Fluxo para obter a URL do arquivo do YouTube

  • A URL real do arquivo de mídia pode ser obtida chamando o endpoint /youtubei/v1/player
  • Essa API retorna o título do vídeo, descrição, miniatura e informações de formato, e é possível escolher a URL do arquivo na qualidade desejada a partir da lista de formatos
    • O ID do vídeo de exemplo é aqz-KE-bpKQ
    • O corpo da requisição inclui valores como videoId, context.client.clientName e context.client.clientVersion
    • Os outros valores do objeto context são pré-condições validadas pela API, e os valores aceitos podem ser encontrados observando requisições do navegador
  • Se adaptiveFormats[0].url retornada pela API for usada diretamente, o download fica praticamente bloqueado de tão lento
    • No exemplo, um arquivo de 1,5GB aparece com velocidade em torno de 66,7kB/s
    • A velocidade costuma ficar limitada a 40~70kB/s
    • Baixar todo um vídeo de 10 minutos pode levar cerca de 6 horas e 30 minutos

A primeira limitação causada pelo parâmetro n

  • Desde meados de 2021, o YouTube inclui o parâmetro de consulta n na maioria das URLs de arquivo
  • Esse valor precisa ser transformado por um algoritmo JavaScript dentro de base.js, distribuído junto com a página web
  • O YouTube usa o valor n como uma espécie de desafio para distinguir clientes oficiais
    • Se n estiver ausente ou não for transformado corretamente, a limitação de velocidade é aplicada silenciosamente
  • Como o algoritmo de transformação é ofuscado e muda com frequência, fazer engenharia reversa manual a cada vez não é prático
  • A implementação de exemplo baixa o base.js da versão atual do player, extrai o código de transformação de n e o executa com o valor original de n
    • Localiza a URL de base.js na página embed do YouTube
    • Extrai com expressões regulares o nome da função do desafio e o corpo da função
    • Executa a função de transformação com vm.runInNewContext do Node.js
    • Substitui o parâmetro n da URL pelo valor transformado

A limitação de velocidade que permanece mesmo após transformar n

  • Ao transformar corretamente o parâmetro n, a limitação extrema inicial desaparece, mas o YouTube ainda aplica uma limitação variável de download
  • O grau da limitação varia conforme o tamanho e a duração do vídeo, ajustando o download para que leve aproximadamente metade da duração do vídeo
  • Do ponto de vista de um serviço de streaming, entregar sempre o arquivo na velocidade máxima possível pode representar grande desperdício de banda
  • No download de exemplo, um arquivo de 1,5GB é baixado a cerca de 4,0MB/s

Recebendo pequenos blocos rapidamente com HTTP Range

  • O ponto central do método de contorno é dividir o arquivo em vários pequenos intervalos de download com o cabeçalho HTTP Range
  • O cabeçalho Range especifica qual intervalo do arquivo será recebido em cada requisição
    • Ex.: Range: bytes=2000-3000
  • O código de exemplo processa o arquivo de mídia em segmentos de 10MB
    • Remove o arquivo de saída existente
    • Calcula o próximo intervalo de 10MB com base na quantidade de bytes já recebida
    • Envia o cabeçalho Range em cada requisição e recebe com responseType: 'stream'
    • Grava os dados recebidos no fim do arquivo
    • Exibe progresso, tamanho total e velocidade por segmento
  • Esse método funciona porque as regras de limitação levam algum tempo para entrar em vigor, e segmentos pequenos podem ser recebidos muito rapidamente em uma nova conexão
  • Na saída de teste, para um arquivo de 1464.99MB, apareceram as seguintes velocidades
    • No ponto de 0,68%: 46.73MB/s
    • No ponto de 1,37%: 60.98MB/s
    • No ponto de 2,05%: 71.94MB/s
    • No ponto de 6,14%: 104.17MB/s
  • Alguns downloads chegaram a usar quase toda uma conexão de 1Gb/s, e a velocidade média normalmente ficou na faixa de 50~70MB/s, ou seja, 400~560Mb/s

Mesclagem de vídeo e áudio e implementações existentes

  • O YouTube distribui os canais de vídeo e áudio em arquivos separados
  • Nessa estrutura, vídeos HD ou UHD podem reutilizar o mesmo arquivo de áudio, economizando espaço de armazenamento
  • Alguns vídeos também oferecem canais de áudio diferentes por idioma
  • Na etapa final, usa-se ffmpeg para unir o arquivo de vídeo e o arquivo de áudio em um só
    • -c copy copia os streams sem recodificação
    • -map 0:v:0 seleciona o stream de vídeo da primeira entrada
    • -map 1:a:0 seleciona o stream de áudio da segunda entrada
    • Após a mesclagem, os arquivos temporários de vídeo e áudio são excluídos
  • O código completo de exemplo é fornecido em youtube-download.js
  • Vários projetos usam técnicas parecidas para contornar as limitações do YouTube

1 comentários

 
GN⁺ 2023-08-15
Opiniões no Hacker News
  • Pelo que vi nas discussões do repositório do yt-dlp, era possível contornar essa restrição não com o cabeçalho HTTP Range, mas simplesmente adicionando o parâmetro de consulta range=xxx
    Mesmo definindo o intervalo como o arquivo inteiro, a velocidade máxima voltava e, se minha memória não falha, o YouTube já removeu essa restrição
    Referência: https://github.com/yt-dlp/yt-dlp/issues/6400

  • Não testei no YouTube, mas já baixei vídeos de sites de streaming mais suspeitos usando as ferramentas de desenvolvedor da web
    Na maioria das vezes, quando você abre as ferramentas de desenvolvedor, eles usam uma proteção que cria instruções debugger impossíveis de pular e executa código que consome muita CPU — talvez um loop infinito ou um minerador de criptomoedas — fazendo o vídeo travar
    O mais importante é que esse código também apaga as informações de requisições de rede, dificultando a análise do tráfego enviado até então, e o “preservar log” do Firefox deveria realmente preservar o log
    Não é uma defesa perfeita, então no fim nunca houve um vídeo que eu não conseguisse baixar, mas gostaria de ver algum material explicando esse mecanismo com mais profundidade

    • Há pouco tempo apareceu um post que contornava exatamente esse método, e a solução era simples e eficaz: recompilar o navegador mudando o nome da palavra-chave debugger
      Foi algo de dar risada
      https://news.ycombinator.com/item?id=36961445
    • Para contornar esse tipo de técnica anti-debugging, vale tentar o Anti-Anti-Debug [0]
      É uma extensão simples que fiz em algumas horas, por motivos parecidos, algum tempo atrás
      0: https://chrome.google.com/webstore/detail/anti-anti-debug/mn...
    • O simples fato de uma página conseguir saber se as ferramentas de desenvolvedor estão abertas parece uma grande falha do lado do navegador
      Uma página web nunca deveria conseguir descobrir se as ferramentas de desenvolvedor estão abertas, e parece algo que daria para implementar corretamente
    • Um método que às vezes funciona no Firefox é, no vídeo, usar shift+clique com o botão direitoThis FrameOpen Frame in New Tab
      Na nova aba, as ferramentas de desenvolvedor funcionam
    • Se a página tenta detectar as ferramentas de desenvolvedor do navegador, a primeira coisa que me vem à cabeça para analisar o tráfego é usar o Wireshark
  • Na etapa final, para continuar vendo a tela, vai ser preciso pagar com WorldCoin, e essa WorldCoin inegociável só poderá ser ganha assistindo a anúncios
    Um pequeno Orb embutido na tela vai fiscalizar isso; você não achava mesmo que aquilo era para renda básica, achava?
    O problema da renda básica já foi resolvido há muito tempo com contas bancárias e verificação de identidade (KYC)

    • Não tem nada a ver com os olhos?
  • Estou curioso se alguém anda enfrentando o problema de limitação de velocidade no yt-dlp
    Sempre assisto ao YouTube com mpv, que usa yt-dlp internamente, e desde a semana passada a situação ficou bem ruim
    No começo ele inicia rápido, no limite que defini de 500 kB/s, mas depois de um tempo só baixa 1 segundo de reprodução a cada 3 segundos de download, então preciso deixar bastante tempo em buffer antes de reproduzir
    Estou usando a versão git do yt-dlp, mas não vi nenhuma issue relacionada

    • O mpv usa o yt-dlp apenas para obter a URL do vídeo e passa essa URL para o ffmpeg
      O ffmpeg não implementa a solução de contorno relacionada ao cabeçalho Range, então fica sujeito à limitação de velocidade
      Dá para fazer o yt-dlp baixar diretamente e passar isso por pipe para o mpv, reproduzindo a partir da entrada padrão, mas aí a busca para trechos que ainda não foram baixados quebra
      Há muitas issues sobre esse problema no rastreador de issues do mpv
  • O YouTube fica mudando pequenos detalhes nesse processo
    Antigamente eu criei uma ferramenta interna de edição para vídeos do YouTube que precisava de arquivos MP4 e, mais ou menos uma vez por mês, o editor quebrava por causa de uma mudança no YouTube, então eu tinha que abrir o depurador para ver o que tinha mudado e ajustar

  • É um desvio do assunto, mas fico me perguntando se é impressão minha que, visto no YouTube, o vídeo parece um pouquinho melhor
    Baixo vídeos que gosto de assistir e vejo no VLC ou no Infuse da AppleTV, e consigo confirmar pelo “nerd stats” do app do YouTube que estou vendo o mesmo stream de vídeo/áudio
    Mas parece que o YouTube aplica um filtro muito sutil que deixa os artefatos de compressão em blocos mais suaves
    Não é que ele realce as bordas; a sensação é de que ele encontra áreas de mudança de cor sem bordas e torna os artefatos em blocos menos perceptíveis
    Pode ser só impressão, mas no YouTube a imagem parece mais viva e firme, enquanto no vídeo baixado dá para ver artefatos e tremulações muito sutis, mas perceptíveis, em fundos ou sombras, fazendo até vídeos em 1440p parecerem ter uma qualidade final pior
    No áudio a diferença também é clara: no YouTube o volume em geral é uniforme, enquanto nos vídeos baixados preciso aumentar o volume, o que é incômodo
    Gostaria que VLC ou Infuse também fizessem algum processamento para deixar o vídeo mais agradável como o YouTube; parece mais algo como nivelamento de áudio, para tornar a experiência consistente entre canais, do que um filtro de cor ou nitidez

    • Sobre o áudio eu consigo responder
      A maioria dos sites de streaming, como YouTube e Spotify, usa algo chamado ReplayGain
      É uma tag que calcula o volume médio do vídeo ou da música, e é calculada no momento do upload
      O cliente oficial do YouTube usa essa tag para ajustar o volume durante a reprodução, mas, ao baixar, a tag pode ficar de fora, ou o MKV talvez não tenha suporte padrão a tags ReplayGain
    • O filtro de escala e o método de escalonamento de crominância usados pelo player afetam a nitidez
      Se você reproduzir em tela cheia um stream na resolução original, a diferença deve desaparecer nas bordas em preto e branco
      Dependendo do sistema operacional, dá para testar a diferença alternando rapidamente entre dois apps em tela cheia, e a ISO 29170-2 recomenda 5 Hz
      Mudanças de cor podem vir de falhas no tratamento do espaço de cor do vídeo ou do perfil do monitor; nesse caso, capturas de tela também podem parecer diferentes da tela real do app
      Tremulação pode ser queda de frames, e, se você vê pixelização nas bordas de objetos coloridos, a causa pode ser upscaling de crominância por vizinho mais próximo
    • Um único vídeo do YouTube tem vários streams de vídeo, áudio e combinados
      O stream escolhido pelo navegador pode ser diferente do escolhido por padrão pelo youtube-dl ou por algum fork
      Antigamente, por um tempo, ele escolhia por padrão o melhor stream combinado, mas streams separados de melhor áudio e melhor vídeo têm qualidade superior
    • Players como o VLC podem fazer melhor, e também dá para criar seus próprios ajustes em GLSL
      Gosto especialmente do pacote de shaders anime4k: ele é baseado em aprendizado de máquina, mas roda em tempo real no mpv e acho que também deve funcionar no VLC
      Como o nome sugere, ele é ajustado para animações, mas a redução de ruído e de desfoque é boa, então muitas vezes deixa conteúdos do YouTube mais agradáveis de ver, e a etapa de restauração lida bem com artefatos de compressão
      Porém, por ser ajustado demais para animações, nem sempre funciona bem e pode até piorar a imagem
      https://github.com/bloc97/Anime4K/releases
    • O pipeline de vídeo do navegador pode ser diferente do usado pelo VLC
      Dá para comparar criando um documento HTML simples com um elemento video apontando para um arquivo local
  • Fico surpreso sempre que o YT lança mais uma medida meia-boca contra downloaders
    A GOOG também tem o Widevine, então me pergunto por que não o usa

    • A versão de software do Widevine seria completamente quebrada em pouquíssimo tempo e contornada até por addons de download com um clique
      Para o usuário nada mudaria, e o YouTube só ficaria com o ônus de operar o Widevine
      Se usassem a versão baseada em hardware, poderia haver muitos problemas em dispositivos não suportados
    • O YouTube não parece se importar muito com pirataria do conteúdo em si nem com o uso de clientes de terceiros
      O que importa para eles é desperdício de largura de banda
      Em sites de streaming de vídeo baseados em anúncios, normalmente o custo de banda é maior que a receita, e isso só fecha porque o Google consegue largura de banda barata o bastante para pressionar ISPs a fazerem peering gratuito
      Esse tipo de limitação de velocidade é uma medida para deixar a maior parte da largura de banda para usuários reais, não para quem sai raspando todo o conteúdo
    • O motivo para não usar Widevine é que ele adiciona uma etapa de descriptografia, tornando tudo mais lento; força decodificação de vídeo por software, também mais lenta; e os navegadores web só suportam a forma mais fraca do Widevine, que tem pouco efeito
      Além de não ser muito eficaz para atingir o objetivo, provavelmente empurraria uma parte considerável dos usuários para fora da plataforma
    • O principal motivo é que isso reduziria um pouco a eficiência do cache da CDN, gerando custo, e exigiria operar um sistema adicional de gerenciamento de chaves
      Na escala do YouTube, eles querem reduzir ao máximo esse tipo de sistema
      Além disso, transformaria o Widevine Level 3 em um alvo de ataque enorme
      No fim, é uma equação financeira: o dinheiro perdido com bloqueio de anúncios ainda não é suficiente para acionar o interruptor do Widevine, mas já é suficiente para medidas mais fracas; e também deve haver pressão das gravadoras, então é possível que isso seja implantado de forma mais ampla nos próximos anos
      Se eu fosse prever, começaria por vídeos que contenham músicas de gravadoras ou clipes de estúdios detectados pelo Content ID, e talvez oferecessem uma tag opcional para outros criadores
      Esses vídeos são mais úteis para monetização e não fariam perder de uma vez os benefícios da CDN
    • É bem possível que o Google queira desestimular clientes de terceiros, mas permitir que as pessoas façam arquivamento
      Tomar discretamente esse tipo de medida meia-boca é a solução perfeita e talvez a única para atingir esse objetivo
  • Sempre tive curiosidade sobre como o YouTube distribui vídeos
    Ele funcionava bem mesmo quando a internet estava uma bagunça, e na América do Sul nem todas as plataformas rodam bem, mas o YouTube é a plataforma de vídeo mais fluida
    O mais próximo é a Netflix, mas ainda fica bem atrás

    • Eles colocam servidores de cache dentro da rede do ISP, perto da sua casa
      O ISP também se beneficia disso, então permite
      O gargalo do ISP é a conexão entre a própria rede e o backbone mais amplo da internet, e os servidores de cache de uma grande CDN aliviam bastante a carga nesse gargalo
      Documentação da configuração semelhante da Netflix: https://openconnect.netflix.com/
  • Você já tentou baixar um vídeo diretamente do YouTube?
    Fazer isso manualmente, sem depender de youtube-dl, yt-dlp ou desses sites, é bem mais complicado do que parece

    • Muito tempo atrás, trabalhei em um script Perl que fazia isso: https://www.perlmonks.org/?node_id=636777
      Claro que o problema desses scripts é ter de ficar correndo atrás de cada mudança que o YouTube faz para impedir downloads de vídeos
    • Eu trato isso injetando diretamente um script de usuário
      Vendo o WEI, é uma abordagem que usa o meu USER AGENT, que talvez não dure muito
      Em vez de tentar reimplementar assinatura, decodificação de n e funções de limitação de velocidade, encontro o player.js com match(/(?:player\/([a-zA-Z0-9_-]+)\/)?(?:html5player|(?:www|player(?:_ias)?))[-\.]([^/]+?)(?:(?:\/html5player(?:-new)?)?|(?:\/[a-z]{2,3}_[A-Z]{2})?\/base)\.js/) e então faço grep das funções relevantes dentro dele e as chamo diretamente
      Do ponto de vista do YouTube, dá para dizer que parece 100% normal, já que a própria função de DRM dele está abrindo o link .mp4 para mim
    • Você quer dizer apertar o botão “Download” e pagar pelo Premium?
  • Tecnicamente tudo isso é interessante, mas, eticamente, se você não estiver pensando apenas “Google que se dane”, parece razoável parar na primeira otimização, ou seja, passar na verificação de navegador real e obter a velocidade de um navegador comum
    Nesse nível, você não desperdiça mais recursos do YouTube do que um usuário de navegador com bloqueador de anúncios
    Usar a velocidade total em Gb/s sem pagar nada parece testar a sorte de todos os usuários com bloqueador de anúncios
    Claro, no fim das contas talvez seja mesmo Google que se dane

    • Tecnicamente, todo mundo paga pelo custo da conexão de rede
      Eu não diria que atingir o YouTube na velocidade máxima chega a ser antiético, mas também não culpo o YouTube por tomar medidas para bloquear isso
      Uso uma extensão de navegador que mostra imagens de redes sociais em tamanho original ao passar o mouse, e o Instagram exibiu um aviso de atividade anormal e ameaça de bloqueio da conta
      Verifiquei se a extensão estava fazendo scraping por trás, mas não parecia haver nada problemático; provavelmente a Meta vê uma ordem de requisições diferente da do cliente padrão e interpreta isso como scraping de dados
      É um ciclo de medidas e contramedidas, e o YouTube também vai implementar suas próprias defesas para fazer os scrapers reagirem de novo; mas, como um consumo legítimo nunca seria mais rápido que 2x a velocidade de reprodução no cliente oficial, em algum momento eles poderão limitar os downloads a algo nesse nível
      Ainda assim, acho que o download em si não deveria ser limitado
      O conteúdo já é protegido por lei, e a maioria das pessoas baixa vídeos por motivos legítimos, como arquivamento, análise ou criação de vídeos de crítica/review
      O conteúdo do YouTube não é criado no vácuo; depois de publicado, ele cria o ambiente em que novos vídeos serão produzidos, por isso essa liberdade de criação é importante
    • Não tenho certeza de quanto isso é abuso
      No fim, é só receber a mesma quantidade de dados em menos tempo, então usa mais largura de banda, mas desaparece mais rápido
      O caso de uso de um navegador comum parece ajustado para a situação frequente em que a pessoa não assiste ao vídeo até o fim
      Se a intenção desde o começo é assistir tudo e arquivar, é difícil dizer que isso consome mais largura de banda do Google; no máximo, pode haver mais overhead por causa do número de conexões
    • Empresas não têm ética, apenas interesses
      É natural que eu aja de modo parecido
    • Fala-se em recursos do YouTube e Gb/s, mas, na maioria dos casos, o vídeo é servido dentro da rede do mesmo ISP
      Isso porque o YouTube tem caches em praticamente todos os ISPs e pontos de troca de tráfego do mundo, e talvez seja a maior CDN já criada
      Por exemplo, a URL do YouTube do autor do post aponta para o ISP canadense Videotron
      https://bgp.he.net/dns/rr1---sn-8qu-t0aee.googlevideo.com
    • Tecnicamente, deveria ser possível baixar vídeos, e isso não deveria ser bloqueado
      Isso é necessário até para preservar provas de que alguém espalhou discurso de ódio ou insultou você e sua família
      Você poderia filmar a tela com uma filmadora, mas isso soa como uma solução da Idade da Pedra
      Por exemplo, no navegador do Mac, a Netflix não permite tirar screenshots, então até a criação de memes, que se enquadraria em uso justo, foi tirada de nós