Skip to content

feat(mobile): add selectable Pocket model size - #3244

Draft
johnmatthewtennant wants to merge 1 commit into
jtennant/mobile-pocket-ttsfrom
jtennant/pocket-tts-harness
Draft

feat(mobile): add selectable Pocket model size#3244
johnmatthewtennant wants to merge 1 commit into
jtennant/mobile-pocket-ttsfrom
jtennant/pocket-tts-harness

Conversation

@johnmatthewtennant

@johnmatthewtennant johnmatthewtennant commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Context

PR #3244 originally proposed a private host-only Pocket TTS harness. The strict KEEP/CLOSE audit found that it duplicated focused Desktop, streaming, and mobile probes and had no active consumer. John repurposed the existing draft into the concrete mobile model-size selection layer instead.

This PR now stacks on the explicit April FP32 mobile adopter in #3290. It does not own the shared April runtime, C ABI, isolate, downloader plumbing, or native playback/session/focus behavior.

Base: #3290 4691cad0c0afa153c7a4ce4d2333340e26b3d9c2
Shared runtime: #3303 d9193add61f4246d0ebb408fbf64470c72aacd88
Canonical extraction: #2467 0f97b7ef6d2f9aa87dea9a639223c39d9f0f9066
Pinned model revision: 58a6d00cf13d239b6748cb0769f35c580a8f606c

Summary

Adds a persisted Higher quality (FP32) / Faster (upstream-supported three-graph hybrid INT8) choice for Pocket voice on mobile. Each variant has an immutable descriptor, checksum-verified variant cache, crash-safe migration, pre-commit synthesis validation, and deterministic fallback to another verified installed variant.

The prior standalone Cargo harness and its test-runner wiring are completely removed from this PR.

Changes

  • Adds exact FP32 and hybrid-INT8 artifact names, byte sizes, SHA-256 checksums, model revision, and license metadata.
  • Uses separate v5 cache roots (v5/fp32 and v5/int8) and atomically migrates verified v4 FP32 installs.
  • Recovers interrupted v4 swaps and v5 migration checkpoints across process restarts without forcing a 440 MB redownload.
  • Persists the selected precision only after the candidate loads and produces non-empty, non-silent PCM.
  • Keeps the active cache/preference on failed validation; falls back to another verified installed variant when the preferred variant is unavailable.
  • Releases the resident engine before candidate validation to avoid a transient dual-engine memory peak, while coordinating overlapping/in-flight engine starts.
  • Adds a minimal Settings model-size picker and exact storage display.
  • Extends the existing production mobile integration probe with precision and cold-load metrics; it continues to measure actual native playback start, RTF, warm synthesis, cancellation, and RSS.
  • Does not expose the unsupported all-five-graph INT8 combination.

Related issue

N/A.

Testing

  • just ci: passed.
  • just mobile-check: passed.
  • just mobile-test: 856 passed, 1 intentionally skipped.
  • Pre-push Rust, mobile, and Desktop Tauri suites: passed.
  • Release-only ancestry refresh: the one-commit range-diff is exactly equal; locked static/shared voice checks, buzz-voice packaging, Desktop 0.5.0 resolution, and the repository pre-push suite passed.
  • Android native libraries built for arm64 and x86_64 using the official sherpa 1.13.4 libraries.
  • Real cached-model Rust synthesis: FP32 and hybrid INT8 both produced non-empty, non-silent 24 kHz audio; FP32 mobile ABI synthesis also passed.
  • Frozen review fanout: NCMB/baseline, Stacksmith/minimize, Timeless Comments, Dead Code, Kalvin, and Builderbot findings resolved; affected-only rereviews are clean.
  • No copied or moved implementation code, so copied-code inline proof is not applicable.

Matched Android emulator comparison through the production worker and native playback path:

Metric Higher quality (FP32) Faster (hybrid INT8)
Installed bytes 440,213,643 165,890,159
Cold load 2,736 ms 2,255 ms
First PCM 1,108 ms 587 ms
Actual playback start 3,683 ms 2,798 ms
RTF 0.378 0.205
Warm PCM 984 ms 644 ms
Queued cancellation 3 ms 6 ms
In-flight cancellation 243 ms 123 ms
Steady RSS 1,239,965,696 B 1,519,190,016 B
Peak RSS 1,647,341,568 B 1,570,140,160 B

Faster reduces installed storage by 62.3% and improved load, synthesis, playback-start, RTF, warm, and in-flight-cancellation measurements in this matched run. Its steady RSS was higher in this emulator run even though peak RSS was lower; this PR does not claim universal memory reduction.

Reviewer-reproducible examples

Run the same production integration path for each installed model directory:

cd mobile

flutter test integration_test/pocket_voice_integration_test.dart -d <device> \
  --dart-define=BUZZ_POCKET_MODEL_DIR=<fp32-device-path> \
  --dart-define=BUZZ_POCKET_PRECISION=fp32

flutter test integration_test/pocket_voice_integration_test.dart -d <device> \
  --dart-define=BUZZ_POCKET_MODEL_DIR=<int8-device-path> \
  --dart-define=BUZZ_POCKET_PRECISION=int8

Each run emits one stable BUZZ_POCKET_METRICS line containing precision, load, first PCM, actual playback start, synthesis/audio/RTF, warm PCM, queued/in-flight cancellation, download time, current RSS, and peak RSS.

Product flow:

  1. Open Mobile Settings → Voice → Model size.
  2. Choose Faster or Higher quality.
  3. Confirm the candidate downloads/verifies before the preference changes.
  4. Restart the app and confirm the selection and variant-specific cache persist.
  5. Make the preferred cache unavailable and confirm the other verified installed variant is selected with an explicit fallback message.

Screenshots

Settings model-size selection

Manual listening / device validation

John must still listen on physical iOS and Android devices using the same controlled prompt corpus and settings, with special attention to onset quality in Faster. The lowest-memory supported devices should also be exercised for selection, validation, fallback, cancellation, and native playback-start behavior. The automated run was headless and validated non-silent PCM plus native playback events, not perceived audio quality.

@johnmatthewtennant
johnmatthewtennant force-pushed the jtennant/pocket-tts-harness branch 3 times, most recently from 9bd9084 to 065a6b0 Compare July 28, 2026 10:57
@johnmatthewtennant
johnmatthewtennant force-pushed the jtennant/pocket-tts-harness branch from 065a6b0 to d04a2c4 Compare July 28, 2026 14:11
@johnmatthewtennant

Copy link
Copy Markdown
Contributor Author

🤖 ### Model-size selection

Settings presents the persisted Higher quality / Faster model-size choice with exact installed storage.

pocket-model-size-settings

johnmatthewtennant added a commit that referenced this pull request Jul 28, 2026
@johnmatthewtennant johnmatthewtennant changed the title test(voice): add standalone Pocket TTS harness feat(mobile): add selectable Pocket model size Jul 28, 2026
@johnmatthewtennant
johnmatthewtennant changed the base branch from jt/buzz-voice-refactor to jtennant/mobile-pocket-tts July 28, 2026 14:13
@johnmatthewtennant
johnmatthewtennant force-pushed the jtennant/mobile-pocket-tts branch from e4ec043 to 4691cad Compare July 28, 2026 14:38
Signed-off-by: John Tennant <jtennant@squareup.com>
@johnmatthewtennant
johnmatthewtennant force-pushed the jtennant/pocket-tts-harness branch from d04a2c4 to 00f5cf8 Compare July 28, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant