A repeater identifying itself in CW over an FM carrier came back from the recogniser as "2-2-2-3-3-5-2-7-0-5-9-7-0-8-1-0" -- one digit per tone, sixteen characters of nothing, which cleared the five-character bar and cost the capture its waterfall. The rule now lives in one place, waterfall.is_readable, shared by the scanner and the waterfall command: voice, no Morse, and more than a handful of characters. bandsaunter waterfall --check-morse runs the CW decoder over the recordings a sidecar calls readable, for sidecars written before the decoder could hear an ident over an FM carrier, and draws -- and records the ident in -- the ones that have one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016PsWPTweCT6pwxKngvVxcg
479 lines
17 KiB
Groff
479 lines
17 KiB
Groff
.\" Generated by packaging/make-browse-man.py -- do not edit by hand.
|
|
.TH SAUNTERBROWSE 1 "2026-09-03" "bandsaunter 2026-09-03_02" "User Commands"
|
|
.SH NAME
|
|
saunterbrowse \- read and listen to what a bandsaunter scan collected
|
|
.SH SYNOPSIS
|
|
.B saunterbrowse
|
|
.RI [ DIRECTORY ]
|
|
.RB [ \-\-sort
|
|
.IR ORDER ]
|
|
.RB [ \-\-filter
|
|
.IR TEXT ]
|
|
.RB [ \-\-player
|
|
.IR CMD ]
|
|
.RB [ \-\-list ]
|
|
.RB [ \-\-callsigns ]
|
|
.RB [ \-\-kml
|
|
.RI [ FILE ]]
|
|
.RB [ \-\-no\-lookup ]
|
|
.SH DESCRIPTION
|
|
A scan leaves a directory of recordings. Beside each one is a JSON file
|
|
holding what the classifier made of it, and for speech a transcript of what
|
|
was said. Reading that by hand means opening files one at a time and guessing
|
|
which are worth playing.
|
|
.PP
|
|
.B saunterbrowse
|
|
shows them as a list you move through with the arrow keys. The transcript of
|
|
whichever recording is highlighted fills the top of the screen, because that
|
|
is the part you actually want to read; underneath it are the identification,
|
|
the bands the frequency falls in, and the list itself. Pressing Enter plays
|
|
the recording.
|
|
.PP
|
|
Each line of the list gives the frequency, the date and time, the mode, how
|
|
long it ran and what was said. The moment is written
|
|
.BR "YY-mm-dd hh:mm:ss am/pm" ,
|
|
date first so that a column of them reads down in order, and on a twelve-hour
|
|
clock so that it reads the way you would say it. The list starts in that
|
|
order, newest first.
|
|
.PP
|
|
With no
|
|
.I DIRECTORY
|
|
it opens the one the scanner writes to, taken from your saved settings, so it
|
|
normally needs no arguments at all.
|
|
.PP
|
|
Recordings can also be dealt with as they are read. A key files one into
|
|
saved/, investigate/ and noise/, another deletes it outright, and another locks its frequency
|
|
out of every later scan. Nothing else is written: without one of those keys
|
|
the browser only reads.
|
|
.SH KEYS
|
|
.TP
|
|
.B "Up Down k j"
|
|
Move through the recordings.
|
|
.TP
|
|
.B "PgUp PgDn"
|
|
A screenful at a time.
|
|
.TP
|
|
.B "Home End"
|
|
The first and the last.
|
|
.TP
|
|
.B Enter
|
|
Play the highlighted recording. Playing a second one stops the first: two
|
|
players talking over each other is worse than either alone.
|
|
.TP
|
|
.B Space
|
|
Stop playing. With nothing playing, it starts, like Enter.
|
|
.TP
|
|
.B t
|
|
Read the whole transcript full screen, scrolling with the arrow keys. Useful
|
|
for a long net, where the panel at the top can only show the first few lines
|
|
\[em] it says so when there is more.
|
|
.TP
|
|
.B /
|
|
Filter. What you type is matched against the frequency, the filename, the
|
|
identification and
|
|
.I everything that was said,
|
|
so "was the repeater mentioned" is a question you can ask directly. Enter
|
|
accepts, Escape clears.
|
|
.TP
|
|
.B s
|
|
Cycle the order: date/time, frequency, duration.
|
|
.TP
|
|
.B r
|
|
Re-read the directory. A scan running in another window is still writing to
|
|
it, and this picks up what has arrived since.
|
|
.TP
|
|
.B o
|
|
Print the highlighted recording's path and quit, for piping into something
|
|
else.
|
|
.TP
|
|
.B "S I N"
|
|
File the highlighted recording into saved/, investigate/ and noise/ respectively \[em] the
|
|
recording and every sidecar written beside it, together. See
|
|
.B MANAGING THE RECORDINGS
|
|
below.
|
|
.TP
|
|
.B u
|
|
Put the last recording that was filed back where it came from. One level
|
|
only, and a delete cannot be undone this way.
|
|
.TP
|
|
.B d
|
|
Delete the highlighted recording and its sidecars for good. It asks first:
|
|
this is the one key here that cannot be taken back.
|
|
.TP
|
|
.B m
|
|
Lock the highlighted recording's frequency out, so that no later scan stops
|
|
on it again. The frequency is written into your saved settings, the same list
|
|
.BR bandsaunter (1)
|
|
maintains, and takes effect on the next scan \[em] a scan already running read
|
|
its settings when it started.
|
|
.TP
|
|
.B "? h"
|
|
The list of keys, and which audio player was found.
|
|
.TP
|
|
.B q
|
|
Quit. With a filter in force, Escape clears the filter first.
|
|
.SH OPTIONS
|
|
.TP
|
|
.BI DIRECTORY
|
|
Where the recordings are. Defaults to the scanner's output directory, or to
|
|
.B $BANDSAUNTER_OUTPUT
|
|
when that is set.
|
|
.TP
|
|
.BI \-\-sort " ORDER"
|
|
Start in this order: date/time, frequency, duration. Date/time is newest first, ordered by the whole
|
|
moment \[em] year, month, day, then hour, minute and second; duration is longest
|
|
first.
|
|
.B time
|
|
is accepted as the old name for
|
|
.BR date/time .
|
|
.TP
|
|
.BI \-\-filter " TEXT"
|
|
Start with only the recordings matching this, exactly as if it had been typed
|
|
at the
|
|
.B /
|
|
prompt.
|
|
.TP
|
|
.BI \-\-player " CMD"
|
|
The command used to play a recording. The path is appended as its last
|
|
argument. By default the first of these that is installed is used:
|
|
pw-play, paplay, aplay, play, ffplay, mpv.
|
|
.TP
|
|
.B \-\-callsigns
|
|
Print every callsign heard in the directory, with the licence it belongs to
|
|
and where and when it was heard, then exit.
|
|
.TP
|
|
.BI \-\-kml " [FILE]"
|
|
Write a map of where the stations heard in this directory are licensed, and
|
|
exit. Without a filename it writes
|
|
.I callsigns.kml
|
|
in the recordings directory \[em] the same file a scan writes, so a map built
|
|
this way is continued by the next scan rather than duplicated. See
|
|
.B THE MAP
|
|
below.
|
|
.TP
|
|
.B \-\-no\-lookup
|
|
Do not contact the licence database. Callsigns are still found and still
|
|
described from their prefix; only the name and address are missing.
|
|
.TP
|
|
.B \-\-list
|
|
Print one line per recording and exit, without drawing anything. This is what
|
|
to use over a pipe, in a script, or anywhere there is no terminal.
|
|
.TP
|
|
.B \-V ", " \-\-version
|
|
Print the version and exit.
|
|
.SH SOUND
|
|
Playback is handed to whichever player is installed rather than done in the
|
|
program: the recordings are ordinary WAV files, every desktop already has
|
|
something that plays them, and a browser that cannot start is worse than one
|
|
that cannot play. If none is found, everything else still works and the
|
|
message says which packages would fix it.
|
|
.PP
|
|
Over ssh there is usually no sound server at the far end. The browser and its
|
|
transcripts work regardless; only Enter has nothing to do.
|
|
.SH DETECTED CALLSIGNS
|
|
A capture that produced no readable words has a waterfall drawn beside it
|
|
instead \[em] a picture of the signal, which for a data burst or a keyed
|
|
carrier is the only view there is. The browser marks it, gives the path in
|
|
full, and
|
|
.B o
|
|
prints it: there is no listening to a data burst.
|
|
.PP
|
|
Under the transcript, headed
|
|
.BR "DETECTED CALLSIGNS:" ,
|
|
is every callsign heard in it, with the name and location on the licence.
|
|
.PP
|
|
Finding them is not a matter of one regular expression over the text as
|
|
written. A speech recogniser is poor at callsigns \[em] they are not words,
|
|
they are said one character at a time \[em] so it breaks them wherever the
|
|
speaker paused and writes the phonetic alphabet down verbatim. It also joins
|
|
the words back up, hyphenates them, spells them the way they sounded, and
|
|
writes down the hesitation in the middle. "KU 0W", "K7 RA",
|
|
"kilo uniform zero whiskey", "Whiskey\-One\-Alpha\-Whiskey",
|
|
"WhiskeyOneAlphaWhiskey", "wiskey one alfa whisky" and
|
|
"whiskey one alpha, uh, whiskey" are all one callsign each, and all of them
|
|
are read back correctly.
|
|
.PP
|
|
A suffix is not part of the callsign. Nothing is joined across a slash, so
|
|
.I W1AW/B
|
|
is W1AW and not W1AWB, which belongs to nobody.
|
|
.PP
|
|
Two shapes are recognised, not one. An amateur callsign is a prefix, a
|
|
district digit and a suffix \[em] W1AW, KU0W, 2E0ABC. Everything else the FCC
|
|
licenses is called the other way round, the letters first and then the digits:
|
|
WQVF960 is a GMRS licence and WXG204 an older Part 90 one. On the GMRS and
|
|
business channels those are most of what is said.
|
|
.PP
|
|
False positives are the thing to avoid: a browser that invents callsigns is
|
|
worse than one that finds none. So a run of words is only accepted when none
|
|
of its parts is an ordinary English word \[em] "or 3. Can you open 4" fits the
|
|
shape once the punctuation is gone, and is not a callsign \[em] while a single
|
|
token said in one breath is trusted, because W1BOY is a perfectly good
|
|
callsign. The GMRS shape is not given that trust: its letters are a run of
|
|
two to four, which is the length of a short word, so "west 120" fits it
|
|
exactly and a licence prefix never spells anything.
|
|
.PP
|
|
The lookup uses the FCC's own licence data, published at callook.info, and
|
|
falls back to hamdb.org; neither needs an account or a key. The second is not
|
|
a spare copy of the first \[em] callook holds United States amateur licences
|
|
only, so a German or Canadian callsign is INVALID there and known to the
|
|
other, and a source that is down takes only itself with it. The callsign is
|
|
the only thing sent, results are cached under
|
|
.I ~/.cache/bandsaunter/
|
|
so the same net is looked up once however many nights it is recorded, and a
|
|
lookup never delays the display: the entry says "looking up" and fills itself
|
|
in.
|
|
.PP
|
|
A GMRS or business callsign is not looked up at all, and says so rather than
|
|
saying "unlisted". Every database reachable without an account is an amateur
|
|
register and WQVF960 was never in one, so reporting it as missing would blame
|
|
the callsign for the absence of a source.
|
|
.PP
|
|
.B \-\-no\-lookup
|
|
contacts nothing at all. Callsigns are still found, and still described from
|
|
their own structure \[em] the prefix is allocated by the ITU and the digit is
|
|
the US licensing district, so a callsign says which country and which region
|
|
it belongs to without any database.
|
|
.PP
|
|
.B \-\-callsigns
|
|
prints every callsign in the directory, who it belongs to, and each frequency
|
|
and time it was heard on, then exits.
|
|
.PP
|
|
US amateur licence records are public by law, and include the street the
|
|
licence was issued to, not merely the town. That is what is shown, and what
|
|
is written into the map: holding it and not saying so would be worse than
|
|
either showing it or not asking for it.
|
|
.B \-\-no\-lookup
|
|
asks for none of it.
|
|
.SH THE MAP
|
|
A licence says where its holder is, so a list of callsigns is also a map. The
|
|
scanner writes one as it runs and
|
|
.B \-\-kml
|
|
builds one from recordings already on disk; both write the same file, so
|
|
either can carry on from the other.
|
|
.PP
|
|
Each station is one placemark, not one per transmission: hearing the same
|
|
repeater twenty times in an evening is one station, and twenty pins stacked
|
|
on the same rooftop would say less than one. The pin holds the callsign, the
|
|
licensee, the town, the grid square, and every frequency and time it was
|
|
heard on, so clicking it answers "when did I hear this, and where on the
|
|
dial".
|
|
.PP
|
|
The file is added to rather than replaced. A scan on Tuesday continues the
|
|
map Monday made, which over a few weeks turns into a picture of what your
|
|
aerial can actually reach.
|
|
.PP
|
|
Where the licence carries no coordinates the grid square is used instead, and
|
|
the placemark says so, because a grid square is kilometres across where a
|
|
licensed address is a street. A callsign with no licence on file at all is
|
|
still recorded, in a folder named
|
|
.IR "no location on file" ,
|
|
switched off by default: that a station was heard is worth keeping even when
|
|
nothing says where it was.
|
|
.PP
|
|
KML is the format Google Earth uses.
|
|
.BR qgis (1),
|
|
.BR marble (1)
|
|
and OsmAnd open it too, and it is XML, so a scan interrupted halfway through
|
|
leaves a file that still opens.
|
|
.SH MANAGING THE RECORDINGS
|
|
A night's scan leaves hundreds of files, most of which are worth nothing and
|
|
a few of which are the reason you left it running. Deciding which is which is
|
|
what this program is for, and the keys that act on a recording are meant to
|
|
be pressed once each, going down the list.
|
|
.TP
|
|
.B S
|
|
Into
|
|
.IR saved /
|
|
\[em] keep this one.
|
|
.TP
|
|
.B I
|
|
Into
|
|
.IR investigate /
|
|
\[em] come back to this one.
|
|
.TP
|
|
.B N
|
|
Into
|
|
.IR noise /
|
|
\[em] not a signal worth keeping.
|
|
.PP
|
|
Each of these moves the whole capture \[em] the
|
|
.IR .wav ,
|
|
the JSON sidecar, the raw IQ where it was kept, the transcript and the decoded
|
|
data \[em] because a recording in one directory and its transcript in another
|
|
is a pair nothing will ever put back together. If the move cannot be finished,
|
|
whatever has already moved is put back: half a capture in each of two places
|
|
is worse than none moved at all.
|
|
.PP
|
|
The subdirectories are ordinary directories inside the recordings directory,
|
|
so a scan writing there never looks into them and never lists what is in
|
|
them. To read what is in one, point the browser at it:
|
|
.IP
|
|
.EX
|
|
saunterbrowse ~/bandsaunter/saved
|
|
.EE
|
|
.PP
|
|
.B u
|
|
puts the last one filed back. One step, not a history: it exists so that a
|
|
mistyped key costs nothing, not so that an evening's sorting can be unwound.
|
|
.PP
|
|
.B d
|
|
deletes instead, and asks first, because nothing puts that back.
|
|
.PP
|
|
.B m
|
|
is the other half of the same job. A birdie, a pager transmitter or a data
|
|
link that fills the recordings directory night after night is not a recording
|
|
problem, it is a scanning problem, and this writes the frequency into the
|
|
lock-out list in your settings file. The width comes from the
|
|
.B lockout_width
|
|
setting, so a lock-out is a channel rather than a single point. Locking out a
|
|
frequency does not delete what has already been recorded on it \[em] the two
|
|
keys are separate on purpose, and pressing both is the usual thing to do.
|
|
.SH PICTURES
|
|
Some recordings are not sounds. Slow-scan television, the NOAA weather
|
|
satellites and the shortwave weather fax stations all send images as audio,
|
|
and
|
|
.BR bandsaunter (1)
|
|
writes what it decodes as a PNG beside the recording.
|
|
.PP
|
|
Those are marked in the list by what they are \[em] "SSTV Martin M1 320x256" \[em]
|
|
and the panel at the top of the screen gives the path of the file in full,
|
|
wrapped rather than cut off, because a terminal cannot draw a PNG and saying
|
|
exactly what to open is the most useful thing left. A weather satellite pass
|
|
has three files: the whole frame, and each of the satellite's two sensors on
|
|
its own.
|
|
.PP
|
|
.B o
|
|
prints the picture's path rather than the recording's, for piping into an
|
|
image viewer:
|
|
.IP
|
|
.EX
|
|
saunterbrowse \-\-filter sstv \-\-list
|
|
xdg\-open "$(saunterbrowse)"
|
|
.EE
|
|
.PP
|
|
Filing a recording moves its pictures with it, and deleting one deletes them.
|
|
.SH CALLSIGNS IN MORSE
|
|
Most stations on the air never say a word. A repeater, a beacon or an
|
|
unattended transmitter sends its callsign in Morse and stops, and what it
|
|
sent takes the place of the transcript at the top of the screen, with the
|
|
licence it belongs to underneath exactly as for speech. It is searchable with
|
|
.B /
|
|
like anything else.
|
|
.PP
|
|
Only the part of it that was not cut in half is looked at for a callsign. A
|
|
capture opens when the squelch does, which is partway through a word as often
|
|
as not, and what is left of that word can read as a whole one:
|
|
.I K1AA
|
|
caught halfway through is
|
|
.IR K1A ,
|
|
which belongs to somebody else.
|
|
.BR bandsaunter (1)
|
|
describes how that is decided. The full text is shown either way.
|
|
.SH DECODED DATA
|
|
Where a capture carried data rather than speech, what was decoded takes the
|
|
place of the transcript at the top of the screen: the kind of packet, and then
|
|
the message. A pager's text, an APRS position report, or the bits and hex of a
|
|
remote control. It is searchable with
|
|
.B /
|
|
like anything else, so "which page mentioned engine 4" is a question that can
|
|
be asked here.
|
|
.PP
|
|
The text comes from the
|
|
.I _data.txt
|
|
beside the recording, or from the sidecar where there is none.
|
|
.BR bandsaunter (1)
|
|
describes how it is decoded and what has to be true before a decode is
|
|
believed.
|
|
.SH TRANSCRIPTS
|
|
A transcript appears only where a recogniser produced one, which means the
|
|
capture was judged to be speech and
|
|
.B bandsaunter\-transcribe
|
|
was installed at the time. Where there is none, the panel says which of the
|
|
several reasons applies \[em] Morse, data, a bare carrier, or speech that was
|
|
never offered to a recogniser \[em] because those want different things done
|
|
about them.
|
|
.PP
|
|
Two places can hold the text: the JSON sidecar records what was recognised
|
|
during the scan, and the
|
|
.I _transcription.txt
|
|
beside the recording is what a later re\-run wrote. The file wins, being the
|
|
more recent of the two.
|
|
.SH FILES
|
|
.TP
|
|
.I ~/bandsaunter/
|
|
Where recordings are written, unless the saved settings say otherwise.
|
|
.TP
|
|
.IR frequency \-\- date _ time \- modulation .wav
|
|
A recording.
|
|
.TP
|
|
.IR ... .json
|
|
Its measurements and identification.
|
|
.TP
|
|
.IR ... _transcription.txt
|
|
What was said, where a recogniser heard speech.
|
|
.TP
|
|
.IR ... _data.txt
|
|
What was decoded, where the capture carried data.
|
|
.TP
|
|
.IR saved /, investigate /, noise /
|
|
Where the filing keys move recordings to. Created on first use; a scan never
|
|
looks in them.
|
|
.TP
|
|
.I ~/.config/bandsaunter/config.yaml
|
|
The settings the
|
|
.B m
|
|
key writes a locked-out frequency into.
|
|
.SH ENVIRONMENT
|
|
.TP
|
|
.B BANDSAUNTER_OUTPUT
|
|
The directory to open, overriding the saved settings.
|
|
.SH EXAMPLES
|
|
.PP
|
|
.RS
|
|
.EX
|
|
saunterbrowse
|
|
.EE
|
|
.RE
|
|
.PP
|
|
Open the scanner's output directory.
|
|
.PP
|
|
.RS
|
|
.EX
|
|
saunterbrowse /mnt/recordings \-\-sort frequency
|
|
.EE
|
|
.RE
|
|
.PP
|
|
Browse somewhere else, grouped by channel rather than by time.
|
|
.PP
|
|
.RS
|
|
.EX
|
|
saunterbrowse \-\-list | grep \-i "mile marker"
|
|
.EE
|
|
.RE
|
|
.PP
|
|
Search the transcripts from a script.
|
|
.PP
|
|
.RS
|
|
.EX
|
|
saunterbrowse \-\-callsigns
|
|
.EE
|
|
.RE
|
|
.PP
|
|
Everyone who identified themselves, and where they were heard.
|
|
.PP
|
|
.RS
|
|
.EX
|
|
saunterbrowse \-\-kml ~/heard.kml
|
|
.EE
|
|
.RE
|
|
.PP
|
|
The same thing as a map, to open in Google Earth.
|
|
.SH EXIT STATUS
|
|
0 on a clean exit, 1 when the directory holds no recordings, 2 when it does
|
|
not exist or there is no terminal to draw on.
|
|
.SH SEE ALSO
|
|
.BR bandsaunter (1)
|
|
.SH BUGS
|
|
The list is read when the browser opens. Press
|
|
.B r
|
|
to pick up recordings a running scan has written since.
|