Record or upload audio and get instant AI-powered summaries — entirely in your browser. No server. No API keys. No setup.
- What It Does
- Why It's Cool
- Key Features
- AI Pipeline
- Tech Stack
- How to Run
- Deploy
- CI/CD — GitHub Pages
- CI/CD — GitLab Pages
- GitHub vs GitLab Comparison
- Project Structure
- Browser Compatibility
Voice Notes Summarizer is a lightweight, fully browser-based application that lets you:
- Record voice notes directly in the browser via microphone
- Or upload pre-recorded audio files (mp3, wav, webm, ogg, m4a, and more)
- Transcribe the audio using a state-of-the-art ASR (Automatic Speech Recognition) model
- Summarize the transcript into a concise, readable summary
Everything — the AI models, the inference, the processing — runs entirely on the client side using Xenova/Transformers.js. No data ever leaves your device.
This project demonstrates a complete AI pipeline running 100% in-browser:
🎤 Voice Input → 📝 Transcription (ASR) → 📄 Summarization (NLP) → 📋 Copy & Share
It's a portfolio-grade showcase of:
- Real-time AI inference without a backend
- WebRTC microphone access and MediaRecorder API
- HuggingFace Transformers running via WebAssembly/ONNX in the browser
- Responsive, accessible UI built with vanilla tooling
No subscriptions. No cloud bills. No data leaks. Just AI in the browser.
| Feature | Description |
|---|---|
| 🎙️ In-Browser Recording | Record voice notes directly via microphone using the Web Audio API |
| 📂 Audio Upload | Upload mp3, wav, webm, ogg, m4a and other popular formats |
| 🧠 Smart Summarization | Switch between a fast (lighter) and accurate (larger) summarization model |
| 🔊 Real-Time Feedback | Blinking recording indicator, live waveform cues, and a modern audio player |
| 🌐 Multilingual Support | Summarization models support multiple languages out of the box |
| 🖥️ Fully Client-Side | Zero server, zero API keys — complete privacy and offline capability |
| 📋 Copy Summaries | One-click copy to clipboard for easy sharing or note-taking |
| 📱 Responsive Layout | Works on desktop and mobile browsers |
flowchart LR
subgraph Browser["🖥️ Browser — Client Only"]
A["🎤 Audio Input mic / file upload"]
B["🧠 ASR Model Whisper via Transformers.js + ONNX"]
C["📄 Summarization Model BART / DistilBART"]
D["📋 Summary Text Copy / Display"]
A --> B --> C --> D
end
Models used (loaded via Xenova/Transformers.js):
| Task | Model | Speed |
|---|---|---|
| Speech-to-Text | Xenova/whisper-tiny.en |
⚡ Fast |
| Speech-to-Text | Xenova/whisper-base |
🎯 Accurate |
| Summarization | Xenova/distilbart-cnn-6-6 |
⚡ Fast |
| Summarization | Xenova/bart-large-cnn |
🎯 Accurate |
Models are fetched from HuggingFace CDN on first use and cached in the browser — subsequent runs are instant.
| Layer | Technology |
|---|---|
| Language | Vanilla JavaScript (ES6+) |
| AI / ML | Xenova/Transformers.js — ONNX models in-browser |
| UI Framework | Bootstrap 5 |
| Audio APIs | Web Audio API, MediaRecorder API |
| Deployment | GitHub Pages / GitLab Pages |
| CI/CD | GitHub Actions / GitLab CI |
Because this is a fully client-side app, there is no backend to configure, no .env file, and no API keys to manage.
If your browser supports ES Modules (all modern browsers do), you can simply:
# Clone the repo
git clone https://github.com/ronaldgosso/vn_summarizer.git
cd voice-notes-summarizer
# Open in browser
open index.html
# or on Linux:
xdg-open index.html
# or on Windows:
start index.html
⚠️ Note: Some browsers block microphone access and Web Workers onfile://URLs. If recording doesn't work, use Option B below.
Serving over http://localhost avoids browser security restrictions on file:// and is recommended for the full experience.
Using Node.js:
# Install a simple static server
npm install -g serve
# Serve the project
serve .
# App is live at http://localhost:3000Using Python:
# Python 3
python -m http.server 8080
# App is live at http://localhost:8080Using VS Code:
Install the Live Server extension, right-click index.html → Open with Live Server.
On first use, Transformers.js will download the AI models from HuggingFace CDN and cache them in your browser's IndexedDB. This happens once per model:
| Model | Size | Time (estimate) |
|---|---|---|
| Whisper Tiny | ~75 MB | ~10–20s on broadband |
| Whisper Base | ~145 MB | ~20–40s on broadband |
| DistilBART CNN | ~220 MB | ~30–60s on broadband |
| BART Large CNN | ~560 MB | ~60–120s on broadband |
After the first download, models load from cache in 2–5 seconds.
Since this is a static site (pure HTML/CSS/JS), it can be deployed to any static hosting platform with zero configuration.
Push to your repository and enable GitHub Pages:
- Go to Settings → Pages
- Under Source, select GitHub Actions (see CI/CD section below)
- Push to
main— the workflow handles the rest
Your site will be live at: https://your-username.github.io/voice-notes-summarizer/
Push to your repository with a .gitlab-ci.yml (see CI/CD section below). GitLab Pages will serve the site at:
https://your-username.gitlab.io/voice-notes-summarizer/
| Platform | Command / Method |
|---|---|
| Netlify | Drag & drop the project folder at netlify.com/drop |
| Vercel | npx vercel in the project directory |
| Cloudflare Pages | Connect repo in dashboard, set build output to / |
| Surge.sh | npx surge . |
Add the following workflow file to your repository. It automatically tests and deploys your static site to GitHub Pages on every push to main.
Create .github/workflows/deploy.yml:
# .github/workflows/deploy.yml
name: Deploy Voice Notes Summarizer to GitHub Pages
on:
push:
branches:
- main # Deploy on every push to main
pull_request:
branches:
- main # Run tests on pull requests (no deploy)
workflow_dispatch: # Allow manual trigger from GitHub UI
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# ── Job 1: Lint & Validate ─────────────────────────────
lint:
name: Lint & Validate
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dev dependencies (if any)
run: |
if [ -f package.json ]; then npm ci; fi
- name: Validate HTML
run: |
npx --yes html-validate index.html || echo "HTML validation complete"
# ── Job 2: Build ───────────────────────────────────────
build:
name: Build Static Site
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies (if any)
run: |
if [ -f package.json ]; then npm ci; fi
- name: Prepare static files
run: |
# If you have a build step (e.g. bundler), run it here.
# For pure static sites, just confirm key files exist.
echo "Checking required files..."
test -f index.html && echo "✅ index.html found"
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: . # Serve from project root (change to ./dist if you use a bundler)
# ── Job 3: Deploy ──────────────────────────────────────
deploy:
name: Deploy to GitHub Pages
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main' # Only deploy on main branch pushes
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4- Go to your repository → Settings → Pages
- Under Source, choose GitHub Actions
- Save — no further config needed
git add .github/workflows/deploy.yml
git commit -m "ci: add GitHub Pages deployment workflow"
git push origin mainGo to the Actions tab in your repository to watch the pipeline run live. Your site will be available at https://your-username.github.io/voice-notes-summarizer/ within a minute or two.
If you're hosting on GitLab, add the following .gitlab-ci.yml to the project root:
# .gitlab-ci.yml
stages:
- validate
- build
- deploy
variables:
NODE_VERSION: "20"
validate:
stage: validate
image: node:20-alpine
script:
- echo "Validating project structure..."
- test -f index.html && echo "✅ index.html found"
- echo "Validation passed."
only:
- main
- merge_requests
build:
stage: build
image: node:20-alpine
script:
- echo "Preparing static files for deployment..."
- mkdir -p public
- cp -r . public/
- rm -rf public/.git public/.gitlab-ci.yml
- echo "Build complete."
artifacts:
paths:
- public/
expire_in: 1 hour
only:
- main
pages:
stage: deploy
script:
- echo "Deploying to GitLab Pages..."
artifacts:
paths:
- public/
only:
- main
environment:
name: production
url: https://$CI_PROJECT_NAMESPACE.gitlab.io/$CI_PROJECT_NAMEThe
public/directory is the magic key — GitLab Pages always serves frompublic/.
| GitHub Actions | GitLab CI/CD | |
|---|---|---|
| Workflow file | .github/workflows/deploy.yml |
.gitlab-ci.yml |
| Pages folder | Configurable (set in path:) |
Must be public/ |
| Enable Pages | Settings → Pages → GitHub Actions | Automatic after pages job runs |
| Secrets | Settings → Secrets → Actions | Settings → CI/CD → Variables |
| Manual trigger | Actions tab → Run workflow | CI/CD → Pipelines → Run pipeline |
| Free CI minutes | 2,000 min/month | 400 min/month |
| Deploy preview | Needs extra config | Environments tab |
| Static site URL | username.github.io/repo |
username.gitlab.io/repo |
| Browser | Recording | Upload | AI Inference |
|---|---|---|---|
| Chrome 90+ | ✅ | ✅ | ✅ |
| Edge 90+ | ✅ | ✅ | ✅ |
| Firefox 90+ | ✅ | ✅ | ✅ |
| Safari 15+ | ✅ | ✅ | |
| Mobile Chrome | ✅ | ✅ |
⚠️ Safari has partial MediaRecorder support. Audio upload works fully on all browsers.
Contributions, issues, and feature requests are welcome!
- Fork the repository
- Create your feature branch:
git checkout -b feat/amazing-feature - Commit your changes:
git commit -m 'feat: add amazing feature' - Push to the branch:
git push origin feat/amazing-feature - Open a Pull Request
MIT © Voice Notes Summarizer Contributors
Built with 🎙️ + 🧠 using Vanilla JS, Transformers.js, and Bootstrap — no backend required.