- YouTube testet per A/B-Test eine Methode, bei Nutzern mit Adblocker statt Werbung vor dem Start des Videos eine Verzögerung zu erzeugen, die wie künstliches Buffering aussieht
- Die Verzögerung wird als backoff im SABR-Streaming umgesetzt; InnerTube antwortet auf die erste
/videoplayback-Anfrage für den Inhalt mit der Anweisung, für 80 % der Werbedauer zu warten
- Bei Nutzern ohne Adblocker wird der Inhalt bereits während der Werbewiedergabe geladen, sodass derselbe backoff subjektiv kaum als Verzögerung auffällt
- Wenn
isInlinePlaybackNoAd auf true gesetzt wird, liefert InnerTube keine Werbung aus; dadurch entfällt auch der backoff im GVS-Stream, und die Standard-Filterliste von uBlock Origin enthält einen entsprechenden Workaround
- In manchen Experimenten stört YouTube Filter-Hooks mit einem locker script, das globale Objekte wie
JSON.stringify sperrt; in Chromium lässt sich das über einen Object.assign-Hook umgehen
Wo das künstliche Buffering entsteht
- YouTube testet seit einigen Monaten neue Anti-Adblock-Maßnahmen per A/B-Test
- Eine der beobachteten Maßnahmen ist künstliches Buffering, das nur beim Start eines Videos auftritt
- Es tritt nicht mitten im Video auf
- Die Verzögerung beträgt 80 % der Länge der Werbung, die man sonst gesehen hätte
- Selbst mit Adblocker spart man also immer noch Zeit gegenüber dem vollständigen Ansehen der Werbung
- Beispiele:
- Bei einer 15-Sekunden-Werbung entsteht ein backoff von 12 Sekunden
- Wenn eine nicht überspringbare 6-Sekunden-Werbung zusammen mit einer 15-Sekunden-Werbung läuft, entsteht ein backoff von 16,8 Sekunden
Die Rolle von InnerTube, GVS und SABR
- InnerTube ist die interne API, über die der YouTube-Webclient und die mobilen Apps Videoinformationen und Details abrufen
- Die Endpunkte haben die Form
https://www.youtube.com/youtubei/
/youtubei/v1/player wird aufgerufen, wenn ein Nutzer auf ein Video klickt, um URL-Daten und die GVS-Stream-URL zu erhalten
- GVS ist Google Video Services, das Videostreams für YouTube, Google Drive und Google Photos bereitstellt
- Um ein Video über GVS zu streamen, muss man eine
/videoplayback-URL von InnerTube oder einer internen API von Drive/Photos erhalten
- GVS-URLs sind signiert und haben normalerweise eine Ablaufzeit von 6 Stunden, daher lassen sie sich nicht direkt erzeugen
- ISPs können Google Global Cache-Server in ihrer eigenen Infrastruktur betreiben, sodass YouTube-Traffic nicht das ISP-Netz verlassen muss
- GGC liefert nur öffentliche oder teils öffentliche YouTube-Videos aus; private YouTube-Videos und Drive/Photos-Videos kommen immer aus Google-Rechenzentren
- Der YouTube-Webclient streamte ursprünglich, indem er den benötigten Videobereich über Query-Parameter der GVS-URL angab
- Später wechselte YouTube zu SABR
- SABR steht für Server ABR, also YouTubes proprietäres binäres Protokoll für serverseitiges adaptives Bitraten-Streaming
- Es ist darauf ausgelegt, Buffering besser zu vermeiden als offene Formate wie MPEG-DASH
- Der Server kann dem Client statt Video- und Audiodaten einen backoff schicken, also die Anweisung, eine bestimmte Zeit zu warten und es dann erneut zu versuchen
backoff wird unabhängig von der Adblock-Erkennung angewendet
- Das künstliche Buffering entsteht, weil InnerTube beim ersten
/videoplayback-Request für den Inhalt einen GVS-Stream mit einem backoff von 80 % der Werbedauer liefert
- Betroffen ist nicht der Werbestream, sondern der Stream des eigentlichen Inhalts
- Werbung und Inhaltsstream bleiben weiterhin getrennt
- Es handelt sich also nicht um serverseitige Werbeeinblendung; entsprechende YouTube-Experimente dazu laufen separat
- Der Dialog „Experiencing interruptions“ wird vermutlich durch den langen backoff von GVS ausgelöst
- Wenn man Teil des A/B-Tests ist, tritt dieser backoff immer auf, unabhängig davon, ob YouTube den Nutzer als Adblock-Nutzer einstuft
- Ohne Adblock lädt der Webclient den eigentlichen Videoinhalt bereits während der Werbewiedergabe
- Der wahrnehmbare Unterschied besteht nur darin, dass das Buffering des Inhalts erst beginnt, nachdem 80 % der Werbung abgespielt wurden
- Online-Behauptungen, YouTube lasse bei Adblock-Nutzern die CPU-Auslastung massiv ansteigen und beschädige so Computer, sind falsch
- Während auf das Ende des backoff gewartet wird, verbraucht YouTube keine CPU
- Selbst wenn das Warten als Spinloop umgesetzt würde, würde eine Auslastung eines einzelnen CPU-Kerns für unter 30 Sekunden keine CPU beschädigen
Werbung mit isInlinePlaybackNoAd vermeiden
- Um den backoff zu vermeiden, darf Werbung gar nicht erst ausgeliefert werden, statt nur das Ende nicht überspringbarer Werbung abzuwarten
- Wenn in der Player-Anfrage
playbackContext.contentPlaybackContext.isInlinePlaybackNoAd auf true gesetzt wird, liefert InnerTube keine Werbung aus
- Wenn keine Werbung ausgeliefert wird, enthält auch der GVS-Stream keinen backoff
- Man kann eine Filterregel erstellen, die beim Stringifizieren des JSONs für Server-Requests
"isInlinePlaybackNoAd":true einfügt
www.youtube.com##+js(trusted-replace-outbound-text, JSON.stringify, 'contentPlaybackContext":{', 'contentPlaybackContext":{"isInlinePlaybackNoAd":true,', condition, 'contentPlaybackContext')
- Die Eigenschaft
isInlinePlaybackNoAd wird im Frontend-JavaScript referenziert
- Mit req2proto lässt sich die für
/youtubei/v1/player verwendete Protobuf-Definition extrahieren, in der sich diese Eigenschaft finden lässt
- Der YouTube-Webclient kommuniziert mit InnerTube zwar per JSON, aber diese JSON-API wird aus Protocol-Buffer-Definitionen generiert
Einschränkung: nur bei warm navigation zuverlässig
- Diese Methode funktioniert nur bei warm navigation, also wenn die YouTube-Single-Page-App bereits geladen ist und man intern weiterklickt
- Bei einem direkten Aufruf der Watch-Seite, also einem cold load, bettet das YouTube-Backend die Player-Antwort direkt als
ytInitialPlayerResponse in die Seite ein
- Da die Player-Anfrage im Backend erzeugt wird, lässt sich
isInlinePlaybackNoAd hier nicht setzen
- Eine Möglichkeit, cold load zu umgehen, besteht darin, die initialen Daten zu entfernen, damit erzwungen wird, dass eine kontrollierbare Player-Anfrage erzeugt wird
www.youtube.com##+js(set, ytInitialData, undefined) ! bad idea, see below
www.youtube.com##+js(set, ytInitialPlayerResponse, undefined) ! bad idea!
- Dieser Ansatz hat starke Nebenwirkungen und ist praktisch schwer nutzbar
- Livestreams werden komplett kaputtgemacht
- Auch andere, nicht getestete Funktionen können kaputtgehen
- Der Videoplayer flackert kurz
- Die Seitenladezeit wird langsamer
locker script und Chromium-Workaround
- Der Filter funktionierte teilweise, aber manchmal konnte uBlock Origin
JSON.stringify nicht hooken
- In manchen A/B-Tests fügt YouTube ganz am Anfang des
<head>-Tags im Frontend-HTML ein locker script ein
- Dieses Skript setzt per
Object.defineProperty Objekte wie fetch, JSON, JSON.stringify, JSON.parse, Array, Array.prototype.push, Array.prototype.forEach usw. auf non-writable
- Damit soll verhindert werden, dass späterer Code das Verhalten per
Proxy verändert
- uBlock Origin kann
JSON.stringify nur dann per Proxy abfangen, wenn es vor dem locker script ausgeführt wird
- In Firefox lässt sich das betreffende Skript-Tag per HTML filter schon vor dem Parsen der Seite aus dem Quell-HTML entfernen
- Chromium unterstützt die dafür nötige Erweiterungs-API nicht, daher funktioniert derselbe Ansatz dort nicht
- Der aktuelle Workaround besteht darin, statt
JSON.stringify Object.assign zu hooken
Object.assign ist ebenfalls eine Funktion, die den Request-Body vor fetch verarbeitet
- Das ist weniger ein Ausschalten des locker script als eher ein Umgehen
- Weil uBO-Scriptlets keine Text-Ersetzung von Objektschlüsseln erlauben, injiziert die Filterliste 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)
})();
- An diesem Workaround waren die Maintainer von uAssets beteiligt
Referenzen
Noch keine Kommentare.