四博 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 智能硬件平台。