四博 AI 音箱方案:从"能对话"到"听得远、打断快、可接客户系统"的 AIoT 语音平台
很多 AI 音箱方案看起来都能接大模型、能语音问答、能播放 TTS,但真正进入产品阶段后,问题往往不在"大模型能不能回答",而在端侧工程能不能扛住真实环境。
用户不会永远贴着设备说话,家庭环境不会一直安静,设备播放语音时用户也可能随时插话。对于客户项目来说,还要考虑 Wi-Fi、蓝牙、4G、屏幕显示、客户平台接入、OTA 升级和二次开发。
所以,一套真正可量产的 AI 音箱方案,不应该只是"语音模块 + 云端大模型",而应该是一套完整的 AIoT 语音硬件平台。
四博 AI 音箱方案可以概括为:
ESP32-S3 主控
+ 远场麦克风拾音
+ AEC 回声消除
+ NS 噪声抑制
+ AGC 自动增益
+ VAD 人声检测
+ 唤醒词识别
+ 实时打断
+ Wi-Fi / 蓝牙 / 4G 多网络
+ 单屏 / 双屏 / 异显
+ MCP 工具调用
+ 客户系统接入
+ OTA 在线升级
1. 远场拾音:AI 音箱首先要"听得清"
真正的音箱不可能只在 1 米内使用。客厅、会议室、酒店房间、办公空间里,用户距离设备 3 米、5 米甚至更远都很常见。
要实现远场拾音,不能只靠提高麦克风灵敏度,而要构建完整的音频前处理链路。
推荐链路如下:
Mic Array
↓
DC Remove
↓
AEC 回声消除
↓
NS 噪声抑制
↓
AGC 自动增益
↓
VAD 人声检测
↓
WakeWord 唤醒词识别
↓
ASR / LLM / TTS
其中:
AEC:消除设备自己播放声音带来的回声
NS:降低空调、电视、风扇、人群背景噪声
AGC:远距离说话时自动补偿音量
VAD:检测用户是否正在说话,用于实时打断
WakeWord:本地唤醒,弱网或断网时仍可响应
音频状态机可以这样设计:
typedef enum {
AUDIO_STATE_IDLE = 0,
AUDIO_STATE_WAKEUP,
AUDIO_STATE_LISTENING,
AUDIO_STATE_UPLOADING,
AUDIO_STATE_THINKING,
AUDIO_STATE_SPEAKING,
AUDIO_STATE_INTERRUPTED,
AUDIO_STATE_ERROR
} audio_state_t;
static volatile audio_state_t g_audio_state = AUDIO_STATE_IDLE;
音频帧结构:
#define AUDIO_SAMPLE_RATE 16000
#define AUDIO_FRAME_MS 20
#define AUDIO_FRAME_SAMPLES (AUDIO_SAMPLE_RATE * AUDIO_FRAME_MS / 1000)
typedef struct {
int16_t pcm[AUDIO_FRAME_SAMPLES];
size_t samples;
int vad_active;
int wake_active;
int noise_level;
int voice_energy;
} audio_frame_t;
2. 高噪声环境:设备不能只在安静房间里好用
真实环境中,AI 音箱会遇到各种噪声:
电视声
儿童说话声
空调风噪
厨房油烟机
办公室背景声
会议室多人交谈
酒店房间环境噪声
如果 VAD 阈值固定,安静环境下可能好用,高噪声环境下就容易误判。因此建议做动态底噪估计。
typedef struct {
int noise_floor;
int vad_threshold;
int agc_gain;
} audio_env_t;
static audio_env_t g_audio_env = {
.noise_floor = 300,
.vad_threshold = 800,
.agc_gain = 1,
};
static int audio_calc_energy(const int16_t *pcm, size_t samples)
{
int64_t sum = 0;
for (size_t i = 0; i < samples; i++) {
sum += abs(pcm[i]);
}
return (int)(sum / samples);
}
void audio_env_update(const int16_t *pcm, size_t samples)
{
int energy = audio_calc_energy(pcm, samples);
if (energy < g_audio_env.vad_threshold) {
g_audio_env.noise_floor =
(g_audio_env.noise_floor * 9 + energy) / 10;
}
g_audio_env.vad_threshold = g_audio_env.noise_floor + 500;
if (g_audio_env.vad_threshold < 700) {
g_audio_env.vad_threshold = 700;
}
if (g_audio_env.vad_threshold > 2200) {
g_audio_env.vad_threshold = 2200;
}
}
bool vad_detect_voice_dynamic(const int16_t *pcm, size_t samples)
{
int energy = audio_calc_energy(pcm, samples);
return energy > g_audio_env.vad_threshold;
}
这个逻辑的核心是:设备持续估计当前环境噪声,再动态调整人声检测门限。安静环境下更灵敏,高噪声环境下更稳。
3. 实时打断:AI 音箱体验的分水岭
传统语音设备最影响体验的一点是:设备正在说话时,用户必须等它说完。
但真实对话不是这样。用户可能随时补充、纠正、打断。
四博 AI 音箱方案建议同时支持两种打断:
唤醒词打断:播放时说唤醒词即可中断
实时打断:播放时检测到用户插话即可中断
打断流程:
用户插话 / 唤醒词触发
↓
本地检测到人声或唤醒词
↓
停止 TTS 播放
↓
通知云端取消当前输出
↓
重新进入监听状态
核心代码:
void ai_interrupt_current_session(void)
{
if (g_audio_state == AUDIO_STATE_SPEAKING) {
audio_player_stop();
ai_ws_send_control("{\"type\":\"interrupt\"}");
screen_show_status("已打断,请继续说");
audio_capture_start();
g_audio_state = AUDIO_STATE_INTERRUPTED;
}
}
播放过程中检测插话:
void audio_capture_task(void *arg)
{
int16_t pcm[AUDIO_FRAME_SAMPLES];
size_t bytes_read = 0;
while (1) {
audio_read_pcm(pcm, sizeof(pcm), &bytes_read);
audio_env_update(pcm, AUDIO_FRAME_SAMPLES);
if (g_audio_state == AUDIO_STATE_SPEAKING) {
if (vad_detect_voice_dynamic(pcm, AUDIO_FRAME_SAMPLES)) {
ai_interrupt_current_session();
continue;
}
}
if (g_audio_state == AUDIO_STATE_LISTENING ||
g_audio_state == AUDIO_STATE_INTERRUPTED) {
ai_ws_send_audio((uint8_t *)pcm, bytes_read);
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
唤醒词打断:
void wakeword_on_detected(const char *word)
{
ESP_LOGI("WAKE", "wakeword detected: %s", word);
if (g_audio_state == AUDIO_STATE_SPEAKING) {
ai_interrupt_current_session();
} else {
audio_capture_start();
screen_show_status("我在听");
g_audio_state = AUDIO_STATE_LISTENING;
}
ai_ws_send_control("{\"type\":\"wakeup\"}");
}
4. 唤醒词可修改:更适合品牌客户
不同品牌客户通常希望设备有自己的唤醒词,例如:
你好四博
你好小博
小 C 小 C
Hi CozyLife
你好管家
唤醒词配置结构:
typedef struct {
char wakeword[64];
int sensitivity;
int enable_barge_in;
int enabled;
} wakeword_config_t;
保存配置:
esp_err_t wakeword_save_config(const wakeword_config_t *cfg)
{
nvs_handle_t nvs;
esp_err_t ret = nvs_open("wakeword", NVS_READWRITE, &nvs);
if (ret != ESP_OK) {
return ret;
}
nvs_set_str(nvs, "word", cfg->wakeword);
nvs_set_i32(nvs, "sens", cfg->sensitivity);
nvs_set_i32(nvs, "bargein", cfg->enable_barge_in);
nvs_set_i32(nvs, "enable", cfg->enabled);
nvs_commit(nvs);
nvs_close(nvs);
return ESP_OK;
}
用户通过 App、小程序或屏幕端修改唤醒词:
void user_update_wakeword(const char *word, int sensitivity)
{
wakeword_config_t cfg = {0};
strncpy(cfg.wakeword, word, sizeof(cfg.wakeword) - 1);
cfg.sensitivity = sensitivity;
cfg.enable_barge_in = 1;
cfg.enabled = 1;
wakeword_save_config(&cfg);
wakeword_apply_to_module(&cfg);
screen_show_status("唤醒词已更新");
}
5. 多网络接入:Wi-Fi、蓝牙、4G 组合使用
AI 音箱强依赖网络,因此不能只考虑单一 Wi-Fi 场景。
推荐网络策略:
家庭 / 办公:优先 Wi-Fi
移动 / 无宽带:使用 4G
手机辅助:蓝牙配网或蓝牙代理
网络不可用:保留本地唤醒和基础控制
网络状态定义:
typedef enum {
NET_TYPE_NONE = 0,
NET_TYPE_WIFI,
NET_TYPE_BLE_PROXY,
NET_TYPE_4G
} net_type_t;
typedef enum {
NET_STATE_IDLE = 0,
NET_STATE_CONNECTING,
NET_STATE_CONNECTED,
NET_STATE_FAILED
} net_state_t;
typedef struct {
net_type_t type;
net_state_t state;
int rssi;
int online;
} net_status_t;
网络管理逻辑:
void net_manager_start(void)
{
screen_show_status("正在连接 Wi-Fi");
if (wifi_connect_saved() == ESP_OK) {
g_net_status.type = NET_TYPE_WIFI;
g_net_status.state = NET_STATE_CONNECTED;
g_net_status.online = 1;
ai_ws_client_start();
return;
}
screen_show_status("Wi-Fi失败,尝试4G");
if (modem_4g_connect() == ESP_OK) {
g_net_status.type = NET_TYPE_4G;
g_net_status.state = NET_STATE_CONNECTED;
g_net_status.online = 1;
ai_ws_client_start();
return;
}
screen_show_status("进入蓝牙代理模式");
if (ble_proxy_start() == ESP_OK) {
g_net_status.type = NET_TYPE_BLE_PROXY;
g_net_status.state = NET_STATE_CONNECTED;
g_net_status.online = 1;
return;
}
g_net_status.type = NET_TYPE_NONE;
g_net_status.state = NET_STATE_FAILED;
g_net_status.online = 0;
screen_show_status("网络不可用");
}
6. 多屏显示:单屏、双屏、异显
四博 AI 音箱不仅可以做无屏音箱,也可以做带屏终端。
三种显示方式:
单屏:显示字幕、二维码、状态、设备信息
双屏同显:适合双目表情屏
双屏异显:左屏显示表情,右屏显示状态、文字和控制信息
显示模式:
typedef enum {
DISPLAY_MODE_SINGLE = 0,
DISPLAY_MODE_DUAL_SAME,
DISPLAY_MODE_DUAL_DIFF
} display_mode_t;
typedef struct {
void *panel_left;
void *panel_right;
display_mode_t mode;
int width;
int height;
} dual_screen_t;
双屏异显:
void screen_show_dual_diff(const char *emotion, const char *status)
{
lcd_fill(g_screen.panel_left, 0x0000);
lcd_fill(g_screen.panel_right, 0x0000);
if (strcmp(emotion, "listening") == 0) {
lcd_draw_eye_listening(g_screen.panel_left);
} else if (strcmp(emotion, "thinking") == 0) {
lcd_draw_eye_thinking(g_screen.panel_left);
} else if (strcmp(emotion, "speaking") == 0) {
lcd_draw_eye_speaking(g_screen.panel_left);
} else {
lcd_draw_eye_normal(g_screen.panel_left);
}
lcd_draw_text(g_screen.panel_right, 10, 30, status, 0xFFFF);
}
7. 客户系统接入:HTTP、MQTT、UART 都可以
四博 AI 音箱方案适合接入客户自己的系统。
常见方式:
HTTP API:对接客户云平台
MQTT:对接 IoT 平台
UART / RS485:对接本地 MCU 或酒店客控系统
MCP 工具定义:
typedef enum {
MCP_TOOL_DEVICE_CONTROL = 0,
MCP_TOOL_SCENE_RUN,
MCP_TOOL_SCREEN_SET,
MCP_TOOL_WAKEWORD_UPDATE,
MCP_TOOL_AUDIO_SET_VOLUME,
MCP_TOOL_NET_SWITCH,
MCP_TOOL_UNKNOWN
} mcp_tool_id_t;
客户设备控制接口:
typedef struct {
char device_id[32];
char action[32];
int value;
} control_cmd_t;
esp_err_t customer_control_device(control_cmd_t *cmd)
{
char json[256];
snprintf(json, sizeof(json),
"{"
"\"device_id\":\"%s\","
"\"action\":\"%s\","
"\"value\":%d"
"}",
cmd->device_id,
cmd->action,
cmd->value);
return http_post_json("https://api.customer.com/device/control", json);
}
8. 方案总结
四博 AI 音箱方案的核心价值不是"能接大模型",而是把端侧产品化能力补齐。
听得远
抗得住噪
打断得快
唤醒词可改
联网方式多
屏幕显示灵活
客户系统接入方便
基于 ESP32-S3 便于二次开发
OTA 后续可持续升级
一句话总结:
四博 AI 音箱不是简单的语音播放器,
而是基于 ESP32-S3 打造的远场拾音、多网络接入、多屏显示、
实时打断、自定义唤醒词、可接入客户系统的 AI 智能硬件平台。