哈迪斯2联机方法 哈迪斯2联机设置教程大全
2026-07-14 3400176
2026-07-14 0
如果你在做智能家居、机器人或者任何需要语音交互的硬件项目,大概率会遇到一个需求:设备能听懂一句特定的唤醒词。
市面上方案不少,但大部分要么贵(云端 ASR),要么绑定特定词("小爱同学"),要么需要联网。而 ESP32-S3 这颗芯片——双核 240MHz、自带 8MB PSRAM、价格不到 30 块——已经足够在本地跑一个完整的神经网络唤醒词检测。
关键组合是 TFLite Micro + ESP-IDF。TFLite 是 Google 的推理引擎,专门为嵌入式设备优化过,ESP-IDF 直接内置了对它的组件支持。模型用 INT8 量化后不到 80KB,推理一次 ~360ms,配合 5 层检测管线,安静环境误触率极低。
很多同学听到"神经网络"就觉得门槛高。其实唤醒词模型做的事情非常直观:
音频 (16kHz) → Mel 频谱 [98帧 × 32维] → Backbone → [256维向量] → Head → 概率 [0~1]
Mel 频谱:把人耳听到的声音画成一张"图"。横轴是时间,纵轴是频率,颜色深浅代表能量大小。1 秒音频被切成 98 帧,每帧 32 个频率通道。
Backbone:模型的主体,负责从这张"图"里提取特征。常见的是 DS-TCN(深度可分离时序卷积网络)或 SRNN。它输出一个 256 维向量——可以理解为"这段音频的关键特征浓缩版"。
Head:把 256 维向量变成一个概率。常用的 MultiProto head 只有 325 个参数(5 个原型 × 256 维 + 一个线性分类器),体积几乎可以忽略。它做的事:L2 归一化 → 和原型算余弦相似度 → 线性加权 → sigmoid。
Mel 频谱Backbone Head 输出┌──────────┐ ┌────────┐┌─────────┐│········│ │ SRNN ││ prob=0.9 │ ← 说出唤醒词│████████│──────→│or│──────→ │ prob=0.0 │ ← 安静/噪音│████████│ │ DS-TCN ││ prob=0.1 │ ← 其他词│········│ └────────┘└─────────┘└──────────┘ ↑ 98×32 256维向量
模型到手后只需要两个文件:.tflite(backbone,INT8 量化,~76KB)和 head.h(MultiProto 权重,~17KB)。
voicute/onnx-wakeword 是一个完整的 ESP-IDF 开源项目,包含唤醒词推理引擎和完整 Demo。
esp32/├── components/voicute/← 核心库(不依赖具体模型)├── main/← Demo 应用│ ├── main.cpp唤醒词 + 语音命令完整示例│ └── head.h模型 head(用户替换)├── spiffs_content/← 放 .tflite 模型├── build.bat / flash.bat← 一键编译烧录└── sdkconfig.defaults ← 预配好 PSRAM、Flash
git clone https://github.com/voicute/onnx-wakeword.gitcd onnx-wakeword/esp32build.bat # Windows
首次编译会下载 ESP-IDF 依赖(esp-tflite-micro、esp-dsp、esp-sr 等),之后双击 build.bat 就行。已经预配好了 ESP32-S3、16MB Flash、PSRAM,开箱即用。
cp your_wakeword.tflite spiffs_content/cp your_head.h main/head.h
flash.batpython wake_monitor.py COM5 # 观察实时 prob/RMS
// 唤醒回调static void on_wake(voice_event_t ev, voice_evt_data_t d, void *u) {if (ev == VOICE_EVT_AWAKEN) ESP_LOGI("APP", ">>> 关键词!");}void app_main() {recognizer_config_t cfg = {.model_path = "/spiffs",.threshold= 0.70f,.l5_enabled = 1,// 能量跳变过滤(防音乐/视频误触).l5_delta = 200.0f,.postprocess= kws_postprocess,};recognizer_start(&cfg);recognizer_register_callback(0, on_wake, NULL);while (1) {// 从麦克风采集 16192 采样点int64_t now = esp_timer_get_time() / 1000;recognizer_run_frame(pcm, rms, now);}}
Demo 还包括 MultiNet 语音命令(唤醒后说"灯光变红/蓝/绿"),完整展示了唤醒→进入命令模式的流程。不需要的话删掉 sdkconfig.defaults 里相关配置即可。
拿概率只是一个基础。真正决定体验的是误触发控制。onnx-wakeword 内置了和 Android 端同款的 L1-L5 检测管线:
| 层 | 作用 | 说明 |
|---|---|---|
| L1 | 连续帧确认 | N 帧连续超阈值才放行 |
| L2 | 峰/底比 | 峰值必须远高于背景概率 |
| L3 | 冷却 | 1.5s 内不重复触发 |
| L4 | 突发阻断 | 短时间连触发 → 拉黑 5s |
| L5 | 能量跳变 | 当前音量必须明显高于历史窗口 → 排除平稳音乐/视频声 |
L5 是最核心的过滤器。它的逻辑是:如果 RMS 突然跳变(说明有人在说话),进入待确认;等 400ms 后检查尾音是否降回安静水平——是就确认唤醒,否则拦截。这个机制能挡住绝大多数 TV、视频、音乐误触。
如果你是第一次跑,推荐配置:L5 开,其他层关。ESP32 推理一帧 ~360ms,唤醒词 ~500ms,最多被一帧覆盖,L1 连续帧确认不适用;L2/L3 按需开。
如果遇到误触发,两步排查:
先开 L5(l5_enabled=1),把 l5_delta 设到 200。这个值适合安静环境,意味着"当前音量比之前 0.52 秒的最低音量高 200 才放行"。安静时底噪 RMS 一般在 1050,说话时能到 300~1000,200 的差值足够区分。
如果还是容易误触发,把 l5_delta 调大:
.l5_enabled = 1,.l5_delta = 800.0f,// 从 200 加大到 800,嘈杂环境用
| 环境 | 建议 delta | 安静 RMS | 说话 RMS |
|---|---|---|---|
| 安静房间 | 200~400 | 10~50 | 200~500 |
| 普通室内 | 400~800 | 50~150 | 300~800 |
| 嘈杂/有音乐 | 800~1200 | 100~300 | 500~1500 |
如果怎么调都唤不醒(l5_delta 太大导致说话也被拦截),就看串口日志里的 L5 steady: curRms=xxx preMin=xxx,把 delta 调到比你说话时的 RMS 差值略小就行。反之,如果没说话也莫名其妙触发,delta 往大了加。
不用准备数据,不用 GPU,不用懂深度学习。
打开 voicute.com,输入你想用的关键词,点击生成,直接下载两个文件:
xxx.tflite → 放到 spiffs_content/head.h → 替换 main/head.h然后重新编译烧录就行了。从改词到跑通,十分钟。
| 你需要的 | 去哪搞 |
|---|---|
| ESP-IDF 推理引擎 + Demo | github.com/voicute/onn… |
| 自定义唤醒词模型 | voicute.com 输关键词直接下载 |
从零到在自己的 ESP32 设备上喊出专属唤醒词,最快一个下午。离线、免费、想换就换。