Android M2: live rolling transcript and automatic final pass
- 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.
This commit is contained in:
+17
-11
@@ -4,10 +4,10 @@ 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: **M1 (recording)** — record a meeting with a foreground service
|
||||
(native sample rate, timer, level meter), then transcribe it on device.
|
||||
Model download + engine load are from M0; the live rolling transcript
|
||||
arrives with M2 (see the milestone plan in the project docs).
|
||||
Status: **M2 (live transcript + automatic final pass)** — record a meeting
|
||||
and watch the live rolling transcript while recording; on Stop the final
|
||||
(better) pass runs automatically and saves `.txt`/`.srt`/`.json` next to
|
||||
the WAV, mirroring the desktop two-pass design.
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -33,10 +33,16 @@ release tag so the JNI layer never breaks on upstream churn.
|
||||
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 **Record**, speak, then tap **Stop** — the recording is saved as WAV
|
||||
(native device rate) and auto-loaded for transcription.
|
||||
4. Tap **Transcribe** — segments with timestamps appear; share via the share
|
||||
sheet. You can also pick any PCM WAV file instead of recording.
|
||||
3. Tap **Record** — live transcript lines appear every few seconds (they use
|
||||
the cheap *live model*, `tiny`/`base`, on a 60 s rolling window).
|
||||
4. Tap **Stop** — the final pass runs automatically with the selected model
|
||||
and writes `<stem>.txt/.srt/.json` next to the WAV.
|
||||
5. Share the transcript via the share sheet. You can also pick any PCM WAV
|
||||
file and transcribe it manually.
|
||||
|
||||
Tip: use `tiny`/`base` as the live model (they keep up on a phone CPU) and
|
||||
a larger model like `small` for the final pass. The **Live model** dropdown
|
||||
also has `off` to disable live transcription (longest battery life).
|
||||
|
||||
Expect roughly realtime transcription with `tiny`/`base` on the
|
||||
Fairphone 6's CPU; `small` is noticeably slower — use it for final passes
|
||||
@@ -51,11 +57,11 @@ only (the live/final split comes with the recorder milestones).
|
||||
## Module layout
|
||||
|
||||
```
|
||||
app/ Compose UI + RecorderService (foreground mic recording)
|
||||
app/ Compose UI + RecorderService (record → live pass → final pass)
|
||||
core/recording/ MeetingRecorder, WavWriter/WavReader, RollingWindow,
|
||||
linear resampler — pure Kotlin, unit tested on the JVM
|
||||
core/whisper/ whisper.cpp JNI wrapper: CMake build + LibWhisper.kt +
|
||||
WhisperEngine.kt (the on-device transcription API)
|
||||
core/whisper/ whisper.cpp JNI wrapper + WhisperEngine + TranscriptFiles
|
||||
(txt/srt/json writers, desktop-compatible formats)
|
||||
tools/ fetch-whisper.sh — vendor the pinned whisper.cpp release
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user