A voice search trainer for toddlers. Parents enroll their child's mispronunciations — "wawa pup", "bibi", "tortor" — and Babble learns to open exactly what they meant. Tap the listen button, speak, and the right YouTube video, search, or website fires.
🌐 babble.co.in • 📱 Google Play Store
Toddlers can't type, can't spell, and don't pronounce things the way Google expects. They know exactly what they want — usually the same five things — but the technology in front of them is built for adults.
Babble is the toddler-shaped fix. Parents do the setup once: record 3–5 samples of the child saying a phrase, pick what should happen ("YouTube search for Paw Patrol", "open YouTube Kids and search for Blippi", etc.). After that the child has a single big button. They press it, they say their thing, the right thing opens.
- Enroll a phrase — record 3–5 audio samples of the child saying it.
- Pick an action — YouTube search, YouTube Kids search, Google search, open a URL, or play a specific YouTube video.
- Child taps the listen button — Babble records, embeds the audio, finds the closest match, and fires the action.
| 1. Enroll | 2. Pick action | 3. Child taps |
|---|---|---|
![]() |
![]() |
![]() |
The matching runs entirely on-device. Audio is converted to MFCC (Mel-Frequency Cepstral Coefficient) embeddings using pure browser math — no neural model download, no server roundtrip, no cloud. Embeddings are compared with cosine similarity against the child's enrolled phrases. If the best match clears the per-child threshold, the action fires; otherwise the clip is saved for the parent to review later.
This approach was a deliberate choice over a neural speech model: MFCCs are tighter for same-speaker matching, work offline from the first load with zero downloads, and don't carry the privacy and quota implications of cloud STT for a kids' app.
- React 18 + Vite 5 + TypeScript (strict mode)
- Tailwind CSS for styling
- IndexedDB via
idb— all storage stays on-device - Pure-JS MFCC pipeline — no ML library, no model download
- Capacitor to wrap the React app as a native Android build
- Firebase Analytics + Crashlytics for kids-safe telemetry (no advertising ID, no ad signals)
src/
lib/
db.ts IndexedDB schema + all CRUD
audio.ts MediaRecorder capture, 16kHz mono PCM downsampler
mfcc.ts Pure-JS MFCC: pre-emphasis → FFT → mel filterbank → DCT
embedder.ts Wraps mfcc.ts; mean-pools to a single embedding vector
matcher.ts Cosine similarity, centroid averaging, best-match search
firebase.ts Analytics init (kids-safe config)
analytics.ts Event tracking
crashlytics.ts Error reporting wrapper
components/
Splash.tsx
onboarding/ First-run flow (welcome, how it works, permissions, capture)
RecognitionScreen.tsx Child-facing: big tap-to-listen button
EnrollPhrase.tsx Record clips, label phrase, pick action
PhraseLibrary.tsx Parent: view, edit, delete phrases
ChildSettings.tsx Per-child similarity threshold tuning
UnmatchedReview.tsx Review clips that didn't match
android/ Capacitor + Gradle Android wrapper
marketing/v2/ babble.co.in landing site
npm install
npm run dev
# http://localhost:5173The web build runs without Firebase — initFirebase() is a no-op when VITE_FIREBASE_API_KEY isn't set. To wire up your own analytics, copy .env.example → .env.local and fill in your Firebase web app config.
The Android wrapper requires your own Firebase project (analytics is bound to a package name, and the production google-services.json is git-ignored):
- Create a Firebase project, register an Android app with package
com.babble.app. - Download
google-services.jsonand place it atandroid/app/google-services.json— seegoogle-services.json.examplefor the expected shape. - Set up signing — see
scripts/generate-keystore.shand copy.env.exampleto.env.localwith your keystore details.
npm run cap:sync
cd android
./gradlew bundleReleaseBabble is registered under Google Play's Designed for Families programme with audiences under 13. That shapes a few things in the codebase:
- The Android
AD_IDpermission and the Privacy SandboxACCESS_ADSERVICES_AD_ID/ACCESS_ADSERVICES_ATTRIBUTIONpermissions are explicitly stripped viatools:node="remove"inAndroidManifest.xml— they get auto-merged by Firebase Analytics, but Babble never collects the advertising ID. - Firebase Analytics is configured with
ad_storage,ad_user_data,ad_personalization,adid_collection, andssaid_collectionall disabled. - Audio recordings stay on-device. Only enrolled embeddings + minimal metadata are stored, all in IndexedDB.
- The only network calls during normal use are: (a) the action itself (opening YouTube/Google), and (b) anonymized analytics events.
See docs/analytics-events.md for the full event taxonomy.
This repository is published for transparency and as a portfolio reference. The code is not open source — all rights reserved. You may read the source, but not copy, redistribute, or use it in your own projects.
The "Babble" name, mascot, and visual design are trademarks of the author.
Built by Amrit Karan. Reach out via babble.co.in.


