制作ai语音助手

目录

一、总体介绍

二、唤醒

http://t.csdnimg.cn/3mf18

三、将语音唤醒和aiui结合

(1)项目合并

 (2)修改CMakeList.txt

(3)demo代码修改

1.添加库

 2.在demo中添加唤醒功能的代码

3.尝试运行代码,观察是否有报错

出现报错

解决方法

(4)添加aiui和wake的代码逻辑

1.main

2.修改唤醒结果

代码分析

 四、总结

 五、相关文章推荐

一、总体介绍

用到的技术:科大讯飞的aiui和语音唤醒 

科大讯飞的aiui:用来实现语音交互的功能

语音唤醒:用来触发aiui的功能

操作系统:ubuntu16.04(Linux)

二、唤醒

实现唤醒的功能可以看之前的文章:

http://t.csdnimg.cn/3mf18

三、将语音唤醒和aiui结合

(1)项目合并

我们以aiui的项目为基础,将语音唤醒的项目合并到aiui。

文件夹合并整理

 (2)修改CMakeList.txt

注意:如果不了解CMakeList.txt,推荐看之前的文章

http://t.csdnimg.cn/UrueG

http://t.csdnimg.cn/NaoYE

target_link_libraries(${PROJECT_NAME} libpthread.so -lasound -lstdc++ aikit pthread dl asound)

代码分析 

这段代码是 CMake 中使用的 add_custom_command 命令,用于在构建目标(TARGET)后执行自定义命令。在这个代码中,这些自定义命令被添加到了项目(PROJECT_NAME)的构建过程中,并且被设置为在构建完成后执行(POST_BUILD)。

这样做的目的是将一些依赖的动态链接库文件或者其他必要的资源文件在构建完成后一同复制到可执行文件的输出目录,以便于程序在运行时能够正常访问这些文件。通常情况下,这些文件可能是程序运行所需的第三方库文件、配置文件或者其他资源文件。

总结:这段代码的作用就是在构建完成后将指定的文件复制到可执行文件的输出目录,以满足程序运行时对这些文件的依赖。

(3)demo代码修改

1.添加库

 2.在demo中添加唤醒功能的代码

//将唤醒的代码添加在aiui的后面
#define SAMPLE_RATE_16K     (16000)#define DEFAULT_FORMAT		\{\WAVE_FORMAT_PCM, \1, \16000, \32000, \2, \16, \sizeof(WAVEFORMATEX)	\}#define E_SR_NOACTIVEDEVICE		1#define E_SR_NOMEM			2#define E_SR_INVAL			3#define E_SR_RECORDFAIL			4#define E_SR_ALREADY			5int times = 1;struct recorder* recorder;void sleep_ms(int ms){usleep(ms * 1000);}//唤醒结果在此回调void OnOutput(AIKIT_HANDLE* handle, const AIKIT_OutputData* output) {string temp = (char*)output->node->value;printf("OnOutput abilityID :%s\n", handle->abilityID);printf("OnOutput key:%s\n", output->node->key);printf("OnOutput value:%s\n", (char*)output->node->value);}void OnEvent(AIKIT_HANDLE* handle, AIKIT_EVENT eventType, const AIKIT_OutputEvent* eventValue) {printf("OnEvent:%d\n", eventType);}void OnError(AIKIT_HANDLE* handle, int32_t err, const char* desc) {printf("OnError:%d\n", err);}void iat_cb(char* dataBuf, unsigned long len, void* user_para){int errcode = 0;AIKIT_HANDLE* handle = (AIKIT_HANDLE*)user_para;if (len == 0 || dataBuf == NULL){return;}AIKIT_DataBuilder* dataBuilder = AIKIT_DataBuilder::create();AiAudio* wavData = AiAudio::get("wav")->data(dataBuf, len)->valid();dataBuilder->payload(wavData);int ret = AIKIT_Write(handle, AIKIT_Builder::build(dataBuilder));if (ret != 0) {printf("AIKIT_Write:%d\n", ret);}}void ivwIns() {AIKIT_ParamBuilder* paramBuilder = nullptr;AIKIT_HANDLE* handle = nullptr;int index[] = { 0 };int ret = 0;int err_code = 0;int count = 0;paramBuilder = AIKIT_ParamBuilder::create();WAVEFORMATEX wavfmt = DEFAULT_FORMAT;wavfmt.nSamplesPerSec = SAMPLE_RATE_16K;wavfmt.nAvgBytesPerSec = wavfmt.nBlockAlign * wavfmt.nSamplesPerSec;if (times == 1) {AIKIT_CustomData customData;customData.key = "key_word";customData.index = 0;customData.from = AIKIT_DATA_PTR_PATH;customData.value = (void*)"./resource/keyword-nhxd.txt";customData.len = strlen("./resource/keyword-nhxd.txt");customData.next = nullptr;customData.reserved = nullptr;printf("AIKIT_LoadData start!\n");ret = AIKIT_LoadData("e867a88f2", &customData);printf("AIKIT_LoadData end!\n");printf("AIKIT_LoadData:%d\n", ret);if (ret != 0) {goto  exit;}times++;}ret = AIKIT_SpecifyDataSet("e867a88f2", "key_word", index, 1);printf("AIKIT_SpecifyDataSet:%d\n", ret);if (ret != 0) {goto  exit;}paramBuilder->param("wdec_param_nCmThreshold", "0 0:999", 8);paramBuilder->param("gramLoad", true);ret = AIKIT_Start("e867a88f2", AIKIT_Builder::build(paramBuilder), nullptr, &handle);printf("AIKIT_Start:%d\n", ret);if (ret != 0) {goto  exit;}err_code = create_recorder(&recorder, iat_cb, (void*)handle);if (recorder == NULL || err_code != 0) {printf("create recorder failed: %d\n", err_code);err_code = -E_SR_RECORDFAIL;goto exit;}err_code = open_recorder(recorder, get_default_input_dev(), &wavfmt);if (err_code != 0) {printf("recorder open failed: %d\n", err_code);err_code = -E_SR_RECORDFAIL;goto exit;}err_code = start_record(recorder);if (err_code != 0) {printf("start record failed: %d\n", err_code);err_code = -E_SR_RECORDFAIL;goto exit;}//监听while (1){sleep_ms(200); printf("Listening...\n");count++;if (count % 20 == 0)	{stop_record(recorder);close_recorder(recorder);destroy_recorder(recorder);recorder = NULL;//struct recorder *recorder;err_code = create_recorder(&recorder, iat_cb, (void*)handle);err_code = open_recorder(recorder, get_default_input_dev(), &wavfmt);err_code = start_record(recorder);}}ret = AIKIT_End(handle);exit:if (paramBuilder != nullptr){delete paramBuilder;paramBuilder = nullptr;}}void TestIVW() {AIKIT_Configurator::builder().app().appID("去科大讯飞找").apiKey("去科大讯飞找").apiSecret("去科大讯飞找").workDir("./").auth().authType(0).ability("e867a88f2").log().logLevel(LOG_LVL_INFO);AIKIT_Callbacks cbs = { OnOutput,OnEvent,OnError };AIKIT_RegisterAbilityCallback("e867a88f2", cbs);AIKIT_SetILogOpen(false);int ret = AIKIT_Init();if (ret != 0) {printf("AIKIT_Init failed:%d\n", ret);goto exit;}ret = AIKIT_EngineInit("e867a88f2", nullptr);if (ret != 0) {printf("AIKIT_EngineInit failed:%d\n", ret);goto exit;}ivwIns();exit:AIKIT_UnInit();}

 注意

3.尝试运行代码,观察是否有报错

在调试的过程中,我们的主代码

int main() {TestIVW();return 0;
}
出现报错

报错找不到资源

解决方法

将aiui_add_awak的resource文件夹复制到bin_x64

分析

当资源文件夹放置在运行代码的同级目录下时,代码可以更轻松地找到并加载这些资源文件。这是因为代码通常会在当前工作目录中查找资源文件。默认情况下,代码在没有明确指定路径的情况下会在当前工作目录中搜索资源文件。如果资源文件位于代码所在的同级目录下,那么代码可以直接找到并加载这些文件。

而当资源文件夹放置在其他位置时,代码可能无法准确地找到资源文件所在的路径,从而导致无法加载这些文件,进而引发错误。通过将资源文件夹放置在与运行代码同级的目录下,提供了一个更直接的路径,使得代码可以成功找到并加载这些资源文件,从而解决了报错问题。

(4)添加aiui和wake的代码逻辑

目标:通过唤醒词“你好智慧机器人”唤醒aiui功能。

1.main

2.修改唤醒结果

找到OnOutput()函数

    string temp = (char*)output->node->value;createAgent();start();wakeup();if (temp.find("你好小迪") != string::npos){printf("----触发你好小迪,拦截----\n");return;}printf("OnOutput abilityID :%s\n", handle->abilityID);printf("OnOutput key:%s\n", output->node->key);printf("OnOutput value:%s\n", (char*)output->node->value);createAgent();start();wakeup();writeAudio();AIUI_SLEEP(10000);stopAudio();
代码分析

四、查看效果

五、总结

 五、相关文章推荐

上面有一些技术问题推荐查看这些文章(如有侵权,告知必删)

ros语音识别实现:http://t.csdnimg.cn/KVSYS

Shell脚本简单学习:http://t.csdnimg.cn/PzjlL

CMake简单学习: http://t.csdnimg.cn/165au

ROS简单学习: http://t.csdnimg.cn/a7Vpf

简单学习语音唤醒: http://t.csdnimg.cn/SJAnt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2808336.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构和算法初阶(c语言)】数据结构前言,初识数据结构(给你一个选择学习数据结构和算法的理由)

1.何为数据结构 数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的 数据元素的集合。本质来讲就是在内存中去管理数据方式比如我们的增删查改。在内存中管理数据的方式有很多种(比如数组结构、链式结构、树型结…

基于Pytorch的猫狗图片分类【深度学习CNN】

猫狗分类来源于Kaggle上的一个入门竞赛——Dogs vs Cats。为了加深对CNN的理解,基于Pytorch复现了LeNet,AlexNet,ResNet等经典CNN模型,源代码放在GitHub上,地址传送点击此处。项目大纲如下: 文章目录 一、问题描述二、数据集处理…

智能SQL生成:后端技术与LLM的完美结合

文章目录 引言一、什么是大模型二、为什么选择LLM三、开发技术说明四、系统架构说明五、编码实战1. Maven2. 讯飞大模型配置类3. LLM相关的封装4. 编写LLM的service5. 编写controller6. 运行测试 六、总结 引言 本篇文章主要是关于实现一个类似Chat2DB的根据自然语言生成SQL的…

新改进!基于改进粒子群算法的微网/综合能源系统多目标优化调度程序代码!

适用平台:MatlabYalmipCplex 程序提出了一种综合考虑微电网系统运行成本和环境保护成本的并网模式下微电网多目标优化调度模型,采用改进的粒子群算法对优化模型进行求解。程序算例丰富、注释清晰、干货满满,可扩展性和创新性很高&#xff01…

readproc.h

Ubuntu22.04系统中 编译自己写的程序的时候,报错,显示找不到readproc.h文件,通过安装libprocps-dev解决 sudo apt install libprocps-dev

c#高级-正则表达式

正则表达式是由普通字符和元字符(特殊符号)组成的文字形式 应用场景 1.用于验证输入的邮箱是否合法。 2.用于验证输入的电话号码是否合法。 3.用于验证输入的身份证号码是否合法。等等 正则表达式常用的限定符总结: 几种常用的正则简写表达式…

女生常用的社交app软件有哪些?分享女生用的最多的社交软件

随着科技的迅猛发展,社交软件也日益多样化。除了常见的社交平台,一些全新的社交软件如雨后春笋般涌现,为用户带来了更多元、更有趣的社交体验。这里为大家介绍 5 款女生用的最多的社交软件,它们分别是丛丛、青藤之恋、meetu、小奢…

【Node.js】自动生成 API 文档

目录 1、直接使用swagger-ui-express 2、配合swagger-jsdoc 如何在Node.js项目中使用 Swagger 来自动生成 API接口文档,使用生成方式有很多种。本文基于swagger-jsdocswagger-ui-express快速实现 1、直接使用swagger-ui-express // 方便来浏览和测试api npm i sw…

分布式知识整理

分布式锁 以商场系统超卖现象举例 超卖现象一 现象: 商品卖出数量超出了库存数量。 产生原因: 扣减库存的动作在程序中进行,在程序中计算剩余库存,在并发场景下,导致库存计算错误。 代码复现 es.shutdown(); cycl…

二分算法(c++版)

二分的本质是什么? 很多人会认为单调性是二分的本质,但其实其本质并非单调性,只是说,有单调性的可以进行二分,但是有些题目没有单调性我们也可以进行二分。其本质其实是一个边界问题,给定一个条件&#xf…

2.WEB渗透测试-前置基础知识-web基础知识和操作系统

web基础知识 1.http协议 超文本传输协议是互联网上应用最广泛的一种网络协议。所有www文件都必须遵守的一个标准,是以 ASCII 码传输,建立在 TCP/IP 协议之上的应用层规范,通俗点说就是一种固定的通讯规则。 2、网络的三种架构及特点 网络应…

【C++STL】迭代器分类 失效问题

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

堆排序、快速排序和归并排序

堆排序、快速排序和归并排序是所有排序中最重要的三个排序&#xff0c;也是难度最大的三个排序&#xff1b;所以本文单独拿这三个排序来讲解 目录 一、堆排序 1.建堆 2.堆排序 二、快速排序 1.思想解析 2.Hoare版找基准 3.挖坑法找基准 4.快速排序的优化 5.快速排序非…

自定义神经网络二之模型训练推理

文章目录 前言模型概念模型是什么&#xff1f;模型参数有哪些神经网络参数案例 为什么要生成模型模型的大小什么是大模型 模型的训练和推理模型训练训练概念训练过程训练过程中的一些概念 模型推理推理概念推理过程 总结 前言 自定义神经网络一之Tensor和神经网络 通过上一篇…

IOBR2 更新(学习自备)

IOBR查看其收录的相关基因集(自备)_肿瘤 tme特征 iobr-CSDN博客 IOBR2&#xff1a;多维度解析肿瘤微环境 - 知乎 (zhihu.com) 学习手册&#xff1a;https://iobr.github.io/book/ &#xff08;里面有详细教程&#xff09; 系统综合的分析工具&#xff08;Immuno-Oncology Bi…

学习python的第7天,她不再开放她的听歌榜单

我下午登录上小号&#xff0c;打开聊天消息看到了她的回复&#xff0c;我很开心兴奋&#xff0c;可是她不再开放她的听歌榜单了&#xff0c;我感觉得到&#xff0c;我要失恋了。 “因为当年电视上看没有王菲版本的” “行”。 “那你以后还会开放听歌榜单吗&#xff1f;”我…

opencv基础 python与c++

question: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple matplotlib Opencv 一、读取图片 (1).imshow Mat imread(const string& filename, intflags1 );flags: enum { /* 8bit, color or not */CV_LOAD_IMAGE_UNCHANGED -1, /* 8bit, gray */CV_LOAD_I…

基于springboot+vue的大型商场应急预案管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

应用回归分析:非参数回归

非参数回归是一种统计方法&#xff0c;它在建模和分析数据时不假设固定的模型形式。与传统的参数回归模型不同&#xff0c;如线性回归和多项式回归&#xff0c;非参数回归不需要预先定义模型的结构&#xff08;例如&#xff0c;模型是否为线性或多项式&#xff09;。这使得非参…

小米标准模组+MCU 快速上手开发(一)——之固件下载

小米标准模组+MCU 开发笔记之固件下载 背景技术名词简介● 小米IoT开发者平台● 小米IoT 模组● ESP系列简介问题描述 + 解决方式问题1:固件下载是否有示例,如何下载到硬件板卡中?问题2:固件下载的官方程序是什么?在哪里?该如何使用?问题3:固件下载时,Flash和Ram 有什…