曦&渊 2023-05-31 18:45 采纳率: 0%
浏览 28

调用百度语音合成的API来进行播报

请问有没有人做过用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位采样精度、单声道格式的语音播放,如需修改,请适当调整代码。

    评论

报告相同问题?

问题事件

  • 修改了问题 6月1日
  • 修改了问题 6月1日
  • 修改了问题 5月31日
  • 创建了问题 5月31日

悬赏问题

  • ¥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回归报错