Add native Android app scaffold (M0): whisper.cpp engine via JNI

- android/: Gradle/Kotlin project (AGP 9.4, Compose, NDK 27.1), monorepo
  subdir as planned; whisper.cpp v1.9.3 vendored via pinned fetch script
- core/whisper: JNI wrapper (beam size, threads, language) + WhisperEngine
  Kotlin API mirroring the desktop engine contract
- app (M0 scope): in-app GGML model download from Hugging Face, engine
  load, WAV picker with resampling, on-device transcription, share sheet
- build validated: assembleDebug OK, libwhisper_jni.so + ggml packaged
This commit is contained in:
2026-09-07 11:00:31 +02:00
parent 66408e291d
commit 404f3db200
22 changed files with 1273 additions and 2 deletions
+62
View File
@@ -0,0 +1,62 @@
# MeetRec for Android
Native Android app with the same functionality as the desktop meetrec:
record meetings and transcribe them on-device with Whisper. Nothing leaves
the phone — no cloud, no telemetry.
Status: **M0 (engine proof)** — the app can download a GGML model, load it
via JNI (whisper.cpp, CPU/NEON) and transcribe a picked WAV file. Recording,
live transcript, and output files arrive in later milestones (see the
milestone plan in the project docs).
## Requirements
- Android Studio (or: SDK Platform 36, Build Tools 36, NDK 27.1, CMake 3.22.1)
- JDK 17+
- Device running Android 10+ (developed against a Fairphone 6 / Snapdragon
7s Gen 3, Android 15+)
## Build
```sh
cd android
./tools/fetch-whisper.sh # vendors whisper.cpp v1.9.3 into third_party/
./gradlew :app:assembleDebug # or open the android/ folder in Android Studio
adb install -r app/build/outputs/apk/debug/app-debug.apk
```
`third_party/whisper.cpp` is gitignored — the fetch script pins the exact
release tag so the JNI layer never breaks on upstream churn.
## Test on device (M0)
1. Launch **MeetRec**, pick a model (`tiny` is fine for a first test) and tap
**Download** (model comes from Hugging Face; tiny is ~75 MB).
2. Tap **Load engine**.
3. Tap **Pick WAV file** and choose a 16 kHz mono WAV for best results
(other PCM WAVs are resampled automatically).
4. Tap **Transcribe** — segments with timestamps appear; share via the
share sheet.
Expect roughly realtime transcription with `tiny`/`base` on the
Fairphone 6's CPU; `small` is noticeably slower — use it for final passes
only (the live/final split comes with the recorder milestones).
## Performance notes
- The engine runs on CPU via NEON, using up to 4 threads.
- GPU/NPU acceleration (e.g. Snapdragon NPU via the QNN backend) is a
stretch goal, not wired up yet.
## Module layout
```
app/ Compose UI (model download, WAV picker, transcript view)
core/whisper/ whisper.cpp JNI wrapper: CMake build + LibWhisper.kt +
WhisperEngine.kt (the on-device transcription API)
tools/ fetch-whisper.sh — vendor the pinned whisper.cpp release
```
Models live in the app's private storage (`filesDir/models`), shared files
with the desktop app's `~/.cache/meetrec/whisper-cpp` naming
(ggml-tiny.bin … ggml-large-v3.bin).