ESP32S3接入百度在线语音合成
Author: kkl
一、概述
使用ESP32S3接入百度在线语音合成,其实是为我后面的某个小项目做铺垫啦!这里记录一下实现的过程。
环境
- 主控:ESP32S3N16R8
- 平台:Arduino + PlatformIO + VScode
二、步骤
大部分内容都和语音识别那趴差不多,百度的语音识别和语音合成是共用同一个应用的,如果创建过了就直接使用相同的就行,密钥和token都是共用的,我就直接搬过来了,只有在POST的时候稍微有些区别,我也贴出了具体的代码和示例。
- 在百度智能云控制端选择
语音技术
并创建应用获取API Key
和Secret Key
- 根据创建应用生成的
API Key
和Secret Key
来获取access_token
- 在ESP32S3中发送POST请求API
三、实现
1. 创建语音合成应用
登录百度智能云的云账号,选择语音识别,创建一个新应用。(注意:分清楚百度账号还是云账号,这两个不一样的)
百度智能云:https://login.bce.baidu.com/?redirect=https%3A%2F%2Fconsole.bce.baidu.com%2Fai%2F#/ai/speech/app/list



2. 根据创建应用生成的API Key和Secret Key来获取access_token
创建好应用,在应用列表里会出现你刚刚创建的应用,当然API Key
和Secret Key
也有啦

有了API Key
和Secret Key
,下面我们可以在ESP32S3上进行GET请求得到access_token的代码!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void gainToken(void) { HTTPClient http_client; http_client.begin("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=your_apikey&client_secret=your_secretkey"); int httpResponseCode = http_client.GET();
if(httpResponseCode == HTTP_CODE_OK) { String response = http_client.getString(); Serial.println(response); } else { Serial.printf("[HTTP] GET... failed, error: %s\n", http_client.errorToString(httpResponseCode).c_str()); } http_client.end(); }
|
请求成功会返回如下数据,我们主要关注access_token
:
1 2 3 4 5 6 7 8
| { "refresh_token": "25.b55fe1d287227ca97aab219bb249b8ab.315360000.1798284651.282335-8574074", "expires_in": 2592000, "scope": "public wise_adapt", "session_key": "9mzdDZXu3dENdFZQurfg0Vz8slgSgvvOAUebNFzyzcpQ5EnbxbF+hfG9DQkpUVQdh4p6HbQcAiz5RmuBAja1JJGgIdJI", "access_token": "24.6c5e1ff107f0e8bcef8c46d3424a0e78.2592000.1485516651.282335-8574074", "session_secret": "dfac94a3489fe9fca7c3221cbf7525ff" }
|
access_token
对应的值就是可用的token,每次申请的token
有效期限为30天,过期就需要重新申请。所以咱定时更新access_token
就行,不用每次调用语音识别或合成都申请一遍。
3. 发送文本数据,通过POST请求发送到语音合成API上
下面是数据上传的格式说明:

下面是ESP32S3的具体实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| char payload[8000] = {0};
void speechSynthesis(String inputText) { HTTPClient http_client;
_LOG("[Synthesis] Start Synthesis!\r\n");
memset(payload, '\0', strlen(payload));
strcat(payload, "tex="); strcat(payload, inputText.c_str()); strcat(payload, "&lan=zh"); strcat(payload, "&cuid=hugokkl"); strcat(payload, "&ctp=1"); strcat(payload, "&spd=7"); strcat(payload, "&pit=5"); strcat(payload, "&vol=15"); strcat(payload, "&per=5118"); strcat(payload, "&aue=5"); strcat(payload, "&tok=24.fc3481a177dfe90487fa0c3ce0892530.2592000.1713939400.282335-57684431");
http_client.begin("http://tsn.baidu.com/text2audio");
http_client.setTimeout(5000); int httpResponseCode = http_client.POST(payload);
if (httpResponseCode == HTTP_CODE_OK) { WiFiClient response; uint32_t streamLength = http_client.getSize(); _LOG("streamSize:%d\r\n", streamLength);
response = http_client.getStream();
while (!response.available()) { }
streamLength = min(streamLength, _samples * 2);
response.readBytes((char *)_rawData, streamLength);
Speaker.playRaw((int16_t *)_rawData, streamLength / 2, 8000);
_LOG("[Synthesis] All done!\r\n"); } else { _LOG("[HTTP] GET... failed, error: %s\n", http_client.errorToString(httpResponseCode).c_str()); } http_client.end();
_LOG("[Synthesis] Synthesis complete!\r\n"); }
|
四、总结
- access_token默认有效期30天,单位是秒,生产环境注意及时刷新。刷新了旧的也能用(只要不超时)
鸣谢
这次没看教程(主要是搞语音合成的教程比较少)。所以!感谢我自己辛勤的劳作😋