Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

streamtop

streamtop is a Rust CLI and terminal UI for monitoring live video streams. Point it at an HLS playlist (.m3u8), an MPEG-DASH manifest (.mpd), an IPTV channel list (.m3u, .json, .yaml), or a WHEP HTTP endpoint. It shows segment timing, codec data read from the wire, ad markers, and health scores in the terminal, without a browser or GUI player.

Typical uses:

  • Debug CDN and origin issues on a live channel (TTFB, HTTP status, cache HIT/MISS, stalls).
  • Check encoder output against the manifest (resolution, FPS, GOP, audio).
  • See SCTE-35 ad markers in HLS tags and DASH emsg boxes.
  • Check which channels in an IPTV playlist are working.
  • Gate CI on a stream with PASS/FAIL JSON, SARIF, or budget thresholds.
  • Scrape Prometheus metrics or send OTLP traces from a live probe.
cargo install streamtop
streamtop "https://example.com/master.m3u8"

Source code, issues, and releases: github.com/Jorji49/streamtop. License: MIT.

Install

Prebuilt binaries for Linux (x86_64 and arm64, glibc and musl), macOS (Apple Silicon and Intel), and Windows x86_64 are on GitHub Releases. Each release includes SHA256SUMS.

# Linux x86_64 (static musl build); use the -gnu archive for glibc
curl -LO https://github.com/Jorji49/streamtop/releases/latest/download/streamtop-x86_64-unknown-linux-musl.tar.gz
curl -LO https://github.com/Jorji49/streamtop/releases/latest/download/SHA256SUMS
sha256sum -c --ignore-missing SHA256SUMS
tar xzf streamtop-x86_64-unknown-linux-musl.tar.gz

cargo

cargo install streamtop
# or, to download a prebuilt binary:
cargo install cargo-binstall && cargo binstall streamtop

The minimum supported Rust version is listed in Cargo.toml (rust-version).

Homebrew (macOS and Linux)

brew tap Jorji49/tap
brew install streamtop

Recent Homebrew versions may ask you to trust third-party taps first: brew trust jorji49/tap.

Scoop (Windows)

scoop bucket add streamtop https://github.com/Jorji49/streamtop
scoop install streamtop

winget (Windows)

Manifests are in dist/winget/ in the repository. The package is not in the winget community index yet, so winget install does not work yet.

Arch Linux

streamtop-bin is not on the AUR yet. dist/aur/PKGBUILD builds the same package locally from the Linux release tarball:

git clone https://github.com/Jorji49/streamtop.git
cd streamtop/dist/aur
makepkg -si

Docker

Images for linux/amd64 and linux/arm64 are on GitHub Container Registry:

docker run -it --rm ghcr.io/jorji49/streamtop:latest <URL>

Release tags are also published, for example ghcr.io/jorji49/streamtop:v1.7.1.

Prometheus metrics on a non-loopback bind require a token:

docker run --rm -p 9184:9184 \
  -e STREAMTOP_METRICS_TOKEN=change-me \
  ghcr.io/jorji49/streamtop:latest \
  <URL> --prometheus --metrics-bind 0.0.0.0 \
  --metrics-token "$STREAMTOP_METRICS_TOKEN"

Quick Play (p) is not available in the container because there is no mpv or ffplay inside it.

From source

git clone https://github.com/Jorji49/streamtop.git
cd streamtop
cargo install --path .

Shell completions and man page

streamtop completions <SHELL> prints a completion script for bash, zsh, fish, elvish, or powershell. It covers the main flags and the check, scte35, completions, and man subcommands.

# bash
streamtop completions bash > ~/.local/share/bash-completion/completions/streamtop
# zsh (a directory in your fpath)
streamtop completions zsh > ~/.zfunc/_streamtop
# fish
streamtop completions fish > ~/.config/fish/completions/streamtop.fish
# PowerShell
streamtop completions powershell >> $PROFILE

streamtop man prints the streamtop(1) man page as roff. streamtop man check prints the page for one subcommand.

mkdir -p ~/.local/share/man/man1
streamtop man > ~/.local/share/man/man1/streamtop.1
streamtop man check > ~/.local/share/man/man1/streamtop-check.1
man streamtop

Quick start

# HLS live stream
streamtop "https://example.com/master.m3u8"

# MPEG-DASH
streamtop "https://example.com/manifest.mpd"

# IPTV channel list: opens a channel picker
streamtop ./channels.m3u

# MPEG-TS TR 101 290 checks and SEI metadata
streamtop "https://example.com/live.m3u8" --tr101290 --probe-sei

# Headless PASS/FAIL for CI
streamtop "https://example.com/master.m3u8" --summary --summary-format json --timeout 10

Segment fetches are range probes by default: streamtop requests only the first bytes of each segment, which is enough for header, container, and timing checks. Pass --full-segment to download whole segments (up to 32 MB) instead.

Common options

OptionMeaning
-H "Key: Value"Extra HTTP header, repeatable
-A <UA>User-Agent
-i <MS>Manifest poll interval in milliseconds
--profile <NAME>Load a named profile from ~/.config/streamtop/config.toml (see config.example.toml)
--full-segmentDownload full segments instead of range probes
--tr101290ETSI TR 101 290 P1/P2 checks on the MPEG-TS probe window
--probe-seiH.264/H.265 SEI: captions (CEA-608/708) and HDR metadata
--probe-drmLicense server / EXT-X-KEY / DASH LA_URL TTFB
--clearkey KID:KEYStaging ClearKey for encrypted probe checks
--doh-provider cloudflare|google|<URL>DNS-over-HTTPS timing

Run streamtop --help for the full list.

Dashboard and keys

Layout

AreaContents
StatusURL, LIVE / ESTIMATED, linter score, FPS, GOP and audio badges, latency, CDN, buffer, G2G, LL-HLS
Last segmentSequence, sizes, DNS / TCP / TLS / DoH / TTFB, container, GOP interval, audio
ABR ladderBitrate, resolution, FPS, codecs. [wire] values come from the bitstream; red means manifest and wire disagree
ChartsLatency or TTFB; download rate or transfer time
LogWarnings, SCTE-35 ad markers, stalls, HTTP errors

FPS comes from the playlist FRAME-RATE or @frameRate when present, otherwise from the bitstream. GOP interval comes from keyframe PTS across segments (fixed or variable). Audio codec, rate, and channels come from ADTS, fMP4, or the MPEG-TS PMT in the probe window.

What is probed

  • HLS: live and VOD media playlists, LL-HLS #EXT-X-PART and PRELOAD-HINT with per-part TTFB and download-to-duration ratio, #EXT-X-PROGRAM-DATE-TIME.
  • MPEG-DASH: live and VOD, ServiceDescription latency, UTCTiming, ContentProtection and PSSH.
  • Containers: fMP4, MPEG-TS, ADTS, and H.264/H.265 elementary streams, read from the probe window without a decoder.
  • AES-128: #EXT-X-KEY fetch and in-memory decrypt so encrypted TS/fMP4 can be inspected.
  • SCTE-35: HLS tags (EXT-X-DATERANGE, EXT-X-CUE-OUT, EXT-OATCLS-SCTE35, EXT-X-SCTE35), DASH inband emsg, and mismatches between the two.
  • CDN edge: HIT/MISS from edge headers for Cloudflare, CloudFront, Akamai, Fastly, BunnyCDN, Azure CDN, Google Cloud CDN, JOCDN, Medianova, Edgio, Lumen, and Gcore.
  • Glass-to-glass estimate: from PRFT, HLS PDT, or the DASH segment availability time (MPD publish time as a fallback). This is an estimate, not player end-to-end latency.
  • Buffer model: rebuffer probability from observed download-to-duration ratios.

Keys

KeyAction
q / Esc / Ctrl+CQuit (Esc leaves the channel list when it is open)
SpaceWrite diagnostics/<channel>_<time>.json (URLs and secrets redacted)
cCopy a curl command for the last segment (redacted)
pPlay with mpv or ffplay using the active headers
rReset metrics
TabChannel overlay
?Help
/Regex log filter (Enter to lock, Esc to clear)
f / FCycle preset log filter / clear it
tTR 101 290 overlay
sSEI / HDR / caption overlay
j / kScroll the log or channel list

Compare mode: Space pause/resume, d detail, l log focus, c curl, h or e HAR, Tab switch pane.

IPTV playlist checking

streamtop reads IPTV channel lists in M3U (#EXTINF with tvg-name, tvg-id, tvg-logo, group-title), JSON, and YAML. A list can be a local file or a URL.

Browse channels

streamtop ./channels.m3u
streamtop "https://example.com/playlist.m3u"

This opens a channel picker with search. Selecting a channel opens the normal dashboard for it.

Check every channel

streamtop ./channels.m3u --audit

--audit probes every channel concurrently (25 workers) and prints a table:

#    Channel                      Group        HTTP   PDT       TTFB CDN                    Verdict
1    News HD                      News         200    yes      182ms Cloudflare HIT         LIVE
2    Sports 2                     Sports       404    no           - -                      ERROR
     404 Not Found

For each channel it fetches the playlist (following a master playlist to its highest-bandwidth variant), then range-requests the last segment. For DASH it probes a segment URL taken from the MPD.

Verdicts:

VerdictMeaning
LIVEPlaylist and segment returned 2xx/3xx and the segment TTFB was under 2500 ms
VODSame as LIVE, but the playlist is on-demand (HLS #EXT-X-ENDLIST or a static MPD). Counted as working
STALLSegment TTFB was 2500 ms or more, or the media playlist had no segments
ERRORHTTP 401, 403, 404, 5xx, a network error, a timeout, or a playlist that could not be parsed

Each request has a 3 second connect timeout and a 5 second total timeout. Results are also written to audit_report.json and audit_report.csv in the current directory, with URLs and tokens redacted. The exit code is non-zero when any channel is ERROR or STALL.

Headers and User-Agent apply to every channel:

streamtop ./channels.m3u --audit -H "Referer: https://example.com" -A "Mozilla/5.0"

streamtop check

streamtop check is the scriptable version of --audit. It takes a playlist file or URL (M3U, JSON, YAML, or a single HLS/DASH URL), probes every entry concurrently with a per-entry time limit, and prints a table, JSON, or CSV. It writes no files unless you ask for them.

streamtop check ./channels.m3u
streamtop check "https://example.com/playlist.m3u" --timeout 5 --concurrency 50
streamtop check ./channels.m3u --format json > report.json
streamtop check ./channels.m3u --format csv --output report.csv
streamtop check ./channels.m3u --alive-out working.m3u
streamtop check ./channels.m3u --fail-on-dead      # exit 1 if any entry is dead
OptionDefaultMeaning
-t, --timeout SECS10Time limit for one entry (playlist, variant, and segment probe together). An entry that runs over is ERROR with timeout after Ns
-j, --concurrency N25Entries probed at the same time
-f, --formattabletable, json, or csv
-o, --output FILEstdoutWrite the report to a file. With table, writes JSON
--alive-out FILEWrite an M3U with the entries that are not dead (LIVE, VOD, and STALL unless --strict), keeping tvg-id, tvg-logo, and group-title
--fail-on-deadoffExit 1 when any entry is ERROR
--strictoffTreat STALL as dead for --fail-on-dead and --alive-out
-H, --headerExtra HTTP header, repeatable
-A, --user-agentUser-Agent override

JSON and CSV reports redact URLs and tokens, like the --audit files. The --alive-out playlist keeps the original URLs, because it is meant to be played.

Without --fail-on-dead, check exits 0 even when entries are dead, so it can be used for reporting. --audit always exits 1 on any ERROR or STALL.

Notes

  • A LIVE verdict means the playlist and one segment were reachable. It does not decode video, so a channel that serves a black frame still counts as live.
  • Some IPTV servers block unknown User-Agents or require a Referer. Pass them with -A and -H.
  • --audit always uses 25 workers and a 5 second limit per HTTP request, so on large lists with many unreachable hosts the run time is set mostly by those timeouts. check lets you set the worker count with -j and a limit per entry with --timeout.

SCTE-35 decoding

While monitoring, streamtop decodes SCTE-35 cues from HLS tags (#EXT-OATCLS-SCTE35, #EXT-X-SCTE35, #EXT-X-DATERANGE with SCTE35-OUT, SCTE35-IN, SCTE35-CMD, and #EXT-X-CUE-OUT / CUE-IN) and from DASH emsg boxes. They appear in the event log and in the summary JSON.

streamtop scte35

To decode a single cue without a stream, pass it to streamtop scte35:

streamtop scte35 "/DAvAAAAAAAA///wFAVIAACPf+/+c2nALv4AUsz1AAAAAAAKAAhDVUVJAAABNWLbowo="
table_id            0xfc
protocol_version    0
splice_command      Splice Insert (0x05)
splice_event_id     1207959695 (0x4800008f)
out_of_network      yes
pts_time            1936310318 (21514.559089s)
break_duration      60.293567s
break_auto_return   yes

Accepted input:

  • Base64 (standard or URL-safe alphabet)
  • Hex, with or without 0x. A string made only of hex digits is always read as hex
  • An HLS tag line: #EXT-OATCLS-SCTE35:..., #EXT-X-SCTE35:CUE="...", or #EXT-X-DATERANGE with SCTE35-OUT, SCTE35-IN, or SCTE35-CMD
  • - to read the payload from stdin
streamtop scte35 0xFC302F000000000000FFFFF014054800008F7FEFFE7369C02EFE0052CCF500000000000A0008435545490000013562DBA30A
grep -m1 OATCLS playlist.m3u8 | streamtop scte35 -
streamtop scte35 --json "/DA0AAAAAAAA///wBQb+cr0AUAAeAhxDVUVJSAAAjn/PAAGlmbAICAAAAAAsoKGKNAIAmsnRfg=="

The text output covers splice_insert, time_signal, splice_schedule, splice_null, and bandwidth_reservation, and each segmentation descriptor (event id, type, duration, UPID, segment numbers, delivery flags). --json prints the same fields as the summary JSON. The command exits 1 when the bytes are not a valid splice_info_section.

It does not verify the CRC, decrypt encrypted sections, or encode new cues. For encoding and injection, see threefive or TSDuck.

Headless and CI

PASS/FAIL summary

streamtop <URL> --summary --summary-format json --timeout 10

--summary listens for --timeout seconds (default 8) and prints a verdict. It returns PASS only when:

  • the status is LIVE, or VOD for a playlist with #EXT-X-ENDLIST,
  • the linter score is at least 85,
  • no critical RFC errors or origin stalls were seen,
  • the last HTTP status was 200 or 206,
  • at least one segment was fetched.

Any failed condition returns FAIL and a non-zero exit code. On FAIL the text output adds a last_error: line and the JSON adds last_error when a fetch or parse failed. If no segment was fetched, the score is 0 with the label No data.

The JSON contract is streamtop.summary.v1; the schema is schemas/summary.v1.json and schema_version is currently 7. Version 7 added the VOD status and the last_error field.

Colors are used only when stdout is a terminal and NO_COLOR is not set.

Formats: text (default), json, sarif.

SARIF for GitHub Code Scanning

streamtop <URL> --summary --summary-format sarif --timeout 10 > streamtop.sarif
# or
streamtop <URL> --export sarif:streamtop.sarif --timeout 10

GitHub Actions step summary

streamtop <URL> --summary --github-step-summary "$GITHUB_STEP_SUMMARY" --timeout 10

When GITHUB_STEP_SUMMARY is set, --summary and budget mode write it automatically. The summary includes the linter score, download-to-duration ratio, TR 101 290 counts, the ABR ladder, and the budget table.

Stream budgets

Budgets are threshold assertions. streamtop prints a JSON verdict and exits non-zero on a breach.

streamtop "$STREAM_URL" \
  --budget-max-rtf 1.0 \
  --budget-max-ttfb 500ms \
  --budget-max-cc-errors 0 \
  --budget-max-drift 2000ms \
  --budget-duration 30
FlagFails when
--budget-max-rtfdownload time divided by segment duration exceeds the ratio
--budget-max-ttfbsegment TTFB exceeds the value (250ms, 2s)
--budget-max-cc-errorsTR 101 290 continuity counter errors exceed N
--budget-max-driftA/V or subtitle drift exceeds the value
--budget-durationprobe window in seconds (default 30)

VOD crawl

streamtop --vod <URL> --summary

Crawls the playlist or MPD tree once without live polling.

WHEP smoke test

streamtop "https://webrtc.example/live/whep" --timeout 5

Sends an SDP offer and parses the answer (TTFB, codecs, ICE candidates). Signaling only; no media path.

Example workflow step

- name: Stream check
  run: |
    cargo install streamtop
    streamtop "$STREAM_URL" --summary --summary-format json --timeout 15

Hermetic end-to-end tests for streamtop itself are in tests/e2e_verify.sh and tests/e2e_verify.ps1.

Exports

--export FORMAT[:FILE] is repeatable.

FormatOutput
report-html[:PATH]Compliance report as HTML (default report.html)
report-json[:PATH]Compliance report as JSON (default report.json)
curlcurl command for the last segment, printed to stdout
har[:PATH]HAR file (default incident.har)
incident[:PATH]Opens the dashboard. Press e to write a redacted bundle (curl, HAR, timeline, findings) to PATH. Needs a terminal.
sarif[:PATH]SARIF 2.1.0 findings (default streamtop.sarif)
grafanaGrafana dashboard JSON for the Prometheus metrics, written to streamtop-grafana.json
streamtop <URL> --export report-html:report.html --timeout 10
streamtop <URL> --export curl --timeout 10
streamtop <URL> --export har:incident.har --export sarif --timeout 10
streamtop --export grafana

All formats except incident run headless and work in CI. In the dashboard, Space writes diagnostics/<channel>_<time>.json and c copies a curl command. URLs, tokens, and secrets are redacted in all exports.

Metrics, agent, and alerts

Prometheus

streamtop <URL> --prometheus            # 127.0.0.1:9184/metrics
streamtop <URL> --prometheus 9184 --metrics-bind 0.0.0.0 \
  --metrics-token "$STREAMTOP_METRICS_TOKEN"
curl -H "Authorization: Bearer $STREAMTOP_METRICS_TOKEN" http://host:9184/metrics

A non-loopback --metrics-bind requires a non-empty --metrics-token or STREAMTOP_METRICS_TOKEN. Only the Authorization: Bearer header is accepted; a ?token= query is rejected.

--prometheus runs until Ctrl+C. It does not open the dashboard, and it cannot be combined with --summary, --audit, --export, --multi-cdn, --compare, or --vod.

streamtop --export grafana writes a dashboard JSON for these metrics.

Multi-stream agent

streamtop --agent agent.example.toml

The agent polls every [[streams]] entry in the TOML file without a TUI and serves aggregated /metrics. See agent.example.toml in the repository.

OpenTelemetry

streamtop <URL> --otel-endpoint http://127.0.0.1:4318

Sends OTLP traces and metric batches to /v1/traces and /v1/metrics. Private, link-local, and cloud metadata hosts are blocked unless --allow-insecure-otel is set.

Webhooks

streamtop <URL> --webhook https://hooks.example/x --alert-on stall,shi_below_70,http_5xx

Slack, Discord, and generic HTTP targets are supported. --alert-on values: stall, shi_below_70, http_5xx, mismatch, ad_start, ad_mismatch. Private and metadata hosts are blocked unless --allow-insecure-webhooks is set (meant for tests).

Profiles

--profile NAME loads headers, User-Agent, interval, and other options from ~/.config/streamtop/config.toml. See config.example.toml.

Compare and multi-CDN

Side by side

streamtop --compare <URL_1> <URL_2>

Two streams in one TUI, for example origin and edge, or two encoder outputs. Keys: Space pause/resume, d detail, l log focus, c curl, h or e HAR, Tab switch pane.

Multi-CDN skew

streamtop --multi-cdn akamai=https://a.example/live.m3u8,cloudflare=https://b.example/live.m3u8
streamtop --multi-cdn https://a.example/live.m3u8,https://b.example/live.m3u8 --summary --timeout 15

Polls every edge concurrently and builds a live-edge skew matrix from media sequence numbers and PDT. When the skew passes --max-cdn-skew-ms (default 3000) it reports ERR_CDN_SYNC_SKEW. With --summary it prints JSON and exits non-zero when the threshold is exceeded.

Comparison with other tools

streamtop overlaps with several established tools. None of them is a replacement for the others; they answer different questions. This page tries to be factual about where each one fits. Corrections are welcome as issues or pull requests.

Summary

streamtopTSDuckffprobethreefiveiptv-checker
Main jobLive HLS/DASH monitoring over timeMPEG-TS analysis and processingContainer and codec inspectionSCTE-35 decode and encodeCheck links in IPTV playlists
LanguageRustC++C (FFmpeg)PythonNode.js
InterfaceTUI and CLICLI (tsp plugins and utilities)CLICLI and libraryCLI and library
HLS / DASH playlistsPolls live playlists continuouslyHLS input pluginReads them as inputsParses SCTE-35 in HLS; DASH SCTE-214 supportUses ffprobe per link
MPEG-TS depthProbe window only (TR 101 290 P1/P2)Whole-stream analysis, PSI/SI tables, PCR and continuity checks, many pluginsDemux and decodeSCTE-35 sections in TSNone
UDP / multicast / SRTNoYesYes (via FFmpeg protocols)UDP and multicast for TSNo
Media decodeNoNo (transport level)YesNoVia ffprobe
SCTE-35Decodes HLS tags and DASH emsg live, flags mismatches; streamtop scte35 decodes one cueSplice monitoring and injection pluginsExposes data streams, no SCTE-35 semanticsFull decode and encode, the main purposeNo
CDN / HTTP timingDNS, TCP, TLS, TTFB, CDN HIT/MISS per segmentNoNoNoNo
Prometheus / OTLPYesNoNoNoNo
CI verdictsPASS/FAIL JSON, SARIF, budgetsExit codes from scriptsExit codes from scriptsNoResults written to an output directory

When to use which

Use TSDuck when the problem is inside the transport stream: PSI/SI tables, PID mapping, PCR and continuity analysis over the whole stream, multicast or DVB input, remultiplexing, or SCTE-35 injection. TSDuck works at the MPEG-TS level and is far deeper there than streamtop. streamtop only inspects the first bytes of each segment.

Use ffprobe when you need exact codec and container parameters from one file or URL, or anything that needs decoding. ffprobe reads a snapshot; it does not track a live playlist over time, and it does not report HTTP timing or CDN behavior.

Use threefive when the job is SCTE-35 itself: decoding cues from TS, HLS, base64, hex, or XML, encoding new cues, or injecting them. streamtop decodes the cues it finds while monitoring, and streamtop scte35 decodes a single Base64 or hex cue, but it does not encode, inject, or verify the CRC.

Use iptv-checker when you want per-channel status plus ffprobe stream metadata (codecs, resolution) for a playlist, with retries, delays, and proxy support. streamtop check probes reachability and segment TTFB without ffprobe, prints a table, JSON, or CSV, and can write the working entries to a new M3U with --alive-out.

Use streamtop when you are watching a live HLS or DASH channel over minutes or hours and want to see segment timing, CDN edge behavior, stalls, ABR ladder versus bitstream mismatches, and ad markers in one terminal view, or when you want that as Prometheus metrics or a CI gate.

Other tools

  • Eyevinn hls-monitor: HTTP service that monitors HLS streams for errors.
  • DASH-IF Conformance: the reference conformance validator for MPEG-DASH. Use it for spec conformance; streamtop does not validate full DASH conformance.
  • Apple mediastreamvalidator: the reference HLS validator, macOS only.

Limits

streamtop is a wire and container probe. It is not a decoder or a full transport stream analyzer.

  • No media decode. Probes read headers and the first bytes of segments (the probe window). A stream that sends black frames or silent audio can still look healthy.
  • TR 101 290 covers P1 and P2 checks on the MPEG-TS probe window only (the first 64 KB of each probed segment), not an analysis of the whole multiplex. Windows are not contiguous, so continuity counter, PCR, and PTS checks restart at each segment and errors at segment boundaries are not seen. PAT and PMT repetition is measured on the PCR clock inside the window. CRC-32 and SI tables (SDT, NIT, EIT) are not checked. Use TSDuck for deep transport stream work.
  • Glass-to-glass is an estimate from HLS PDT, DASH segment availability time (or MPD publish time), and PRFT when present. DASH timestamps more than one hour from the local clock are ignored. It is not player end-to-end latency.
  • WHEP is signaling only (SDP offer and answer). There is no WebRTC media path.
  • No SRT, RTMP, UDP, or multicast input. srt:// and rtmp:// URLs are rejected at startup.
  • DASH live edge. For a dynamic MPD with a SegmentTemplate, streamtop probes the newest media segment: the last S of a SegmentTimeline, or for duration templates one segment behind the last complete one by the local clock. If the local clock is off by more than a segment, those probes can return 404. Without a SegmentTemplate it probes the first Representation URL when MPD@publishTime changes.
  • DASH conformance is not validated against the full specification. Use the DASH-IF Conformance tool for that.
  • Linter score (TUI) uses four flags: RFC -15, origin stall -20, CDN MISS -5, high TTFB -10. The summary JSON keeps the older SHI field names (schema_version 7).
  • Quick Play needs mpv or ffplay on the PATH and does not work in the Docker image.

FAQ

How is streamtop different from ffprobe or VLC? ffprobe inspects a single file or URL snapshot, and VLC plays the stream. streamtop polls live playlists, tracks segment health over time, shows SCTE-35 markers and linter score trends, and exports Prometheus metrics and CI summary JSON. See Comparison.

Does it work headless in CI? Yes. Use --summary --summary-format json --timeout N for PASS/FAIL output, --summary-format sarif or --export sarif:FILE for Code Scanning, and --budget-max-* for threshold gates. See Headless and CI.

Which protocols are supported? HLS (including LL-HLS parts), MPEG-DASH, IPTV channel lists (M3U, JSON, YAML), and WHEP HTTP endpoints. Wire probes cover fMP4, MPEG-TS, ADTS, and H.264/H.265 elementary streams without a decoder.

Can it check which channels in my IPTV playlist work? Yes. streamtop check playlist.m3u prints LIVE, STALL, or ERROR for every entry, with JSON/CSV output, --alive-out for a cleaned playlist, and --fail-on-dead for scripts. See IPTV playlist checking.

Is it safe to expose Prometheus metrics? The default bind is loopback. A non-loopback bind requires --metrics-token or STREAMTOP_METRICS_TOKEN, and requests must send Authorization: Bearer.

Are tokens in my URLs written to disk? Exports and diagnostics redact URLs, query tokens, and secrets.

Does it need FFmpeg? No. Only Quick Play (p) uses mpv or ffplay if they are installed.

Where do I report a bug? GitHub issues. Questions and ideas can go to Discussions.