fix multiple wakenet words and custom wake word (#1226)

* fix multiple wakenet words and custom wake word

* fix idf_component.yml
This commit is contained in:
Xiaoxia
2025-09-22 10:49:08 +08:00
committed by GitHub
parent 96e39bea1b
commit d3e7fee828
5 changed files with 217 additions and 146 deletions

View File

@@ -86,37 +86,37 @@ choice BOARD_TYPE
help
Board type. 开发板类型
config BOARD_TYPE_BREAD_COMPACT_WIFI
bool "面包板新版接线WiFi"
bool "Bread Compact WiFi (面包板)"
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_BREAD_COMPACT_WIFI_LCD
bool "面包板新版接线(WiFi+ LCD"
bool "Bread Compact WiFi + LCD (面包板)"
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_BREAD_COMPACT_WIFI_CAM
bool "面包板新版接线(WiFi+ LCD + Camera"
bool "Bread Compact WiFi + LCD + Camera (面包板)"
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_BREAD_COMPACT_ML307
bool "面包板新版接线ML307 AT"
bool "Bread Compact ML307/EC801E (面包板 4G)"
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_BREAD_COMPACT_ESP32
bool "面包板WiFi ESP32 DevKit"
bool "Bread Compact ESP32 DevKit (面包板)"
depends on IDF_TARGET_ESP32
config BOARD_TYPE_BREAD_COMPACT_ESP32_LCD
bool "面包板WiFi+ LCD ESP32 DevKit"
bool "Bread Compact ESP32 DevKit + LCD (面包板)"
depends on IDF_TARGET_ESP32
config BOARD_TYPE_XMINI_C3_V3
bool "虾哥 Mini C3 V3"
bool "Xmini C3 V3"
depends on IDF_TARGET_ESP32C3
config BOARD_TYPE_XMINI_C3_4G
bool "虾哥 Mini C3 4G"
bool "Xmini C3 4G"
depends on IDF_TARGET_ESP32C3
config BOARD_TYPE_XMINI_C3
bool "虾哥 Mini C3"
bool "Xmini C3"
depends on IDF_TARGET_ESP32C3
config BOARD_TYPE_ESP32S3_KORVO2_V3
bool "ESP32S3_KORVO2_V3开发板"
bool "ESP32S3 KORVO2 V3"
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_ESP_SPARKBOT
bool "ESP-SparkBot开发板"
bool "ESP-SparkBot"
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_ESP_SPOT_S3
bool "ESP-Spot-S3"
@@ -146,10 +146,10 @@ choice BOARD_TYPE
bool "Kevin C3"
depends on IDF_TARGET_ESP32C3
config BOARD_TYPE_KEVIN_SP_V3_DEV
bool "Kevin SP V3开发板"
bool "Kevin SP V3"
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_KEVIN_SP_V4_DEV
bool "Kevin SP V4开发板"
bool "Kevin SP V4"
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_ESP32_CGC
bool "ESP32 CGC"
@@ -158,13 +158,13 @@ choice BOARD_TYPE
bool "ESP32 CGC 144"
depends on IDF_TARGET_ESP32
config BOARD_TYPE_KEVIN_YUYING_313LCD
bool "鱼鹰科技3.13LCD开发板"
bool "鱼鹰科技 3.13LCD"
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_LICHUANG_DEV
bool "立创·实战派ESP32-S3开发板"
bool "立创·实战派 ESP32-S3"
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_LICHUANG_C3_DEV
bool "立创·实战派ESP32-C3开发板"
bool "立创·实战派 ESP32-C3"
depends on IDF_TARGET_ESP32C3
config BOARD_TYPE_DF_K10
bool "DFRobot 行空板 k10"
@@ -373,7 +373,7 @@ choice BOARD_TYPE
depends on IDF_TARGET_ESP32S3
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_SURFER_C3_1_14TFT
bool "Surfer-C3-1-14TFT"
bool "Surfer-C3-1.14TFT"
depends on IDF_TARGET_ESP32C3
config BOARD_TYPE_YUNLIAO_S3
bool "小智云聊-S3"
@@ -384,8 +384,6 @@ choice ESP_S3_LCD_EV_Board_Version_TYPE
depends on BOARD_TYPE_ESP_S3_LCD_EV_Board
prompt "EV_BOARD Type"
default ESP_S3_LCD_EV_Board_1p4
help
开发板硬件版本型号选择
config ESP_S3_LCD_EV_Board_1p4
bool "乐鑫ESP32_S3_LCD_EV_Board-MB_V1.4"
config ESP_S3_LCD_EV_Board_1p5
@@ -397,13 +395,13 @@ choice DISPLAY_OLED_TYPE
prompt "OLED Type"
default OLED_SSD1306_128X32
help
OLED 屏幕类型选择
OLED Monochrome Display Type
config OLED_SSD1306_128X32
bool "SSD1306, 分辨率128*32"
bool "SSD1306 128*32"
config OLED_SSD1306_128X64
bool "SSD1306, 分辨率128*64"
bool "SSD1306 128*64"
config OLED_SH1106_128X64
bool "SH1106, 分辨率128*64"
bool "SH1106 128*64"
endchoice
choice DISPLAY_LCD_TYPE
@@ -411,37 +409,37 @@ choice DISPLAY_LCD_TYPE
prompt "LCD Type"
default LCD_ST7789_240X320
help
屏幕类型选择
LCD Display Type
config LCD_ST7789_240X320
bool "ST7789, 分辨率240*320, IPS"
bool "ST7789 240*320, IPS"
config LCD_ST7789_240X320_NO_IPS
bool "ST7789, 分辨率240*320, IPS"
bool "ST7789 240*320, Non-IPS"
config LCD_ST7789_170X320
bool "ST7789, 分辨率170*320"
bool "ST7789 170*320"
config LCD_ST7789_172X320
bool "ST7789, 分辨率172*320"
bool "ST7789 172*320"
config LCD_ST7789_240X280
bool "ST7789, 分辨率240*280"
bool "ST7789 240*280"
config LCD_ST7789_240X240
bool "ST7789, 分辨率240*240"
bool "ST7789 240*240"
config LCD_ST7789_240X240_7PIN
bool "ST7789, 分辨率240*240, 7PIN"
bool "ST7789 240*240, 7PIN"
config LCD_ST7789_240X135
bool "ST7789, 分辨率240*135"
bool "ST7789 240*135"
config LCD_ST7735_128X160
bool "ST7735, 分辨率128*160"
bool "ST7735 128*160"
config LCD_ST7735_128X128
bool "ST7735, 分辨率128*128"
bool "ST7735 128*128"
config LCD_ST7796_320X480
bool "ST7796, 分辨率320*480 IPS"
bool "ST7796 320*480 IPS"
config LCD_ST7796_320X480_NO_IPS
bool "ST7796, 分辨率320*480, IPS"
bool "ST7796 320*480, Non-IPS"
config LCD_ILI9341_240X320
bool "ILI9341, 分辨率240*320"
bool "ILI9341 240*320"
config LCD_ILI9341_240X320_NO_IPS
bool "ILI9341, 分辨率240*320, IPS"
bool "ILI9341 240*320, Non-IPS"
config LCD_GC9A01_240X240
bool "GC9A01, 分辨率240*240, 圆屏"
bool "GC9A01 240*240 Circle"
config LCD_TYPE_800_1280_10_1_INCH
bool "Waveshare 101M-8001280-IPS-CT-K Display"
config LCD_TYPE_800_1280_10_1_INCH_A
@@ -451,7 +449,7 @@ choice DISPLAY_LCD_TYPE
config LCD_TYPE_720_720_4_INCH
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-4C with 720*720 4inch round display"
config LCD_CUSTOM
bool "自定义屏幕参数"
bool "Custom LCD (自定义屏幕参数)"
endchoice
choice DISPLAY_ESP32S3_KORVO2_V3
@@ -459,11 +457,11 @@ choice DISPLAY_ESP32S3_KORVO2_V3
prompt "ESP32S3_KORVO2_V3 LCD Type"
default ESP32S3_KORVO2_V3_LCD_ST7789
help
屏幕类型选择
LCD Display Type
config ESP32S3_KORVO2_V3_LCD_ST7789
bool "ST7789, 分辨率240*280"
bool "ST7789 240*280"
config ESP32S3_KORVO2_V3_LCD_ILI9341
bool "ILI9341, 分辨率240*320"
bool "ILI9341 240*320"
endchoice
choice DISPLAY_ESP32S3_AUDIO_BOARD
@@ -471,11 +469,11 @@ choice DISPLAY_ESP32S3_AUDIO_BOARD
prompt "ESP32S3_AUDIO_BOARD LCD Type"
default AUDIO_BOARD_LCD_JD9853
help
屏幕类型选择
LCD Display Type
config AUDIO_BOARD_LCD_JD9853
bool "JD9853, 分辨率320*172"
bool "JD9853 320*172"
config AUDIO_BOARD_LCD_ST7789
bool "ST7789, 分辨率240*320"
bool "ST7789 240*320"
endchoice
choice DISPLAY_STYLE
@@ -495,40 +493,51 @@ choice DISPLAY_STYLE
depends on BOARD_TYPE_ESP_BOX_3 || BOARD_TYPE_ECHOEAR
endchoice
config USE_ESP_WAKE_WORD
bool "Enable Wake Word Detection (without AFE)"
default n
depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32C6 || (IDF_TARGET_ESP32 && SPIRAM)
choice WAKE_WORD_TYPE
prompt "Wake Word Implementation Type"
default USE_AFE_WAKE_WORD if (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
default WAKE_WORD_DISABLED
help
支持 ESP32 C3、ESP32 C5 与 ESP32 C6增加ESP32支持需要开启PSRAM
Choose the type of wake word implementation to use
config USE_AFE_WAKE_WORD
bool "Enable Wake Word Detection (AFE)"
default y
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
help
需要 ESP32 S3 与 PSRAM 支持
config WAKE_WORD_DISABLED
bool "Disabled"
help
Disable wake word detection
config USE_ESP_WAKE_WORD
bool "Wakenet model without AFE"
depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32C6 || (IDF_TARGET_ESP32 && SPIRAM)
help
Support ESP32 C3、ESP32 C5 与 ESP32 C6, and (ESP32 with PSRAM)
config USE_AFE_WAKE_WORD
bool "Wakenet model with AFE"
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
help
Support AEC if available, requires ESP32 S3 and PSRAM
config USE_CUSTOM_WAKE_WORD
bool "Multinet model (Custom Wake Word)"
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
help
Requires ESP32 S3 and PSRAM
endchoice
config USE_CUSTOM_WAKE_WORD
bool "Enable Custom Wake Word Detection"
default n
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM && (!USE_AFE_WAKE_WORD)
help
需要 ESP32 S3 与 PSRAM 支持
config CUSTOM_WAKE_WORD
string "Custom Wake Word"
default "xiao tu dou"
depends on USE_CUSTOM_WAKE_WORD
help
自定义唤醒词,中文用拼音表示,每个字之间用空格隔开
Custom Wake Word, use pinyin for Chinese, separated by spaces
config CUSTOM_WAKE_WORD_DISPLAY
string "Custom Wake Word Display"
default "小土豆"
depends on USE_CUSTOM_WAKE_WORD
help
唤醒后发送给服务器的问候语
Greeting sent to the server after wake word detection
config CUSTOM_WAKE_WORD_THRESHOLD
int "Custom Wake Word Threshold (%)"
@@ -536,14 +545,21 @@ config CUSTOM_WAKE_WORD_THRESHOLD
range 1 99
depends on USE_CUSTOM_WAKE_WORD
help
自定义唤醒词阈值范围1-99越小越敏感默认10
Custom Wake Word Threshold, range 1-99, the smaller the more sensitive, default 20
config SEND_WAKE_WORD_DATA
bool "Send Wake Word Data"
default y
depends on USE_AFE_WAKE_WORD || USE_CUSTOM_WAKE_WORD
help
Send wake word data to the server as the first message of the conversation and wait for response
config USE_AUDIO_PROCESSOR
bool "Enable Audio Noise Reduction"
default y
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
help
需要 ESP32 S3 PSRAM 支持
Requires ESP32 S3 and PSRAM
config USE_DEVICE_AEC
bool "Enable Device-Side AEC"
@@ -554,46 +570,46 @@ config USE_DEVICE_AEC
|| BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_XC || BOARD_TYPE_ESP_S3_LCD_EV_Board_2 || BOARD_TYPE_YUNLIAO_S3 \
|| BOARD_TYPE_ECHOEAR || BOARD_TYPE_ESP32S3_Touch_LCD_3_49)
help
因为性能不够,不建议和微信聊天界面风格同时开启
To work properly, device-side AEC requires a clean output reference path from the speaker signal and physical acoustic isolation between the microphone and speaker.
config USE_SERVER_AEC
bool "Enable Server-Side AEC (Unstable)"
default n
depends on USE_AUDIO_PROCESSOR
help
启用服务器端 AEC需要服务器支持
To work perperly, server-side AEC requires server support
config USE_AUDIO_DEBUGGER
bool "Enable Audio Debugger"
default n
help
启用音频调试功能通过UDP发送音频数据
config USE_ACOUSTIC_WIFI_PROVISIONING
bool "Enable Acoustic WiFi Provisioning"
default n
help
启用声波配网功能,使用音频信号传输 WiFi 配置数据
Enable audio debugger, send audio data through UDP to the host machine
config AUDIO_DEBUG_UDP_SERVER
string "Audio Debug UDP Server Address"
default "192.168.2.100:8000"
depends on USE_AUDIO_DEBUGGER
help
UDP服务器地址,格式: IP:PORT用于接收音频调试数据
UDP server address, format: IP:PORT, used to receive audio debugging data
config USE_ACOUSTIC_WIFI_PROVISIONING
bool "Enable Acoustic WiFi Provisioning"
default n
help
Enable acoustic WiFi provisioning, use audio signal to transmit WiFi configuration data
config RECEIVE_CUSTOM_MESSAGE
bool "Enable Custom Message Reception"
default n
help
启用接收自定义消息功能,允许设备接收来自服务器的自定义消息(最好通过 MQTT 协议)
Enable custom message reception, allow the device to receive custom messages from the server (preferably through the MQTT protocol)
choice I2S_TYPE_TAIJIPI_S3
depends on BOARD_TYPE_ESP32S3_Taiji_Pi
prompt "taiji-pi-S3 I2S Type"
default TAIJIPAI_I2S_TYPE_STD
help
I2S 类型选择
I2S Type
config TAIJIPAI_I2S_TYPE_STD
bool "I2S Type STD"
config TAIJIPAI_I2S_TYPE_PDM

View File

@@ -630,7 +630,7 @@ void Application::OnWakeWordDetected() {
auto wake_word = audio_service_.GetLastWakeWord();
ESP_LOGI(TAG, "Wake word detected: %s", wake_word.c_str());
#if CONFIG_USE_AFE_WAKE_WORD || CONFIG_USE_CUSTOM_WAKE_WORD
#if CONFIG_SEND_WAKE_WORD_DATA
// Encode and send the wake word data to the server
while (auto packet = audio_service_.PopWakeWordPacket()) {
protocol_->SendAudio(std::move(packet));
@@ -711,11 +711,7 @@ void Application::SetDeviceState(DeviceState state) {
if (listening_mode_ != kListeningModeRealtime) {
audio_service_.EnableVoiceProcessing(false);
// Only AFE wake word can be detected in speaking mode
#if CONFIG_USE_AFE_WAKE_WORD
audio_service_.EnableWakeWordDetection(true);
#else
audio_service_.EnableWakeWordDetection(false);
#endif
audio_service_.EnableWakeWordDetection(audio_service_.IsAfeWakeWord());
}
audio_service_.ResetDecoder();
break;

View File

@@ -91,7 +91,7 @@ bool CustomWakeWord::Initialize(AudioCodec* codec, srmodel_list_t* models_list)
if (models_list == nullptr) {
language_ = "cn";
models_ = esp_srmodel_init("model");
#if CONFIG_CUSTOM_WAKE_WORD
#ifdef CONFIG_CUSTOM_WAKE_WORD
threshold_ = CONFIG_CUSTOM_WAKE_WORD_THRESHOLD / 100.0f;
commands_.push_back({CONFIG_CUSTOM_WAKE_WORD, CONFIG_CUSTOM_WAKE_WORD_DISPLAY, "wake"});
#endif

View File

@@ -4,10 +4,13 @@ dependencies:
espressif/esp_lcd_ili9341: ==1.2.0
espressif/esp_lcd_gc9a01: ==2.0.1
espressif/esp_lcd_st77916: ^1.0.1
espressif/esp_lcd_st7701: "^1.1.*"
espressif/esp_lcd_axs15231b: ^1.0.0
espressif/esp_lcd_st7701:
version: ^1.1.4
rules:
- if: target in [esp32s3, esp32p4]
espressif/esp_lcd_st7796:
version: 1.3.4
version: 1.3.5
rules:
- if: target not in [esp32c3]
espressif/esp_lcd_spd2010: ==1.0.2

View File

@@ -17,8 +17,6 @@ import shutil
import sys
import json
import struct
import math
from pathlib import Path
from datetime import datetime
@@ -156,9 +154,9 @@ def copy_directory(src, dst):
return False
def process_sr_models(wakenet_model_dir, multinet_model_dirs, build_dir, assets_dir):
def process_sr_models(wakenet_model_dirs, multinet_model_dirs, build_dir, assets_dir):
"""Process SR models (wakenet and multinet) and generate srmodels.bin"""
if not wakenet_model_dir and not multinet_model_dirs:
if not wakenet_model_dirs and not multinet_model_dirs:
return None
# Create SR models build directory
@@ -169,13 +167,14 @@ def process_sr_models(wakenet_model_dir, multinet_model_dirs, build_dir, assets_
models_processed = 0
# Copy wakenet model if available
if wakenet_model_dir:
wakenet_name = os.path.basename(wakenet_model_dir)
wakenet_dst = os.path.join(sr_models_build_dir, wakenet_name)
if copy_directory(wakenet_model_dir, wakenet_dst):
models_processed += 1
print(f"Added wakenet model: {wakenet_name}")
# Copy wakenet models if available
if wakenet_model_dirs:
for wakenet_model_dir in wakenet_model_dirs:
wakenet_name = os.path.basename(wakenet_model_dir)
wakenet_dst = os.path.join(sr_models_build_dir, wakenet_name)
if copy_directory(wakenet_model_dir, wakenet_dst):
models_processed += 1
print(f"Added wakenet model: {wakenet_name}")
# Copy multinet models if available
if multinet_model_dirs:
@@ -203,11 +202,6 @@ def process_sr_models(wakenet_model_dir, multinet_model_dirs, build_dir, assets_
return None
def process_wakenet_model(wakenet_model_dir, build_dir, assets_dir):
"""Process wakenet_model parameter (legacy compatibility function)"""
return process_sr_models(wakenet_model_dir, None, build_dir, assets_dir)
def process_text_font(text_font_file, assets_dir):
"""Process text_font parameter"""
if not text_font_file:
@@ -440,12 +434,12 @@ def pack_assets_simple(target_path, include_path, out_file, assets_path, max_nam
def read_wakenet_from_sdkconfig(sdkconfig_path):
"""
Read wakenet model from sdkconfig (based on movemodel.py logic)
Returns the wakenet model name or None if no wakenet is configured
Read wakenet models from sdkconfig (based on movemodel.py logic)
Returns a list of wakenet model names
"""
if not os.path.exists(sdkconfig_path):
print(f"Warning: sdkconfig file not found: {sdkconfig_path}")
return None
return []
models = []
with io.open(sdkconfig_path, "r") as f:
@@ -461,8 +455,7 @@ def read_wakenet_from_sdkconfig(sdkconfig_path):
model_name = label.split("_SR_WN_")[-1].lower()
models.append(model_name)
# Return the first model found, or None if no models
return models[0] if models else None
return models
def read_multinet_from_sdkconfig(sdkconfig_path):
@@ -514,6 +507,46 @@ def read_multinet_from_sdkconfig(sdkconfig_path):
return models
def read_wake_word_type_from_sdkconfig(sdkconfig_path):
"""
Read wake word type configuration from sdkconfig
Returns a dict with wake word type info
"""
if not os.path.exists(sdkconfig_path):
print(f"Warning: sdkconfig file not found: {sdkconfig_path}")
return {
'use_esp_wake_word': False,
'use_afe_wake_word': False,
'use_custom_wake_word': False,
'wake_word_disabled': True
}
config_values = {
'use_esp_wake_word': False,
'use_afe_wake_word': False,
'use_custom_wake_word': False,
'wake_word_disabled': False
}
with io.open(sdkconfig_path, "r") as f:
for line in f:
line = line.strip("\n")
if line.startswith('#'):
continue
# Check for wake word type configuration
if 'CONFIG_USE_ESP_WAKE_WORD=y' in line:
config_values['use_esp_wake_word'] = True
elif 'CONFIG_USE_AFE_WAKE_WORD=y' in line:
config_values['use_afe_wake_word'] = True
elif 'CONFIG_USE_CUSTOM_WAKE_WORD=y' in line:
config_values['use_custom_wake_word'] = True
elif 'CONFIG_WAKE_WORD_DISABLED=y' in line:
config_values['wake_word_disabled'] = True
return config_values
def read_custom_wake_word_from_sdkconfig(sdkconfig_path):
"""
Read custom wake word configuration from sdkconfig
@@ -591,19 +624,23 @@ def get_language_from_multinet_models(multinet_models):
return 'cn' # Default to Chinese
def get_wakenet_model_path(model_name, esp_sr_model_path):
def get_wakenet_model_paths(model_names, esp_sr_model_path):
"""
Get the full path to the wakenet model directory
Get the full paths to the wakenet model directories
Returns a list of valid model paths
"""
if not model_name:
return None
if not model_names:
return []
wakenet_model_path = os.path.join(esp_sr_model_path, 'wakenet_model', model_name)
if os.path.exists(wakenet_model_path):
return wakenet_model_path
else:
print(f"Warning: Wakenet model directory not found: {wakenet_model_path}")
return None
valid_paths = []
for model_name in model_names:
wakenet_model_path = os.path.join(esp_sr_model_path, 'wakenet_model', model_name)
if os.path.exists(wakenet_model_path):
valid_paths.append(wakenet_model_path)
else:
print(f"Warning: Wakenet model directory not found: {wakenet_model_path}")
return valid_paths
def get_multinet_model_paths(model_names, esp_sr_model_path):
@@ -661,7 +698,7 @@ def get_emoji_collection_path(default_emoji_collection, xiaozhi_fonts_path):
return None
def build_assets_integrated(wakenet_model_path, multinet_model_paths, text_font_path, emoji_collection_path, extra_files_path, output_path, multinet_model_info=None):
def build_assets_integrated(wakenet_model_paths, multinet_model_paths, text_font_path, emoji_collection_path, extra_files_path, output_path, multinet_model_info=None):
"""
Build assets using integrated functions (no external dependencies)
"""
@@ -679,7 +716,7 @@ def build_assets_integrated(wakenet_model_path, multinet_model_paths, text_font_
print("Starting to build assets...")
# Process each component
srmodels = process_sr_models(wakenet_model_path, multinet_model_paths, temp_build_dir, assets_dir) if (wakenet_model_path or multinet_model_paths) else None
srmodels = process_sr_models(wakenet_model_paths, multinet_model_paths, temp_build_dir, assets_dir) if (wakenet_model_paths or multinet_model_paths) else None
text_font = process_text_font(text_font_path, assets_dir) if text_font_path else None
emoji_collection = process_emoji_collection(emoji_collection_path, assets_dir) if emoji_collection_path else None
extra_files = process_extra_files(extra_files_path, assets_dir) if extra_files_path else None
@@ -734,19 +771,17 @@ def main():
args = parser.parse_args()
# Get script directory (not needed anymore but keep for future use)
script_dir = os.path.dirname(os.path.abspath(__file__))
# Set default paths if not provided
if not args.esp_sr_model_path:
# Default ESP-SR model path relative to project root
project_root = os.path.dirname(os.path.dirname(script_dir))
args.esp_sr_model_path = os.path.join(project_root, "managed_components", "espressif__esp-sr", "model")
if not args.xiaozhi_fonts_path:
# Default xiaozhi-fonts path relative to project root
project_root = os.path.dirname(os.path.dirname(script_dir))
args.xiaozhi_fonts_path = os.path.join(project_root, "managed_components", "78__xiaozhi-fonts")
if not args.esp_sr_model_path or not args.xiaozhi_fonts_path:
# Calculate project root from script location
script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(script_dir)
if not args.esp_sr_model_path:
args.esp_sr_model_path = os.path.join(project_root, "managed_components", "espressif__esp-sr", "model")
if not args.xiaozhi_fonts_path:
args.xiaozhi_fonts_path = os.path.join(project_root, "components", "xiaozhi-fonts")
print("Building default assets...")
print(f" sdkconfig: {args.sdkconfig}")
@@ -754,19 +789,40 @@ def main():
print(f" emoji_collection: {args.emoji_collection}")
print(f" output: {args.output}")
# Read wake word type configuration from sdkconfig
wake_word_config = read_wake_word_type_from_sdkconfig(args.sdkconfig)
# Read SR models from sdkconfig
wakenet_model_name = read_wakenet_from_sdkconfig(args.sdkconfig)
wakenet_model_names = read_wakenet_from_sdkconfig(args.sdkconfig)
multinet_model_names = read_multinet_from_sdkconfig(args.sdkconfig)
# Get model paths
wakenet_model_path = get_wakenet_model_path(wakenet_model_name, args.esp_sr_model_path)
multinet_model_paths = get_multinet_model_paths(multinet_model_names, args.esp_sr_model_path)
# Apply wake word logic to decide which models to package
wakenet_model_paths = []
multinet_model_paths = []
# Print model information
if wakenet_model_name:
print(f" wakenet model: {wakenet_model_name}")
if multinet_model_names:
print(f" multinet models: {', '.join(multinet_model_names)}")
# 1. Only package wakenet models if USE_ESP_WAKE_WORD=y or USE_AFE_WAKE_WORD=y
if wake_word_config['use_esp_wake_word'] or wake_word_config['use_afe_wake_word']:
wakenet_model_paths = get_wakenet_model_paths(wakenet_model_names, args.esp_sr_model_path)
elif wakenet_model_names:
print(f" Note: Found wakenet models {wakenet_model_names} but wake word type is not ESP/AFE, skipping")
# 2. Error check: if USE_CUSTOM_WAKE_WORD=y but no multinet models selected, report error
if wake_word_config['use_custom_wake_word'] and not multinet_model_names:
print("Error: USE_CUSTOM_WAKE_WORD is enabled but no multinet models are selected in sdkconfig")
print("Please select appropriate CONFIG_SR_MN_* options in menuconfig, or disable USE_CUSTOM_WAKE_WORD")
sys.exit(1)
# 3. Only package multinet models if USE_CUSTOM_WAKE_WORD=y
if wake_word_config['use_custom_wake_word']:
multinet_model_paths = get_multinet_model_paths(multinet_model_names, args.esp_sr_model_path)
elif multinet_model_names:
print(f" Note: Found multinet models {multinet_model_names} but USE_CUSTOM_WAKE_WORD is disabled, skipping")
# Print model information (only for models that will actually be packaged)
if wakenet_model_paths:
print(f" wakenet models: {', '.join(wakenet_model_names)} (will be packaged)")
if multinet_model_paths:
print(f" multinet models: {', '.join(multinet_model_names)} (will be packaged)")
# Get text font path if needed
text_font_path = get_text_font_path(args.builtin_text_font, args.xiaozhi_fonts_path)
@@ -781,7 +837,7 @@ def main():
custom_wake_word_config = read_custom_wake_word_from_sdkconfig(args.sdkconfig)
multinet_model_info = None
if custom_wake_word_config and multinet_model_names:
if custom_wake_word_config and multinet_model_paths:
# Determine language from multinet models
language = get_language_from_multinet_models(multinet_model_names)
@@ -803,7 +859,7 @@ def main():
print(f" wake word threshold: {custom_wake_word_config['threshold']}")
# Check if we have anything to build
if not wakenet_model_path and not multinet_model_paths and not text_font_path and not emoji_collection_path and not extra_files_path and not multinet_model_info:
if not wakenet_model_paths and not multinet_model_paths and not text_font_path and not emoji_collection_path and not extra_files_path and not multinet_model_info:
print("Warning: No assets to build (no SR models, text font, emoji collection, extra files, or custom wake word)")
# Create an empty assets.bin file
os.makedirs(os.path.dirname(args.output), exist_ok=True)
@@ -813,7 +869,7 @@ def main():
return
# Build the assets
success = build_assets_integrated(wakenet_model_path, multinet_model_paths, text_font_path, emoji_collection_path,
success = build_assets_integrated(wakenet_model_paths, multinet_model_paths, text_font_path, emoji_collection_path,
extra_files_path, args.output, multinet_model_info)
if not success: