Detect callsigns in transcripts, and say whose they are

Under the transcript, headed DETECTED CALLSIGNS:, every callsign heard in
it with the name and location on its licence.

Finding them is not one regular expression over the text as written.  A
speech recogniser is poor at callsigns -- they are not words, they are
said one character at a time -- so it breaks them wherever the speaker
paused and writes the phonetic alphabet down verbatim.  The recording that
prompted this has "Alright, KU 0W" in it, with a space; spelled out it
would have been "kilo uniform zero whiskey".  All three forms read back to
KU0W.

Not inventing them matters more.  A run of words is accepted only when
none of its parts is an ordinary English word: "or 3. Can you open 4" and
"CC1 boy", both from real transcripts here, fit the shape once the
punctuation is gone and are not callsigns.  A single token said in one
breath is still trusted, because W1BOY is a perfectly good callsign, and a
lone "a" or "i" cannot start a join or "a B4U player" becomes AB4U.
Across the 126 transcripts in the recordings directory that turns three
candidates into the one that was actually said.

Lookups use the FCC's own licence data at callook.info -- no account, no
key, the callsign the only thing sent.  They never delay the display: the
entry reads "looking up" and fills itself in, and results are cached under
~/.cache so a net recorded night after night is looked up once.
--no-lookup contacts nothing and still describes a callsign from its own
structure, the ITU prefix giving the country and the digit the US
district, which is also all there is to say for callsigns outside the US.
--callsigns prints everyone who identified themselves and where they were
heard.

Also asked: are transcripts appended to, or overwritten, when another
transmission arrives on the same frequency?  Neither could be shown from
reading the code alone, so there are now three tests that run real scans
and look at the files.  By default each transmission has a transcript of
its own -- the timestamp is in the name, so two overs cannot land on one
file.  With --combine there is one recording per frequency and therefore
one transcript, opened for append with the time of each over; a second
scan into the same directory adds to it rather than starting it over,
which is the case the last of the three tests covers.

The browser and callsign tests refuse to reach the network at all.  One
test did, quietly, and passed -- visible only because the assertion it
failed printed a real operator's address.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016PsWPTweCT6pwxKngvVxcg
This commit is contained in:
The Dust Council 2026-08-22 15:41:02 -07:00
parent cc317914e1
commit 739a2faaf4
11 changed files with 1502 additions and 16 deletions

View file

@ -803,6 +803,25 @@ Only voice is transcribed — running a recogniser over Morse or a data burst
costs seconds and produces nothing. CW is decoded separately and appears in
the metadata as text already.
**One transcript per transmission, and none is ever overwritten.** The
timestamp is part of the name, so two overs on the same frequency cannot land
on the same file — a second transmission on 146.52 MHz writes
`...12_19_44-nfm_transcription.txt` beside the first, not over it.
With `--combine` there is one recording per frequency, so there is one
transcript per frequency too, and it works the other way: each over is
**appended** with the time it was heard, and an unattended receiver keeps
adding to it night after night.
```
[2026-08-21 12:18:38] Net control, this is W1AW, standing by.
[2026-08-21 12:19:44] Roger, copy that, back to you.
```
Both behaviours have tests that run a real scan and check the files, including
one that runs a second scan into the same directory and asserts the earlier
text is still at the top.
**A capture with nothing recognisable in it produces no file.** Music, a
carrier with an open mic, a fragment too short to make out: nothing is
written, rather than a directory of placeholders. The transcript is also
@ -982,11 +1001,65 @@ or symbol rate where there is one, and the bands the frequency falls in.
| `space` | stop playing |
| `t` | read the whole transcript full screen, scrolling |
| `/` | filter — by frequency, filename, identification, **or anything that was said** |
| — | callsigns are found and looked up automatically; no key needed |
| `s` | sort by time, frequency or length |
| `r` | re-read the directory, picking up what a running scan has written |
| `o` | print the file's path and quit |
| `q` | quit |
### Detected callsigns
Under the transcript, every callsign heard in it is listed with the name and
location on its licence:
```
╭─ transcript ──────────────────────────────────────────────────────────╮
│ │
│ Alright, moving on. There is an HF net at 1.30pm on 7.242 │
│ megahertz. Are there any announcements? Alright, KU 0W. │
│ │
│ DETECTED CALLSIGNS: │
│ KU0W Rod R Gowdy — Tucson, AZ · Extra · DM42lj · 85742 │
│ │
╰───────────────────────────────────────────────────────────────────────╯
```
Note what the recogniser actually wrote: **"KU 0W"**, with a space. Speech
recognisers are poor at callsigns — they are not words, they are said one
character at a time — so a callsign arrives broken wherever the speaker
paused, and an operator who spells it out gets *"kilo uniform zero whiskey"*
written down verbatim. All three forms read back to `KU0W`.
The other half of the problem is not inventing them. A browser that reports
callsigns nobody said is worse than one that reports none, so a run of words
is only accepted when none of its parts is an ordinary English word — *"or 3.
Can you open 4"* fits the shape once the punctuation is gone, and is not a
callsign. A single token said in one breath is trusted, because `W1BOY` is a
perfectly good callsign. Across 126 real transcripts from an overnight scan,
that turns three candidates into the one that was actually said.
```bash
saunterbrowse --callsigns # everyone who identified themselves, and where
saunterbrowse --no-lookup # find them, but contact nothing
```
Lookups use the FCC's own licence data via [callook.info](https://callook.info),
which needs no account or key. The callsign is the only thing sent; results are
cached in `~/.cache/bandsaunter/callsigns.json`, so the same net is looked up
once however many nights you record it, and a lookup never delays the display —
the entry reads `looking up…` and fills itself in.
`--no-lookup` contacts nothing. Callsigns are still found and still described
from their own structure: the prefix is allocated by the ITU and the digit is
the US licensing district, so `VE3ABC` is Canada and `N7XYZ` is US district 7
with no database at all. Outside the US that structural description is all
there is — callook.info holds US licences only.
US amateur licence records are public by law and include the licensee's
address; that is what is shown.
### Searching what was said
Searching the transcripts is the point of it: *"did anyone mention the
repeater"* is a question about content, not about filenames.