Back to selected work

Applied AI · Mobile engineering

A spoken thought.
A considered next step.

Voice to Action turns voice notes into editable transcripts, grounded summaries and draft tasks—with the final decision left to you.

Project
Voice to Action
My role
Mobile, backend & AI integration
Built with
Flutter · FastAPI · PostgreSQL
Current stage
Private Android beta
Current Android Home screen with separate backend and approved-access indicators
Development capture screen with a glass orb and audio waveform
Development review screen with source quotations and an ambiguous-date warning

Actual app screens: current Android Home, plus development recording and review captures. Screen sizes shown together for illustration.

01 / The problem

Capturing is easy.
Following through takes work.

A voice note is easy to record and easy to forget. Useful next steps get buried inside a recording, and turning them into tasks takes another pass through the audio.

An AI extractor can help, but a possible action is not automatically a commitment. A question can look like an instruction. A tentative idea can become an obligation. “By Friday” can acquire a deadline the speaker never confirmed.

The design goal: help people find and review possible actions without silently deciding for them.

I built the Flutter app and its Python/FastAPI backend, including native audio capture, local persistence, cloud orchestration, validation and a controlled live-demo experience.

02 / The experience

Capture → understand → decide.

  1. Capture locally. Record or import a note, save it and replay it before choosing cloud processing.
  2. Process explicitly. Sign in with approved access and review the cloud-processing disclosure.
  3. Inspect the result. Read the transcript, summary and suggested actions. Every action includes its source evidence.
  4. Make it yours. Edit details, resolve uncertainty and accept only the drafts you want. Complete tasks in the local task list.

The app also implements pasted text, documents, public YouTube audio and consent-based meeting capture through Recall. The full live-provider matrix is still being verified.

An interface that responds to the audio.

The pastel interface pairs asymmetric capture cards with an audio-reactive glass orb. Real PCM frequency and loudness measurements drive its deformation during recording and supported playback. The animation reflects the audio signal, not model confidence or reasoning.

A sample of the review decision
“I also need to finish the API integration by Friday.”

Draft: Finish the API integration.
Uncertainty: which Friday? Keep the deadline unresolved until the person reviews it.

03 / Engineering decisions

The model call is one step.
The system has to hold together.

Local capture comes first.

Drift/SQLite stores notes, revisions, drafts and accepted tasks. App-private files retain the original audio. The server being asleep should not prevent someone from saving a thought.

A single 16 kHz, mono, 16-bit PCM stream feeds WAV writing and frequency analysis. Physical Android testing caught a fixed-length waveform-history list throwing when its oldest sample was removed. I replaced it with a growable, bounded history and verified microphone frames, pause/resume and valid WAV saving on a Pixel 10 Pro XL.

Extract from the transcript, independently.

Summaries compress information and can omit details needed for an action. Summarization and extraction therefore consume the transcript separately. The extractor does not rely on the summary as its evidence.

Each candidate references an immutable transcript revision and exact source spans. Edits create a new revision rather than moving the evidence underneath an existing result. Missing metadata stays unset; ambiguous dates stay visible.

Schema validation and quote matching establish structure and provenance. They do not prove semantic truth. A matching quote can still be misinterpreted, so every result remains a draft.

Persist the job, not just the request.

FastAPI returns a job ID while PostgreSQL stores processing state. The runner uses row claims, expiring leases, heartbeats and per-stage checkpoints. Lease tokens fence stale-worker writes; idempotent submissions protect against duplicate jobs and quota reservations when mobile requests retry.

Accepting a draft and updating its review state happen in one local transaction. A unique candidate relationship prevents duplicate accepted tasks. Cancellation and deletion also fence late results.

A deliberate beta tradeoff: the runner lives in one API process with one worker. A crash before checkpointing a provider response can repeat a paid call. Durable recovery is not a promise of exactly-once billing.

04 / Privacy & access

Exploring the app should not
silently spend an API budget.

The hosted backend runs on Render Free, with durable data in Supabase PostgreSQL and private audio storage. OpenAI, Recall and Supabase server keys stay on the server.

The app separates backend availability from live approval. Signing in does not unlock processing. Protected routes check an explicit Auth-user UUID allowlist; editable profile metadata cannot approve an account.

Anyone with the app can explore a clearly labeled prepared sample. Requesting live access opens an email draft for the tester to review and send. I approve users individually. Duration limits and retry-aware quotas provide safeguards, but they are not exact dollar caps.

Deletion has a state, too.

Deleting a local note cascades to related drafts and tasks. Cloud deletion uses a durable outbox; offline deletion stays visibly pending. Worker sleep, provider outages and upload/database crash windows complicate cleanup, so confirmed provider purge and orphan reconciliation remain release gates.

The local database is not encrypted by the app itself; it relies on platform protection. There is no general multi-device sync or background recording. Free hosting can sleep and delay processing or cleanup.

Android private beta. iOS simulator builds checked; physical iPhone testing and TestFlight distribution remain open. No public store listing or downloadable release is published here. Email requests do not automatically grant live access.

05 / Evidence & limits

Working software.
Honest boundaries.

These are the recorded verification results as of 26 October 2026—not estimates of model quality.

EvidenceWhat it establishes
50 backend testsFixture and mocked pipeline behavior, media parsing, quotas, authentication and validation regressions.
23 mobile testsUI/state behavior, review flows, audio handling and approval gating.
Physical Android captureReal microphone frames, pause/resume and a valid saved WAV on Pixel.
Hosted access checksHTTPS readiness, unsigned-request rejection and approval for the existing owner account.
iOS simulator integrationsSample playback and review; not physical iPhone validation.
Manual recording & meeting testsUser-confirmed operation; not a complete live-source or retention audit.

Evaluation infrastructure is not an accuracy claim.

I prepared 40 authored synthetic speech scenarios across development, validation and test splits, including no-task inputs, negation and ambiguous dates. A deterministic heuristic baseline completed the 20-case held-out run without execution failures.

Human-adjudicated precision, recall, summary faithfulness, noisy-speech robustness, latency and cost benchmarks remain unmeasured. Synthetic voices are not evidence of real accent coverage. I have not substituted proposed targets for results.

06 / What I learned

Useful AI needs a clear
point of human decision.

The surrounding system has to preserve the input, track provenance, survive retries, communicate uncertainty and give the person a clear choice. That is where much of the engineering work sits.

Next are the full live-source matrix, deployed two-user isolation and recovery checks, broader physical-device testing and a human-reviewed evaluation. Voice to Action remains a mobile project; this page documents it rather than simulating a live AI run.

Back to selected work
Interested in the engineering?

Let’s talk through it.

Say hello ↗