Passive CLI monitor for professional AV-over-IP networks. Designed for AV engineers and technicians who need to visualise stream activity and diagnose problems on live Dante, AES67, ST 2110, NDI, and AVB installations — without touching switches or interrupting traffic.
AVStreamLens reads the network passively using pcap, identifies streams and clock sources, and prints a plain-language report every 5 seconds.
| Protocol | Transport | What is monitored |
|---|---|---|
| AES67 | UDP multicast (239.69.*) | Loss, jitter, SSRC changes, timing discontinuities, payload type, signal gap detection, PTPv2 clock, ts-refclk validation, DSCP; streams from a known Dante device labelled AES67 (Dante: "Name") |
| SMPTE ST 2110 | UDP multicast (239.x.x.x) | Video (2110-20), audio (2110-30), ancillary (2110-40) — same RTP metrics as AES67; video clock rate confirmed without SDP |
| Dante | UDP unicast or multicast / mDNS / ConMon | Device names from mDNS, live-device detection + channel count from ConMon multicast (no SPAN needed), audio stream metrics (RTP, or presence/bitrate for ATP-framed flows), signal gap detection, DSCP (flags Dante Virtual Soundcard via DSCP=0), PTPv1 clock; Dante devices in AES67 mode appear in the AES67 section with a (Dante) tag |
| NDI | TCP (dynamic ports) | Source names from mDNS, bitrate, TCP quality, retransmissions, RST/FIN |
| AVB / IEEE 802.1 | L2 Ethernet | gPTP grandmaster (802.1AS), MSRP bandwidth reservations (802.1Qat), MVRP VLAN registrations (802.1Q), AVTP stream IDs, AVDECC entity discovery (IEEE 1722.1) |
Always monitored regardless of selection: LLDP (for EEE detection). Monitored when relevant: PTP when AES67/ST2110/Dante/AVB selected — IGMP when AES67/ST2110/Dante selected — SAP when AES67/ST2110 selected.
Most users should grab a prebuilt binary from the GitHub Releases page — no Rust toolchain required.
| Platform | Artifact |
|---|---|
| macOS (Apple Silicon) | avstreamlens-<version>-aarch64-apple-darwin.tar.gz |
| macOS (Intel) | avstreamlens-<version>-x86_64-apple-darwin.tar.gz |
| Linux (x86_64) | avstreamlens-<version>-x86_64-unknown-linux-gnu.tar.gz |
| Windows (x86_64) | avstreamlens-<version>-x86_64-pc-windows-msvc.zip |
macOS / Linux:
tar xzf avstreamlens-<version>-<target>.tar.gz
cd avstreamlens-<version>-<target>
sudo ./avstreamlens
Windows (from an Administrator terminal — use Windows Terminal or VS Code for colour output, classic cmd.exe does not support ANSI colour):
Expand-Archive avstreamlens-<version>-x86_64-pc-windows-msvc.zip
cd avstreamlens-<version>-x86_64-pc-windows-msvc
.\avstreamlens.exe
You still need the runtime capture library installed regardless of how you got the binary — see Prerequisites below.
Unsigned binary — v1 releases are not code-signed or notarized. Your OS will warn you the first time you run it:
- macOS (Gatekeeper): right-click the binary → Open → confirm in the dialog, or run
xattr -d com.apple.quarantine ./avstreamlensonce to clear the quarantine flag. - Windows (SmartScreen): click More info → Run anyway.
These are needed whether you downloaded a binary above or are building from source.
macOS
brew install libpcap # usually already present
Linux
sudo apt install libpcap-dev
Windows
Install Npcap (the modern WinPcap replacement). During installation, enable "Install Npcap in WinPcap API-compatible mode".
Capturing packets requires elevated privileges — run as sudo on macOS/Linux, or as Administrator on Windows.
Most users should use the prebuilt binaries above. To build from source, you'll additionally need:
Rust toolchain
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Windows only — Npcap SDK (separate from the Npcap runtime installer above; provides the .lib files the linker needs):
- Download the SDK from npcap.com/dist.
- Extract it and add its
Lib\x64folder to yourLIBenvironment variable.
Then:
cargo build --release
The binary is at target/release/avstreamlens.
Interactive (prompts for interface and protocol on startup):
sudo ./target/release/avstreamlens
Non-interactive (skip prompts — useful for scripts and SSH sessions):
sudo ./target/release/avstreamlens --interface en0 --protocol aes67,dante
sudo ./target/release/avstreamlens -i eth0 -p all
sudo ./target/release/avstreamlens -i en0 -p aes67 --duration 30 && echo OK
sudo ./target/release/avstreamlens --help
Offline pcap replay (no root required — analyse a file captured earlier):
./target/release/avstreamlens --read capture.pcapng
./target/release/avstreamlens -r site_visit.pcap --protocol dante
On startup:
- Select the network interface to monitor (or supply
--interface) - Select which protocols to watch (or supply
--protocol, or press Enter for all) - Reports print every 5 seconds; a timestamped
.logfile is written in the current directory
| Flag | Short | Description |
|---|---|---|
--interface <name> |
-i |
pcap device name to capture on (e.g. en0, eth0) |
--protocol <list> |
-p |
Comma-separated protocols: all audio video aes67 avb dante ndi st2110 |
--read <file> |
-r |
Replay a .pcap / .pcapng file offline — no root required |
--duration <secs> |
-d |
Stop after N seconds; exit 0 if healthy (100%), exit 1 if any issues detected |
--quiet |
-q |
Silent on healthy cycles; print the full report only when issues are detected |
--no-color |
Disable ANSI colour output (also honoured via the NO_COLOR env var) |
|
--help |
-h |
Show usage and exit |
Protocol names are case-insensitive. The interactive-mode numbers (0–7) are also accepted for scripting convenience. When a flag is omitted, AVStreamLens falls back to the interactive prompt for that item.
--quiet is useful for long-running monitoring sessions piped to a log file or tail -f: no output is produced on healthy cycles, so the terminal stays clean and each new report is immediately visible as an issue. The log file always receives the full report regardless of --quiet.
--duration enables one-shot scripted health checks. AVStreamLens captures for N seconds (at least one full 5-second report cycle), then exits with code 0 if the network health score is 100% or code 1 if any issue was detected. Pair with --quiet to suppress the intermediate report output: avstreamlens -i en0 -p aes67 --duration 30 --quiet && echo OK.
AVStreamLens opens a live pcap handle on the selected interface in promiscuous mode. It joins multicast groups dynamically so IGMP-snooped switches deliver stream traffic to the capture port without a SPAN. Reports print every 5 seconds; use Ctrl-C to stop.
sudo ./target/release/avstreamlens -i en0 -p dante
To avoid typing sudo every time on macOS (non-persistent, resets on reboot):
sudo chmod o+r /dev/bpf*
./target/release/avstreamlens -i en0 -p dante
On Linux (permanent, survives reboots):
sudo setcap cap_net_raw+ep ./target/release/avstreamlens
./target/release/avstreamlens -i eth0 -p dante
Capture a .pcap or .pcapng file on-site with Wireshark or tcpdump, then replay it anywhere — no network interface, no root required. 5-second report windows are driven by the pcap packet timestamps, so you see the same view as a live capture would have produced. The tool exits at EOF and prints a final report.
# Capture on-site:
sudo tcpdump -i en0 -w site_visit.pcap
# Analyse later (no sudo):
./target/release/avstreamlens --read site_visit.pcap --protocol dante
./target/release/avstreamlens -r site_visit.pcapng
Protocol defaults to all when --read is given without --protocol. BPF filter is still applied. mDNS startup probe and IGMP joins are skipped (not meaningful for offline data). Device names from mDNS will only appear if mDNS traffic was captured in the file — there is no live probe to trigger responses.
What AVStreamLens can see depends entirely on which switch port you connect to. The right choice depends on which protocols you are monitoring.
AVStreamLens is a passive capture tool — it reads traffic delivered to its network interface. Multicast and L2 broadcast traffic is delivered to every port on the switch, so the following is visible from any access port, trunk port, or SPAN port:
| Protocol | Why visible without SPAN |
|---|---|
| AES67 | UDP multicast (239.69.*) — AVStreamLens auto-joins these groups |
| SMPTE ST 2110 | UDP multicast (239.x.x.x) — AVStreamLens auto-joins these groups |
| Dante audio (multicast) | 239.255.x.x — AVStreamLens auto-joins groups as streams are discovered |
| AVB — AVTP stream data | MAAP-allocated multicast MACs — forwarded like normal multicast |
| AVB — AVDECC entities | ADP uses MAC 91:E0:F0:01:00:00 (globally registered, bridges MUST forward) |
| PTP, IGMP, SAP | Multicast — AVStreamLens joins PTP and SAP groups at startup |
| Dante / NDI discovery | mDNS multicast (link-local, always flooded) — delivered to every port |
| Dante device liveness (ConMon) | Control & monitoring multicast (224.0.0.230–233, link-local, always flooded) — every live Dante device is visible at ~33 packets/s, with its channel count |
| Dante PTPv1 clock | Multicast — delivered to every port |
| Dante IP misconfiguration | mDNS + ConMon reveal device IPs — AVStreamLens flags 169.254.x.x (DHCP failure) and subnet splits automatically |
| Dante clock sync status | PTPv1 Delay_Req is multicast — AVStreamLens counts how many discovered devices are actively syncing ("N of M") |
AVB gPTP / MSRP / MVRP are NOT delivered to every port. They use link-local reserved MACs (
01:80:C2:00:00:0E,…:21) in the IEEE range that bridges must not forward — they are hop-by-hop, so you only ever see the copy on your own link, not a remote grandmaster. See Monitoring gPTP / the AVB grandmaster below.
IGMP snooping: Managed switches with IGMP snooping only deliver multicast traffic to ports that have sent an IGMP Membership Report for that group. AVStreamLens handles this automatically — at startup it joins the PTP and SAP groups, and during capture it dynamically joins stream multicast addresses as they are discovered from SAP/SDP announcements and from IGMPv3 Membership Reports sent by other devices on the network. On a snooping switch the stream groups appear in the log file as ✓ Joined stream multicast 239.69.x.x entries. No switch configuration is needed.
For AES67 and ST 2110 you can plug into any port on the switch and get full visibility. For AVB you will see stream data and your own link's MSRP/gPTP, but the grandmaster and time domain are only visible on a time-aware (AVB-enabled) port — see below.
A switch forwards unicast frames only to the destination port. Promiscuous mode does not change this — it lets the NIC accept frames addressed to other MAC addresses, but only frames the switch has already forwarded to that port.
SPAN is required when you need to see unicast flows between two other devices:
- Dante audio (unicast subscriptions) — Dante subscriptions are unicast by default. If a flow runs between two devices that are not the capture machine, the switch delivers those packets only to those two ports. A SPAN session mirroring those ports (or the whole VLAN) is the only way to see them. Note: Dante multicast audio (239.255.x.x) does not require SPAN — AVStreamLens joins those groups automatically.
- NDI streams — NDI uses TCP (unicast). Same constraint as Dante unicast audio.
AVStreamLens detects this situation for you: because mDNS discovery is multicast and always visible, the report lists the discovered Dante/NDI devices under 📇 Discovered (mDNS) and warns when devices are present but their flows are not visible — distinguishing multicast-snooping (resolved automatically by IGMP join) from unicast flows that still need a mirror port.
How to configure a SPAN session depends on the switch vendor:
| Switch family | How to configure port mirroring |
|---|---|
| Cisco IOS / IOS-XE | monitor session 1 source interface Gi0/1 - 24 / monitor session 1 destination interface Gi0/48 |
| Cisco Catalyst (GUI) | Admin → Diagnostics → Port Mirroring |
| Aruba / HP ProCurve | mirror 1 port Trk1 + interface X mirror 1 |
| Juniper EX | set forwarding-options analyzer <name> input ... output interface <port> |
| Luminex GigaCore | Port Mirroring tab in the web UI — select source ports and mirror destination |
| Netgear ProSafe | Switching → Port Mirroring in the web UI |
| Unmanaged switch | No SPAN capability — use a network tap or replace with a managed switch |
Typical SPAN setup for a Dante or NDI network:
- Connect the capture machine to a spare port on the managed switch.
- Configure a SPAN session that mirrors the uplink port (or the entire AV VLAN) to that port.
- Run AVStreamLens — it will now see all unicast and multicast flows on the mirrored segment.
AVB's clock protocol, gPTP (IEEE 802.1AS), behaves differently from every other protocol here, and it surprises people: you cannot see the grandmaster from an arbitrary port.
gPTP frames use the link-local destination MAC 01:80:C2:00:00:0E, which lives in the reserved 01:80:C2:00:00:00–0F range that bridges are required not to forward. gPTP is hop-by-hop: each time-aware switch consumes the grandmaster's Sync/Announce on its upstream port and regenerates its own Sync/Announce on each downstream port. So the grandmaster's actual Announce never travels more than one link — you only ever see the gPTP of your direct link partner.
This is the opposite of AES67/Dante/ST 2110 PTP, which is ordinary IP multicast and floods the whole VLAN (so those grandmasters show up from any port).
Consequences for monitoring:
- If your capture port is not an AVB-enabled (time-aware) port, you will see at most the directly-attached device's
P_Delay_Reqtraffic — no Sync, no Announce, no grandmaster. AVStreamLens reports this aspeer-delay requests only — link partner may not be gPTP-capableand addsℹ gPTP is link-local — the grandmaster is only visible on a time-aware (AVB-enabled) port. - To actually observe the grandmaster's Announce, capture on (or SPAN-mirror) a time-aware, AVB-enabled link — ideally the link directly between the grandmaster device and its first switch. A mirror of a non-AVB port will not show it, because the frames were never forwarded there in the first place.
- The same link-local rule applies to MSRP (
01:80:C2:00:00:0E) and MVRP (…:21): you see your own link's declarations, not a network-wide view. AVB stream data (AVTP) uses normal forwardable multicast and is not subject to this limitation.
A trunk port carries multiple VLANs tagged with 802.1Q. It does not affect unicast forwarding — a trunk port gives the same unicast visibility as an access port. The difference is VLAN scope, not traffic coverage.
AVStreamLens has no per-VLAN configuration: it parses any VLAN delivered to the capture interface. 802.1Q, 802.1ad, and QinQ tags are stripped transparently before protocol detection, so AVB, PTP, and IP streams are recognised regardless of tagging.
| Port type | VLANs visible | Unicast between other devices |
|---|---|---|
| Access port | One VLAN, untagged | No |
| Trunk port | All VLANs the trunk carries, tagged | No |
| SPAN / mirror port | Depends on mirror session scope | Yes, for mirrored ports/VLANs |
To monitor streams across multiple VLANs, plug into a trunk port or configure a SPAN session scoped to the trunk.
Caveats
- macOS — Many macOS drivers strip the 802.1Q tag before pcap sees it. Stream detection still works (the inner payload is intact), but you lose visibility into which VLAN a stream rode on. Linux generally preserves the tag.
- QinQ — libpcap's BPF compiler handles a single 802.1Q tag transparently for
ether protomatches, but stacked QinQ can hide L2 protocols (PTP, AVB) from the kernel filter on some drivers. If AVB or gPTP is missing on a known-good QinQ trunk, that's the first place to look.
Choose the protocols to monitor:
0) All
1) Audio (AES67 + Dante + AVB)
2) Video (ST2110 + NDI)
3) AES67
4) AVB
5) Dante
6) NDI
7) ST2110
[Separate by commas, e.g. '1,2,3' or enter for all]
- Audio and Video are convenience groups — selecting Audio captures AES67, Dante, and AVB streams in one step.
- PTP, IGMP, and SAP are enabled automatically when the selected protocols require them — see the "Always monitored" note in Supported Protocols above.
──────────────────────────────────────────────────────────────────
AVStreamLens · 2026-05-17 14:32:00
──────────────────────────────────────────────────────────────────
🔬 Network Health — 85% | AES67: 3 | Dante: 1
⚠ EEE active on 1 switch port(s)
📇 Discovered:
Dante (4) · 2 live
▸ "Amp-1" 192.168.1.47
▸ "Stage Box" 192.168.1.45
▸ "TASCAM" 192.168.1.48
▸ 192.168.1.50 (name pending)
⚠ "AC44F2C8DDF9" 169.254.118.122 (mDNS only, no ConMon)
NDI (2)
▸ "Playback PC" 192.168.1.60
▸ "Studio Camera" 192.168.1.61
🕐 Clock Sources:
✓ PTPv2 — grandmaster 00:1a:e5:ff:fe:78:9a:bc (192.168.1.1)
clock quality: Primary reference — locked < 100 ns
✓ PTPv1 — grandmaster "Stage Box" (192.168.1.45)
clock quality: Preferred grandmaster
✓ AVB — grandmaster 00:1a:e5:ff:fe:ab:cd:ef
📡 Streams:
▸ AES67 "Stage Mix" [L24/48000/2] — 239.69.0.1:5004
loss: 0.0% | jitter: 0.18 ms | 2.3 Mbps
▸ Dante [unicast] "Stage Box" — 192.168.1.45:5010
loss: 0.0% | jitter: 0.04 ms | 0.8 Mbps
▸ NDI "Studio Camera" — 192.168.1.61
healthy | 120.3 Mbps | retrans: 0
▸ AVB IEC 61883 — 00:1a:e5:ff:fe:12:34:56:0001
loss: 0.0% | 2.3 Mbps
✓ Reserved VLAN 100 prio 3 ✓ Listener Ready
📊 Network Status:
Bandwidth: 12.4 Mbps (last 5s)
QoS: ✓ all streams correctly marked
IGMP: ✓ querier 192.168.1.1 [d0:69:9e:10:10:e4] 42s ago (interval 125s)
⚠ EEE active on 1 switch port(s) — may cause audio/video glitches
port "Gi0/1" chassis 00:1a:2b:3c:4d:5e Tx wake: 16µs Rx wake: 16µs
📦 48120 pkts received
0 kernel drop(s)
0 interface drop(s)
48120 parsed
Health Summary — directly under the score line, a ⚠ bullet for every factor pulling the Health Score below 100%: stream issues collapsed by type (e.g. ⚠ 2 stream(s) with packet loss) and infrastructure issues listed individually. A fully healthy (100%) report shows no summary at all. pcap capture drops are a tool limitation, not a network fault — they appear only in Network Status at the bottom, never as a summary bullet.
Discovered — Dante and NDI devices announce themselves over multicast mDNS, which reaches every switch port. This section lists those devices even when their actual audio/video flows are not visible. Each device appears on its own line; devices whose name has not yet been resolved show (name pending). The · N live suffix shows real-time liveness from ConMon: Dante devices transmit control & monitoring multicast at ~33 packets/s on the link-local 224.0.0.230–233 groups, which snooping switches always flood — so AVStreamLens knows which devices are alive right now, not just which announced via mDNS at some point (· all live when every discovered device is also active in ConMon). On a plain (non-SPAN) port where Dante audio or NDI is unicast between other devices, you will see the devices here but no matching stream above — in that case AVStreamLens adds (once per session):
⚠ Devices announced but no active flows — mirror port may be needed
This distinguishes "wrong interface / nothing here" from "the devices are present but their flows are unicast and need a mirror port" — see Capture Setup.
Some devices respond to Dante mDNS queries without being real Dante audio endpoints — a common example is a console's management NIC on the same network segment as its Dante interface. AVStreamLens detects these by waiting 15 seconds (3 report windows): if an mDNS-discovered IP shows no ConMon activity and no active streams, it is shown inline in the device list with a ⚠ prefix:
⚠ "AC44F2C8DDF9" 169.254.118.122 (mDNS only, no ConMon)
Alerts appear inline when problems are detected. Alerts on cumulative metrics (loss, timing discontinuities) include both a per-window count and the lifetime total, so an old loss does not re-alert forever:
Per-stream:
⚠ Audio glitch risk — timing discontinuity detected (N in last 5s)⚠ Packet loss detected (N in last 5s, X.XX% cumulative)⚠ Packet reorder X.X% (N in last 5s) — possible per-packet load-balancing⚠ QoS: N packet(s) not marked EF (46) — may be deprioritised by switches⚠ Signal gap detected (N in last 5s, worst X.X ms) — stream interrupted⚠ RTP payload type mismatch — encoder/SDP misconfiguration⚠ Dante clock or subscription issue⚠ Dante traffic routed (TTL N) — Dante audio should stay on a single L2 segment⚠ Likely Dante Virtual Soundcard — software Dante does not apply QoS markings (DSCP Best Effort)⚠ Stream not announced (no SAP) — audio glitch detection unavailable⚠ Stream type unknown — SDP required to classify as video/audio/ancillary💀 No signal for 12s
Clock / PTP:
⚠ No PTPv2 clock — AES67 streams may lose sync(orAES67 and ST2110)⚠ No PTPv1 or PTPv2 clock — Dante streams may lose sync(Dante devices use PTPv1 by default; devices in AES67 or RTP mode switch to PTPv2 and may disable PTPv1 — both versions are checked)⚠ No L2 gPTP clock — AVB streams may lose sync⚠ Multiple PTP Sync senders in domain N— two or more devices sending Sync in the same PTP domain; common causes: (1) IGMP snooping misconfiguration isolating network segments so each elects its own master; (2) mixing console clock source mismatch ("Enable Sync to External" set incorrectly); (3) a device with external word clock input conflicting with a separate Preferred Leader — Audinate warns this causes one device to lose sync and be muted unless both share the same external reference⚠ Large PTP correction field — transparent clock or path issue⚠ PTP path-delay variance > 10µs — unstable link (EEE, half-duplex, or cable)⚠ PTP path delay > 1ms — too many hops between this node and grandmasterpath delay: 14.2µs – 15.1µs (spread 0.9µs) ~3 hops— rough hop count (5µs per switch) shown inline on the path delay lineℹ 3 hops: Dante latency should be ≥ 0.5ms— Dante-only advisory when hop count suggests the configured latency may be too low (Audinate minimums: 3–4 hops → 0.5ms, 5–9 hops → 2ms, ≥10 hops → 5ms)
Dante device health:
⚠ Unverified (mDNS only, no ConMon): IP "Name" — may be a management NIC or non-Dante device— device appeared via mDNS but showed no ConMon activity and no audio stream for 15s; likely a non-Dante NIC on the same network segment❌ Dante redundancy bridged: "Name" seen from N IPs— a device in Dante Redundancy mode has its primary and secondary networks physically connected; this causes a network loop and PTP failure. The secondary port must be kept on a separate physical network from the primary⚠ Only N of M Dante devices syncing to clock— fewer devices are sending PTPv1 Delay_Req than are known on the network; some devices may not be locked to the grandmaster❌ "Device" (169.254.x.x) has no DHCP address — subscriptions will fail(primary network link-local; secondary network uses172.31.*.*instead) — note: on dedicated AV networks without a DHCP server, all Dante devices using APIPA (169.254.x.x) is intentional and fully functional; this alert only fires when some devices have routable addresses and others do not (mixed-subnet condition)⚠ DHCP may be down — all Dante devices have link-local addresses— on a dedicated Dante-only network without a DHCP server this is expected; the alert is advisory⚠ Dante devices on multiple subnets — mDNS and PTP cannot cross subnet boundaries without Dante Domain Manager (DDM) or Dante Director
Network infrastructure:
⚠ Stream count spike: N streams (avg last 3 windows: M) — possible runaway multicast flood⚠ ECN: N congestion mark(s) — router congestion detected on the path⚠ PAUSE frames: N in last 5s — upstream link congestion causing tx-side freezes⚠ PFC frames: N in last 5s — priority flow control engaged on upstream link⚠ EEE active on switch port(s) — may cause audio/video glitches⚠ No VLAN registration — L2 QoS may not be configured❌ Capture drops detected — loss/jitter figures may be understated(shown in red when pcap kernel or interface drops are non-zero)
PAUSE and PFC detection is best-effort: most NICs consume these frames at the MAC layer before pcap sees them. The absence of these alerts therefore does NOT prove no upstream congestion is happening.
The pcap capture stats (📦 N pkts received, then kernel drop(s), interface drop(s), and parsed each on their own line) always appear at the bottom of the Network Status section. Kernel drops mean the pcap ring buffer overflowed; interface drops mean packets were lost at the NIC before pcap. A drop count turns red when non-zero. Either type of drop corrupts loss and jitter numbers — if you see this, reduce traffic load or increase the pcap buffer size.
The health percentage reflects the overall network quality. Factors that reduce the score include packet loss, high jitter, timestamp discontinuities, source interruptions (SSRC changes), dead streams, PTP clock loss or instability, QoS tagging violations, IGMP querier absence or multiple competing queriers, AVB bandwidth reservation failures, and EEE active on switch ports.
- macOS and Linux — requires libpcap
- Windows — requires Npcap; run as Administrator; colour output requires Windows Terminal or VS Code (not supported in classic
cmd.exe) - Loopback (
lo/lo0) is excluded — macOS loopback uses a non-Ethernet link layer incompatible with the packet parser - Promiscuous mode is enabled automatically on the selected interface
- Virtual and tunnel interfaces (utun, awdl, docker, vpn…) are filtered from the interface list on macOS/Linux; Windows interface names are passed through as-is
- PAUSE / PFC detection is best-effort — most NICs consume these frames at the MAC layer before pcap sees them. Absence of these alerts does not prove no upstream congestion.
- EEE absence is not confirmed — AVStreamLens detects EEE only when the switch sends LLDP with the EEE TLV. No LLDP does not mean EEE is disabled.
- macOS VLAN tag stripping — many macOS drivers strip 802.1Q tags before pcap, so per-VLAN stream attribution may be unavailable on macOS trunk/SPAN ports. Linux generally preserves tags.
- NDI on loopback unsupported — macOS loopback uses a non-Ethernet link layer; mDNS multicast does not flow over loopback.
- No per-VLAN filtering — the tool processes all VLANs delivered by the capture interface. Use a SPAN session scoped to the target VLAN(s) to limit visibility.
See TODO.md for the full list of open issues and planned features. Highlights:
--vlan <id>flag to filter captured traffic to a specific VLAN- Dante AV video stream detection and metrics
- Health score penalty weight review