Skip to content

kindlyops/hls-monitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hls-monitor

A Chrome extension for monitoring the performance and availability of HLS video livestreams playing in the browser. It watches the network traffic a player (hls.js, video.js, Shaka, etc.) produces and records, for every playlist and media-segment request:

  • TTFB (time to first byte) and download time
  • size (from Content-Length) and throughput
  • HTTP status, cache hits, server IP, and network errors
  • download speed vs realtime — how much faster than its media duration each segment downloads (below ~1× means imminent rebuffering)

It also re-fetches and parses the playlists themselves to track playlist refresh cadence, target duration, and media sequence advancement, so it can tell you when a live stream has stalled at the origin (playlist stops advancing) versus failing to download (segment errors) versus slowing down (shrinking download headroom).

Install

Chrome on desktop (Windows, Mac, Linux, ChromeOS)

  1. Download the extension ZIP from the latest release and unzip it. (Or clone this repo and use its extension/ folder — same thing.)
  2. Open chrome://extensions in Chrome.
  3. Turn on Developer mode (toggle in the top-right corner).
  4. Click Load unpacked and select the unzipped folder.
  5. Done. Open any page playing an HLS stream — the toolbar badge turns green with HLS when a stream is detected, or shows a red error count if segment requests are failing. Click the icon for details.

The same steps work in other desktop Chromium browsers (Edge, Brave, Opera, Vivaldi) via their own extensions page.

Chrome on mobile

Chrome for Android and iOS does not support extensions, so HLS Monitor cannot be installed in mobile Chrome itself.

  • Android: use a Chromium-based browser that supports extensions — for example Microsoft Edge Canary or Lemur Browser. Enable developer mode on its extensions page and load the same release ZIP.
  • iOS/iPadOS: there is no way to run Chrome extensions on iOS — use the monitor page instead, which needs no install at all.

Monitor without the extension (iPad, mobile, any browser)

https://kindlyops.github.io/hls-monitor/monitor.html is a standalone monitor: give it an .m3u8 URL and it fetches the playlist and segments itself on the standard HLS cadence, measuring every request — the same dashboard as the extension, in any browser on any device. It doesn't decode video; like the extension, it measures delivery. Master playlists get a variant picker (highest bandwidth auto-selected).

The catch: it only works on CORS-enabled streams. A web page can only read another origin's responses if that server sends Access-Control-Allow-Origin, and many streams don't. When the header is missing the monitor shows a CORS error and can go no further — no browser page can, that's the browser's cross-origin rule. The Chrome extension has no such limit (it observes the player's own traffic), so streams without CORS can only be monitored from desktop. If you control the origin, adding Access-Control-Allow-Origin: * to playlists and segments enables the monitor page.

Two one-tap launchers discover the stream URL on whatever page is currently playing it (from Resource Timing, <video> elements, and .m3u8 URLs embedded in the page markup) and open the monitor — set them up at https://kindlyops.github.io/hls-monitor/ipad.html:

  • an Apple Shortcuts share-sheet action (best on iPad/iPhone), and
  • a bookmarklet (works everywhere, including desktop browsers, with zero install).

Limitations vs the extension: launchers can't see players inside cross-origin iframes, and the monitor measures its own fetches rather than the page player's traffic.

Releases

Every merge to main that changes extension/ automatically publishes a new GitHub Release: the workflow patch-bumps the latest version tag (e.g. v0.1.3v0.1.4, starting at v0.1.0), stamps the version into manifest.json, and attaches the installable ZIP.

For a minor or major bump, run the Release extension workflow manually from the Actions tab and enter the version (e.g. 0.3.0).

Use

  • Popup (click the toolbar icon): at-a-glance health of the stream in the active tab — status, segment count, errors, average TTFB/throughput, download speed, and last-segment age.
  • Side panel (popup → Open side panel): the dashboard docked next to the player page, so you can watch the livestream and its metrics at the same time. It follows the active tab, and its header has a live segment counter with a pulse animation that fires each time a new video segment arrives. The panel is only available on tabs with a detected stream — switching to a tab without one hides it. Failed requests are drawn as red ✗ marks on the charts.
  • Full dashboard (popup → Full dashboard): the same view as a full page — live charts of per-segment TTFB and throughput, playlist health (refresh cadence, media sequence, advancement), a table of recent requests, the segment-arrival pulse, and Export JSON for offline analysis. Opening panel.html without a ?tab= parameter lists all tabs with detected streams.

Status levels: Live, healthySlow (average download speed under 1.2× realtime) → ErrorsNo segments / Stalled / Failing.

The parse playlists toggle controls whether the extension re-fetches playlists to read their bodies (needed for target duration, media sequence, and per-segment durations). It is throttled to the player's own refresh cadence; turn it off if you don't want the extra origin requests.

Website

The landing page is served with GitHub Pages at https://kindlyops.github.io/hls-monitor/ (deployed automatically from site/ on every push to main by .github/workflows/pages.yml).

site/ is a three.js landing page for the extension: a broadcast tower streams video frames along a glowing pipeline while the Inspector — a scientist with glasses and a clipboard — checks each one as it flows by. Good segments earn a ✓ 200 OK and land in a floating browser window; bad ones are flagged ✗ 404 and ejected. The stream continues on to a retro TV watched by an old man on his couch, and a live HUD tallies segments inspected, delivered, and flagged.

The page is fully self-contained (three.js is vendored), so any static file server works:

python3 -m http.server 8899 -d site
# then open http://127.0.0.1:8899/

Test drive locally

test/server.py is a fake live HLS origin (sliding-window playlist like example/master_720p.m3u8, advancing every 2s) plus a synthetic player page that fetches playlists and segments exactly like a real player:

python3 test/server.py                    # healthy stream
python3 test/server.py --fail-every 5     # every 5th segment 404s
python3 test/server.py --slow-every 4 --slow-ms 1500   # inject latency

Then open http://127.0.0.1:8765/ in Chrome with the extension loaded.

The monitor page works against the same fake origin — handy on any device on your LAN:

python3 test/server.py --fail-every 5
python3 -m http.server 8899 -d site
# open http://127.0.0.1:8899/monitor.html and paste
# http://127.0.0.1:8765/stream/live.m3u8

Automated end-to-end check

node test/verify.mjs          # extension
node test/verify-monitor.mjs  # monitor page + launcher discovery

verify.mjs starts the fake origin, loads the extension into headless Chromium via Playwright, streams for ~14s, asserts the recorded metrics (TTFB, sizes, parsed durations, media-sequence tracking, injected 404s), and screenshots the dashboard to dashboard.png.

verify-monitor.mjs does the same for the monitor page (served statically from site/), and also runs the launcher discovery snippet inside the synthetic player page and asserts it finds the playlist URL. Screenshot goes to monitor.png.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors