人工智能系列① esp-adf 本地唤醒&百度语音识别,轻松迈入人工智能。Hi,乐鑫!

一 前言

1.1 什么是本地唤醒和百度语音识别

本地唤醒是基于乐鑫的语音框架实现的离线语音唤醒功能呢,那么这个框架就是ESP-Skainet 是乐鑫开发的智能语音助手,可支持唤醒词引(WakeNet),离线语音命令识别引擎(MultiNet)和前端声学算法。那么问题来了为什么不用这个框架的离线语音命令呢?原因是在我测试来看这个离线的语音准确率相较于在线语音识别没有那么好,感兴趣的你们可以去尝试一下,另外一个原因就是比较耗费flash的资源。

百度语音识别就是百度智能云的在线短语音识别,百度短语音识别可以将60秒以下的音频识别为文字。适用于语音对话、语音控制、语音输入等场景。
接口类型: 通过 REST API 的方式提供的通用的 HTTP 接口。适用于任意操作系统,任意编程语言
**接口限制:**需要上传完整的录音文件,录音文件时长不超过60秒。浏览器由于无法跨域请求百度语音服务器的域名,因此无法直接调用API接口。
支持音频格式: pcm、wav、amr、m4a
音频编码要求: 采样率 16000、8000,16bit 位深,单声道
那么本次博文用的在线语音识别就是使用http post的方式将语音文件上传至百度智能云语音别的接口,然后的到处理结果

二 创建百度智能云语音技术应用

2.1 首先登录百度智能云控制台

2.2 选择语音技术

语音技术

2.3 填写相关信息

信息

2.4 得到API Key和Secret Key

key
这里的APIkey和Secret key就是使用百度语音识别的密钥了,后面会用到,至此百度智能云的语音技术就创建完成了。

三 ESP-ADF的框架搭建

我的思路是这样的,使用乐鑫的离线语音唤醒框架,唤醒后呢会播放MP3提示音:叮咚,然后录音,再把录音内容通过http上传至百度智能云,然后前端回传识别结果,完成语音识别。
这里使用的开发板呢,是安信可的ESP32-Audio-Kit(A1s),当然在乐鑫其他的板子上也能使用。

3.1 将mp3放在内部Flash播放

在main文件夹下的component.mk文件下添加依赖

COMPONENT_EMBED_TXTFILES := dingdong.mp3

在main文件夹下的CMakeLists.txt文件下添加依赖

set(COMPONENT_EMBED_TXTFILES dingdong.mp3)

然后把MP3文件放入main文件夹下,这样就能把MP3嵌入在内部flash下,具体的实现代码看文末的源代码,这里就不做具体阐述了。

3.2 本地唤醒&百度语音识别

这里希望大家先去了解一下百度语音识别的技术文档REST文档,了解一下是怎样上传的

3.21首先得获取百度语音识别的token

int get_access_token(void)
{
    if (baidu_access_token == NULL) {
        // Must freed `baidu_access_token` after used
        baidu_access_token = baidu_get_access_token(CONFIG_BAIDU_ACCESS_KEY, CONFIG_BAIDU_SECRET_KEY);
    }
    if (baidu_access_token == NULL) {
        ESP_LOGE(TAG, "Error issuing access token");
        return ESP_FAIL;
    }
    snprintf(baidu_asr_url, 256, "%s%s", baidu_asr, baidu_access_token);
    return ESP_OK;
}

这里使用了一个库函数,include进来就行

#include "baidu_access_token.h"

这样就获取了token

3.22 处理唤醒识别之间的关系

ESP_LOGI(TAG, "Initialize SR wn handle");
esp_wn_iface_t *wakenet;
model_coeff_getter_t *model_coeff_getter;
model_iface_data_t *model_wn_data;
get_wakenet_iface(&wakenet);
get_wakenet_coeff(&model_coeff_getter);
model_wn_data = wakenet->create(model_coeff_getter, DET_MODE_90);
int wn_num = wakenet->get_word_num(model_wn_data);
for (int i = 1; i <= wn_num; i++) {
    char *name = wakenet->get_word_name(model_wn_data, i);
    ESP_LOGI(TAG, "keywords: %s (index = %d)", name, i);
}
float wn_threshold = wakenet->get_det_threshold(model_wn_data, 1);
int wn_sample_rate = wakenet->get_samp_rate(model_wn_data);
int audio_wn_chunksize = wakenet->get_samp_chunksize(model_wn_data);
ESP_LOGI(TAG, "keywords_num = %d, threshold = %f, sample_rate = %d, chunksize = %d, sizeof_uint16 = %d", wn_num, wn_threshold, wn_sample_rate, audio_wn_chunksize, sizeof(int16_t));
int size = audio_wn_chunksize;
int16_t *buffer = (int16_t *)malloc(size * sizeof(short));
bool enable_wn = true;     
while (1) {
    if (enable_wn) {
        raw_stream_read(raw_read, (char *)buffer, size * sizeof(short));
        if (wakenet->detect(model_wn_data, (int16_t *)buffer) ==  WAKE_UP) {
            start_play_mp3();
            ESP_LOGI(TAG, "wake up");
            enable_wn = false;
        }
    } else {
        if (baidu_asr_url[0] != '\0') {     //得到token
            char *buff = (char *)heap_caps_malloc(96 * 1024, MALLOC_CAP_SPIRAM);
            if (NULL == buff) {
                ESP_LOGE(TAG, "Memory allocation failed!");
                return;
            }
            memset(buff, 0, 96 * 1024);

            for(size_t i = 0; i < 12; i++) {
                raw_stream_read(raw_read, (char *)buff + i * 8 * 1024, 8 * 1024);
            }
            esp_http_client_config_t config = {
                .url = baidu_asr_url,
                .method = HTTP_METHOD_POST,
            };       
            esp_http_client_handle_t client = esp_http_client_init(&config);
            esp_http_client_set_header(client, "Content-Type", "audio/pcm;rate=16000");  
            esp_http_client_set_post_field(client, (const char *)buff, 96 * 1024);
            esp_err_t err = esp_http_client_perform(client);
            if (err == ESP_OK) {
                ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %d",
                        esp_http_client_get_status_code(client),
                        esp_http_client_get_content_length(client));
                int max_len = 1 * 1024;
                char *data = (char *)heap_caps_malloc(max_len, MALLOC_CAP_SPIRAM);
                int read_index = 0, total_len = 0;
                int read_len = 0;
                //得到返回的数据
                while (1) {
                    read_len = esp_http_client_read(client, data + read_index, max_len - read_index);
                    if (read_len <= 0) {
                        break;
                    }
                    read_index += read_len;
                    total_len += read_len;
                    data[read_index] = 0;
                }
                ESP_LOGI(TAG, "%d%s", read_len, data);
                free(data);
                data = NULL;
            } 
            else {
                ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));
            }
            esp_http_client_cleanup(client);

            free(buff);
            enable_wn = true;
            buff = NULL;    
        }
    }
}

这么长一串代码内,原理其实很简单,首先初始化本地唤醒词,这里定义了一个flag来实现,唤醒后播放叮咚mp3文件,播放完后录音,录音后使用http上传,然后得到结果,这里重点说一下上传部分。

我这里使用的是外都RAM,这点需要特别注意,使用heap_caps_malloc()函数来分配内存,上传格式是16KHz 16bit 单声道,那么录音1秒钟所需要的内存是16000 Hz × 16 bit × 1 × 1 s = 256000bit,就是32Kbyte,那么我们录3秒就是需要96K内存,然后raw的录音缓存时8k,那么我们需要循环读取12次,然后根据格式通过HTTP上传。最终得到我们想要的结果。

四 menuconfig菜单面板的配置

4.1 基础配置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里分别填入WIFI的名称、密码,前面创建的API Key和Secret Key

4.2 配置外部SPI RAM

Component config ->ESP32-specific->SPI RAM config->
在这里插入图片描述
这里要注意把spi ram的速度调为80Mhz,否则可能会出问题

五 其他配置

打开esp_http_client.h文件

#include "esp_http_client.h"

将缓存buffer改为1024,否则接收回传数据会错误

#define DEFAULT_HTTP_BUF_SIZE (1024)

六 运行结果

首先我们打开monitor,说Hi,乐鑫,然后听到叮咚音乐后,随便说一句,就能得到想要的结果。在这里插入图片描述
那么到这一步恭喜你们迈入人工智能的大门,人工智能或许没那么复杂。

本博文源码:FEIYUE_ESP32 欢迎star!欢迎star!欢迎star!

  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
引用: 在Ubuntu 20.04.4 LTS操作系统中,我已经安装了ESP-idf开发环境并使用了一段时间。现在我想安装esp-adf音频开发框架,但遇到了问题。可以在https://***/index.html找到相关文档。 引用: LinkGUI™ Air E32是一个开发平台,基于ESP32 WROVER芯片组,可以实现完美的图形交互体验。它将GUI系统嵌入到乐鑫开源的ESP-ADF/ESP-IDF开发环境中,提供了丰富的UI交互功能。LinkGUI™ Air E32平台由ESP32 WROVER芯片、LCD、按键、T卡插槽、喇叭插槽、麦克风和扩展接口组成。它的SDK以基于ESP-ADF的LinkGUI图形系统为核心,与ESP-ADF开发环境无缝连接,实现了WIFI/BT/音频和高级图形交互的功能。 根据您的问题,您想了解在Ubuntu操作系统上使用esp-adf和lvgl。首先,esp-adf是一个音频开发框架,用于在ESP32芯片上开发音频应用程序。它提供了丰富的音频功能和示例,可以实现音频播放、录制、语音识别等功能。 而lvgl是一个开源的图形库,用于创建嵌入式设备上的用户界面。它提供了丰富的图形元素和交互功能,可以实现按钮、滑块、进度条、列表等常见的UI元素。 在Ubuntu操作系统上,您可以按照ESP-ADF文档中提供的步骤安装和配置esp-adf开发环境。然后,您可以使用lvgl库开发具有图形界面的应用程序。您可以参考lvgl的官方文档和示例来学习如何使用lvgl库进行UI设计和交互。 总结起来,esp-adf是一个音频开发框架,lvgl是一个图形库。您可以在Ubuntu操作系统上使用esp-adf开发音频应用程序,并结合lvgl库创建图形界面。希望这能帮助到您。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Ubuntn环境下安装ESP 音频框架时出现Failed to resolve component ‘jsmn‘.问题(已解决)](https://blog.csdn.net/qq_41601311/article/details/124293303)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [基于ESP-ADF的图形系统](https://blog.csdn.net/skdev/article/details/120765588)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值