☰
ESP-SR MultiNet 命令词识别:模型选择、命令词自定义与离线识别实战
2026/10/14 17:02:25 网站建设 项目流程
  • 语音
  • 音频
  • 人工智能
  • 嵌入式
  • 物联网

【免费下载链接】esp-sr

Speech recognition

项目地址:https://gitcode.com/gh_mirrors/es/esp-sr
点击查看免费下载

ESP-SR 的 MultiNet 模型是乐鑫在 ESP32 系列芯片上离线实现多命令词识别的核心组件,支持最多 200 个自定义命令词、运行时动态增删改,并在 500 ms 内完成识别。本文围绕 MultiNet 的工作原理、不同版本模型的命令词格式要求、三种命令词自定义方法(fst 文件、menuconfig、API)、以及与 AFE/WakeNet 配合的完整调用链展开,帮助你在自己的语音控制应用中落地“唤醒 + 命令词”的离线交互方案。

MultiNet 模型概览

MultiNet 是为 ESP32 系列设计的轻量化多命令词识别模型,其核心特性如下:

  • 多语言支持(因芯片而异):ESP32-S3 支持中文和英文命令词识别;ESP32 仅支持中文命令词识别
  • 用户自定义命令词:无需重新训练模型即可更换识别词表
  • 运行时动态修改:支持运行过程中增加 / 删除 / 修改命令词
  • 命令词数量上限:最多支持 200 个命令词
  • 两种识别模式:单次识别与连续识别
  • 低资源消耗、低延时:延时在 500 ms 内
  • 模型单独分区:支持对模型应用独立 OTA(ESP32-S3 还支持中英文模型在线切换)

MultiNet 的输入是经过 AFE(音频前端)处理后的音频,格式固定为16 KHz、16 bit、单声道。不同芯片可使用的 MultiNet 模型版本可通过menuconfig中的ESP Speech Recognition > Chinese/English Speech Commands Model选择,当前仓库 Kconfig.projbuild 中定义的中文模型选项包括:

Kconfig 选项模型名适用芯片
SR_MN_CN_MULTINET2_SINGLE_RECOGNITIONmn2_cnESP32
SR_MN_CN_MULTINET5_RECOGNITION_QUANT8mn5q8_cnESP32-S3
SR_MN_CN_MULTINET6_QUANTmn6_cnESP32-S3
SR_MN_CN_MULTINET6_AC_QUANTmn6_cn_ac(空调控制场景微调版)ESP32-S3
SR_MN_CN_MULTINET7_QUANTmn7_cnESP32-S3 / ESP32-P4 / ESP32-S31
SR_MN_CN_MULTINET7_AC_QUANTmn7_cn_acESP32-S3 / ESP32-P4 / ESP32-S31

英文模型对应SR_MN_EN_MULTINET5_SINGLE_RECOGNITION_QUANT8(mn5q8_en)、SR_MN_EN_MULTINET6_QUANT(mn6_en)、SR_MN_EN_MULTINET7_QUANT(mn7_en)等选项,芯片依赖关系与中文模型一致。

注:以Q8结尾的模型名(如mn5q8_cn)代表模型的 8 bit 量化版本,更加轻量化。

模型选择的完整流程(包括分区表中model分区的大小配置、idf.py flash自动加载模型、Arduino 框架下用 movemodel.py 手动生成srmodels.bin)参见仓库文档 模型选择和加载;各芯片支持的模型清单及资源消耗参见 性能测试结果。

命令词识别原理

命令词识别在系统中的位置如下图所示:麦克风采集的音频先进入 AFE 进行回声消除、降噪、VAD 等处理,再与 WakeNet 唤醒检测、MultiNet 命令词识别串联工作——唤醒成功后启动 MultiNet 检测,识别到命令词后返回命令 ID 与置信度。

命令词格式要求

不同版本的 MultiNet 命令词格式不同,自定义命令词前必须先了解目标版本的输入单元:

模型版本中文识别单元英文识别单元
MultiNet5汉语拼音(无声调)音素(phoneme)
MultiNet6汉语拼音字母拼写(grapheme,建议全大写)
MultiNet7拼音/字母(fst 文件配置)音素,可用 multinet_g2p.py 从字母转音素

通用的命令词约束(中文版文档明确要求):

  • 不支持中英文混合的命令词
  • 不能含有阿拉伯数字和特殊字符
  • 命令词 ID 不能为 0

MultiNet5 和 MultiNet6 使用汉语拼音作为中文基本识别单元,比如“打开空调”应写成da kai kong tiao。仓库提供了 tool/multinet_pinyin.py 工具将汉字转为拼音(基于pypinyin并内置了一批多音字纠正词典):

python tool/multinet_pinyin.py --text "打开空调" # in: 打开空调 # out: da kai kong tiao

自定义命令词方法

MultiNet 支持在线(API / menuconfig)与离线(fst 文本文件)多种命令词设置方式,并允许运行时动态增删改。

方法一:修改 fst 命令词文件(MultiNet6 / MultiNet7)

MultiNet6 中文:修改 model/multinet_model/fst/commands_cn.txt。格式为每行一条命令,第一个字段是 command id,后面是指令的中文拼音,两者及拼音之间用空格/分隔符隔开,command id 不能为 0:

# command_id command_sentence 1 da kai kong tiao 2 guan bi kong tiao

仓库自带的commands_cn.txt预置了 300 余条空调控制场景命令(da kai kong tiao、guan bi kong tiao、tiao gao wen du等),可直接参考其格式。

英文(MultiNet6 / MultiNet7):修改 model/multinet_model/fst/commands_en.txt,格式为command_id,command_grapheme,command_phoneme三列:

# command_id,command_grapheme,command_phoneme 1,TELL ME A JOKE,TfL Mm c qbK 2,SING A SONG,Sgl c Sel
  • 第 1 列 command ID,从 1 开始,不能为 0;
  • 第 2 列 command_grapheme,即命令句子(MultiNet6 建议全大写;MultiNet7 建议小写,专有缩写除外);
  • 第 3 列 command_phoneme,音素序列,可选。推荐用 tool/multinet_g2p.py 做 Grapheme-to-Phoneme 转换后填入;若留空,运行时会调用内置 G2P 工具,但由于算法差异准确率会略有下降。

方法二:通过 menuconfig(MultiNet5)

MultiNet5 通过idf.py menuconfig配置命令词:

  1. 进入idf.py menuconfig>ESP Speech Recognition>Add Chinese speech commands/Add English speech commands,为每个 Command ID 填入拼音字符串。

注意:单个 Command ID 可以对应多个短语。例如“打开空调”(da kai kong tiao)和“开空调”(kai kong tiao)语义相同,可以写在同一个 Command ID 的词条中,用英文逗号,隔开相邻词条(,前后无需空格)。从 Kconfig.projbuild 可见,CN_SPEECH_COMMAND_ID0的默认值即为da kai kong tiao。

  1. 在代码中调用 API 将 menuconfig 中的配置应用到模型:
/** * @brief Update the speech commands of MultiNet by menuconfig * * @param multinet The multinet handle * * @param model_data The model object to query * * @param language The language of MultiNet * * @return * - ESP_OK Success * - ESP_ERR_INVALID_STATE Fail */ esp_err_t esp_mn_commands_update_from_sdkconfig(esp_mn_iface_t *multinet, const model_iface_data_t *model_data);

方法三:通过 API 动态修改(MultiNet5/6/7 通用)

命令词也可以通过 API 在运行时修改,对 MultiNet5 和 MultiNet6(以及 MultiNet7)都适用。所有添加、移除、修改及清空操作都是先写入缓存链表,在调用esp_mn_commands_update()之后才会被应用到语言模型。API 声明在 src/include/esp_mn_speech_commands.h,实现在 src/esp_mn_speech_commands.c:

  • 添加一条新指令,格式不正确返回ESP_ERR_INVALID_STATE:
/** * @brief Add one speech commands with command string and command ID * * @param command_id The command ID * @param string The command string of the speech commands * * @return * - ESP_OK Success * - ESP_ERR_INVALID_STATE Fail */ esp_err_t esp_mn_commands_add(int command_id, char *string);
  • 移除一条指令,指令不存在时返回ESP_ERR_INVALID_STATE:
esp_err_t esp_mn_commands_remove(char *string);
  • 修改一条指令(旧串不存在时返回ESP_ERR_INVALID_STATE):
esp_err_t esp_mn_commands_modify(char *old_string, char *new_string);
  • 清空所有指令:
esp_err_t esp_mn_commands_clear(void);
  • 应用所有修改(必须在 add/remove/modify/clear 之后调用,否则语言模型不会更新;返回值为无法被 MultiNet 解析的错误短语列表,NULL表示全部成功):
/** * @brief Update the speech commands of MultiNet * * @Warning: Must be used after [add/remove/modify/clear] function, * otherwise the language model of multinet can not be updated. * * @return * - NULL Success * - others The list of error phrase which can not be parsed by multinet. */ esp_mn_error_t *esp_mn_commands_update();
  • 打印缓存的指令(esp_mn_commands_update()之后才生效)与打印当前已生效的指令:
void esp_mn_commands_print(void); void esp_mn_active_commands_print(void);

从源码结构看,esp_mn_commands_add() 在插入节点前会调用模型句柄的check_speech_command()校验字符串格式(MultiNet7 下还会先经flite_g2p()转成音素再校验),并通过esp_mn_commands_num()检查数量是否超过ESP_MN_MAX_PHRASE_NUM上限——esp_mn_iface.h 中该宏定义为 400,即链表层面的硬上限,而官方文档承诺的对外支持数量为 200 个。esp_mn_commands_update()的底层实现则是把整条命令链表通过set_speech_commands()下发给具体模型(见 src/esp_mn_speech_commands.c),因此“缓存 + 统一提交”的设计可以保证语言模型(FST/前缀树)一次性整体重建,避免中途状态不一致。

MultiNet 的使用

MultiNet 命令词识别建议与 ESP-SR 中的 AFE 声学算法模块一起运行(参见 AFE 介绍及使用),并在 WakeNet 唤醒触发后再启动命令词检测。

初始化

  1. 模型加载与初始化:通过esp_mn_handle_from_name()按模型名获取句柄,再用create()创建模型实例,模型选择与加载流程参见 模型选择和加载。参考 test_apps/esp-sr-multinet/main/test_multinet.cpp 中的标准用法:
srmodel_list_t *models = esp_srmodel_init("model"); char *model_name = esp_srmodel_filter(models, ESP_MN_PREFIX, NULL); esp_mn_iface_t *multinet = esp_mn_handle_from_name(model_name); // duration 为超时时间(ms),例如 6000 model_iface_data_t *model_data = multinet->create(model_name, 6000);
  1. 设置命令词:按上文三种方法之一完成。

运行

MultiNet 与 AFE 配合时,必须满足两条约束:

  • 传入 MultiNet 的帧长必须与 AFEfetch的帧长相等;
  • 音频格式为 16 KHz、16 bit、单通道,AFEfetch拿到的数据正是此格式。

先确定每帧应传入的short点数:

int mu_chunksize = multinet->get_samp_chunksize(model_data);

mu_chunksize与 AFE 中 fetch 的每帧数据点数完全一致。然后将 AFE 实时fetch到的数据送入识别接口(buff长度为mu_chunksize * sizeof(int16_t)):

esp_mn_state_t mn_state = multinet->detect(model_data, buff);

识别结果与识别模式

命令词识别必须和唤醒搭配使用:唤醒后运行 MultiNet 检测。detect()每帧返回当前识别状态mn_state:

  • ESP_MN_STATE_DETECTING:正在识别中,尚未识别到目标命令词;
  • ESP_MN_STATE_DETECTED:识别到了目标命令词,此时调用get_results()获取结果:
esp_mn_results_t *mn_result = multinet->get_results(model_data);

结果存储在返回值中,数据结构定义于 esp_mn_iface.h(ESP_MN_RESULT_MAX_NUM为 5):

typedef struct{ esp_mn_state_t state; int num; // The number of phrase in list, num<=5. When num=0, no phrase is recognized. int phrase_id[ESP_MN_RESULT_MAX_NUM]; // The list of phrase id. float prob[ESP_MN_RESULT_MAX_NUM]; // The list of probability. } esp_mn_results_t;

其中state为当前识别状态,num为识别到的词条数目(最多 5 个候选结果,0 表示未识别到),phrase_id为词条对应的 Phrase ID,prob为识别概率、从大到小排列。用户可直接使用phrase_id[0]和prob[0]拿到概率最高的识别结果;仓库中的英文头文件版本还额外包含command_id[]、string[256]、raw_string[256]字段,可直接输出识别到的命令 ID 与文本。

  • ESP_MN_STATE_TIMEOUT:长时间未检测到命令词,自动退出,等待下次唤醒。

由此定义两种识别模式:

  • 单次识别模式:状态返回ESP_MN_STATE_DETECTED时退出命令词识别;
  • 连续识别模式:状态返回ESP_MN_STATE_TIMEOUT时退出命令词识别。

test_apps/esp-sr-multinet/main/test_multinet.cpp 给出了一个完整的“喂帧—检测—取结果”参考循环:逐帧memcpy音频到buffer,调用detect(),若返回ESP_MN_STATE_DETECTED则get_results()打印command_id[0]与string后退出。

资源消耗与精度参考

各芯片上 MultiNet 的资源消耗与性能数据见 性能测试结果。以 ESP32-S3 为例:

模型Internal RAMPSRAM单帧平均耗时帧长
MultiNet 416.8 KB1866 KB18 ms32 ms
MultiNet 4 Q810.5 KB1009 KB11 ms32 ms
MultiNet 5 Q816 KB2310 KB12 ms32 ms
MultiNet 632 KB4100 KB12 ms32 ms
MultiNet 718 KB2920 KB11 ms32 ms

ESP32-P4 上 MultiNet 7 单帧平均耗时约 8 ms。官方还给出了空调控制场景(3 m 距离)的实测准确率:mn5_cn 安静环境 88.9%;mn6_cn 安静环境 98.8%;在空调场景数据集上额外微调的 mn6_cn_ac 安静环境 97.1%、平稳噪声下 95.1%、人声噪声下 96.8%——从这组数据可以推断,对垂直场景(如空调控制)选用场景微调模型(_ac后缀)收益明显。

小结

MultiNet 提供了“模型选择(Kconfig)→ 命令词配置(fst 文件 / menuconfig / API)→ 与 AFE、WakeNet 串联运行 → 状态机取结果”的完整离线命令词识别链路。落地时建议:先按芯片在menuconfig选定模型并配置model分区;按版本要求准备拼音/音素形式的命令词表;在detect()循环中按ESP_MN_STATE_DETECTED/ESP_MN_STATE_TIMEOUT选择单次或连续识别模式,并用get_results()中的phrase_id[0]/prob[0]驱动上层业务逻辑。完整示例可参考 test_apps/esp-sr-multinet 工程。

  • 语音
  • 音频
  • 人工智能
  • 嵌入式
  • 物联网

【免费下载链接】esp-sr

Speech recognition

项目地址:https://gitcode.com/gh_mirrors/es/esp-sr
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询