- O YouTube está fazendo testes A/B de uma abordagem que impõe a usuários com bloqueador de anúncios um atraso antes do início do vídeo que parece buffering falso, em vez de exibir anúncios
- O atraso é implementado como backoff no streaming SABR, e o InnerTube responde à primeira solicitação de conteúdo
/videoplayback instruindo a aguardar 80% da duração do anúncio
- Usuários que não bloqueiam anúncios carregam o conteúdo enquanto o anúncio é reproduzido, então quase não percebem o atraso mesmo com o mesmo backoff
- Ao enviar
isInlinePlaybackNoAd como true, o InnerTube não fornece anúncios, e o backoff do stream GVS também desaparece; a lista de filtros padrão do uBlock Origin inclui uma evasão relacionada
- Em alguns experimentos, o YouTube atrapalha hooks de filtros com um locker script que bloqueia objetos globais como
JSON.stringify; no Chromium, a evasão é feita com um hook em Object.assign
Onde surge o buffering falso
- Nos últimos meses, o YouTube vem fazendo testes A/B de novas medidas anti-bloqueio de anúncios
- Uma das medidas observadas é um buffering falso que aparece apenas no início do vídeo
- Não ocorre no meio do vídeo
- O tempo de atraso é 80% da duração do anúncio que teria sido visto originalmente
- Mesmo usando um bloqueador de anúncios, ainda se economiza tempo em comparação a assistir ao anúncio inteiro
- Exemplos:
- Se houver um anúncio de 15 segundos, ocorre um backoff de 12 segundos
- Se houver um anúncio não pulável de 6 segundos junto com um anúncio de 15 segundos, ocorre um backoff de 16,8 segundos
O papel do InnerTube, GVS e SABR
- InnerTube é uma API interna usada pelo cliente web e pelos apps móveis do YouTube para obter informações e dados detalhados de vídeos
- O endpoint tem o formato
https://www.youtube.com/youtubei/
/youtubei/v1/player é chamado quando o usuário clica em um vídeo, para obter dados de URL e URLs de streams GVS
- GVS é o Google Video Services, que fornece streams de vídeo do YouTube, Google Drive e Google Photos
- Para fazer streaming de um vídeo pelo GVS, é necessário receber uma URL
/videoplayback do InnerTube ou das APIs internas do Drive/Photos
- As URLs GVS são assinadas e normalmente expiram em 6 horas, portanto não podem ser criadas diretamente
- ISPs podem hospedar servidores Google Global Cache em sua própria infraestrutura, fornecendo tráfego do YouTube sem enviá-lo para fora da rede do ISP
- O GGC fornece apenas vídeos públicos ou parcialmente públicos do YouTube; vídeos privados do YouTube e vídeos do Drive/Photos sempre são fornecidos pelos data centers do Google
- Originalmente, o cliente web do YouTube fazia streaming especificando o intervalo necessário do vídeo como parâmetros de consulta da URL GVS
- Depois, o YouTube passou a usar SABR
- SABR é Server ABR, um protocolo binário próprio do YouTube para bitrate adaptativo do lado do servidor
- Ele foi projetado para evitar buffering melhor do que formatos abertos como MPEG-DASH
- Em vez de enviar dados de vídeo e áudio ao cliente, o servidor pode enviar um backoff, instruindo-o a aguardar por um certo tempo e tentar novamente
O backoff é aplicado independentemente da detecção de bloqueio de anúncios
- O buffering falso ocorre quando o InnerTube fornece um stream GVS que inclui um backoff equivalente a 80% da duração do anúncio na primeira solicitação de conteúdo
/videoplayback
- O alvo não é o stream do anúncio, mas o stream de vídeo do conteúdo
- Os streams de anúncio e de conteúdo continuam separados
- Isso não é inserção de anúncios do lado do servidor; os experimentos de inserção de anúncios do lado do servidor do YouTube são conduzidos separadamente
- A caixa de diálogo “Experiencing interruptions” pode ser disparada por causa do longo backoff do GVS
- Se o usuário estiver no grupo do teste A/B, esse backoff ocorre sempre, independentemente de o YouTube julgar que ele usa bloqueador de anúncios
- Se os anúncios não forem bloqueados, o cliente web carrega o vídeo de conteúdo enquanto o anúncio é reproduzido
- A diferença percebida pelo usuário é que o buffering do vídeo de conteúdo só começa depois que 80% do anúncio já foi exibido
- Alegações online de que o YouTube aumenta drasticamente o uso de CPU de usuários com bloqueador de anúncios e danifica computadores não são verdadeiras
- O YouTube não usa CPU enquanto espera o backoff expirar
- Mesmo que a espera fosse implementada como um spinloop, usar um único núcleo ao máximo por menos de 30 segundos não danifica a CPU
Como evitar a entrega de anúncios com isInlinePlaybackNoAd
- Para evitar o backoff, em vez de esperar até o fim de um anúncio não pulável, é preciso impedir que o anúncio seja fornecido desde o início
- Ao definir a propriedade
playbackContext.contentPlaybackContext.isInlinePlaybackNoAd da solicitação do player como true, o InnerTube não fornece anúncios
- Se anúncios não forem fornecidos, o stream GVS também não inclui backoff
- É possível criar uma regra de filtro que adiciona
"isInlinePlaybackNoAd":true quando o cliente web serializa o JSON para a solicitação ao servidor
www.youtube.com##+js(trusted-replace-outbound-text, JSON.stringify, 'contentPlaybackContext":{', 'contentPlaybackContext":{"isInlinePlaybackNoAd":true,', condition, 'contentPlaybackContext')
- A propriedade
isInlinePlaybackNoAd é referenciada no JavaScript do front-end
- Usando req2proto, é possível extrair a definição protobuf usada nas chamadas a
/youtubei/v1/player e encontrar essa propriedade
- O cliente web do YouTube se comunica com o InnerTube via JSON, mas essa API JSON é gerada a partir de definições de Protocol Buffers
Limitação estável apenas em warm navigation
- Esse método funciona apenas em warm navigation, quando a página de aplicação de página única do YouTube já foi carregada e a navegação ocorre por clique interno
- Em um cold load, ao acessar diretamente a página watch, o backend do YouTube insere a resposta do player diretamente na página como
ytInitialPlayerResponse
- Como a solicitação do player é criada no backend, não é possível definir
isInlinePlaybackNoAd
- Uma forma de contornar o cold load é remover os dados iniciais para forçar a criação de uma solicitação do player controlável
www.youtube.com##+js(set, ytInitialData, undefined) ! bad idea, see below
www.youtube.com##+js(set, ytInitialPlayerResponse, undefined) ! bad idea!
- Essa abordagem tem muitos efeitos colaterais, tornando-a difícil de usar
- Quebra completamente transmissões ao vivo
- Outros recursos não testados também podem quebrar
- O player de vídeo pisca brevemente
- O carregamento da página fica mais lento
Locker script e evasão no Chromium
- Embora o filtro tenha funcionado em certa medida, às vezes o uBlock Origin não conseguia fazer hook em
JSON.stringify
- Em alguns testes A/B, o YouTube adiciona um locker script logo no início da tag
<head> do HTML de front-end
- Esse script usa
Object.defineProperty para tornar fetch, JSON, JSON.stringify, JSON.parse, Array, Array.prototype.push, Array.prototype.forEach etc. non-writable
- Isso impede que código posterior altere o comportamento com
Proxy
- O uBlock Origin só consegue aplicar proxy em
JSON.stringify quando é executado antes do locker script
- No Firefox, é possível remover essa tag de script do HTML de origem antes do parsing da página com um HTML filter
- O Chromium não oferece suporte à API de extensão necessária, então não é possível tratá-lo da mesma forma
- A evasão atual faz hook em
Object.assign em vez de JSON.stringify
Object.assign também é uma função que processa o corpo da solicitação antes do fetch
- Não é uma forma de neutralizar o locker script em si, mas sim uma evasão
- Como o scriptlet do uBO não permite substituição de texto em chaves de objeto, a lista de filtros injeta JavaScript
(() => {
const e = {
apply: (e, n, arguments) => {
let t = Reflect.apply(e, n, arguments);
return 3 === arguments.length && t?.body && "string" == typeof t.body && !t.body.includes(`"isInlinePlaybackNoAd":true`) && (t.body = t.body.replace(`"contentPlaybackContext":{`, `"contentPlaybackContext":{"isInlinePlaybackNoAd":true,`)), t
}
};
window.Object.assign = new Proxy(window.Object.assign, e)
})();
- Os mantenedores do uAssets ajudaram nesse trabalho de evasão
Referências
Ainda não há comentários.