- esp32 --》 pc录音传输
esp32 ---》 websocket ---》 电脑服务器 ---》 保存wav
目标:
你说一句:
"你好"
电脑生成:
test.wav
能正常播放。
这个阶段练:
WiFi
TCP/WebSocket
PCM格式
wav封装
你之前已经学了 socket,这一步正好串起来。
ASR : automatic speech recognition : 自动语音识别 ===》 语音转文字
可以使用:
Whisper
FunASR
百度语音
科大讯飞
ESP32 不适合跑大型 ASR。
ESP32负责:
采集 + 上传
电脑/服务器负责:
AI计算
- 核心作用
把麦克风采集到的 PCM 人声音频,通过算法 / 云端模型翻译成可读文字。
你的硬件链路完整流程:
INMP441 拾音 → I2S 读取 PCM 音频 → ASR 模型处理 → 输出汉字 / 文本 - 两种主流使用方式(ESP32 设备)
① 云端 ASR(最常用)
设备只负责采集 PCM 音频,通过 WiFi 把音频上传到服务器,云端大模型做识别,再把文字下发给 ESP32。
例:百度语音、阿里云 ASR、腾讯云语音识别。
优点:识别准确率极高,支持方言、长句子;
缺点:必须联网,依赖网络。
② 本地离线 ASR(嵌入式专用)
模型轻量化后直接烧录进 ESP32S3 芯片,不用 WiFi,本地实时识别。
例:ESP-SR(乐鑫官方离线语音识别库),可识别自定义唤醒词、简单指令(开灯、关灯、播放音乐)。
优点:断网可用、响应快、无流量;
缺点:词汇量有限,只能识别预设短句,复杂长句识别差。

第3步:接入大模型
流程:
语音
|
ASR
|
"今天北京天气怎么样"
|
LLM
|
"北京今天晴天..."
这里可以接:
GPT
DeepSeek
Claude
通义
小智类似方案也是 ESP32 作为终端,通过网络连接 LLM
第4步:TTS语音合成
LLM返回:
北京今天晴,温度25度
变成:
audio.wav
例如:
Edge TTS
Azure TTS
百度TTS
然后:
服务器
↓
ESP32
↓
MAX98357A
↓
声音
第5步:做成实时对话
最终:
WiFi
|
±---------------+
| ESP32-S3 |
| |
| INMP441 |
| MAX98357A |
| |
±---------------+
|
|
WebSocket
|
|
±---------------+
| Python Server |
| |
| ASR |
| LLM |
| TTS |
±---------------+
你现在最适合的项目路线
根据你目前水平(已经会 ESP-IDF、FreeRTOS、I2S、WiFi、TCP),我建议:
第一阶段(3天)
完成:
ESP32录音
↓
WiFi发送
↓
PC保存wav
先 TCP/WebSocket 传 PCM
接 Whisper/FunASR 做 ASR
接大模型
TTS返回音频
最后加 MQTT 控制设备

c
#include "wifi_manager.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_wifi.h"
#include "esp_wifi_default.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "lwip/ip4_addr.h"
#define MAX_CONNECT_RETRY 10
static int sta_connect_cnt = 0;// 重连的次数
#define TAG "wifi_manager"
// 当前sta连接状态
static bool is_sta_connected = false;
static p_wifi_state_cb wifi_callback = NULL;
/***
*wifi连接 或 工作的 时候,,有很多事件,,通过回调函数通知
*STA参数
*
**/
/**
*@param1 : 用户自定义的参数
*@param2 : 事件类型 wifi 还是 ip
*@param3 :
*@param4 : 事件数据
*
*/
static void event_handler(void* event_handler_arg,
esp_event_base_t event_base,
int32_t event_id,
void* event_data) {
if (event_base == WIFI_EVENT) {
switch (event_id) {
case WIFI_EVENT_STA_START:
// sta启动了,,触发这个事件
// 启动wifi连接
printf("wifi start...");
esp_wifi_connect();
break;
case WIFI_EVENT_STA_DISCONNECTED:
wifi_event_sta_disconnected_t *reason = event_data;
ESP_LOGI(TAG,"disconnected reason %d",reason->reason);
if (is_sta_connected) {
is_sta_connected = false;
// 连接成功,,, 连接中失败
if (wifi_callback) {
wifi_callback(WIFI_STATE_DISCONNECTED);
}
}
if (sta_connect_cnt < MAX_CONNECT_RETRY) {
esp_wifi_connect();
sta_connect_cnt++;
printf("retry count is %d\n",sta_connect_cnt);
}
break;
case WIFI_EVENT_STA_CONNECTED:
// 连接成功
ESP_LOGI(TAG,"connected to ap");
break;
default:
break;
}
}else if (event_base == IP_EVENT) {
if (event_id == IP_EVENT_STA_GOT_IP) {
// 获取到ip
ESP_LOGI(TAG,"got ip:%s",ip4addr_ntoa(event_data));
is_sta_connected = true;
if (wifi_callback) {
wifi_callback(WIFI_STATE_CONNECTED);
}
}
}
}
void wifi_manager_init(p_wifi_state_cb cb) {
// tcp/ip协议的初始化
ESP_ERROR_CHECK(esp_netif_init());
// 创建时间循环
ESP_ERROR_CHECK(esp_event_loop_create_default());
// 创建sta对象 : 如果要使用sta功能,就要创建一个sta对象,,底层会把这个sta对象绑定到wifi的接口,将相关的wifi STA事件注册到默认的事件循环中
esp_netif_create_default_wifi_sta();
// 初始化整个wifi
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config));
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_ip;
// 事件回调
esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,event_handler,NULL,&instance_any_id);
esp_event_handler_instance_register(IP_EVENT,IP_EVENT_STA_GOT_IP,event_handler,NULL,&instance_ip);
// callback保存
wifi_callback = cb;
// //
// // 设置wifi的工作模式
// esp_wifi_set_mode(WIFI_MODE_STA);
//
//
// // 设置wifi配置
// esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
}
void wifi_manager_connect(const char* ssid, const char* password) {
wifi_config_t wifi_config = {
.sta = {
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
// .ssid =ssid
}
};
/**
*sprintf : 无长度限制,ssid超长会越界写烂内存
*snprintf : 有长度保护
*
*@param1 : 存放结果的缓冲区
*@param2 : 缓冲区最大可写入字节数,,, 预留1字节的结束符'\0'
*@param3 : 格式化字符串
*@param4 : 可变参数
**/
snprintf((char*)wifi_config.sta.ssid,31,"%s",ssid);
snprintf((char*)wifi_config.sta.password,63,"%s",password);
// 重连清零
sta_connect_cnt=0;
// 判断当前wifi模式是不是STA
wifi_mode_t mode;
esp_wifi_get_mode(&mode);
if (mode != WIFI_MODE_STA) {
// 停止wifi工作
esp_wifi_stop();
// 设置wifi的工作模式
esp_wifi_set_mode(WIFI_MODE_STA);
}
// 设置wifi配置
esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
// 启动wifi
esp_wifi_start();
}
c
#ifndef __WIFI_MANAGER_H__
#define __WIFI_MANAGER_H__
typedef enum {
WIFI_STATE_CONNECTED,
WIFI_STATE_DISCONNECTED,
}WIFI_STATE;
// 指针 p_wifi_state_cb 指向一个函数,,, void:没有返回值 ():没有入参
typedef void(*p_wifi_state_cb)(WIFI_STATE);
void wifi_manager_init(p_wifi_state_cb f);
// 发起连接
void wifi_manager_connect(const char* ssid, const char* password);
#endif
c
#include <stdio.h>
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_wifi.h"
#include "esp_wifi_default.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "wifi_manager.h"
#define TAG "main"
#define default_wifi_ssid "csl"
#define default_wifi_password "12348888"
/**
* 配网方式
*
*
*/
void wifi_state_handler(WIFI_STATE state) {
if (state == WIFI_STATE_CONNECTED) {
ESP_LOGI(TAG, "WIFI CONNECTED");
}
if (state == WIFI_STATE_DISCONNECTED) {
ESP_LOGI(TAG, "WIFI DISCONNECTED");
}
}
void app_main(void)
{
// wifi信息会默认保存在nvs
nvs_flash_init();
wifi_manager_init(wifi_state_handler);
wifi_manager_connect("csl","12348888");
while (1) {
vTaskDelay(pdMS_TO_TICKS(50));
}
}
shell
idf.py menuconfig
Component config
└── HTTP Server
└── Enable WebSocket server support