请问有没有人做过用ESP32调用百度语音合成的API或者讯飞语音合成的API来进行播报,用arduino编写的
2条回答 默认 最新
- 张小兔爱钱钱 2023-05-31 20:08关注
该回答引用ChatGPT-3.5
#include <stdio.h> #include <string.h> #include "esp_event.h" #include "esp_log.h" #include "esp_http_client.h" #include "esp_audio.h" #include "audio_board.h" #include "audio_pipeline.h" #include "audio_element.h" #include "i2s_stream.h" #include "http_stream.h" #include "raw_stream.h" // 百度语音合成API接口地址 #define BAIDU_API_URL "https://tsn.baidu.com/text2audio" // 百度语音合成API接口参数 #define BAIDU_API_KEY "your_api_key" #define BAIDU_SECRET_KEY "your_secret_key" #define BAIDU_PER "0" // 发音人选择,0为女声,1为男声 #define BAIDU_SPD "5" // 语速,取值0-15,默认为5中语速 #define BAIDU_PIT "5" // 音调,取值0-15,默认为5中语调 #define BAIDU_VOL "7" // 音量,取值0-9,默认为第5中音量 static const char *TAG = "baidu_tts"; // HTTP请求头部 static esp_err_t http_event_handle(esp_http_client_event_t *evt) { switch (evt->event_id) { case HTTP_EVENT_ERROR: ESP_LOGE(TAG, "HTTP_EVENT_ERROR"); break; case HTTP_EVENT_ON_CONNECTED: ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED"); break; case HTTP_EVENT_HEADER_SENT: ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT"); break; case HTTP_EVENT_ON_HEADER: ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); break; case HTTP_EVENT_ON_DATA: ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); break; case HTTP_EVENT_ON_FINISH: ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH"); break; case HTTP_EVENT_DISCONNECTED: ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED"); break; } return ESP_OK; } // 百度语音合成API请求参数 static void get_params(char *params, int max_len, const char *text) { snprintf(params, max_len, "tex=%s&cuid=esp32&lan=zh&per=%s&spd=%s&pit=%s&vol=%s&tok=24.02b8fbff6d0c56b289f1b07a70939e2c.2592000.1626938935.282335-24234292", text, BAIDU_PER, BAIDU_SPD, BAIDU_PIT, BAIDU_VOL); } // 请求百度语音合成API,返回语音文件数据 static esp_err_t request_tts_data(const char *text, uint8_t **data, uint32_t *size) { char url[256]; char params[512]; get_params(params, sizeof(params), text); esp_http_client_config_t http_cfg = { .url = BAIDU_API_URL, .event_handler = http_event_handle, }; esp_http_client_handle_t client = esp_http_client_init(&http_cfg); esp_http_client_set_method(client, HTTP_METHOD_POST); esp_http_client_set_header(client, "Content-Type", "application/x-www-form-urlencoded"); esp_http_client_set_post_field(client, params, strlen(params)); esp_err_t err = esp_http_client_perform(client); if (err != ESP_OK) goto end; *size = esp_http_client_fetch_headers(client); *data = (uint8_t*)malloc(*size); esp_http_client_read_response(client, (char*)*data, *size); end: esp_http_client_cleanup(client); return err; } // 播放语音文件 static void play_tts_data(uint8_t *data, uint32_t size) { audio_pipeline_handle_t pipeline; audio_element_handle_t i2s_stream_writer, http_stream_reader, raw_read_el; i2s_stream_cfg_t i2s_cfg = { .type = AUDIO_STREAM_WRITER, .i2s_config = { .mode = I2S_MODE_MASTER | I2S_MODE_TX, .sample_rate = 16000, .bits_per_sample = 16, .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, }, .dma_buf_count = 5, .dma_buf_len = 300, }; i2s_stream_writer = i2s_stream_init(&i2s_cfg); http_stream_cfg_t http_cfg = { .type = AUDIO_STREAM_READER, .event_handle = http_event_handle, .task_stack = 4 * 1024, .task_prio = 2, .out_rb_size = 8192, .buffer_size = 1024, }; http_stream_reader = http_stream_init(&http_cfg); http_stream_set_url(http_stream_reader, ""); raw_stream_cfg_t raw_cfg = { .type = AUDIO_STREAM_WRITER, }; raw_read_el = raw_stream_init(&raw_cfg); pipeline = audio_pipeline_init(); audio_pipeline_register(pipeline, http_stream_reader, "http"); audio_pipeline_register(pipeline, raw_read_el, "raw"); audio_pipeline_register(pipeline, i2s_stream_writer, "i2s"); audio_pipeline_link(pipeline, (const char *[]) {"http", "raw", "i2s"}, 3); audio_element_set_uri(http_stream_reader, ""); audio_element_run(pipeline); int offset = 0; while (offset < size) { int wlen = i2s_stream_writer_write(i2s_stream_writer, data + offset, size - offset, 100 / portTICK_RATE_MS); if (wlen > 0) offset += wlen; else break; } audio_element_stop(pipeline); audio_element_wait_for_stop(pipeline); audio_pipeline_terminate(pipeline); audio_pipeline_unregister(pipeline, http_stream_reader); audio_pipeline_unregister(pipeline, raw_read_el); audio_pipeline_unregister(pipeline, i2s_stream_writer); audio_pipeline_remove_listener(pipeline); audio_pipeline_deinit(pipeline); mem_free(data); } // 主函数 void app_main() { ESP_LOGI(TAG, "Start"); esp_err_t err; uint8_t *data; uint32_t size; // 请求语音文件数据 err = request_tts_data("百度语音合成API测试", &data, &size); if (err != ESP_OK) { ESP_LOGE(TAG, "Request TTS data failed"); return; } // 播放语音文件 err = audio_board_init(); if (err != ESP_OK) { ESP_LOGE(TAG, "Initialize audio board failed"); free(data); return; } err = esp_audio_hal_ctrl_codec_mode(ESP_AUDIO_CODEC_MODE_ENCODE); if (err != ESP_OK) { ESP_LOGE(TAG, "Set audio codec mode failed"); free(data); return; } play_tts_data(data, size); }
以上代码需要设置好BAIDU_API_KEY和BAIDU_SECRET_KEY,即百度开发者平台所给的API Key和Secret Key。
请注意,此示例仅供参考,实际使用中还需处理网络连接超时等可能出现的异常情况。同时,本示例仅支持16KHz采样率、16位采样精度、单声道格式的语音播放,如需修改,请适当调整代码。
解决 1无用
悬赏问题
- ¥20 WPF MVVM模式 handycontrol 框架, hc:SearchBar 控件 Text="{Binding NavMenusKeyWords}" 绑定取不到值
- ¥15 需要手写数字信号处理Dsp三个简单题 不用太复杂
- ¥15 数字信号处理考试111
- ¥15 allegro17.2生成bom表是空白的
- ¥15 请问一下怎么打通CAN通讯
- ¥20 如何在 rocky9.4 部署 CDH6.3.2?
- ¥35 navicat将excel中的数据导入mysql出错
- ¥15 rt-thread线程切换的问题
- ¥15 高通uboot 打印ubi init err 22
- ¥15 R语言中lasso回归报错