frosty/docs/DESIGN-adblock.md
copilot 1aae7438bb
Some checks failed
CI / Analyze, test, and build Android (push) Has been cancelled
CI / Build iOS (push) Has been cancelled
Add TwitchAdSolutions-style ad blocking for native and WebView players.
Request playback with non-site player types and swap to backup Usher streams on stitched ad breaks; inject vendored vaft into the legacy WebView and expose a Settings toggle.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-30 10:55:50 +02:00

1.7 KiB

Design: Twitch ad blocking (vaft) in Frosty fork

Intent

Personal Forgejo fork of Frosty blocks Twitch live ads using TwitchAdSolutions vaft ideas, adapted to Flutter.

Upstream baseline

Frosty did not ship an adblocker. The native player only detects stitched ad breaks (adBreakStream) to avoid bad latency/stall recovery. Turbo/sub may get hide_ads via linked web GQL session — server-side, not client blocking.

Strategy

Native player (primary — this is the reliable path)

  1. When SettingsStore.blockTwitchAds is true, request PlaybackAccessToken with playerType=popout (vaft ForceAccessTokenPlayerType) instead of site.
  2. When the native plugin reports an ad break, resolve a backup Usher URL trying embed → popout → autoplay, preferring playlists whose media m3u8 does not contain stitched, then loadUrl that stream.
  3. When the ad break ends, restore the primary popout URL.
  4. Overlay shows “Blocking ads” while _blockingAds is true.

Implementation: lib/apis/twitch_ad_solutions.dart, lib/apis/twitch_gql_api.dart, lib/screens/channel/video/native_video_store.dart.

WebView player (legacy, best-effort)

Inject vendored assets/js/vaft.user.js on page start/finish. Not true @run-at document-start on Android via webview_flutter, so native remains preferred. Enabling adblock in Settings forces native on.

Settings

  • blockTwitchAds (default true)
  • Turning adblock on sets useNativePlayer = true

Non-goals

  • Upstream PR
  • Full browser Worker prototype rewriting on native
  • Third-party CDN proxies unless player-type swap proves insufficient