A permanent record of what actually went out on air
Register a station once. Everything below runs from that point on, with no audio to upload and nothing to install.
Each recognised airing, timestamped, with the recording's ISRC, artists, release, and cross-platform IDs. It lives in your account and stays queryable for as long as you are a customer. It is not a feed that scrolls away.
Ask for a window and get per-track spin counts with first and last play, alongside a row for every individual airing. Every row carries the ISRC, which is the field a play log is usually missing.
A signed webhook or a live event stream, delivered as the play is confirmed rather than on a polling interval. Stations dropping offline and recovering are events too, so you always know when a gap in the log is the station and not us.
The inverse setup: instead of matching one station against the whole catalog, you supply your own recordings and we watch for those specific tracks across a large fleet of stations. Because the reference set is small, this scales to far more stations for far less. You pay per station rather than per song, so a whole roster rides on one station list.
Four very different reasons to watch a station
- Labels and distributors
- Show that a record is actually being played, station by station, and see which markets picked it up before the statements arrive.
- Artists and managers
- Find out a song aired the day it aired, instead of discovering it in a royalty statement a quarter later.
- Webcasters and radio operators
- Turn your own output into a report of use. Your automation software exports artist and title; the monitor fills in the ISRC and label fields the societies actually ask for.
- Rights administrators
- Cross-check what a broadcaster reported against an independent recording of what went out on air.
Built for a station that never stops, not for a clip
Recognising one song from a clean twenty-second clip is a solved problem. Recognising every song on a live station, around the clock, through talkover, jingles, tempo shifts, and a stream that drops out twice a week, is a completely different problem. We built the engine for the second one. Here is what it does, in plain terms.
- 01
A dedicated listener for every station
Each station you monitor gets its own long-lived audio connection and its own isolated process. Radio streams misbehave constantly: they stall mid-song, they hand back expired URLs, they quietly serve silence for an hour without ever returning an error.
Keeping every station in its own lane means a badly behaved one cannot slow down, block, or wedge any of the others.
- 02
Overlapping listening windows
The audio is not chopped into neat consecutive blocks. The engine analyses a rolling window that advances a few seconds at a time, so every moment of the broadcast is covered by several overlapping windows.
Nothing can slip through a gap between windows, and a record that starts halfway through one is still caught by the next.
- 03
Two recognition methods, running side by side
Most services run a single fingerprinting method. We run two fundamentally different ones on every station.
The first compares the spectral shape of the audio. It is fast and it shrugs off the heavy compression broadcast streams apply.
The second builds warp-robust fingerprints and then geometrically aligns them against the reference, recovering the match even when the station has shifted the pitch or nudged the tempo. Playout systems do this constantly, to fit a track into a slot or tighten a segue, and it is exactly what defeats a single-method matcher.
Running both means that where one is blind, the other is usually not.
- 04
The engine learns each station
Which method wins is not the same on a dance station as on a classical one. So when monitoring starts, both run while the engine tallies which one is actually landing matches on that specific stream.
After that the stronger one leads, and the other keeps running underneath to fill in the moments the leader goes quiet. Each station also carries its own detection profile, and a controller re-tunes its sensitivity on an ongoing basis rather than leaving it on a value someone picked months ago.
- 05
A hot set held in memory, per station
Radio repeats itself. A few hundred records carry a station's rotation for weeks at a time. So each listener keeps the tracks it has recently confirmed in memory, seeded from that station's own history the moment it starts up, and checks those first.
This is the single largest optimisation in the system. On a live station we measured a hit against the in-memory set resolving in roughly a millisecond, against about 2.7 seconds for a full index probe. It is what makes watching many stations at once affordable, and it means the engine gets faster on a station the longer it listens to it.
- 06
Nothing reaches your log until it is confirmed
One window agreeing with a reference is not evidence. Speech over a music bed, a jingle built from a sample, or the crossfade between two records can all make a single window look like a confident match.
So a candidate has to be confirmed by several consecutive windows before it is written to your log, and a play is only closed out after the audio has disagreed for a sustained stretch.
That is a deliberate trade. The per-window threshold is loose, which protects recall, and the confirmation requirement is what supplies the precision. It also means one airing lands as one entry in your log rather than as dozens of detection ticks.
- 07
A fleet that repairs itself
The monitors run as a fleet across multiple machines, each reconciling against a central record of what should be running. If a machine dies, the survivors adopt its stations.
A watchdog catches a listener that has gone quiet without throwing an error, tears down its audio process, and restarts it on a widening backoff. A station that drops out at three in the morning is being retried, not sitting dead until someone notices in the morning. Streams that keep failing are recorded with the reason rather than failing silently.
- 08
Your log does not live inside the engine
The recognition engine keeps no history of its own. Every confirmed play is handed straight over to your account, which is the single source of truth for both history and now-playing.
That separation is on purpose. An engine restart, a deploy, or a bad night on one monitor never costs you history, and your log keeps answering questions either way.
A recognition API pointed at a station is not a monitoring engine
You can bolt a clip-recognition service onto a scheduled job and call it monitoring. It falls over on the parts that matter.
| Aspect | Recognition API on a timer | Purpose-built monitoring engine |
|---|---|---|
| The unit of work | One clip you send in | A station held open continuously for months |
| Matching | A single fingerprinting method | Two methods, picked per station, each covering the other |
| Pitch or tempo-shifted playout | Usually a miss | Warp-robust matching with geometric alignment |
| Avoiding false matches | A strict threshold, which costs recall | Multi-window confirmation, which keeps recall |
| Repeat plays | A full index lookup every single time | Per-station memory, roughly a millisecond |
| A station going down | Your problem to detect | Watchdog, backoff retry, and an offline event |
| What you end up with | A match | A spin log and an airplay report |
To be straight about what is ours: the underlying fingerprinting techniques are established signal processing and we did not invent them. What we built is everything around them. The per-station listener, the two-method selection and cross-cover, the multi-window confirmation gate, the in-memory hot set, the self-healing fleet, and the reporting layer are all our own design, built for continuous broadcast rather than adapted from one-shot clip recognition.
Spin counts and every individual airing
One call covers all of your stations, or a single one. Each station carries its own summary (per-track spin counts with first and last play) alongside a detail log with a row per airing. Both carry the ISRC. Windows can span up to 92 days, and reading your own reports uses no API credits.
# Every spin across all your stations, for a date rangecurl "https://api.sonovault.now/v1/streams/report?from=2026-07-01&until=2026-08-01" \-H "x-api-key: YOUR_API_KEY"
{"report": {"from": "2026-07-01","until": "2026-08-01","generated_at": "2026-08-01T09:00:00Z","scope": { "stream_id": null },"streams": [{"id": "9f2c8e1a-...","name": "My Station","url": "https://stream.example.com/radio.mp3","summary": [{"track_id": 121217540,"title": "One More Time","artist": "Daft Punk","isrc": "GBDUW0000054","play_count": 34,"first_played_at": "2026-07-01T07:12:44Z","last_played_at": "2026-07-31T22:48:03Z"}],"detail": [{"played_at": "2026-07-01T07:12:44Z","ended_at": "2026-07-01T07:18:04Z","duration_seconds": 320,"track_id": 121217540,"title": "One More Time","artist": "Daft Punk","isrc": "GBDUW0000054"}]}]}}
Play counts are counted per airing, never per detection tick, so a five-minute record that the engine confirmed forty times over its run counts exactly once. The stream monitoring reference covers registering a station, now-playing, webhooks, and the live feed, and the API docs have every route in full.
Try it on a station in about a minute
Paste a stream URL into the dashboard and watch the now-playing track and the recognition history fill in. Same engine as the API, nothing to install, and you can stop monitoring with a click.
Pricing and data notes
Frequently asked questions
Start watching a station
Create a free account and register your first stream from the dashboard. If you want to watch your own catalog across a large fleet of stations instead, that is the private beta, so talk to us first.