ARLIResearch
Local Voice AI · Product Architecture

Two Products, One Engine:
Realtime Diarization & Local Voice Input

Deep market/tech analysis and phase-by-phase build plans for (1) a dialogue recorder with realtime speaker diarization + content-based name assignment, and (2) a Typeless-style AI voice input method, both running lightweight, preferably local, models.

2k★Diart, realtime diarization engine
90★AriaType, local-first voice input
482★OpenTypeless. Typeless clone
MITFront-running licenses (Diart/OpenTypeless)

Executive Summary

Both products are realisable today with open-source, local-first components, no cloud dependency, no API fees. The two projects share a single AI foundation (speech → text → meaning) and are technically synergistic: the voice input method is essentially a single-speaker special case of the dialogue recorder. Building them as a shared "voice-AI core" with two thin product surfaces is the highest-leverage architecture.

Core recommendation

Build a shared Rust/Python voice-AI core (streaming STT + diarization + local LLM polish). Project 2 (voice input) is a strict subset and should ship first, it is simpler, delivers standalone value, and de-risks the harder Project 1. Then Project 1 layers diarization + identity/name assignment on the same core.

Research Method

Analysis grounded in live open-source reconnaissance (Agent-Reach / Exa semantic search + GitHub/README extraction, August 2026) plus the local stt-transcription skill reference. Key sources: Diart, pyannote.audio 3.x, sherpa-onnx, OpenTypeless, AriaType, and speaker-to-name LLM literature (arXiv 2509.15082). Figures marked as of 2026-08.


Part 1: Project 1: Dialogue Recorder & Realtime Analyzer

Goal: record a multi-person conversation in real time; continuously identify who is speaking by voice characteristics; then assign names to those voices based on content context, all with lightweight, preferably local, models.

1.1 Decomposing the problem

The task splits into four distinct capabilities, each with a mature open-source answer:

CapabilityWhat it doesFlagship open-source
VAD (voice activity)Detect speech vs. silence, when someone talksSilero, pyannote.audio segmentation
Speaker diarizationGroup segments into distinct voices (SPK_0, SPK_1…) — "who, when"Diart (realtime, MIT), pyannote 3.1 (offline)
STTTurn speech into text (for content + name inference)Whisper (turbo/small), sherpa-onnx streaming
Name assignmentBind a cluster to a real identity from content ("…as Mike said…")Local LLM over the transcript + names

1.2 The realtime engines: Diart (the right choice)

juanmc2005/diart is a Python framework purpose-built for real-time speaker diarization (MIT, ~2k★). It fuses a speaker-segmentation model and a speaker-embedding model into an incremental clustering pipeline that becomes more accurate as the conversation progresses, exactly the online behavior Project 1 requires. Configurable latency (as low as ~500 ms) and native WebSocket serving make it the natural engine.

Why Diart over pyannote for this project

pyannote.audio 3.1 is superb offline (5–10× real-time on GPU, native overlap handling) but is batch-oriented. Diart is the only mainstream engine that streams diarization online, the deciding factor for a "realtime analyzer." Use Diart for live, pyannote for batch post-processing.

# Diart streaming speaker diarization (core loop)
from diart import OnlineSpeakerDiarization
from diart.sources import MicrophoneAudioSource
from diart.inference import RealTimeInference
from diart.sinks import RTTMWriter
import diart.inference as rec

pipeline = OnlineSpeakerDiarization.from_pretrained("diart/speaker-diarization-xenova")
config = pipeline.config
async def on_stream(wav):
    for turn, _, speaker in pipeline(wav):
        yield turn, speaker  # (start,end) → SPK_x, live

# Serve over WebSocket for a recorder + live UI
inference = RealTimeInference(pipeline, MicrophoneAudioSource(config.sample_rate))

1.3 Name assignment from content: the "context" trick

Diarization gives anonymous clusters (SPK_0). Assigning real names is a content-inference problem, solved in the research literature (e.g. arXiv 2509.15082 "Identity-Aware LLM Refinement of Speaker Diarization") and by AssemblyAI's LLM workflows: feed the diarized transcript + a roster of expected names into a local LLM, which maps clusters to identities using linguistic context, "as Mike said," self-introductions, topic affinity.

SignalExample in transcriptStrength
Self-introduction"Hi, I'm Mike…" (SPK_0's turn)Strong, ground truth
Direct address"…as Mike said" (one turn later)Strong cross-cluster link
Role/topic affinitySPK_1 always explains technicalsMedium (role → name via roster)
Turn cadence/countdominant speaker = manager, etc.Weak, use as tiebreak

Local model choice: any instruct LLM ≥7B (Llama-3.1-8B, Qwen-2.5-7B, Mistral-7B) running via llama.cpp/Ollama is enough, the task is a short structured reasoning pass over segments, not heavy generation. Prompt: give diarized transcript + name roster, ask for a cluster→name map with confidence.

Honest limitation to design around

Name assignment is probabilistic, it can mislabel on noisy audio. Ship it as suggested with an edit affordance, and persist the user's mapping so the identity sticks for the session (voice embedding cache per name). Do not present it as infallible.

1.4 Recommended stack (all local, lightweight)

LayerChoiceWhy
Audio capturePortAudio / Python sounddevice (or Rust cpal)16 kHz mono, streamed in chunks
Diarization (live)Diart + speaker embedding (pyannote or xenova)Realtime online clustering, WebSocket-ready
VADSilero VAD (10 ms) or Diart built-inCheap, accurate onset/offset
STTWhisper small/turbo (or sherpa-onnx streaming)On-device, multilingual, good quality/speed
Name mappingLocal LLM (8B via Ollama/llama.cpp) + embedding cachePrivate, no cloud cost
Record + replaylocal WAV/MP3 + timestamps (.rttm/JSON)Export SRT/meeting minutes

1.5 Build plan: Project 1 (phases)

Phase 0 · Skeleton (0.5–1 wk)

Repo scaffold (Rust or Python backend + minimal web UI). Audio capture to 16 kHz mono chunks. Verify Silero VAD fires correctly on a two-voice test recording.

Phase 1 · Realtime diarization (1–2 wk)

Integrate Diart online pipeline. Stream turns with live SPK_x labels to the UI. Benchmark latency (~500 ms–2 s) and correctness on a 3-speaker recording. Milestone: live "who is talking now" indicator.

Phase 2 · STT + transcript per speaker (1 wk)

Attach Whisper (small/turbo) segments to diarized turns. Produce per-speaker transcript lines with timestamps. Render an aligned, color-coded live transcript.

Phase 3 · Name assignment from content (1–2 wk)

Roster UI (user enters expected names). Local LLM pass maps SPK_x → name with confidence. Editable + persistent voice-embedding cache per name. Milestone: "Mike (conf 0.93)" labels.

Phase 4 · Analysis & exports (1 wk)

Meeting-minutes generation (LLM summary), SRT/VTT export, re-open recorded sessions for name re-assignment after the fact.

Phase 5 · Hardening (ongoing)

Overlapping-speech handling, noise robustness, accent coverage, GPU/CPU fallback, Windows/macOS packaging (Tauri).

Project-1 go-to-market note

The killer positioning is "meeting recorder that knows who said what, 100% on-device." Differentiation vs. cloud meeting-AI (Otter, Fireflies) is privacy + realtime + no per-minute fees. Win on a privacy-sensitive segment (legal, HR, healthcare, journalists).

Part 2: Project 2: Voice Input Method (Typeless-style, local)

Goal: a global hotkey → speak naturally → polished text injected into whatever app you're in. Like Typeless, but powered by a lightweight local model (no cloud).

2.1 State of the open-source market

The space already has two strong references, one cloud-BYOK, one local-first:

ProjectStackPhilosophyLicense
OpenTypeless (tover0314-w)Tauri 2 + React 19 + Rust; Whisper + LLM providersBYOK — bring your own (mostly cloud) API keyMIT
AriaType (joe223)Desktop (macOS/Windows); llama.cpp sidecar, SenseVoice, WhisperFlowLocal-first, privacy-first, GLM/SenseVoiceAGPL-3.0
sherpa-onnx (k2-fsa)Streaming ASR, C++/Python, offlineTrue streaming local STT (Zipformer-transducer)Apache-2.0

Key insight: AriaType already proves the exact architecture you want, a Tauri desktop app driving a llama.cpp/ONNX sidecar for fully local speech-to-text + LLM "polish." Your build is a focused, product-polished iteration on this pattern (ideally landing as your own opinionated app, or a clean fork), not a from-scratch research problem.

Local STT model recommendation

For on-device Chinese+English dictation, SenseVoice-Small (Alibaba, ~220M params, very fast, multilingual, punctuation-aware) is the sweet spot; Whisper small for maximum accuracy; sherpa-onnx streaming (Zipformer-transducer) if you need true per-word streaming as you speak. All run on CPU comfortably on a modern laptop.

2.2 Architecture (local-first)

Global hotkey ─▶ microphone capture (Rust cpal)
                     │
                     ▼
              [ Local STT: SenseVoice / Whisper / sherpa-onnx ]  ── text
                     │
                     ▼
              [ Local LLM "polish": llama.cpp sidecar (8B) ]  ── clean, punctuated text
                     │
                     ▼
              Inject into focused app (Windows SendInput / macOS CGEvent)
                     │
              Optional: per-app context & custom templates

Two-level polish design

Keep a fast path (STT → raw text, injected immediately, sub-300ms feel) and a polish path (after silence, local LLM fixes punctuation, capitalization, filler words, and applies app-specific templates). This matches how Typeless/AriaType feel "instant yet polished."

2.3 Build plan: Project 2 (phases)

Phase 0 · Hotkey + capture (0.5–1 wk)

Tauri app shell; global hotkey (Rust global-hotkey crate); mic capture to 16 kHz mono; permission handling (mic + accessibility).

Phase 1 · Local STT running (1 wk)

Integrate SenseVoice-Small via ONNX Runtime or llama.cpp (or sherpa-onnx for streaming). Hold-to-talk → live partial transcript. Milestone: raw dictation into any app, fully offline.

Phase 2 · LLM polish sidecar (1 wk)

Spawn llama.cpp server with an 8B model; on utterance end, run punctuation/casing/cleanup pass; inject polished text. Add custom templates + per-app rules.

Phase 3 · Product polish (1 wk)

Settings UI (model selection, hotkey, language, templates), error states, first-run model download, tray icon, "learn corrections" (record user edits as correction maps, as AriaType does).

Phase 4 · Cross-platform packaging (1–2 wk)

macOS + Windows installers; model bundling/lazy download; memory footprint tuning; startup speed. Milestone: two-OS installers with zero cloud calls.

Phase 5 · Distribution & tuning

Model-quality regression harness on a personal dictation testset (Chinese+English); telemetry-free usage stats; community model packs.

Honest challenges for Project 2

(1) On-device latency and first-word delay are the UX battleground, tune aggressively. (2) Chinese dictation quality varies sharply across local models; benchmark SenseVoice vs Whisper on your accent before committing. (3) Accessibility-permission UX is fiddly on macOS, budget time. (4) AriaType is AGPL, if you fork it, your derivative must stay AGPL; if you build fresh with MIT libs (OpenTypeless-style), keep MIT.

Part 3: Shared Core & Cross-Cutting Strategy

The two products are one engine with two surfaces. Recommene building a shared voice-AI core:

Shared moduleUsed by P1Used by P2
Streaming STT (SenseVoice / Whisper / sherpa)✅ transcript✅ dictation
VAD (Silero)✅ turn boundaries✅ hold-to-talk
Local LLM runner (llama.cpp sidecar)✅ name mapping + minutes✅ polish + templates
Audio capture/IO (Rust cpal / Python)✅ record✅ capture
Tauri shellrecorder UIinput-method UI

Build order recommendation

Ship Project 2 first

It is simpler (single speaker, no identity resolution), delivers standalone daily value, and proves the entire local voice stack (capture → STT → LLM → injection). Project 1 then only adds diarization + name inference on the same proven core, dramatically cutting its risk and time-to-value.

Risks & mitigations

RiskImpactMitigation
Local STT quality below cloudHigh (P2 core)Benchmark SenseVoice/Whisper on your own accents; allow optional API fallback
Realtime diarization accuracy in noise/overlapHigh (P1)Ship suggestions + edit UX; batch pyannote re-run for recorded sessions
Latency/first-word delayHigh (P2 UX)VAD-triggered streaming, model warm start, quantization (Q4)
License entanglement (AGPL forks)MediumPrefer MIT (Diart, OpenTypeless) or Apache-2.0 (sherpa); avoid wholesale AGPL forks
On-device model footprint (RAM/disk)MediumSmall models (~200M STT + 4–8B Q4 LLM), lazy download, CPU-friendly
Privacy positioning vs cloud incumbentsStrategicLead with "nothing leaves your device" — legal/HR/journalist segments

Bottom line

Both products are fully achievable with today's open-source, local-first stack. Build the shared core once; ship the voice input method first for quick standalone value and stack validation; then layer realtime diarization + content-based naming on top for the more ambitious conversation recorder. The differentiators, realtime on-device "who said what" and fully-offline voice input, are exactly where cloud incumbents are structurally weak.

Deep analysis grounded in Agent-Reach / Exa / GitHub reconnaissance, August 2026. Model names, star counts and licenses as of research date; verify before committing.

ARLI membership: the notes from the workshop

One site of yours, measured, with the price for the work in the same document

ARLI, Inc., a Delaware corporation. Questions: hq@arliwork.com.