Repository navigation
feat(app): on-device overflow engines, processing and summaries (flagged off) - #21466
Git-on-my-level wants to merge 17 commits into
Conversation
When live hours run out (or by choice), Omi keeps recording and can transcribe on the phone. This adds the mobile UI for that, behind the default-off PostHog flag mobile-on-device-overflow: - at-cap choice sheet (transcribe on this phone / upgrade), offered from the existing freemium prompt only when the flag is on and live hours are used up - model setup (step 1) and schedule picker (step 2: while charging, every few hours, as you talk) - conversations-list banner for audio waiting on the phone, waiting chips on recording rows, finish-setup and unsupported-phone variants - provenance chips on conversation rows and a provenance section on the summary (why, Redo with Omi Cloud, keep everything on this phone) - On-Device Transcription settings page and its entry row - settings model persisted via SharedPreferencesUtil, a pure scheduling policy, an OnDeviceModel abstraction (Android Whisper, iOS unavailable until Parakeet lands), and placeholder benchmark numbers in one file With the flag off every new surface renders nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add gated native engines, phone-only WAL custody, charging schedulers, and hash-bound summary provenance. Co-Authored-By: Codex <noreply@openai.com>
Preserve both main localization updates and flagged on-device copy through the l10n tool. Co-Authored-By: Codex <noreply@openai.com>
Regenerate the complete merged locale set and record all 22 audited UI states with SF Pro fonts. Co-Authored-By: Codex <noreply@openai.com>
Use SafeDefaults for the background charging policy and guard the dynamically loaded native bridge. Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Codex <noreply@openai.com>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Codex <noreply@openai.com>
Keep the READY fallback failure fixes equivalent while retaining overflow batch engines and provenance. Native resources are released on errors, PCM is normalized, polling consumes silence, and local setup failures preserve WAL audio with actionable recovery. Co-Authored-By: Codex <noreply@openai.com>
Retain the lead trailing-silence regression and operational kill-switch registry semantics; assert the consumed clock without extending speech timestamps. Co-Authored-By: Codex <noreply@openai.com>
Use the same SpeechTranscriber hardware guard as READY before asset preparation and native transcription. Co-Authored-By: Codex <noreply@openai.com>
Retain both default-off capture policies and documentation sections, plus all operational flag entries. No rollout or PR merge is performed. Co-Authored-By: Codex <noreply@openai.com>
Keep the READY fixture migration and real Home-card recovery regression equivalent. Healthy capture fakes expose the nullable failure state; permission denial shows saved audio and a working retry without ending capture. Co-Authored-By: Codex <noreply@openai.com>
Port READY recovery corrections while preserving overflow engines and provenance. Latch custody when frames arrive and repair historical device imports. Co-Authored-By: Codex <noreply@openai.com>
Preserve approved overflow translations through the repository localization validator and generator.
|
Closing as fully contained in the ladder-v1 draft #21488: this branch's head 55ce061 is an ancestor of #21488's head 13e4314 (verified with |
|
Hey @Git-on-my-level 👋 Thank you so much for taking the time to contribute to Omi! We truly appreciate you putting in the effort to submit this pull request. After careful review, we've decided not to merge this particular PR. Please don't take this personally — we genuinely try to merge as many contributions as possible, but sometimes we have to make tough calls based on:
Before your next PR, please skim:
If this was declined for direction or taste, maintainers should cite an invariant ID or open a proposed one — ask if that citation is missing. Your contribution is still valuable to us, and we'd love to see you contribute again in the future! If you'd like feedback on how to improve this PR or want to discuss alternative approaches, please don't hesitate to reach out. Thank you for being part of the Omi community! |
Summary
Replace the draft's native-engine, power-source, runner and summary stubs with working implementations. Everything remains behind
mobile-on-device-overflow(default OFF), including the enhanced iOS freemium fallback. No remote flag is changed. This PR remains a draft for UX audit.19600a485baa4998812e4654b70d2bab8f2c9949, with the 443 MB setup download, Wi-Fi-only cancellation, status and removal. A dynamically loaded iOS-17 framework preserves the app's iOS-15 minimum. Older/other-locale devices keep explicitly lower-quality SFSpeech.client_processingdisplay projection (runtime=local). Otherwise Omi Cloud processes transcript text; this does not consume live-STT hours. Keep everything on this phone creates transcript-only local conversations and submits nothing.stt_providersupport. Local summary projections survive refresh only while their transcript digest matches. On-device transcripts have one unlabeled voice; speaker labels/counts and export prefixes are suppressed.Redo with Omi Cloud
POST /v1/conversations/{id}/reprocessregenerates intelligence from the saved transcript; it does not rerun STT. The audio re-transcription button remains hidden for these phone-only recordings rather than calling that endpoint. No new cloud-audio endpoint is added in this PR.Copy ruling follow-up
The on-device upgrade line is exactly “Upgrade to Pro for speaker separation and higher accuracy”, localized through the repository flow in all 49 locales. Four affected renders were regenerated and inspected.
How to audit
Use a debug dev build with
--dart-define=OMI_ON_DEVICE_OVERFLOW=true(for example, add it to the repository's normalflutter run --flavor devflow). The override is debug-only; the remote flag stays off.Internal benchmark evidence
Aggregate results from an internal pendant sample, measured on M5 Max. These are disagreement with cloud, not truth-labelled accuracy: SpeechAnalyzer 44.5%; FluidAudio Parakeet v2 45.5%; sherpa Parakeet int8 44.7%; bounded 30-second whisper.cpp tiny 52.2% (whole-file diagnostic 80.4%); legacy on-device SFSpeech 84.1%. FluidAudio ASR was approximately 443 MB and 0.008 Mac RTF. Sherpa's approximately 2.4 GB Mac RSS excludes it from this Android change.
On-device speaker separation is omitted: FluidAudio 52.9% and sherpa 49.7% both trailed the 54.5% one-speaker control. No transcript text, audio, sample identifiers or private benchmark outputs are included.
Unmeasured and decisions to audit
Phone battery/energy, thermals, phone throughput/memory, model-install recovery on real phones, and OS scheduling/cold-launch acceptance remain unmeasured. OS background execution is best effort. “As you talk” processes finalized existing WAL/batch files; latency and conversation boundaries include their rotation behavior (native pendant batch files currently rotate at 15 minutes). This draft does not claim live-like second-level latency.
The iOS free fallback upgrade stays behind the same flag because model availability, language coverage and phone acceptance still need audit. A local summary can be generated on the phone while transcript text and its display projection are synced to Omi; only Keep everything on this phone prevents that submission. The earlier “nothing left the device” claim was removed.
Verification
flutter analyze: no issues for the on-device modules/screens, engine providers and new tests../gradlew :app:testDevDebugUnitTest --tests com.friend.ios.ondevice.OnDeviceBackgroundWorkerTestpassed (charging and interval constraints).BACKEND_UNIT_TEST_FILE_LIST=<four-file-list> bash backend/test.shpassed; files:test_transcript_hash.py,test_client_processing_schema.py,test_client_processing_acceptance.py,test_developer_from_segments_idempotency.py.say: current Parakeet bridge returned 18 word timestamps; current Foundation Models summarizer returned a bounded overview; SpeechAnalyzer transcribed the synthetic clip. No private sample was used.flutter build ios --debug --no-codesign --flavor devandflutter build apk --debug --flavor dev: both passed on the final post-merge source; no codesigning or device installation was performed.Failure-Class: none
Product invariants affected
UI evidence
Round-2 fallback recovery port
Equivalent fixes from READY #21474: consumed-audio clocks include trailing silence; canonical 16 kHz PCM and <=30-second Whisper calls; unconditional native context/WAV cleanup on rejection and exceptions; permanent input/model failures pause retained retries. Actual selected-engine readiness includes legacy permissions. Rollback with denied/unavailable SFSpeech keeps recording/audio custody active and shows existing localized saved-recording copy with setup/settings and retry actions. The existing WAL owns the retained audio; cloud drains reject phone-only WALs. Locale changes release prior OS asset reservations.
The existing free fallback now shares
mobile-speech-analyzer-disabledwith READY (false/missing selects the improved engine, true rolls back). Overflow batch engines/Parakeet, runner, schedule and provenance remain behindmobile-on-device-overflow. Batch readiness probes its selected engine; the common fallback core/native coordinator is equivalent to READY, with only the cutover batch and word/provenance extensions retained. No remote flag was changed.Behavioral validation covers polling speech-then-silence offset, permanent input pause, denied/unavailable rollback, readiness and retained recovery, physical WAL persistence and no cloud-audio drain, composite capture continuity and actionable localized recovery at 200% text. Actual pinned native wrapper passes 600 rejection/error/exception paths under ASan/UBSan without leaked contexts or WAV handles; Swift fallback coordinator/deadline tests pass. Existing overflow runner/policy/UI regression tests run separately. Phone battery and physical-device runtime remain unmeasured.
INV-CAP-1: captured audio remains in the existing account-owned WAL through local engine failure. INV-UI-1 and INV-UI-3: shared Omi controls and existing localization are reused.
Final local evidence: READY focused 209 tests plus 150 custody/recovery and the retained lead regression; overflow 205 focused, 60 runner/schedule/UI, 150 custody/recovery and the retained lead regression. Analyzer ratchets pass without baseline edits; iOS and Android dev debug builds pass on both branches. A fresh current-native SpeechAnalyzer synthetic
sayhost smoke passes with unsupported-locale rejection.Line-Count-Exception: app/lib/pages/conversation_detail/conversation_detail_provider.dart | 1514 -> 1523 | Existing owner retains overflow plus shared local recovery; behavioral coverage verifies capture and custody.
Line-Count-Exception: app/lib/pages/settings/transcription_settings_page.dart | 1554 -> 1575 | Existing owner retains overflow plus shared local recovery; behavioral coverage verifies capture and custody.
Line-Count-Exception: app/lib/providers/conversation_provider.dart | 2119 -> 2131 | Existing owner retains overflow plus shared local recovery; behavioral coverage verifies capture and custody.
Line-Count-Exception: app/lib/services/capture/capture_controller.dart | 4437 -> 4488 | Existing owner retains overflow plus shared local recovery; behavioral coverage verifies capture and custody.
Line-Count-Exception: app/lib/services/wals/local_wal_sync.dart | 2663 -> 2714 | Existing owner retains overflow plus shared local recovery; behavioral coverage verifies capture and custody.
Line-Count-Exception: backend/routers/developer.py | 2752 -> 2753 | Existing owner retains overflow plus shared local recovery; behavioral coverage verifies capture and custody.
Synchronized current main for the synthetic-merge metadata gate; resolved adjacent capture initialization, flag additions and pipeline documentation by retaining both sides. This retires the previously expected pipeline-doc conflict.
Full-suite follow-up: nullable recovery state was missing from two healthy capture fixtures, producing the Dart CI failures. Both lanes now share the fixture update and real Home-card saved-audio/retry regression. Capture Home plus full visual-audit suite: 171 passed, 2 existing skips on each branch. Final
make preflight: 65 selected checks passed. Simulator compile and Android emulator acceptance passed on the engine fix; no production-code change was needed for the fixture failure.Final integration caution
New main localization additions currently conflict with this draft’s locale additions and suppress fresh pull-request workflows. No cutover merge was performed. Existing Mobile App Checks was dispatched on the exact published head
ffbc5c6cd4ece17a67f01700a31acebdea51ba92: run 38596611353 passed, including full Dart tests, Android emulator acceptance and release eligibility. Native compile was scoped out for this test-only commit; the identical engine source passed simulator and Android compile/acceptance on its preceding head, plus both local dev debug builds.Round-3 engine recovery corrections
The overlapping different-locale reservation test nit is deferred: safely changing reservation ownership across asynchronous installs requires separate concurrency work. Existing reservation release and native fallback behavior remain unchanged. Phone battery and real-device iOS 15–25 execution remain unmeasured.
Latest round-3 read-only integration rehearsal: shared polling/readiness/language/codec-clock code is byte-identical and native AppDelegate merges cleanly. Expected Git conflicts: Apple provider, Whisper provider, local WAL sync, WAL model, and feature-flag registry. Preserve overflow batch engines/provenance and
onDeviceConversation, retaining one shared custody flag, recording-time marker and their JSON entries. The former silently duplicated WAL field problem is gone; the model now requires an explicit conflict resolution. The lead owns integration; no PR was merged.