Repository files navigation

FrameWatch

Browser extension for real-time video playback diagnostics. FrameWatch overlays a compact in-page HUD on YouTube, Twitch, and generic HTML5 video players so you can inspect resolution, FPS, dropped frames, buffering, playback state, and observed bitrate without leaving the page.

WXTReactTypeScriptTailwind CSSLicense: AGPL v3

Features

  • In-page Shadow DOM HUD with strong CSS isolation.
  • Active video detection across dynamic pages, SPA navigation, and visible iframe depth.
  • Site adapters for YouTube and Twitch, with a generic HTML5 fallback.
  • Universal HTML5 metrics: decoded resolution, estimated FPS, dropped frames, total frames, buffer ahead, playback rate, ready state, and network state.
  • Observed bitrate estimate from media network resources, shown as N/A when unavailable.
  • Standard fullscreen and detectable pseudo-fullscreen handling.
  • Popup and options pages with persisted browser storage settings.
  • Keyboard command to toggle the HUD: Alt+Shift+Q.
  • English and French extension locales.

Supported Sites

  • YouTube.
  • Twitch.
  • Generic HTML5 video sites.

YouTube and Twitch use site-specific adapters first, then fall back to the generic detector when needed.

Requirements

  • Node.js compatible with WXT and Vite: ^20.19.0 or >=22.12.0.
  • pnpm.
  • Chromium-compatible browser for the default build.
  • Firefox for the Firefox build target.

Getting Started

pnpm install
pnpm dev

WXT prints the development browser target and output directory.

Build

pnpm build # Chromium MV3 build
pnpm build:firefox # Firefox build
pnpm zip # package Chromium build
pnpm zip:firefox # package Firefox build

Load Unpacked

For Chromium:

pnpm build

Then open chrome://extensions, enable Developer mode, click "Load unpacked", and select:

.output/chrome-mv3

Permissions & Privacy

FrameWatch requests storage, tabs, and <all_urls> because the content script needs to detect videos on arbitrary pages and the popup needs to communicate with the active tab.

Settings are stored in browser local extension storage. FrameWatch does not include analytics, does not send collected metrics to a backend, and does not persist video metrics outside the extension UI.

Commands

pnpm dev # run WXT development mode
pnpm dev:firefox # run WXT for Firefox
pnpm build # build Chromium extension
pnpm build:firefox
pnpm zip
pnpm zip:firefox
pnpm lint # Biome lint
pnpm check # Biome check
pnpm compile # TypeScript check
pnpm lints # Biome check + lint + TypeScript check

Repository Layout

  • entrypoints/: WXT background, content, popup, and options entrypoints.
  • src/content/: content-script controller and HUD mounting.
  • src/core/: video detection, metric collection, throughput estimation, and fullscreen handling.
  • src/adapters/: YouTube, Twitch, and generic site adapters.
  • src/hud/: React HUD UI and isolated styles.
  • src/popup/ and src/options/: extension UI surfaces.
  • src/storage/: persisted settings.
  • public/_locales/: Chrome extension i18n messages in English and French.

Limits

  • Browser APIs expose some video metrics inconsistently by site and browser.
  • Cross-origin iframes can block direct video inspection; FrameWatch counts blocked iframes when detection cannot enter them.
  • Observed bitrate is an estimate from media resource timing, not a player-provided ground truth.
  • Safari packaging is not currently documented.

Documentation

French documentation is available in README.fr.md.

License

Licensed under the GNU AGPL-3.0. You are free to use, study, modify, and redistribute it. Any distributed or network-hosted fork must also be released under the AGPL-3.0, which keeps derivatives open.

© 2026 Pierre Guillemot

About

Browser extension for real-time video playback diagnostics on YouTube, Twitch, and HTML5 players. Shadow DOM HUD with FPS, dropped frames, buffer, and bitrate.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

FrameWatch

Browser extension for real-time video playback diagnostics. FrameWatch overlays a compact in-page HUD on YouTube, Twitch, and generic HTML5 video players so you can inspect resolution, FPS, dropped frames, buffering, playback state, and observed bitrate without leaving the page.

WXTReactTypeScriptTailwind CSSLicense: AGPL v3

Features

  • In-page Shadow DOM HUD with strong CSS isolation.
  • Active video detection across dynamic pages, SPA navigation, and visible iframe depth.
  • Site adapters for YouTube and Twitch, with a generic HTML5 fallback.
  • Universal HTML5 metrics: decoded resolution, estimated FPS, dropped frames, total frames, buffer ahead, playback rate, ready state, and network state.
  • Observed bitrate estimate from media network resources, shown as N/A when unavailable.
  • Standard fullscreen and detectable pseudo-fullscreen handling.
  • Popup and options pages with persisted browser storage settings.
  • Keyboard command to toggle the HUD: Alt+Shift+Q.
  • English and French extension locales.

Supported Sites

  • YouTube.
  • Twitch.
  • Generic HTML5 video sites.

YouTube and Twitch use site-specific adapters first, then fall back to the generic detector when needed.

Requirements

  • Node.js compatible with WXT and Vite: ^20.19.0 or >=22.12.0.
  • pnpm.
  • Chromium-compatible browser for the default build.
  • Firefox for the Firefox build target.

Getting Started

pnpm install
pnpm dev

WXT prints the development browser target and output directory.

Build

pnpm build # Chromium MV3 build
pnpm build:firefox # Firefox build
pnpm zip # package Chromium build
pnpm zip:firefox # package Firefox build

Load Unpacked

For Chromium:

pnpm build

Then open chrome://extensions, enable Developer mode, click "Load unpacked", and select:

.output/chrome-mv3

Permissions & Privacy

FrameWatch requests storage, tabs, and <all_urls> because the content script needs to detect videos on arbitrary pages and the popup needs to communicate with the active tab.

Settings are stored in browser local extension storage. FrameWatch does not include analytics, does not send collected metrics to a backend, and does not persist video metrics outside the extension UI.

Commands

pnpm dev # run WXT development mode
pnpm dev:firefox # run WXT for Firefox
pnpm build # build Chromium extension
pnpm build:firefox
pnpm zip
pnpm zip:firefox
pnpm lint # Biome lint
pnpm check # Biome check
pnpm compile # TypeScript check
pnpm lints # Biome check + lint + TypeScript check

Repository Layout

  • entrypoints/: WXT background, content, popup, and options entrypoints.
  • src/content/: content-script controller and HUD mounting.
  • src/core/: video detection, metric collection, throughput estimation, and fullscreen handling.
  • src/adapters/: YouTube, Twitch, and generic site adapters.
  • src/hud/: React HUD UI and isolated styles.
  • src/popup/ and src/options/: extension UI surfaces.
  • src/storage/: persisted settings.
  • public/_locales/: Chrome extension i18n messages in English and French.

Limits

  • Browser APIs expose some video metrics inconsistently by site and browser.
  • Cross-origin iframes can block direct video inspection; FrameWatch counts blocked iframes when detection cannot enter them.
  • Observed bitrate is an estimate from media resource timing, not a player-provided ground truth.
  • Safari packaging is not currently documented.

Documentation

French documentation is available in README.fr.md.

License

Licensed under the GNU AGPL-3.0. You are free to use, study, modify, and redistribute it. Any distributed or network-hosted fork must also be released under the AGPL-3.0, which keeps derivatives open.

© 2026 Pierre Guillemot

About

Browser extension for real-time video playback diagnostics on YouTube, Twitch, and HTML5 players. Shadow DOM HUD with FPS, dropped frames, buffer, and bitrate.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

FrameWatch

Browser extension for real-time video playback diagnostics. FrameWatch overlays a compact in-page HUD on YouTube, Twitch, and generic HTML5 video players so you can inspect resolution, FPS, dropped frames, buffering, playback state, and observed bitrate without leaving the page.

WXTReactTypeScriptTailwind CSSLicense: AGPL v3

Features

  • In-page Shadow DOM HUD with strong CSS isolation.
  • Active video detection across dynamic pages, SPA navigation, and visible iframe depth.
  • Site adapters for YouTube and Twitch, with a generic HTML5 fallback.
  • Universal HTML5 metrics: decoded resolution, estimated FPS, dropped frames, total frames, buffer ahead, playback rate, ready state, and network state.
  • Observed bitrate estimate from media network resources, shown as N/A when unavailable.
  • Standard fullscreen and detectable pseudo-fullscreen handling.
  • Popup and options pages with persisted browser storage settings.
  • Keyboard command to toggle the HUD: Alt+Shift+Q.
  • English and French extension locales.

Supported Sites

  • YouTube.
  • Twitch.
  • Generic HTML5 video sites.

YouTube and Twitch use site-specific adapters first, then fall back to the generic detector when needed.

Requirements

  • Node.js compatible with WXT and Vite: ^20.19.0 or >=22.12.0.
  • pnpm.
  • Chromium-compatible browser for the default build.
  • Firefox for the Firefox build target.

Getting Started

pnpm install
pnpm dev

WXT prints the development browser target and output directory.

Build

pnpm build # Chromium MV3 build
pnpm build:firefox # Firefox build
pnpm zip # package Chromium build
pnpm zip:firefox # package Firefox build

Load Unpacked

For Chromium:

pnpm build

Then open chrome://extensions, enable Developer mode, click "Load unpacked", and select:

.output/chrome-mv3

Permissions & Privacy

FrameWatch requests storage, tabs, and <all_urls> because the content script needs to detect videos on arbitrary pages and the popup needs to communicate with the active tab.

Settings are stored in browser local extension storage. FrameWatch does not include analytics, does not send collected metrics to a backend, and does not persist video metrics outside the extension UI.

Commands

pnpm dev # run WXT development mode
pnpm dev:firefox # run WXT for Firefox
pnpm build # build Chromium extension
pnpm build:firefox
pnpm zip
pnpm zip:firefox
pnpm lint # Biome lint
pnpm check # Biome check
pnpm compile # TypeScript check
pnpm lints # Biome check + lint + TypeScript check

Repository Layout

  • entrypoints/: WXT background, content, popup, and options entrypoints.
  • src/content/: content-script controller and HUD mounting.
  • src/core/: video detection, metric collection, throughput estimation, and fullscreen handling.
  • src/adapters/: YouTube, Twitch, and generic site adapters.
  • src/hud/: React HUD UI and isolated styles.
  • src/popup/ and src/options/: extension UI surfaces.
  • src/storage/: persisted settings.
  • public/_locales/: Chrome extension i18n messages in English and French.

Limits

  • Browser APIs expose some video metrics inconsistently by site and browser.
  • Cross-origin iframes can block direct video inspection; FrameWatch counts blocked iframes when detection cannot enter them.
  • Observed bitrate is an estimate from media resource timing, not a player-provided ground truth.
  • Safari packaging is not currently documented.

Documentation

French documentation is available in README.fr.md.

License

Licensed under the GNU AGPL-3.0. You are free to use, study, modify, and redistribute it. Any distributed or network-hosted fork must also be released under the AGPL-3.0, which keeps derivatives open.

© 2026 Pierre Guillemot

About

Browser extension for real-time video playback diagnostics on YouTube, Twitch, and HTML5 players. Shadow DOM HUD with FPS, dropped frames, buffer, and bitrate.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

FrameWatch

Browser extension for real-time video playback diagnostics. FrameWatch overlays a compact in-page HUD on YouTube, Twitch, and generic HTML5 video players so you can inspect resolution, FPS, dropped frames, buffering, playback state, and observed bitrate without leaving the page.

WXTReactTypeScriptTailwind CSSLicense: AGPL v3

Features

  • In-page Shadow DOM HUD with strong CSS isolation.
  • Active video detection across dynamic pages, SPA navigation, and visible iframe depth.
  • Site adapters for YouTube and Twitch, with a generic HTML5 fallback.
  • Universal HTML5 metrics: decoded resolution, estimated FPS, dropped frames, total frames, buffer ahead, playback rate, ready state, and network state.
  • Observed bitrate estimate from media network resources, shown as N/A when unavailable.
  • Standard fullscreen and detectable pseudo-fullscreen handling.
  • Popup and options pages with persisted browser storage settings.
  • Keyboard command to toggle the HUD: Alt+Shift+Q.
  • English and French extension locales.

Supported Sites

  • YouTube.
  • Twitch.
  • Generic HTML5 video sites.

YouTube and Twitch use site-specific adapters first, then fall back to the generic detector when needed.

Requirements

  • Node.js compatible with WXT and Vite: ^20.19.0 or >=22.12.0.
  • pnpm.
  • Chromium-compatible browser for the default build.
  • Firefox for the Firefox build target.

Getting Started

pnpm install
pnpm dev

WXT prints the development browser target and output directory.

Build

pnpm build # Chromium MV3 build
pnpm build:firefox # Firefox build
pnpm zip # package Chromium build
pnpm zip:firefox # package Firefox build

Load Unpacked

For Chromium:

pnpm build

Then open chrome://extensions, enable Developer mode, click "Load unpacked", and select:

.output/chrome-mv3

Permissions & Privacy

FrameWatch requests storage, tabs, and <all_urls> because the content script needs to detect videos on arbitrary pages and the popup needs to communicate with the active tab.

Settings are stored in browser local extension storage. FrameWatch does not include analytics, does not send collected metrics to a backend, and does not persist video metrics outside the extension UI.

Commands

pnpm dev # run WXT development mode
pnpm dev:firefox # run WXT for Firefox
pnpm build # build Chromium extension
pnpm build:firefox
pnpm zip
pnpm zip:firefox
pnpm lint # Biome lint
pnpm check # Biome check
pnpm compile # TypeScript check
pnpm lints # Biome check + lint + TypeScript check

Repository Layout

  • entrypoints/: WXT background, content, popup, and options entrypoints.
  • src/content/: content-script controller and HUD mounting.
  • src/core/: video detection, metric collection, throughput estimation, and fullscreen handling.
  • src/adapters/: YouTube, Twitch, and generic site adapters.
  • src/hud/: React HUD UI and isolated styles.
  • src/popup/ and src/options/: extension UI surfaces.
  • src/storage/: persisted settings.
  • public/_locales/: Chrome extension i18n messages in English and French.

Limits

  • Browser APIs expose some video metrics inconsistently by site and browser.
  • Cross-origin iframes can block direct video inspection; FrameWatch counts blocked iframes when detection cannot enter them.
  • Observed bitrate is an estimate from media resource timing, not a player-provided ground truth.
  • Safari packaging is not currently documented.

Documentation

French documentation is available in README.fr.md.

License

Licensed under the GNU AGPL-3.0. You are free to use, study, modify, and redistribute it. Any distributed or network-hosted fork must also be released under the AGPL-3.0, which keeps derivatives open.

© 2026 Pierre Guillemot

About

Browser extension for real-time video playback diagnostics on YouTube, Twitch, and HTML5 players. Shadow DOM HUD with FPS, dropped frames, buffer, and bitrate.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

FrameWatch

Browser extension for real-time video playback diagnostics. FrameWatch overlays a compact in-page HUD on YouTube, Twitch, and generic HTML5 video players so you can inspect resolution, FPS, dropped frames, buffering, playback state, and observed bitrate without leaving the page.

WXTReactTypeScriptTailwind CSSLicense: AGPL v3

Features

  • In-page Shadow DOM HUD with strong CSS isolation.
  • Active video detection across dynamic pages, SPA navigation, and visible iframe depth.
  • Site adapters for YouTube and Twitch, with a generic HTML5 fallback.
  • Universal HTML5 metrics: decoded resolution, estimated FPS, dropped frames, total frames, buffer ahead, playback rate, ready state, and network state.
  • Observed bitrate estimate from media network resources, shown as N/A when unavailable.
  • Standard fullscreen and detectable pseudo-fullscreen handling.
  • Popup and options pages with persisted browser storage settings.
  • Keyboard command to toggle the HUD: Alt+Shift+Q.
  • English and French extension locales.

Supported Sites

  • YouTube.
  • Twitch.
  • Generic HTML5 video sites.

YouTube and Twitch use site-specific adapters first, then fall back to the generic detector when needed.

Requirements

  • Node.js compatible with WXT and Vite: ^20.19.0 or >=22.12.0.
  • pnpm.
  • Chromium-compatible browser for the default build.
  • Firefox for the Firefox build target.

Getting Started

pnpm install
pnpm dev

WXT prints the development browser target and output directory.

Build

pnpm build # Chromium MV3 build
pnpm build:firefox # Firefox build
pnpm zip # package Chromium build
pnpm zip:firefox # package Firefox build

Load Unpacked

For Chromium:

pnpm build

Then open chrome://extensions, enable Developer mode, click "Load unpacked", and select:

.output/chrome-mv3

Permissions & Privacy

FrameWatch requests storage, tabs, and <all_urls> because the content script needs to detect videos on arbitrary pages and the popup needs to communicate with the active tab.

Settings are stored in browser local extension storage. FrameWatch does not include analytics, does not send collected metrics to a backend, and does not persist video metrics outside the extension UI.

Commands

pnpm dev # run WXT development mode
pnpm dev:firefox # run WXT for Firefox
pnpm build # build Chromium extension
pnpm build:firefox
pnpm zip
pnpm zip:firefox
pnpm lint # Biome lint
pnpm check # Biome check
pnpm compile # TypeScript check
pnpm lints # Biome check + lint + TypeScript check

Repository Layout

  • entrypoints/: WXT background, content, popup, and options entrypoints.
  • src/content/: content-script controller and HUD mounting.
  • src/core/: video detection, metric collection, throughput estimation, and fullscreen handling.
  • src/adapters/: YouTube, Twitch, and generic site adapters.
  • src/hud/: React HUD UI and isolated styles.
  • src/popup/ and src/options/: extension UI surfaces.
  • src/storage/: persisted settings.
  • public/_locales/: Chrome extension i18n messages in English and French.

Limits

  • Browser APIs expose some video metrics inconsistently by site and browser.
  • Cross-origin iframes can block direct video inspection; FrameWatch counts blocked iframes when detection cannot enter them.
  • Observed bitrate is an estimate from media resource timing, not a player-provided ground truth.
  • Safari packaging is not currently documented.

Documentation

French documentation is available in README.fr.md.

License

Licensed under the GNU AGPL-3.0. You are free to use, study, modify, and redistribute it. Any distributed or network-hosted fork must also be released under the AGPL-3.0, which keeps derivatives open.

© 2026 Pierre Guillemot

About

Browser extension for real-time video playback diagnostics on YouTube, Twitch, and HTML5 players. Shadow DOM HUD with FPS, dropped frames, buffer, and bitrate.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

FrameWatch

Browser extension for real-time video playback diagnostics. FrameWatch overlays a compact in-page HUD on YouTube, Twitch, and generic HTML5 video players so you can inspect resolution, FPS, dropped frames, buffering, playback state, and observed bitrate without leaving the page.

WXTReactTypeScriptTailwind CSSLicense: AGPL v3

Features

  • In-page Shadow DOM HUD with strong CSS isolation.
  • Active video detection across dynamic pages, SPA navigation, and visible iframe depth.
  • Site adapters for YouTube and Twitch, with a generic HTML5 fallback.
  • Universal HTML5 metrics: decoded resolution, estimated FPS, dropped frames, total frames, buffer ahead, playback rate, ready state, and network state.
  • Observed bitrate estimate from media network resources, shown as N/A when unavailable.
  • Standard fullscreen and detectable pseudo-fullscreen handling.
  • Popup and options pages with persisted browser storage settings.
  • Keyboard command to toggle the HUD: Alt+Shift+Q.
  • English and French extension locales.

Supported Sites

  • YouTube.
  • Twitch.
  • Generic HTML5 video sites.

YouTube and Twitch use site-specific adapters first, then fall back to the generic detector when needed.

Requirements

  • Node.js compatible with WXT and Vite: ^20.19.0 or >=22.12.0.
  • pnpm.
  • Chromium-compatible browser for the default build.
  • Firefox for the Firefox build target.

Getting Started

pnpm install
pnpm dev

WXT prints the development browser target and output directory.

Build

pnpm build # Chromium MV3 build
pnpm build:firefox # Firefox build
pnpm zip # package Chromium build
pnpm zip:firefox # package Firefox build

Load Unpacked

For Chromium:

pnpm build

Then open chrome://extensions, enable Developer mode, click "Load unpacked", and select:

.output/chrome-mv3

Permissions & Privacy

FrameWatch requests storage, tabs, and <all_urls> because the content script needs to detect videos on arbitrary pages and the popup needs to communicate with the active tab.

Settings are stored in browser local extension storage. FrameWatch does not include analytics, does not send collected metrics to a backend, and does not persist video metrics outside the extension UI.

Commands

pnpm dev # run WXT development mode
pnpm dev:firefox # run WXT for Firefox
pnpm build # build Chromium extension
pnpm build:firefox
pnpm zip
pnpm zip:firefox
pnpm lint # Biome lint
pnpm check # Biome check
pnpm compile # TypeScript check
pnpm lints # Biome check + lint + TypeScript check

Repository Layout

  • entrypoints/: WXT background, content, popup, and options entrypoints.
  • src/content/: content-script controller and HUD mounting.
  • src/core/: video detection, metric collection, throughput estimation, and fullscreen handling.
  • src/adapters/: YouTube, Twitch, and generic site adapters.
  • src/hud/: React HUD UI and isolated styles.
  • src/popup/ and src/options/: extension UI surfaces.
  • src/storage/: persisted settings.
  • public/_locales/: Chrome extension i18n messages in English and French.

Limits

  • Browser APIs expose some video metrics inconsistently by site and browser.
  • Cross-origin iframes can block direct video inspection; FrameWatch counts blocked iframes when detection cannot enter them.
  • Observed bitrate is an estimate from media resource timing, not a player-provided ground truth.
  • Safari packaging is not currently documented.

Documentation

French documentation is available in README.fr.md.

License

Licensed under the GNU AGPL-3.0. You are free to use, study, modify, and redistribute it. Any distributed or network-hosted fork must also be released under the AGPL-3.0, which keeps derivatives open.

© 2026 Pierre Guillemot

About

Browser extension for real-time video playback diagnostics on YouTube, Twitch, and HTML5 players. Shadow DOM HUD with FPS, dropped frames, buffer, and bitrate.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

FrameWatch

Browser extension for real-time video playback diagnostics. FrameWatch overlays a compact in-page HUD on YouTube, Twitch, and generic HTML5 video players so you can inspect resolution, FPS, dropped frames, buffering, playback state, and observed bitrate without leaving the page.

WXTReactTypeScriptTailwind CSSLicense: AGPL v3

Features

  • In-page Shadow DOM HUD with strong CSS isolation.
  • Active video detection across dynamic pages, SPA navigation, and visible iframe depth.
  • Site adapters for YouTube and Twitch, with a generic HTML5 fallback.
  • Universal HTML5 metrics: decoded resolution, estimated FPS, dropped frames, total frames, buffer ahead, playback rate, ready state, and network state.
  • Observed bitrate estimate from media network resources, shown as N/A when unavailable.
  • Standard fullscreen and detectable pseudo-fullscreen handling.
  • Popup and options pages with persisted browser storage settings.
  • Keyboard command to toggle the HUD: Alt+Shift+Q.
  • English and French extension locales.

Supported Sites

  • YouTube.
  • Twitch.
  • Generic HTML5 video sites.

YouTube and Twitch use site-specific adapters first, then fall back to the generic detector when needed.

Requirements

  • Node.js compatible with WXT and Vite: ^20.19.0 or >=22.12.0.
  • pnpm.
  • Chromium-compatible browser for the default build.
  • Firefox for the Firefox build target.

Getting Started

pnpm install
pnpm dev

WXT prints the development browser target and output directory.

Build

pnpm build # Chromium MV3 build
pnpm build:firefox # Firefox build
pnpm zip # package Chromium build
pnpm zip:firefox # package Firefox build

Load Unpacked

For Chromium:

pnpm build

Then open chrome://extensions, enable Developer mode, click "Load unpacked", and select:

.output/chrome-mv3

Permissions & Privacy

FrameWatch requests storage, tabs, and <all_urls> because the content script needs to detect videos on arbitrary pages and the popup needs to communicate with the active tab.

Settings are stored in browser local extension storage. FrameWatch does not include analytics, does not send collected metrics to a backend, and does not persist video metrics outside the extension UI.

Commands

pnpm dev # run WXT development mode
pnpm dev:firefox # run WXT for Firefox
pnpm build # build Chromium extension
pnpm build:firefox
pnpm zip
pnpm zip:firefox
pnpm lint # Biome lint
pnpm check # Biome check
pnpm compile # TypeScript check
pnpm lints # Biome check + lint + TypeScript check

Repository Layout

  • entrypoints/: WXT background, content, popup, and options entrypoints.
  • src/content/: content-script controller and HUD mounting.
  • src/core/: video detection, metric collection, throughput estimation, and fullscreen handling.
  • src/adapters/: YouTube, Twitch, and generic site adapters.
  • src/hud/: React HUD UI and isolated styles.
  • src/popup/ and src/options/: extension UI surfaces.
  • src/storage/: persisted settings.
  • public/_locales/: Chrome extension i18n messages in English and French.

Limits

  • Browser APIs expose some video metrics inconsistently by site and browser.
  • Cross-origin iframes can block direct video inspection; FrameWatch counts blocked iframes when detection cannot enter them.
  • Observed bitrate is an estimate from media resource timing, not a player-provided ground truth.
  • Safari packaging is not currently documented.

Documentation

French documentation is available in README.fr.md.

License

Licensed under the GNU AGPL-3.0. You are free to use, study, modify, and redistribute it. Any distributed or network-hosted fork must also be released under the AGPL-3.0, which keeps derivatives open.

© 2026 Pierre Guillemot

About

Browser extension for real-time video playback diagnostics on YouTube, Twitch, and HTML5 players. Shadow DOM HUD with FPS, dropped frames, buffer, and bitrate.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

FrameWatch

Browser extension for real-time video playback diagnostics. FrameWatch overlays a compact in-page HUD on YouTube, Twitch, and generic HTML5 video players so you can inspect resolution, FPS, dropped frames, buffering, playback state, and observed bitrate without leaving the page.

WXTReactTypeScriptTailwind CSSLicense: AGPL v3

Features

  • In-page Shadow DOM HUD with strong CSS isolation.
  • Active video detection across dynamic pages, SPA navigation, and visible iframe depth.
  • Site adapters for YouTube and Twitch, with a generic HTML5 fallback.
  • Universal HTML5 metrics: decoded resolution, estimated FPS, dropped frames, total frames, buffer ahead, playback rate, ready state, and network state.
  • Observed bitrate estimate from media network resources, shown as N/A when unavailable.
  • Standard fullscreen and detectable pseudo-fullscreen handling.
  • Popup and options pages with persisted browser storage settings.
  • Keyboard command to toggle the HUD: Alt+Shift+Q.
  • English and French extension locales.

Supported Sites

  • YouTube.
  • Twitch.
  • Generic HTML5 video sites.

YouTube and Twitch use site-specific adapters first, then fall back to the generic detector when needed.

Requirements

  • Node.js compatible with WXT and Vite: ^20.19.0 or >=22.12.0.
  • pnpm.
  • Chromium-compatible browser for the default build.
  • Firefox for the Firefox build target.

Getting Started

pnpm install
pnpm dev

WXT prints the development browser target and output directory.

Build

pnpm build # Chromium MV3 build
pnpm build:firefox # Firefox build
pnpm zip # package Chromium build
pnpm zip:firefox # package Firefox build

Load Unpacked

For Chromium:

pnpm build

Then open chrome://extensions, enable Developer mode, click "Load unpacked", and select:

.output/chrome-mv3

Permissions & Privacy

FrameWatch requests storage, tabs, and <all_urls> because the content script needs to detect videos on arbitrary pages and the popup needs to communicate with the active tab.

Settings are stored in browser local extension storage. FrameWatch does not include analytics, does not send collected metrics to a backend, and does not persist video metrics outside the extension UI.

Commands

pnpm dev # run WXT development mode
pnpm dev:firefox # run WXT for Firefox
pnpm build # build Chromium extension
pnpm build:firefox
pnpm zip
pnpm zip:firefox
pnpm lint # Biome lint
pnpm check # Biome check
pnpm compile # TypeScript check
pnpm lints # Biome check + lint + TypeScript check

Repository Layout

  • entrypoints/: WXT background, content, popup, and options entrypoints.
  • src/content/: content-script controller and HUD mounting.
  • src/core/: video detection, metric collection, throughput estimation, and fullscreen handling.
  • src/adapters/: YouTube, Twitch, and generic site adapters.
  • src/hud/: React HUD UI and isolated styles.
  • src/popup/ and src/options/: extension UI surfaces.
  • src/storage/: persisted settings.
  • public/_locales/: Chrome extension i18n messages in English and French.

Limits

  • Browser APIs expose some video metrics inconsistently by site and browser.
  • Cross-origin iframes can block direct video inspection; FrameWatch counts blocked iframes when detection cannot enter them.
  • Observed bitrate is an estimate from media resource timing, not a player-provided ground truth.
  • Safari packaging is not currently documented.

Documentation

French documentation is available in README.fr.md.

License

Licensed under the GNU AGPL-3.0. You are free to use, study, modify, and redistribute it. Any distributed or network-hosted fork must also be released under the AGPL-3.0, which keeps derivatives open.

© 2026 Pierre Guillemot

About

Browser extension for real-time video playback diagnostics on YouTube, Twitch, and HTML5 players. Shadow DOM HUD with FPS, dropped frames, buffer, and bitrate.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages