Skip to content

Repository files navigation

SignalScribe

Offline 2m-band monitor. Captures the entire amateur 2m band (144–148 MHz) from an SDRPlay RSP1, detects and demodulates live NBFM transmissions across all channels in parallel, transcribes them locally, archives everything searchable, identifies speakers, and detects and summarizes nets — with no cloud dependencies.

See plan.md for the roadmap and design rationale, and CLAUDE.md for project rules.

Architecture

RSP1 ──IQ (~6 MSPS)──► Capture Daemon (C#)
│ polyphase filterbank channelizer (~300 ch)
│ per-channel adaptive squelch + NBFM demod
│ segmentation markers (squelch crash, courtesy
│ tone, RF edges, discriminator DC-offset jumps)
│
├──► Opus (OGG) clips on disk
└──► metadata/events ──► Web Host (ASP.NET Core)
│ EF Core → SQLite (WAL)
│ ** single writer **
│ job queue API
│ Vue 3 dashboard
▼
Processing Workers (C#) ◄── claim jobs via host API
│ transcription — Whisper.net (whisper.cpp)
│ speaker embed — ECAPA-TDNN via ONNX Runtime
│ net analysis — deterministic heuristics
│ net summaries — LLamaSharp (llama.cpp, 8B Q4)
└──► results posted back to host API

Hardware requirements

ComponentMinimumRecommendedNotes
SDRSDRPlay RSP1RSP1 + 2m bandpass filterRSP1 has minimal preselection; FM broadcast/pagers can overload it. Run ~6 MSPS (2m band is only 4 MHz wide).
CPU6 cores with AVX28+ cores (Zen 3+/12th-gen Intel+)LLM inference is memory-bandwidth bound — dual-channel RAM matters more than core count; >8 threads gives diminishing returns. CPUs without AVX (e.g. QEMU default vCPUs — use -cpu host!) work via bundled no-AVX runtimes but inference is several times slower.
RAM16 GB (tight)32 GBSee per-model budget below.
Disk50 GB100 GB+ SSDAudio recorded directly as 16 kHz Opus-in-OGG, 32 kbps VBR voice mode (~14 MB per hour of recorded audio). Optional raw WAV/IQ capture behind a debug flag for DSP development.
USBUSB 2.0 port6 MSPS fits USB 2.0.
OSLinux, .NET 8+Requires SDRPlay API service (proprietary, free download).

Compute budget by workload

WorkloadModelRAMCPU costLatency expectation
Channelizer + demod— (custom PFB)< 1 GB1–2 cores, continuousReal-time
TranscriptionWhisper small.en (q5)~1 GBBurstyFaster than real-time on 8 cores; 1.12× real-time on 3 threads of a 4-core box (measured)
Transcription (higher accuracy)Whisper medium.en (q5)~2.5 GBBursty~Real-time; backlog drains overnight
Speaker embeddingsECAPA-TDNN (ONNX)~100 MBNegligiblePer-clip, milliseconds
Net summariesQwen 2.5 1.5B Q4_K_M (default)~1 GBBatch, after net closesUnder a minute per summary on four cores
Net summaries (better prose)Qwen 2.5 / Llama 3.x 7–8B Q4_K_M~5 GB model, 6–8 GB processBatch5–15 tok/s → 2–4 min per net summary; wants 8 cores

Everything above runs concurrently on one 8-core / 32 GB machine. Four cores is enough for the defaults, but leaves no headroom: give inference cores − 1 threads (Settings → CPU threads) so the capture daemon, which consumes a 6.4 MSPS stream in real time, is never descheduled. Summary quality holds up at 1.5B because the facts come from the deterministic layer — the model only phrases them. All inference is local; nothing requires network access after model download.

Software stack

LayerTech
DSP / captureC# (.NET 8), sdrplay_api P/Invoke, System.Runtime.Intrinsics
Audio encodingOpus in OGG via Concentus (managed Opus, native 16 kHz speech mode)
TranscriptionWhisper.net (whisper.cpp bindings)
Speaker IDONNX Runtime + ECAPA-TDNN embeddings, clustered per session, labeled via extracted callsigns
SummariesLLamaSharp (llama.cpp bindings)
StorageSQLite (WAL mode) via EF Core; FTS5 transcript index (see CLAUDE.md for the pattern)
API / UIASP.NET Core (controllers, api/v0/) + Vue 3 + Vuetify

Legal note

US amateur transmissions carry no expectation of privacy (Part 97; encryption prohibited), so recording, transcribing, and publishing this traffic is permitted.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages