Skip to main content

Models & Training

RFWhisper ships two model families out of the box and makes it easy to add your own.

ModelFlavorTypical useSizeCPU RTF (M1)CPU RTF (RPi 5)
DeepFilterNet3 (ham-tuned)FP32Default on laptops/desktops~3.1 MB0.120.41
DeepFilterNet3 (INT8 QDQ)INT8Laptops + RPi 5~0.9 MB0.070.22
RNNoise-ham (retuned)FP32Pi 4 / Zero 2 W / anywhere CPU is tight~180 KB0.030.09
NullModel (identity)—CI / dev runners without weights — --model null0n/an/a
Your fine-tune (v0.5)FP32 / INT8Tuned to your QTH's noiseanyvariesvaries
Every model ships with
  • SHA-256 pinned in source (rfwhisper/models/registry.py — ARTIFACTS)
  • A model card in docs/models/model-cards (architecture, training data, license, known failure modes, maintainer)
  • PyTorch ↔ ONNX parity verification (RMS diff ≤ 1e-3, max ≤ 1e-2)
  • CW + FT8 regression test results on the reference eval set
  • Latency p50 / p99 on reference hardware

Pick a model​

# Default — pipeline will choose based on your hardware
rfwhisper denoise-live --model auto

# Explicit
rfwhisper denoise-live --model deepfilternet3 --model-variant int8
rfwhisper denoise-live --model rnnoise-ham
rfwhisper denoise-live --model my-qth-tuned-v1 # your fine-tune

Model registry​

Models are registered in rfwhisper/models/registry.py as a tuple of ModelArtifact dataclasses:

ARTIFACTS: tuple[ModelArtifact, ...] = (
ModelArtifact(
name="DeepFilterNet3 ONNX (community export — verify before production)",
relpath="models/deepfilternet3/dfn3.onnx",
url="https://huggingface.co/aufklarer/DeepFilterNet3-ONNX/resolve/main/deepfilter.onnx",
sha256="VERIFY_ON_FIRST_RUN",
license_note="Upstream DeepFilterNet: MIT OR Apache-2.0. Third-party export; test parity.",
),
# ...
)

python -m rfwhisper.models.fetch downloads, verifies, and caches these under the repo's models/ directory. The first run captures the artefact's SHA-256 in a .sha256.local sidecar — pin that value into ARTIFACTS once you've validated parity.

Loading a model in Python​

from rfwhisper.models import load

model = load("null") # identity pass-through (CI / dev)
model = load("deepfilternet3") # raises if weights missing
model = load("deepfilternet3", fallback_to_null=True) # warns and returns NullModel

The factory picks ONNX Runtime execution providers in priority order — CoreML on macOS, DirectML on Windows, then CUDA → XNNPACK → CPU on every platform — and applies intra_op_num_threads=2, enable_cpu_mem_arena=True, ORT_ENABLE_ALL per the AGENTS.md realtime budget. Missing EPs are skipped with a RuntimeWarning, never a crash.

The non-regression gates (every model must pass)​

  1. CW keying transients — RMS within ±1 dB of raw on every transient.
  2. FT8 decodes — denoised decodes ≥ raw, zero false decodes.
  3. No-op sanity — clean in, clean out. PESQ drop ≤ 0.3, STOI drop ≤ 0.02.

A model that fails any of these is not merged, even if it scores higher on SNR gain.

Next​

  • Training — build a dataset + train from scratch
  • Fine-tuning — adapt a stock model to your shack in ~30 minutes
  • Model Cards — what's in each model, who maintains it, and how it was evaluated