A browser-based Text-to-Speech and Speech Recognition application powered by Piper TTS, Sherpa-ONNX, and ONNX Runtime Web. Generate high-quality speech and transcribe audio directly in your browser without requiring a server for inference. Supports Vietnamese (home page), other languages (English, Indonesian), and ASR (Automatic Speech Recognition) on separate pages. Live demo: https://nghitts.app.
- 🌐 Browser-Based TTS: Fully client-side text-to-speech processing using Web Workers
- 🌍 Multi-Language Pages: Vietnamese (default), English (
/en), and Indonesian (/id) each have their own page—switch via the tab bar. - 🇻🇳 Vietnamese Language Support: Advanced Vietnamese text processing with automatic conversion of:
- Numbers to words (0 to billions)
- Dates and date ranges
- Time expressions
- Currency (VND, USD)
- Percentages and decimals
- Phone numbers
- Ordinals
- Roman numerals (I–XXX)
- Numeric ranges with units and currency (e.g., "1-10m", "1/10kg")
- 🎤 Multi-Speaker Models: Support for models with multiple voices
- ⚡ Real-Time Streaming: Stream audio chunks as they're generated
- 🎚️ Speed Control: Adjustable speech speed
- 📥 Audio Download: Export generated audio as WAV files
- 🌙 Dark Mode: Built-in theme toggle
- 📊 Text Statistics: Character and word count display
- 🔄 Dynamic Model Loading: Load models on-demand from Cloudflare R2 storage
- 📜 Generation History: Automatically saves TTS results to IndexedDB—replay, download, or copy past generations from a slide-out history panel
- 🔗 Share Button: Copy the current page URL to clipboard for easy sharing
- 🎙️ Browser-Based ASR: Client-side speech recognition using Sherpa-ONNX WASM
- 🎤 Microphone Mode: Real-time recording with Voice Activity Detection (VAD)
- 📂 File Upload Mode: Transcribe any audio file with progress tracking
- 📝 SRT Subtitle Export: Download transcription as SRT subtitles with timestamps
- 🔁 Multiple Model Support: Switch between ASR models (SenseVoice, Whisper, Transducer, Paraformer, etc.)
- 💾 Model Persistence: Selected ASR model is saved in localStorage
This project is built on top of Piper TTS and fine-tuned using a custom dataset to generate realistic voices. Please see the Training Video here: https://www.youtube.com/watch?v=WgvBOljtNvE
- Based on Piper (English checkpoint)
- Lightweight, fast, and optimized for local inference
- Designed for real-time speech generation
Dataset:
- Dataset size: ~1,000 audio samples
- Voices: Multiple famous celebrity voices
- Training method: Fine-tuning on existing Piper English checkpoint
- Epochs: ~2,000 epochs
- Download training datasets: View Datasets on Google Drive
Available datasets include:
- Vietnamese celebrity voices (Mỹ Tâm, Ngọc Ngân, Trấn Thành, Việt Thảo)
- Multi-speaker datasets
- Various dataset sizes (200, 1000+ samples)
- English voice datasets
Audio Preparation:
- Cleaned and normalized audio
- Matched text–audio pairs
- Consistent sample rate
- Noise removed
What the Model Learns:
- Voice tone
- Accent
- Speech rhythm
- Natural pronunciation
- Web-based inference: No server required
- Runs fully locally: All processing happens in your browser
- Very fast inference: ~5× real-time speed
- User-friendly: Simply enter text, select a voice, and generate speech instantly
- ✔ Based on Piper TTS
- ✔ Fine-tuned with 1,000+ audio samples
- ✔ Trained for ~2,000 epochs
- ✔ No server required
- ✔ Web-based & lightweight
- ✔ Fast inference (≈5× real-time)
- ✔ Free & open-source
- ✔ Allowed for commercial use
- ✔ Easy to deploy or modify
Pre-trained Vietnamese TTS models are available for download:
Download from Google Drive: View Available Models
-
calmwoman3688 (~60.6 MB)
- Files:
calmwoman3688.onnx+calmwoman3688.onnx.json - Description: Female voice
- Files:
-
deepman3909 (~60.6 MB)
- Files:
deepman3909.onnx+deepman3909.onnx.json - Description: Male voice
- Files:
-
ngocngan3701 (~60.6 MB)
- Files:
ngocngan3701.onnx+ngocngan3701.onnx.json - Description: Vietnamese celebrity voice (Ngọc Ngân)
- Files:
-
vietthao3886 (~60.6 MB)
- Files:
vietthao3886.onnx+vietthao3886.onnx.json - Description: Vietnamese celebrity voice (Việt Thảo)
- Files:
-
New Voices: Mỹ Tâm, Trấn Thành, Ngọc Huyền (review phim), Oryx (giọng nam siêu trầm)
Each TTS model requires two files with the same base name:
{model-name}.onnx- The ONNX model file (binary){model-name}.onnx.json- The model configuration file (JSON)
For local development, place models in the appropriate folders under public/:
public/
├── tts-model/
│ ├── vi/ # Vietnamese TTS (home page /)
│ │ ├── calmwoman3688.onnx
│ │ ├── calmwoman3688.onnx.json
│ │ └── ...
│ ├── en/ # English TTS (/en)
│ │ ├── en_US-libritts_r-medium.onnx
│ │ ├── en_US-libritts_r-medium.onnx.json
│ │ └── ...
│ └── id/ # Indonesian TTS (/id)
│ └── ...
├── asr-model/ # ASR models (/asr)
│ └── {model-name}/
│ └── ... # Model-specific files
└── vad-model/silero-vad/ # VAD model (included)
└── silero_vad.onnx
The dev server lists and serves TTS models from tts-model/{lang}/ and ASR models from asr-model/ when you run npm run dev.
- Open the language page: Use the tab bar Tiếng Việt | English | Indonesia (or go to
/enor/id). - Add models locally: Put
.onnxand.onnx.jsonpairs inpublic/tts-model/en/for English orpublic/tts-model/id/for Indonesian. - Select a model: Choose a model from the dropdown (the app auto-selects a default model if none is chosen), then pick a voice (if the model has multiple speakers), enter text, and click Generate/Play.
- Production (Cloudflare R2): Upload English models under the
piper/en/prefix and Indonesian underpiper/id/in your R2 bucket; the app will list and serve them via/api/piper/{lang}/modelsand/api/model/piper/{lang}/{name}.
- Open the ASR page: Click the Nhận dạng giọng nói tab in the tab bar (or go to
/asr). - Select an ASR model: Choose from the model dropdown. The selected model is persisted in localStorage.
- Microphone mode: Click the mic button to start real-time recording with VAD. Speech segments are automatically detected and transcribed.
- File upload mode: Switch to the Upload tab and select an audio file. The file is decoded, segmented, and transcribed with timestamps.
- Export: Download the transcription as plain text or SRT subtitles.
- Add ASR models locally: Place model directories in
public/asr-model/for local development. - Production (Cloudflare R2): Upload ASR models under the
asr/prefix in your R2 bucket; discovered via/api/asr/modelsand served via/api/model/asr/{model}/{name}.
- Frontend: Vue 3 + Vite
- TTS Engine: Piper TTS (ONNX format)
- ASR Engine: Sherpa-ONNX (WASM) with Silero VAD
- Runtime: ONNX Runtime Web (WASM)
- Hosting: Cloudflare Pages
- Storage: Cloudflare R2 (for TTS and ASR model files)
- Styling: Tailwind CSS
- Icons: Lucide Vue Next
piper-tts-web-demo/
├── src/
│ ├── App.vue # Shell with tab bar (TTS + ASR), share/history buttons
│ ├── router/index.js # Routes: / (Vietnamese), /en, /id, /asr
│ ├── views/
│ │ ├── VietnameseView.vue # Vietnamese TTS page
│ │ ├── LanguageView.vue # English/Indonesian TTS page (reusable)
│ │ └── ASRView.vue # Speech recognition page (mic + file upload)
│ ├── components/
│ │ ├── HistoryPanel.vue # Slide-out sidebar for TTS generation history
│ │ └── ... # AudioChunk, ModelSelector, SpeedControl, etc.
│ ├── lib/
│ │ ├── piper-tts.js # Piper TTS (Vietnamese preprocessing)
│ │ └── piper-tts-i18n.js # Piper TTS for /en and /id (no Vietnamese pipeline)
│ ├── utils/
│ │ ├── history-store.js # IndexedDB-backed TTS history (max 50 entries)
│ │ ├── text-cleaner.js # Text normalization and transliteration
│ │ ├── vietnamese-processor.js # Vietnamese number/date/currency/Roman numeral conversion
│ │ └── ... # model-cache, model-detector, etc.
│ ├── workers/
│ │ ├── tts-worker.js # Worker for Vietnamese page
│ │ └── tts-worker-i18n.js # Worker for English/Indonesian pages
│ └── config.js # TTS and ASR model URLs, defaults, and configuration
├── functions/api/
│ ├── models.ts # List Vietnamese TTS models (R2 prefix piper/vi/)
│ ├── model/[name].ts # Serve Vietnamese TTS model files
│ ├── piper/[lang]/models.ts # List TTS models for a language
│ ├── model/piper/[lang]/[name].ts # Serve TTS model for a language
│ ├── asr/models.ts # List ASR models (R2 prefix asr/)
│ └── model/asr/[model]/[name].ts # Serve ASR model files
└── public/
├── favicon.png # Site favicon
├── tts-model/vi/ # Vietnamese TTS models (local)
├── tts-model/en/ # English TTS models (local)
├── tts-model/id/ # Indonesian TTS models (local)
├── asr-model/ # ASR models (local, for dev)
├── code/asr-wasm/ # Sherpa-ONNX WASM scripts (ASR + VAD)
├── vad-model/silero-vad/ # Silero VAD model (silero_vad.onnx)
├── non-vietnamese-words.csv
└── acronyms.csv
- Model Loading: TTS models are stored in Cloudflare R2 and served via Cloudflare Pages Functions
- Text Processing: Vietnamese text is processed to convert numbers, dates, times, Roman numerals, ranges, etc. to spoken words
- Text Chunking: Input text is intelligently split into chunks for optimal processing
- Phoneme Conversion: Text is converted to phonemes using the phonemizer library
- Audio Generation: ONNX Runtime Web runs the Piper TTS model in a Web Worker
- Streaming: Audio chunks are streamed back to the main thread and played as they're generated
- Audio Merging: Chunks are merged, normalized, and trimmed for final output
- History: Generated audio is automatically saved to IndexedDB for later replay or download
- Model Loading: ASR models are loaded from Cloudflare R2 (or local
public/asr-model/in dev) - WASM Initialization: Sherpa-ONNX WASM module is loaded with the selected ASR model
- Microphone Mode: Audio is captured from the microphone, processed through Silero VAD for voice activity detection, and fed to the offline recognizer
- File Upload Mode: Audio files are decoded, segmented by VAD, and transcribed with timestamps
- Output: Transcription text is displayed and can be downloaded as plain text or SRT subtitles
The application includes comprehensive Vietnamese text processing that handles:
- Numbers: Automatic conversion to Vietnamese words (e.g., "123" → "một trăm hai mươi ba")
- Dates: Multiple formats (DD/MM/YYYY, DD-MM-YYYY, date ranges)
- Times: Time expressions (HH:MM, HH:MM:SS, "X giờ Y phút")
- Currency: VND (đồng) and USD conversion
- Percentages: Automatic conversion (e.g., "50%" → "năm mươi phần trăm")
- Decimals: Vietnamese decimal format (comma as decimal separator)
- Phone Numbers: Digit-by-digit reading
- Ordinals: Conversion of ordinal numbers (thứ 2 → thứ hai)
- Roman Numerals: Conversion of I–XXX to Arabic digits (configurable via
UnlimitedRomanNumeralsinconfig.json) - Ranges with Units/Currency: Numeric ranges and fractions with units (e.g., "1-10m" → "1 đến 10 m", "1/10kg" → "1 phần 10 kg")
- Node.js 18+
- npm or yarn
npm install
npm install phonemizer-1.2.2.tgz-
Download models from Google Drive: View Available Models
-
Create the models directory (if it doesn't exist):
mkdir -p public/tts-model/vi
-
Place Vietnamese model files in
public/tts-model/vi/:- Each model requires two files:
{model-name}.onnx- The ONNX model file (~60-80 MB){model-name}.onnx.json- The model configuration file
- Example: For the
calmwoman3688model, you need:public/tts-model/vi/calmwoman3688.onnxpublic/tts-model/vi/calmwoman3688.onnx.json
- Each model requires two files:
-
Recommended models to start with (in
public/tts-model/vi/):calmwoman3688- Female voicedeepman3909- Male voicengocngan3701- Vietnamese celebrity voicevietthao3886- Vietnamese celebrity voice
Note: The app detects all models in
public/tts-model/vi/. For English or Indonesian, put models inpublic/tts-model/en/orpublic/tts-model/id/and use the tab bar to switch pages. -
(Optional) ASR models: Place ASR model directories in
public/asr-model/for speech recognition:public/asr-model/{model-name}/The VAD model (
silero_vad.onnx) is already included inpublic/vad-model/silero-vad/.
npm run devThe application will be available at http://localhost:5173 (or the port shown in the terminal).
The development server automatically:
- Serves Vietnamese TTS models from
public/tts-model/vi/(list:/api/models, files:/api/model/{name}) - Serves English/Indonesian TTS models from
public/tts-model/en/andpublic/tts-model/id/(list:/api/piper/{lang}/models, files:/api/model/piper/{lang}/{name}) - Serves ASR models from
public/asr-model/(list:/api/asr/models, files:/api/model/asr/{model}/{name})
- Open your browser and navigate to the development server URL.
- Vietnamese (home): Use the Tiếng Việt tab or
/. Select a model from the dropdown (frompublic/tts-model/vi/), enter text, then Generate/Play. - English or Indonesian: Click English or Indonesia in the tab bar (or go to
/enor/id). Add models topublic/tts-model/en/orpublic/tts-model/id/, then select a model, choose a voice if available, enter text, and Generate/Play. - ASR: Click Nhận dạng giọng nói in the tab bar (or go to
/asr). Select an ASR model, then use the mic or upload an audio file for transcription.
npm run buildThe production build will be in the dist/ folder.
npm run previewThis serves the production build locally for testing.
The project is configured for Cloudflare Pages deployment:
-
TTS models should be stored in a Cloudflare R2 bucket (e.g.
tts-bucket) with language prefixes:- Vietnamese:
piper/vi/{model-name}.onnxandpiper/vi/{model-name}.onnx.json(discovered via/api/models) - English:
piper/en/{model-name}.onnxand.onnx.json(discovered via/api/piper/en/models) - Indonesian:
piper/id/{model-name}.onnxand.onnx.json(discovered via/api/piper/id/models) - Each TTS model requires two files (
.onnx+.onnx.json) per language folder.
- Vietnamese:
-
ASR models should be stored under the
asr/prefix in the same R2 bucket:asr/{model-name}/{file}(discovered via/api/asr/models, served via/api/model/asr/{model}/{name})- Model files are served with 1-year immutable cache headers.
The Cloudflare Pages Functions discover and serve models by prefix.
The wrangler.toml file configures:
- Pages build output directory
- R2 bucket binding (
piper→tts-bucket)
src/config.json controls runtime behavior:
debug– Enable/disable debug loggingUnlimitedRomanNumerals– Whenfalse, only Roman numerals I–XXX are converted; whentrue, all valid Roman numerals are converted
TTS models must be in Piper TTS ONNX format with:
.onnxfile containing the ONNX model.onnx.jsonfile containing voice configuration (phoneme_id_map, audio settings, etc.)
- Removes emojis and special characters
- Normalizes Unicode (NFC)
- Handles Vietnamese-specific punctuation
- Cleans whitespace
- Intelligently splits text into optimal chunks
- Respects sentence boundaries
- Handles long sentences by splitting at word boundaries
- Maintains minimum and maximum chunk sizes for optimal processing
- Real-time streaming of audio chunks
- Automatic normalization and peak limiting
- Silence trimming
- Sample rate preservation
- Modern browsers with WebAssembly support
- Web Workers support required
- ES Modules support required
This project is:
- ✅ Free to use
- ✅ Open source
- ✅ Allowed for commercial use
- ✅ Customizable and deployable
- Built on Piper TTS (GPL) by OHF-Voice
- Inspired by piper-tts-web-demo by clowerweb
- Uses ONNX Runtime Web for browser-based TTS inference
- Uses Sherpa-ONNX for browser-based ASR with Silero VAD