基于RTL8722DMMINI实现云语音识别开发

原创 面包板社区 2022-02-28 17:58

前言


Ameba RTL8722DM MINI 板载功能非常丰富,支持 Wifi,蓝牙,Codec,麦克风耳机孔,Micro SD卡接口等……并且还有丰富的外围接口可以连接各种传感器。因此我们能够通过这块套件实现绝大部分物联网场景下的应用,如云语音识别。


Realtek 官网上提供了 RTL8722DM MINI 详细资料,并给出了针对其不同功能的各种 ARDUINO 示例程序,数量多达七十多个,而且各种库写的非常简洁、源码注释清晰,因此开发起来非常舒适。


简单浏览,找到几个与本测评项目相关的库:

  • HttpClient:支持http协议一些比较基本的操作。

  • FatFs_SD:读写 Fat 文件格式的 SD 卡。

  • RecordWav:能直接录制 wav 格式音频到 SD 卡上,也可以播放。


因此,云语音识别的实现流程为:

  • 按键检测,利用 RecordWav 录制音频到 SD 卡。

  • 利用 FatFs_SD 读取刚录制的音频。

  • 利用 HttpClient 将音频 POST 到服务器,服务器调用语音识别 api 后将识别结果返回给 Ameba。最后返回流程1。


开发流程

Ameba

HttpClient

HttpClient 支持 HTTP 的各种请求,不过功能还不够完善。目前该库还不支持持久连接,如 post() 源码的主要调用流程为:

  • startRequest():



    • sendInitialHeaders():发送请求头信息,包括“Connection: close”


    • finishHeaders():发送空行结束 header


  1. /* HttpClient.cpp */

  2. // We don't support persistent connections, so tell the server to

  3. // close this connection after we're done

  4. sendHeader(HTTP_HEADER_CONNECTION, "close");

这样 POST 在发送请求头信息后就会结束连接,因此我们需要作一定的拓展。


POST 二进制流类型的文件对 POST 请求头和请求体的格式具有一定要求,我们只需要按照要求的格式和流程发送数据即可。由于我们一次流程只发送一个语音文件,并且其体积较大,因此请求体中只有头部及尾部的两个 boundary,以及中间的音频内容。因此我们可以提前设置好两个 boundary,以及 Content_Type, Content-Length 等内容以制作请求头,并在请求体中分三个部分发送即可:

  1. /* speech_recognizer.ino */

  2. char Content_Type[] = "multipart/form-data; boundary=----WebKitFormBoundarypNjgoVtFRlzPquKE";

  3. // 请求体头部及尾部数据

  4. char post_start[] = "------WebKitFormBoundarypNjgoVtFRlzPquKE\r\nContent-Disposition: form-data; name="file"; filename="ameba_recording"\r\nContent-Type: application/octet-stream\r\n\r\n";

  5. char post_end[] = "\r\n------WebKitFormBoundarypNjgoVtFRlzPquKE--\r\n";

  6. const int post_start_len = strlen(post_start);

  7. const int post_end_len = strlen(post_end);

在 setup() 中将它们写入我们在 HttpClient 中添加的成员变量中。在本项目中需要一边读取 sd 卡一边发送,因此不提前设置 post_content。

  1. /* speech_recognizer.ino */

  2. void setup()

  3. {

  4.     uint8_t *post_content = NULL;

  5.     http.mysetPostData(post_start, post_end, post_content, post_start_len, post_end_len, 0, Content_Type);

  6. }


  7. /* HttpClient.cpp */

  8. int HttpClient::mysetPostData(char *post_start_d, char *post_end_d, uint8_t *post_content_d, int post_start_len_d,

  9.                               int post_end_len_d, int post_content_len_d, char *content_type_d)

  10. {

  11.     post_start = post_start_d;

  12.     post_end = post_end_d;

  13.     post_content = post_content_d;

  14.     post_start_len = post_start_len_d;

  15.     post_end_len = post_end_len_d;

  16.     post_content_len = post_content_len_d;

  17.     post_len = post_start_len_d + post_content_len_d + post_end_len_d;

  18.     content_type = content_type_d;

  19. }

每次录音成功后再读取文件,更新内容大小相关变量:

  1. /* HttpClient.cpp */

  2. int HttpClient::mysetPostContent(uint8_t *post_content_d, int post_content_len_d, int post_len_d)

  3. {

  4.     post_content = post_content_d;

  5.     post_content_len = post_content_len_d;

  6.     post_len = post_len_d;

  7. }

最后添加方法 mypost(),流程:


  • mystartRequest():


    • mysendInitialHeaders():发送请求头信息。

    • finishHeaders():发送空行结束 header。


  • 发送请求体头部,一边读取音频一边发送,发送请求体尾部。



实现:


  1. /* HttpClient.h */

  2. #define HTTP_CONTENT_TYPE "Content-Type"


  3. /* HttpClient.cpp */

  4. int HttpClient::mysendInitialHeaders(const char *aServerName, IPAddress aServerIP, uint16_t aPort, const char *aURLPath, const char *aHttpMethod, const char *aUserAgent)

  5. {

  6. // 与 sendInitialHeaders() 主要区别部分

  7. sendHeader(HTTP_HEADER_CONNECTION, "keep-alive");

  8. sendHeader(HTTP_HEADER_CONTENT_LENGTH, post_len);

  9. sendHeader(HTTP_CONTENT_TYPE, content_type);

  10. }/* HttpClient.cpp */

  11. int HttpClient::mypost(const char *aServerName, const char *aURLPath, SdFatFile file, const char *aUserAgent)

  12. {

  13.     const int MY_BODY_SIZE = 1000;

  14.     uint8_t buf_temp[MY_BODY_SIZE]; // 读取音频并发送的缓冲

  15.     memset(buf_temp, 0, MY_BODY_SIZE);


  16.     // 发送请求头

  17.     int req_ret = mystartRequest(aServerName, kHttpPort, aURLPath, HTTP_METHOD_POST, aUserAgent);

  18.     if (HTTP_SUCCESS != req_ret)

  19.     {

  20.         return req_ret;

  21.     }


  22.     // 发送请求体头部

  23.     iClient->write((const uint8_t *)post_start, post_start_len);


  24.     // 发送音频文件,可能分多次发送

  25.     int read_bytes = file.read(buf_temp, MY_BODY_SIZE);

  26.     iClient->write(buf_temp, read_bytes);

  27.     while (read_bytes == MY_BODY_SIZE)

  28.     {

  29.         read_bytes = file.read(buf_temp, MY_BODY_SIZE);

  30.         iClient->write(buf_temp, read_bytes);

  31.     }


  32.     // 发送请求体尾部

  33.     iClient->write((const uint8_t *)post_end, post_end_len);


  34.     return HTTP_SUCCESS;

  35. }



FatFs_SD

功能完善可以直接使用。貌似只支持Fat32?需要提前制备 SD 卡。


没有获取文件大小的方法,自己实现:


  1. /* SdFatFile.cpp */

  2. int SdFatFile::size() {

  3.     return f_size((FIL *)m_file);

  4. }



RecordWav

功能完善,可以直接录制生成 Wav 格式的音频文件,不需要手动给 PCM 文件写文件头,能直接发给云端进行语音识别,非常方便。只需要提前设置采样率位深等信息。


主循环

实现了各种方法后就能在主循环内实现云语音识别的流程了:

  1. void loop()

  2. {

  3.     if ((digitalRead(RECORDBTN) == HIGH) && (!recWav.fileOpened()))

  4.     {

  5.         // 按下按钮录制音频

  6.         sprintf(record_file_name, "%d.wav", record_counter);

  7.         sprintf(absolute_filename, "%s%s", fs.getRootPath(), record_file_name);

  8.         Serial.println("Recording started");

  9.         recWav.openFile(absolute_filename);

  10.     }

  11.     else if ((digitalRead(RECORDBTN) == LOW) && (recWav.fileOpened()))

  12.     {   

  13.         // 松开按钮停止录制

  14.         Serial.println("Recording stopped");

  15.         recWav.closeFile();

  16.         

  17.         // 文件保存后再打开文件,获取大小

  18.         SdFatFile record_file = fs.open(absolute_filename);

  19.         int record_file_len = record_file.size();

  20.         printf("size:%d", record_file_len);

  21.         

  22.         // 设置 Post Content 相关变量

  23.         http.mysetPostContent(NULL, record_file_len, post_start_len + record_file_len + post_end_len);

  24.         // POST 音频数据

  25.         err = http.mypost(kHostname, kPath, record_file);

  26.         // 关闭文件句柄

  27.         record_file.close();

  28.         

  29.         // 读取解析 response (省略)

  30.         if (err == 0){...}

  31.         delay(100);

  32. }

服务器

服务器端搭建在我的个人网站上,nginx+PHP架构,使用腾讯云提供的语音识别 api。假设板端将请求提交到 http://asr.hazhuzhu.com/ameba_asr.php


nginx

  1. server

  2. {

  3.     listen 80;

  4.     server_name asr.hazhuzhu.com;


  5.     client_max_body_size 128m;


  6.     root /home/wwwroot/asr;

  7.     index index.html index.htm index.php;


  8.     location / {

  9.         try_files $uri $uri/ =404;

  10.     }


  11.     location ~ \.php$ {

  12.         include fastcgi.conf;

  13.         fastcgi_pass    unix:/tmp/php-cgi.sock;

  14.         fastcgi_keep_conn on;

  15.     }

  16. }


PHP

后端负责存储音频文件并调用语音识别 api(需要使用腾讯云相关 SDK),最后返回识别结果。api 调用部分腾讯云提供了相关文档和代码生成工具,比较方便。

  1. $uploads_dir = 'ameba_recordings';


  2. if ($_FILES['file']['error'] == UPLOAD_ERR_OK)

  3. {

  4.         $tmp_name = $_FILES['file']['tmp_name'];

  5.         // $name = $_FILES['file']['name'];

  6.         $date_str=date('YmdHis');

  7.         move_uploaded_file($tmp_name, "$uploads_dir/$date_str".'.wav');

  8.         

  9.          try {

  10.          // 调用 api 部分,省略

  11.                 $result_str=$resp->getResult();

  12.                 $result_file=fopen("$uploads_dir/$date_str".'.txt',"a");

  13.                 fwrite($result_file,$result_str);

  14.                 fclose($result_file);

  15.                 echo $result_str;

  16.         }

  17.         catch(TencentCloudSDKException $e) {

  18.                 echo $e;

  19.         }

至此我们完成了一个完整的基于 Ameba RTL8722DM MINI 的云语音识别应用。


总结

首先我想谈谈使用 Ameba RTL8722DM MINI 的开发体验。正如前文所述,MINI 体积小但功能强大,能够实现大部分物联网场景应用。并且 MINI 支持 Arduino 开发,很快就能上手实现,不需要构建繁杂的单片机工程。而且官网的文档非常详尽,大量的示例程序、api文档、硬件细节以及详细的源码注释等,极大地方便了我们的开发。相关工作人员也很有耐心,点赞!


其次,其它开发者有提到麦克风的问题。我感觉确实录制下来的声音比较小,可能是缺省增益不够大?不过最终实现的语音识别效果还不错,没有什么影响。


最后再次感谢 Realtek 与面包板平台提供的这次测评与学习的机会。囿于时间和技术水平,本项目还有许多值得改进的地方,包括代码规范与识别效率等,希望能和大家共同交流学习!也祝主办方的技术生态越来越好!


项目源码:https://github.com/ha-zhuzhu/RTL8722DM-MINI-speech_recognizer

项目演示视频:点击阅读原文即可观看。

面包板社区 面包板社区——中国第一电子人社交平台 面包板社区是Aspencore旗下媒体,整合了电子工程专辑、电子技术设计、国际电子商情丰富资源。社区包括论坛、博客、问答,拥有超过250万注册用户,加入面包板社区,从菜鸟变大神,打造您的电子人脉社交圈!
评论 (0)
  • 在汽车行业的变革浪潮中,智界汽车的诞生备受瞩目。作为华为与奇瑞两大巨头携手合作的结晶,智界汽车自孕育之初便承载着众人的期待,被视为融合前沿科技与卓越制造的典范,有望在竞争激烈的新能源汽车市场中开辟出一片新天地。2024年,智界品牌首款车型智界S7正式上市,凭借华为的技术赋能,如先进的鸿蒙智能座舱、强大的HUAWEI ADS高阶智能驾驶辅助系统,以及奇瑞多年积累的深厚造车底蕴,在上市前赚足了眼球。智界S7的亮相,犹如一颗投入平静湖面的石子,激起了层层涟漪,消费者对其充满了好奇与期待,行业内也纷纷将
    用户1742991715177 2025-04-21 20:28 54浏览
  •   海上安全事件应急处置系统解析   北京华盛恒辉海上安全事件应急处置系统是为应对船舶碰撞、火灾等海上突发事件打造的综合管理体系,通过技术与协同机制,实现快速响应救援、优化资源配置,守护海上生命、财产与环境安全。以下从系统构成、功能、技术、应用及趋势展开阐述。   应用案例   目前,已有多个海上安全事件应急处置系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润海上安全事件应急处置系统。这些成功案例为海上安全事件应急处置系统的推广和应用提供了有力支持。   一、系统构成
    华盛恒辉l58ll334744 2025-04-21 15:50 76浏览
  • 导读在智能汽车技术发展浪潮中,车辆控制系统的智能化、网络化已成为行业发展的必然趋势。虹科PEAK智行定位车控系统,集成了尖端科技,能够实现车辆全方位监控与控制。从实时GPS定位到CAN/CAN FD信号处理,虹科方案不仅提升了车辆的智能化水平,更在安全性和效率上迈出了革命性的一步。虹科PEAK智行定位车控系统,通过CAN/CAN FD信号实现车辆的精准控制,包括加减速、转弯、倒退等动作,模拟真实车辆平台的动态表现。该系统搭载了虹科各型号设备,通过紧密协作,实时反映车辆位置、总线报文等信息,实现车
    虹科汽车智能互联 2025-04-21 16:04 79浏览
  • 导读在当今快速发展的智能通讯领域,时间敏感网络(TSN)已成为确保网络通信高可靠性和低延迟的关键技术。IEEE 802.1 Qci作为TSN的一个重要组成部分,提供了一套强大的机制来管理网络流量,确保关键数据流的优先级和带宽得到保障。本文将深入探讨IEEE 802.1 Qci协议的基本概念、工作原理以及虹科提供的Qci解决方案,帮您理解如何通过精确的流量控制来提升网络的稳定性和效率。虹科TSN解决方案01# 技术简介时间敏感网络(TSN)通过IEEE 802.1 Qci标准定义了一种关
    虹科工业智能互联 2025-04-21 16:17 90浏览
  • 引言:老龄化社会的健康守护需求随着全球老龄化进程加速,老年人的健康管理与生活质量成为社会焦点。记忆衰退、用药混乱、日程遗漏等问题频发,催生了智能健康设备的市场需求。WTR096录音语音芯片,凭借其高度集成的录放音、计时时钟与计划管理功能,为老年人量身打造了一站式健康管理方案,重新定义智能语音时钟的价值。功能亮点:1. 用药安全守护:多维度提醒,拒绝遗忘多时段精准提醒:支持一天内设置多个用药时间(如早、中、晚),适配复杂用药需求。个性化语音定制:家属可录制专属提醒语音(如“上午9点,请服用降压药”
    广州唯创电子 2025-04-22 08:41 64浏览
  •   北京华盛恒辉机场保障能力评估系统软件深度解析   在航空运输业快速发展的背景下,机场保障任务愈发复杂,传统人工评估方式已无法满足高效精准的管理需求。机场保障能力评估系统软件作为提升机场运行效率、保障飞行安全的关键工具,其重要性日益凸显。   应用案例   目前,已有多个机场保障能力评估系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润机场保障能力评估系统。这些成功案例为机场保障能力评估系统的推广和应用提供了有力支持。   一、系统功能模块   数据采集与整合模块  
    华盛恒辉l58ll334744 2025-04-22 10:28 35浏览
  • 职场烂摊子,每个人都难免遇上如果你在职场待久了,总会碰到一些让人无奈的情况:比如刚接手的项目混乱不堪、前任同事留下的任务一团乱麻,甚至有时因为自己的疏忽造成麻烦。面对这种烂摊子,烦躁、焦虑、甚至怀疑人生的情绪都会扑面而来。但如果你冷静想想,会发现真正消耗你的,往往不是工作本身,而是持续不断的心理内耗。那么问题来了,如何摆脱内耗,快速有效地“自救”?摆脱内耗,从情绪中抽离我曾经历过一个典型的职场烂摊子:前任项目负责人突然辞职,项目资料缺失严重,进度远远落后,客户抱怨不断。当时接手后的第一反应就是慌
    优思学院 2025-04-21 18:21 35浏览
  • 北京贞光科技有限公司作为紫光同芯授权代理商,深耕电子元器件领域数十载,专为汽车与工业客户提供车规级安全芯片及配套服务。公司整合硬件供应、软件SDK与技术支持为一体,配备专业团队提供选型咨询与现场指导,助力客户实现完整的芯片应用解决方案。在全球芯片供应链重构的大背景下,我国车规级芯片产业正迎来前所未有的发展机遇。北京贞光科技有限公司作为紫光同芯授权代理商,深耕电子元器件领域数十载,专为汽车与工业客户提供车规级安全芯片及配套服务。公司整合硬件供应、软件SDK与技术支持为一体,配备专业团队提供选型咨询
    贞光科技 2025-04-21 16:10 98浏览
  •   有效数据智能分拣系统平台深度解析   一、系统概述   北京华盛恒辉有效数据智能分拣系统平台融合人工智能、机器视觉、物联网及大数据分析技术,为物流包裹、数据信息等提供高效精准的智能化分拣处理方案。通过自动化设备与智能算法协同运作,取代传统人工分拣模式,显著提升分拣效率、降低错误率,满足电商、快递及供应链不断增长的业务需求。   应用案例   目前,已有多个有效数据智能分拣系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润有效数据智能分拣系统。这些成功案例为有效数据智能分
    华盛恒辉l58ll334744 2025-04-21 16:22 123浏览
  •   有效数据智能分拣系统详解   北京华盛恒辉有效数据智能分拣系统融合人工智能、大数据分析与机器学习等前沿技术,实现海量数据自动化分类、筛选、整理及分配。凭借强大的数据处理效能,助力企业精准提取关键信息,优化决策流程,提升运营效率。以下从系统架构、核心功能、技术特性、应用场景及发展趋势展开解读。   应用案例   目前,已有多个有效数据智能分拣系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润有效数据智能分拣系统。这些成功案例为有效数据智能分拣系统的推广和应用提供了有力支持。
    华盛恒辉l58ll334744 2025-04-21 16:46 110浏览
  • 在消费金融的赛道上,马上消费曾是备受瞩目的明星企业。自2015年成立以来,它以年均 30% 的净利润增速一路狂奔,成为持牌消费金融公司的标杆,2023年更是斩获19.82亿元净利润,风光无限。然而,2024年却成了马上消费的一道分水岭。2024年上半年,其营收为77.38亿元,同比下降2.11%;净利润更是同比骤降20.66%,仅为10.68亿元,创下历史最大跌幅 。与此同时,不良贷款率攀升至2.5%,不良余额高达16.54亿元,核心资本充足率降至12.72%,融资
    用户1742991715177 2025-04-21 21:29 61浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦