File size: 7,160 Bytes
c3edab4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | ---
license: apache-2.0
library_name: esp-idf
tags:
- voice-activity-detection
- vad
- esp32-p4
- embedded
- audio
- risc-v
- dfsmn
- quantization
---
# FireRedVAD Models for ESP32-P4
Converted [FireRedVAD](https://github.com/FireRedTeam/FireRedVAD) models optimized for ESP32-P4 microcontrollers.
All models use the custom `.frvd` binary format with native RISC-V PIE (Position Independent Execution) acceleration.
**Source Code:** https://github.com/Strg-Alt-Entf-0x00/firered-vad-esp32-p4
## Quick Start
```bash
cd examples/console_vad
pip install huggingface-hub
python download_models.py
```
```bash
idf.py build flash monitor
```
```
firevad> vad_model_list
firevad> vad_model_load stream-vad/int8-ch/firered-stream-vad-int8-ch.frvd
firevad> vad_infer_mic
```
## Available Models
### stream-vad/ β Real-time streaming (causal, 10ms latency)
Best for real-time voice activity detection. Model is fully **causal** β no future context.
Runs in ~4.5ms per 10ms frame on ESP32-P4 @ 400MHz.
| Quantization | File | Size | Notes |
|---|---|---|---|
| **INT8-CH** | `stream-vad/int8-ch/firered-stream-vad-int8-ch.frvd` | 576 KB | **Recommended.** Per-channel scale factors, near-FP32 accuracy |
| INT8 | `stream-vad/int8/firered-stream-vad-int8.frvd` | 556 KB | Global scale factor per layer, slightly lower accuracy |
| INT16 | `stream-vad/int16/firered-stream-vad-int16.frvd` | 1.1 MB | Higher precision, ~2x memory use |
| FP32 | `stream-vad/fp32/firered-stream-vad-fp32.frvd` | 2.2 MB | Development only. Too slow for real-time on P4 (~35ms/frame) |
### vad/ β Offline batch VAD (non-causal, 1-second chunks)
Uses bidirectional context. Higher accuracy than stream-vad, but adds latency.
Not suitable for real-time streaming.
| Quantization | File | Size | Notes |
|---|---|---|---|
| **INT8-CH** | `vad/int8-ch/firered-vad-int8-ch.frvd` | 597 KB | Recommended for batch processing |
| INT8 | `vad/int8/firered-vad-int8.frvd` | 576 KB | |
| INT16 | `vad/int16/firered-vad-int16.frvd` | 1.1 MB | |
| FP32 | `vad/fp32/firered-vad-fp32.frvd` | 2.3 MB | |
### aed/ β Audio Event Detection (Speech / Music / Singing)
Multi-class audio classifier. Identifies speech, music, and singing simultaneously.
| Quantization | File | Size | Notes |
|---|---|---|---|
| **INT8-CH** | `aed/int8-ch/firered-aed-int8-ch.frvd` | 598 KB | Recommended |
| INT8 | `aed/int8/firered-aed-int8.frvd` | 576 KB | |
| INT16 | `aed/int16/firered-aed-int16.frvd` | 1.1 MB | |
| FP32 | `aed/fp32/firered-aed-fp32.frvd` | 2.3 MB | |
## Quantization Explained
### Why INT8-CH (Per-Channel) is Recommended
Standard per-tensor INT8 quantization assigns **one** global scale factor per weight matrix.
DFSMN architectures have wide variance in weight distribution across output channels β a single
scale factor cannot capture this range accurately, causing silent accuracy loss.
**Per-Channel INT8 (`int8-ch`, Version 4 in the `.frvd` format)** assigns **one scale factor
per output channel**. This preserves near-FP32 accuracy at INT8 speed and memory cost.
| | int8 | int8-ch | int16 | fp32 |
|---|---|---|---|---|
| Format version | 2 | 4 | 3 | 1 |
| Inference time (P4) | ~4.47ms | ~4.54ms | ~6ms | ~35ms |
| Memory bandwidth | 4x less than FP32 | 4x less than FP32 | 2x less than FP32 | baseline |
| Accuracy vs FP32 | Lower | Near-identical | High | Reference |
## Benchmark Results (ESP32-P4, 400MHz, 10ms audio frame)
| Model | Avg Latency | Real-Time Load | Usable? |
|---|---|---|---|
| stream-fp32 | 35.2 ms | 352% | No β audio drops |
| stream-int8 | 4.47 ms | 44.7% | Yes |
| **stream-int8-ch** | **4.54 ms** | **45.4%** | **Yes β Recommended** |
Real-time budget for 10ms frames: 10ms. Anything above 10ms (>100% load) causes audio drops.
## Hardware Requirements
- MCU: ESP32-P4 (RISC-V dual-core, 400MHz)
- PSRAM: 32 MB
- Flash: 16β32 MB
- RAM at runtime: ~150 KB
- Microphone: INMP441 or equivalent I2S digital microphone @ 16kHz
**Note:** INT8 and INT8-CH models use ESP32-P4 PIE vector instructions
(`esp.vmulas.s8.xacc` etc.) with mandatory 16-byte memory alignment, handled automatically
by the runtime. FP32/INT16 models work on other ESP32 variants (S2, S3) but without
PIE acceleration.
## Known Limitations (Honest Assessment)
1. **Noise sensitivity:** Performance degrades in low-SNR environments (loud machinery, strong wind).
False positive rate increases at SNR < 5dB.
2. **Microphone dependency:** Model was trained on clean 16kHz PCM. A high-quality I2S
microphone with hardware PGA gain control is required for reliable results.
3. **No built-in noise suppression:** The ESP-IDF runtime does not include NS/AEC.
Echo cancellation is available via the shared APLL (I2S0 + I2S1 synchronized clocking).
4. **APLL sharing warning:** When both TX and RX I2S ports are active, the ESP32-P4 APLL
runs at 8,191,999 Hz instead of 8,192,000 Hz (1 Hz deviation). This is hardware-expected
behavior, not a bug. Both ports share the same clock, which is ideal for AEC.
## .frvd File Format
Custom binary format, version-tagged in header byte [4..7]:
```
Header (32 bytes):
[0..3] Magic: "FRVD"
[4..7] Version: 1=fp32, 2=int8, 3=int16, 4=int8-per-channel
[8..11] Model type: 0=VAD, 1=Stream-VAD, 2=AED
[12..15] Total parameter count
[16..23] DFSMN block count + DNN layer count
[24..31] Reserved
Architecture Metadata (32 bytes):
Input dim, hidden size, projection size, output dim,
lookback order/stride, lookahead order/stride
CMVN block:
dim (uint32) + means[dim] (float32) + istd[dim] (float32)
Layer data (sequential):
Per tensor: CRC32 name hash + element count + [scale per channel for int8-ch] + data
```
## Conversion Pipeline
Original FireRedVAD PyTorch checkpoints -> `.frvd`:
```bash
# Requirements
pip install torch kaldiio numpy
# Stream-VAD INT8-CH (recommended)
python tools/converter/export_weights.py \
--model-dir tools/original_models/Stream-VAD \
--output-dir examples/console_vad/converted_models/stream-vad/int8-ch \
--model-type stream-vad \
--quantize-int8-per-ch
# Stream-VAD INT8
python tools/converter/export_weights.py \
--model-dir tools/original_models/Stream-VAD \
--output-dir examples/console_vad/converted_models/stream-vad/int8 \
--model-type stream-vad \
--quantize-int8
# Verify conversion
python tools/converter/verify_conversion.py \
--frvd examples/console_vad/converted_models/stream-vad/int8-ch/firered-stream-vad-int8-ch.frvd
```
## License & Attribution
### Original Models
- **FireRedVAD** by Xiaohongshu (FireRedTeam) β Apache 2.0
- Source: https://github.com/FireRedTeam/FireRedVAD
- HuggingFace: https://huggingface.co/FireRedTeam/FireRedVAD
### ESP32-P4 Port
- **FireRedVAD-ESP32-P4** by Strg-Alt-Entf-0x00 β Apache 2.0
- Repository: https://github.com/Strg-Alt-Entf-0x00/firered-vad-esp32-p4
## Citation
```bibtex
@misc{fireredvad-esp32p4,
title={FireRedVAD for ESP32-P4: Optimized Voice Activity Detection for Embedded Systems},
author={Strg-Alt-Entf-0x00},
year={2026},
howpublished={\url{https://github.com/Strg-Alt-Entf-0x00/firered-vad-esp32-p4}},
}
```
|