- server/whisper-server: compose stack built from the pinned whisper.cpp
v1.9.3 release, same as the Android JNI layer
- Vulkan GPU backend (AMD Radeon AI PRO R9700 / RADV) with transparent
CPU fallback and NO_GPU override; GGML models auto-download on first
start (MODEL env, default large-v3)
- API bound to the Tailscale interface only (100.103.83.12:8080) since
whisper-server has no authentication; render-group GID passthrough for
/dev/dri
- validated locally: image builds, entrypoint downloads tiny, POST
/inference returns verbose_json with language + segments; GPU-less
fallback confirmed
- RecorderService: rolling-window live pass with a dedicated live model
(off/tiny/base, beam 1, 8 s ticks, time-based dedupe) and an automatic
final pass with the selected model (beam 5) writing txt/srt/json
- TranscriptFiles in core/whisper: desktop-compatible outputs, 5 JVM tests
- WhisperEngine exposes modelName; UI: live-model dropdown, merged
transcript view, share sheet; falls back to manual path without engine
- live loop failures now logged (MeetRec tag) and surfaced in the UI
(was silently swallowed), plus final-pass timing logs
On-device measurements (Fairphone 6): tiny live ~0.6x realtime, small
final ~0.8x realtime — motivates the planned whisper-server engine.
Fixed list per current needs; "auto" passes null to the engine like
the desktop app. Live-mode model defaults (tiny/base live, small for
final) will follow with M2.
- core/recording: MeetingRecorder (AudioRecord at the device's native
rate, WAV on disk + 60 s rolling window resampled to 16 kHz), streaming
WavWriter, thread-safe RollingWindow, linear resampler; WavReader moved
here from the app
- app: RecorderService (foreground, type microphone) with ongoing
notification and StateFlow state; Record/Stop UI with timer and level
meter; runtime permission flow; finished recordings auto-load for
transcription
- launcher icon (mic + waveform, matching the desktop brand) and
notification glyph
- fix real M0 bug caught by the new unit tests: WavReader parsed 16-bit
fmt fields (audioFormat/channels/bitsPerSample) with 32-bit reads
- JVM tests: WAV round trip, native-rate header, resampler, rolling
window — 5/5 green; assembleDebug and aapt2 APK checks pass
- validated on-device on a Fairphone 6 (Android 16): model download,
engine load, recording and transcription all working
- share/icons/hicolor/: SVG source + PNG fallbacks (48-256 px); the
desktop entry now uses Icon=meetrec instead of a stock theme icon
- install.sh installs the icon into the hicolor tree, refreshes the
GTK icon cache, and cleans up on uninstall
- Categories fixed to AudioVideo;Audio per the menu spec (bare Audio
is a subcategory requiring its main category); desktop-file-validate
is clean now
- Recorder queries default_samplerate and streams/WAVs at that rate
instead of forcing 16 kHz (helps devices that don't support it
natively and keeps recordings at full fidelity)
- new resample_16k() linear resampler: the live rolling window is
converted to Whisper's 16 kHz before being handed to the engines
- snapshot() now returns (16 kHz audio, absolute start time in s)
- final pass unchanged: faster-whisper (PyAV) and whisper.cpp
(miniaudio) resample native-rate WAVs themselves
- GUI status shows the active rate; README updated
Validated with real 44.1 kHz and 48 kHz inputs: WAV headers match the
device rate, live-window resampling is length- and spectrum-correct.
- meetrec.py: engine layer with a common transcribe() contract;
WhisperCppEngine shells out to whisper-cli, GGML + Silero VAD models
auto-download to ~/.cache/meetrec; faster-whisper import now lazy;
new --engine CLI option
- meetrec_gui.py: Engine dropdown; Device/Compute greyed out for
whisper-cpp; model reload keyed on (engine, model, device, compute)
- install.sh: --whisper-cpp builds whisper.cpp with -DWHISPER_VULKAN=ON,
installs whisper-cli into the prefix and wires WHISPER_CPP_BIN via a
generated whisper-cpp.env; build failures degrade to a warning
- launchers source whisper-cpp.env; README documents engines
- Recorder.stop() is now idempotent (GUI close path called it twice)
- meetrec.py: CLI recorder with live rolling transcript (faster-whisper)
- meetrec_gui.py: PySide6 GUI reusing the CLI's recording/transcription
logic, with model/device/compute selection and live transcript
- install.sh: local install into ~/.local (venv, deps, launchers,
desktop entry), with --model/--no-model/--uninstall
- bin/meetrec, bin/meetrec-cli: launchers
- share/applications/meetrec.desktop: XDG desktop entry
- README.md, requirements.txt, .gitignore