g-group-ai-lab/gipformer-demo

Space

🎙️ Gipformer - Efficient Vietnamese Speech Recognition

2

15 commits

1 linked in READMEs

updated Sep 17, 2026

See the code

README

🎙️ Gipformer - Efficient Vietnamese Speech Recognition

A handcrafted demo for the gipformer family of efficient Vietnamese ASR models (Zipformer Transducer, 68M params). Everything fits one screen — no scrolling.

What you can change per request

ControlOptionsEffect
Model (dropdown)g-group-ai-lab/gipformer1.5-68M-rnnt (default) · g-group-ai-lab/gipformer-68M-rnnt1.5 is the newer, more accurate release
QuantizationFP32 · INT8INT8 weights are ~4× smaller and faster on CPU
DecodingBeam search · GreedyModified beam search trades speed for a lower WER

Load a file once, then switch any control and press Chạy lại to re-run the same audio — that is the quickest way to compare configurations.

The first request for a configuration has to build its recognizer. That happens behind POST /api/warm, which the UI calls after GET /api/ready reports the configuration is cold, so the wait is labelled "Đang nạp mô hình…" rather than looking like a slow model — and the load never lands inside the reported inference time.

  • 📤 Upload an audio file, or 🎤 record from the microphone
  • ▶️ Play it back in the dropzone — the same player for an upload or a recording
  • 🎬 ffmpeg resamples any audio format (mp3, wav, m4a, flac, ogg, …) at any sample rate to 16 kHz mono, up to 100 MB — video files are turned away
  • ✂️ Long files are segmented automatically — a one-hour recording works the same as a ten-second clip
  • ⚡ ONNX Runtime on CPU via sherpa-onnx — no GPU required
  • 🔠 Transcript returned in UPPERCASE, with a per-segment view and timings
  • ⏸️ Sentence breaks from silence — a pause of 0.7 s or longer becomes a period

Segmentation

Audio up to 20 s is transcribed in one pass. Anything longer goes through chunking.py, which follows the same policy as the gipformer ASR skill:

StepBehaviour
VADSilero (via sherpa-onnx), min_silence=0.2s, min_speech=0.2s
MergeAdjacent speech segments are merged into chunks of up to 20 s
Padding100 ms kept around each speech boundary
Hard cutA segment still longer than 30 s is cut into 30 s pieces
DropChunks shorter than 0.5 s are discarded

Chunks are decoded in batches (GIPFORMER_BATCH_SIZE, default 8) and the transcripts are stitched back together. The response carries the merged text plus each segment's text and start/end offsets.

Sentence breaks

The VAD also reports where each long silence sits inside a chunk. A period is placed before the first token emitted at or after a silence starts — the VAD marks speech onset late while the decoder emits early, so anchoring on the end of the silence lands a word or two past the break. Measured against a file built from clips with known boundaries, the silence start put 55/65 periods within a second of a real boundary versus 45/65 for the silence end.

Gaps between token timestamps are deliberately not used: the decoder can stall mid-phrase, which punctuates inside a word group (ĐẦU. CƠ, TỨC. LÀ).

Architecture

A small FastAPI app serves a static, custom frontend (static/) and two endpoints for configuration (GET /api/config, GET /api/ready, POST /api/warm) and one for work (POST /api/transcribe). Model files are pulled from the Hub on first boot and cached; recognizers are built lazily per configuration and kept in a small LRU. Runs as a Docker Space.

static/index.html  → UI shell (fixed viewport, two panes)
static/style.css    → warm/amber theme
static/app.js       → model dropdown / controls / upload / record / fetch
chunking.py         → Silero VAD segmentation for long audio
app.py              → FastAPI + sherpa-onnx
Dockerfile          → python:3.11-slim + ffmpeg

Configuration

VariableDefaultPurpose
GIPFORMER_THREADS4ONNX Runtime threads
GIPFORMER_BATCH_SIZE8Segments decoded per batch
GIPFORMER_MAX_UPLOAD_MB100Upload cap, enforced while the request streams in
GIPFORMER_MAX_ACTIVE_PATHS4Beam width for modified beam search
GIPFORMER_CACHE_SIZE4Recognizers kept resident (of 8 combinations)
HF_TOKEN—Only needed if a model repo is made private again

Both models are public, so no token is required.

Static assets are served with a ?v= stamp and the shell with Cache-Control: no-store. Bump the stamp in index.html whenever app.js or style.css changes, otherwise browsers keep serving the old bundle.


Built by G-Group AI Lab · See DEPLOY.md for push instructions.

docker

g-group-ai-lab/gipformer-demo

Space

🎙️ Gipformer - Efficient Vietnamese Speech Recognition

2

15 commits

1 linked in READMEs

updated Sep 17, 2026

See the code

README

🎙️ Gipformer - Efficient Vietnamese Speech Recognition

A handcrafted demo for the gipformer family of efficient Vietnamese ASR models (Zipformer Transducer, 68M params). Everything fits one screen — no scrolling.

What you can change per request

ControlOptionsEffect
Model (dropdown)g-group-ai-lab/gipformer1.5-68M-rnnt (default) · g-group-ai-lab/gipformer-68M-rnnt1.5 is the newer, more accurate release
QuantizationFP32 · INT8INT8 weights are ~4× smaller and faster on CPU
DecodingBeam search · GreedyModified beam search trades speed for a lower WER

Load a file once, then switch any control and press Chạy lại to re-run the same audio — that is the quickest way to compare configurations.

The first request for a configuration has to build its recognizer. That happens behind POST /api/warm, which the UI calls after GET /api/ready reports the configuration is cold, so the wait is labelled "Đang nạp mô hình…" rather than looking like a slow model — and the load never lands inside the reported inference time.

  • 📤 Upload an audio file, or 🎤 record from the microphone
  • ▶️ Play it back in the dropzone — the same player for an upload or a recording
  • 🎬 ffmpeg resamples any audio format (mp3, wav, m4a, flac, ogg, …) at any sample rate to 16 kHz mono, up to 100 MB — video files are turned away
  • ✂️ Long files are segmented automatically — a one-hour recording works the same as a ten-second clip
  • ⚡ ONNX Runtime on CPU via sherpa-onnx — no GPU required
  • 🔠 Transcript returned in UPPERCASE, with a per-segment view and timings
  • ⏸️ Sentence breaks from silence — a pause of 0.7 s or longer becomes a period

Segmentation

Audio up to 20 s is transcribed in one pass. Anything longer goes through chunking.py, which follows the same policy as the gipformer ASR skill:

StepBehaviour
VADSilero (via sherpa-onnx), min_silence=0.2s, min_speech=0.2s
MergeAdjacent speech segments are merged into chunks of up to 20 s
Padding100 ms kept around each speech boundary
Hard cutA segment still longer than 30 s is cut into 30 s pieces
DropChunks shorter than 0.5 s are discarded

Chunks are decoded in batches (GIPFORMER_BATCH_SIZE, default 8) and the transcripts are stitched back together. The response carries the merged text plus each segment's text and start/end offsets.

Sentence breaks

The VAD also reports where each long silence sits inside a chunk. A period is placed before the first token emitted at or after a silence starts — the VAD marks speech onset late while the decoder emits early, so anchoring on the end of the silence lands a word or two past the break. Measured against a file built from clips with known boundaries, the silence start put 55/65 periods within a second of a real boundary versus 45/65 for the silence end.

Gaps between token timestamps are deliberately not used: the decoder can stall mid-phrase, which punctuates inside a word group (ĐẦU. CƠ, TỨC. LÀ).

Architecture

A small FastAPI app serves a static, custom frontend (static/) and two endpoints for configuration (GET /api/config, GET /api/ready, POST /api/warm) and one for work (POST /api/transcribe). Model files are pulled from the Hub on first boot and cached; recognizers are built lazily per configuration and kept in a small LRU. Runs as a Docker Space.

static/index.html  → UI shell (fixed viewport, two panes)
static/style.css    → warm/amber theme
static/app.js       → model dropdown / controls / upload / record / fetch
chunking.py         → Silero VAD segmentation for long audio
app.py              → FastAPI + sherpa-onnx
Dockerfile          → python:3.11-slim + ffmpeg

Configuration

VariableDefaultPurpose
GIPFORMER_THREADS4ONNX Runtime threads
GIPFORMER_BATCH_SIZE8Segments decoded per batch
GIPFORMER_MAX_UPLOAD_MB100Upload cap, enforced while the request streams in
GIPFORMER_MAX_ACTIVE_PATHS4Beam width for modified beam search
GIPFORMER_CACHE_SIZE4Recognizers kept resident (of 8 combinations)
HF_TOKEN—Only needed if a model repo is made private again

Both models are public, so no token is required.

Static assets are served with a ?v= stamp and the shell with Cache-Control: no-store. Bump the stamp in index.html whenever app.js or style.css changes, otherwise browsers keep serving the old bundle.


Built by G-Group AI Lab · See DEPLOY.md for push instructions.

docker