智能语音生活助手实现(QT)

  • 一、功能介绍
  • 二、实现步骤
    • 2.1 语音识别模块
      • 2.1.1 录音
      • 2.1.2 点击释放按钮槽函数
      • 2.1.3 申请百度AI开发平台语音识别应用
      • 2.1.4 HTTP请求类实现
      • 2.1.5 发送请求
      • 2.1.6 MainWindow类调用函数
      • 2.1.7 语音控制设备联动
    • 2.2 智慧生活模块
      • 2.2.1 创建API应用
      • 2.2.2 Get方法获取API的JSON数据
      • 2.2.3 解析JSON数据
    • 2.3 出行地图模块
      • 2.3.1 申请百度地图API秘钥
      • 2.3.2 新建map.html
      • 2.3.3 在map.html文件添加方法
      • 2.3.4 QT端实现
    • 2.4 智能闹钟模块
      • 2.4.1 开启线程,检测时间
      • 2.4.2 提交闹钟时间
  • 总结

一、功能介绍


1、 调用百度 AI 开发平台 API 进行语音识别,进行语音控制传感器的联
动,实现智能语音识别平台的功能。
2、 调用天气生活指数 API,获取不同城市每天的运动指数、 舒适度指数、
化妆指数等等。
3、 调用百度地图 api,显示不同城市的地图。
4、 实现智能闹钟,定时提醒。








二、实现步骤

2.1 语音识别模块

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

2.1.1 录音

在 pro 文件添加

QT += network
QT += multimedia

在 mainwindow.h 头文件添加下面定义

void RecorderStart(QString fileName);//开始录音
void RecorderEnd();//结束录音并转换格式
QFile *outFile;//录音时的变量
QAudioInput *my_audio;//录音时的变量
QAudioFormat audioFormat;//录音时的变量

Mainwindow.cpp 录音函数实现:

void MainWindow::RecorderStart(QString fileName)
{QAudioDeviceInfo device = QAudioDeviceInfo::defaultInputDevice();if(device.isNull()){QMessageBox::warning(NULL,"QAudioDeviceInfo","录音设备不存在");return;}
//    设置通道数audioFormat.setChannelCount(1);
//    设置编码audioFormat.setCodec("audio/pcm");
//    设置采样频率audioFormat.setSampleRate(16000);
//    设置位深audioFormat.setSampleSize(16);
//    判断设备是否支持该格式if(!device.isFormatSupported(audioFormat)){ //当前使用设备是否支持audioFormat = device.nearestFormat(audioFormat); //转换为最接近格式}
//    创建录音对象my_audio = new QAudioInput(audioFormat,this);outFile = new QFile;outFile->setFileName(fileName); //语音原始文件outFile->open(QIODevice::WriteOnly);
//     开始录音my_audio->start(outFile);
}

结束录音函数实现

/*********************** 结束录音并转换格式
**********************/
void MainWindow::RecorderEnd()
{//    结束录音my_audio->stop();outFile->close();delete outFile;outFile =NULL;delete my_audio;my_audio = NULL;
}

2.1.2 点击释放按钮槽函数

2.1.3 申请百度AI开发平台语音识别应用

语音识别是利用百度的 API 在线识别。所以需要申请项目 ID。进入百度AI开放平台
在产品服务下选择语音识别:

点击立即使用:

申请账号点击登录:

点击创建应用:

输入应用名称、应用描述,点击立即创建:

点击返回应用列表:

获取 AppID、API Key 和 Secret Key:

我们记住其中的API Key 和 Secret Key,下面会用到。

2.1.4 HTTP请求类实现

我们录好的音频文件需要通过HTTPS协议上传到百度AI开发平台进行语音识别,之后AI平台会返回给我们识别的结果。
http类只需要封装一个方法

 bool post_sync(QString url,QMap<QString,QString>header,QByteArray requestData,QByteArray &replyData);

使用这个方法去URL发送请求会收到URL的返回值。
http.h

#ifndef HTTP_H
#define HTTP_H#include <QObject>
#include <QMap>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QEventLoop>
#include <QDebug>
class Http : public QObject
{Q_OBJECT
public:explicit Http(QObject *parent = nullptr);bool post_sync(QString url,QMap<QString,QString>header,QByteArray requestData,QByteArray &replyData);};#endif // HTTP_H

http.cpp
这个方法的第一个参数是 post方法发送请求的URL,第二个参数是请求的方法头,第三个参数是请求的数据,第四个参数是返回的数据。
这里要说的是必须要设置openssl签名配置,否则在ARM上会报错。

bool Http::post_sync(QString url,QMap<QString,QString>header,QByteArray requestData,QByteArray &replyData)
{//    发送请求的对象QNetworkAccessManager manager;
//    请求 对象QNetworkRequest request;request.setUrl(url);QMapIterator<QString,QString> it(header);while (it.hasNext()) {it.next();request.setRawHeader(it.key().toLatin1() ,it.value().toLatin1());}
//设置openssl签名配置,否则在ARM上会报错QSslConfiguration conf = request.sslConfiguration();conf.setPeerVerifyMode(QSslSocket::VerifyNone);
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))conf.setProtocol(QSsl::TlsV1_0);
#elseconf.setProtocol(QSsl::TlsV1);
#endifrequest.setSslConfiguration(conf);QNetworkReply *reply = manager.post(request,requestData);QEventLoop l;//一旦服务器返回,reply会发出信号connect(reply,&QNetworkReply::finished,&l,&QEventLoop::quit);l.exec();if(reply != nullptr && reply->error() == QNetworkReply::NoError){replyData = reply->readAll();return true;}else{qDebug()<<"request error!";return false;}
}

2.1.5 发送请求

这里需要向两个URL发送两个请求,第一个请求是把我们4.2.3创建应用得到的API Key 和 Secret Key组合成一个URL获取access_token,第二个请求是把音频文件发送请求到语音识别的URL才能返回语音识别的结果。
我们新建一个类Speech
Speech.h
这里我们把API Key和Secret Key作为参数传到const QString baiduTokenUrl里面去。把主机名和获取的access_token做为参数传入const QString baiduSpeechUrl。

#include <QObject>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray>
#include <QFile>
#include "http.h"
#include <QHostInfo>
//    获取Access Token
const QString baiduTokenUrl = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%1&client_secret=%2&";
const QString client_id = "我们创建应用的API Key";
const QString client_secret = "我们创建应用的Secret Key";
//    语音识别url
const QString baiduSpeechUrl = "https://vop.baidu.com/server_api?dev_pid=1537&cuid=%1&token=%2";
class Speech:public QObject
{Q_OBJECT
public:Speech();QString speechIdentify(QString fileName);
private:QString getJsonValue(QByteArray ba,QString key);
};
#endif // SPEECH_H
Speech.cpp
QString Speech::speechIdentify(QString fileName)
{//    获取Access TokenQString tokenUrl =QString(baiduTokenUrl).arg(client_id).arg(client_secret);Http my_http;QMap<QString,QString>header;header.insert(QString("Content-Type"),QString("audio/pcm;rate=16000"));QByteArray requestData;//请求内容QByteArray replyData;//url返回内容qDebug()<<tokenUrl;bool result = my_http.post_sync(tokenUrl,header,requestData,replyData);if(result) {QString key = "access_token";QString accessToken =getJsonValue(replyData,key);qDebug()<<accessToken;//    语音识别QString speechUrl = QString(baiduSpeechUrl).arg(QHostInfo::localHostName()).arg(accessToken);QFile file;file.setFileName(fileName);file.open(QIODevice::ReadOnly);requestData = file.readAll();file.close();replyData.clear();
//        再次发起请求result = my_http.post_sync(speechUrl,header,requestData,replyData);if(result) {QString key = "result";QString retText =getJsonValue(replyData,key);qDebug()<<retText;return retText;}else{return NULL;}}else {return  "error";}
}

解析返回的数据
返回的数据是这种Json类型的,我们只需要获取里边result的值就能得到我们想要的结果了。

{"err_no":0,"err_msg":"success.","corpus_no":"15984125203285346378","sn":"481D633F-73BA-726F-49EF-8659ACCC2F3D","result":["北京天气"]}
QString Speech::getJsonValue(QByteArray ba,QString key)
{QJsonParseError parseError;QJsonDocument jsondocument = QJsonDocument::fromJson(ba,&parseError);if(parseError.error ==QJsonParseError::NoError){if(jsondocument.isObject()){QJsonObject jsonObject = jsondocument.object();if(jsonObject.contains(key)){QJsonValue jsonvalue = jsonObject.value(key);if(jsonvalue.isString())return jsonvalue.toString();else if(jsonvalue.isArray()){QJsonArray arr = jsonvalue.toArray();QJsonValue val =arr.at(0);return val.toString();}}}}return "";
}

2.1.6 MainWindow类调用函数

我们在释放按钮的槽函数里添加以下代码。

void MainWindow::on_pushButton_video_released()
{ui->pushButton_video->setText("按住说话");RecorderEnd();Speech my_speech;QString text =my_speech.speechIdentify("./1.pcm");ui->textEdit->append(text);audioCtrl(text);

2.1.7 语音控制设备联动

void MainWindow::audioCtrl(QString text)
{if(text == "开灯。"){system("echo 1 >/sys/class/leds/user1/brightness");system("echo 1 >/sys/class/leds/user2/brightness");system("echo 1 >/sys/class/leds/user3/brightness");ui->textEdit_2->setText("灯已打开");}else if(text == "关灯。"){system("echo 0 >/sys/class/leds/user1/brightness");system("echo 0 >/sys/class/leds/user2/brightness");system("echo 0 >/sys/class/leds/user3/brightness");ui->textEdit_2->setText("灯已关闭");}else if(text == "报警。"){int fd;struct input_event event;struct timeval time;fd = open("/dev/input/by-path/platform-beeper-event", O_RDWR);event.type = EV_SND;event.code = SND_TONE;event.value = 1000;time.tv_sec = 1;time.tv_usec = 0;event.time = time;write(fd, &event, sizeof(struct input_event));ui->textEdit_2->setText("蜂鸣器已报警");}else if(text == "关闭。"){int fd;struct input_event event;struct timeval time;fd = open("/dev/input/by-path/platform-beeper-event", O_RDWR);event.type = EV_SND;event.code = SND_TONE;event.value = 0;time.tv_sec = 0;time.tv_usec = 0;event.time = time;write(fd, &event, sizeof(struct input_event));ui->textEdit_2->setText("蜂鸣器报警已关闭");}else if(text == "关风扇。"){unsigned char arg;Ioctl(EXIT_FAN,&arg);ui->textEdit_2->setText("风扇已关闭");}else if(text == "开风扇。"){unsigned char arg;Ioctl(EXIT_FAN,&arg);Ioctl(INIT_FAN,&arg);Ioctl(FAN_UP,&arg);ui->textEdit_2->setText("风扇已打开");}else if(text == "温度。"){QString tem = temCollect();ui->textEdit_2->setText(QString("此时温度为:").append(tem).append("'C"));}else if(text == "湿度。"){QString hum = humCollect();ui->textEdit_2->setText(QString("此时湿度为:").append(hum).append("%"));}
}

2.2 智慧生活模块

2.2.1 创建API应用

浏览器进入和风天气官网,注册账号并登陆,点击进入控制台。

进入控制台后,点击应用管理。

点击创建应用,选择免费开发板


填写天气数据应用名称后选择WebAPI,自定义天气数据应用名称。



完成上述操作后,把key复制下来,后边代码需要用到。

2.2.2 Get方法获取API的JSON数据

我们将key填写到下面的URL里面,使用get方法就能从API爬下JSON数据来了。
https://devapi.qweather.com/v7/indices/1d?type=1,2&location=101010100&key=你的KEY
其中请求参数
Location:需要查询地区的LocationID或以英文逗号分隔的经度,纬度坐标(十进制),LocationID可通过城市搜索服务获取。例如 location=101010100
Key:用户认证key,即上面获取到的key。
Type:生活指数的类型ID,包括洗车指数、穿衣指数、钓鱼指数等。可以一次性获取多个类型的生活指数,多个类型用英文,分割。例如type=3,5。具体生活指数的ID和等级参考生活指数常量。各项生活指数并非适用于所有城市。
所以我们以参数的形式将城市的LocationID填入URL就能获取不同城市的生活指标。
具体代码参考下面:

//get方法获取信息
void LifeWidget::sendQuest(QString cityStr)
{QString key = "您申请的key";QString quest_url = "https://devapi.qweather.com/v7/indices/1d?type=0&location=%1&key=%2";quest_url = quest_url.arg(cityStr).arg(key);QNetworkRequest quest;quest.setUrl(QUrl(quest_url));//设置openssl签名配置,否则在ARM上会报错QSslConfiguration conf = quest.sslConfiguration();conf.setPeerVerifyMode(QSslSocket::VerifyNone);#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))conf.setProtocol(QSsl::TlsV1_0);#elseconf.setProtocol(QSsl::TlsV1);#endifquest.setSslConfiguration(conf);manager->get(quest);    /*发送get网络请求*/
}
//数据接收槽函数
void LifeWidget::replyFinished(QNetworkReply *reply)
{replyall = reply->readAll();reply->deleteLater(); //销毁请求对象
}
void LifeWidget::init_networt_life()
{manager = new QNetworkAccessManager(this);   connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));//关联信号和槽
}

2.2.3 解析JSON数据

{"code": "200","updateTime": "2021-02-06T16:36+08:00","fxLink": "http://hfx.link/2ax2","daily": [{"date": "2021-02-06","type": "2","name": "洗车指数","level": "2","category": "较适宜","text": "较适宜洗车,未来一天无雨,风力较小,擦洗一新的汽车至少能保持一天。"},{"date": "2021-02-06","type": "1","name": "运动指数","level": "3","category": "较不宜","text": "天气较好,但考虑天气寒冷,推荐您进行室内运动,户外运动时请注意保暖并做好准备活动。"}],"refer": {"sources": ["Weather China"],"license": ["commercial license"]}
}

我们通过get方法获取到的JOSN数据如上所示。只需要解析key为daily的值即可。其中daily的值是一个数组类型的数据,只需要取出我们需要的即可。

void DetaInfo::setInfo(QString info,int type)
{qDebug()<<"setINfo";QJsonParseError err;QJsonDocument json_recv = QJsonDocument::fromJson(info.toUtf8(), &err);//解析json对象if (!json_recv.isNull()){QJsonObject object = json_recv.object();if (object.contains("daily")){QJsonValue value = object.value("daily");  // 获取指定 key 对应的 valueif (value.isArray()){QJsonObject today_life = value.toArray().at(type).toObject();QString category = today_life.value("category").toString();QString text = today_life.value("text").toString();ui->label_category->setText(category);ui->label_text->setText(text);}}}
}

2.3 出行地图模块

2.3.1 申请百度地图API秘钥

进入百度地图官网

点击进入控制台。

这里需要登录百度账号,扫码或者输入用户名密码登录即可。

登录成功后点击应用管理下的我的应用。

点击创建应用

自定义应用名称后,应用类型选择浏览器端,在白名单输入框输入*。

这里就是我们需要的AK秘钥。

2.3.2 新建map.html

复制百度地图API源码。

新建map.html

将上面API的源码复制到吗map.html

将代码里面的红框里的您的秘钥替换刚才申请的AK即可。

2.3.3 在map.html文件添加方法

添加函数,通过QT程序传参来改变地图路线的起点,途经点,终点。

2.3.4 QT端实现

这里使用了webkit模块,在pro文件中添加

QT += webkit webkitwidgets

具体代码如下

void MainWindow::mapinit()
{QWebSettings *settings = QWebSettings::globalSettings();settings->setAttribute(QWebSettings::PluginsEnabled, true);//允许插件settings->setAttribute(QWebSettings::JavascriptEnabled, true);//JavaScriptsettings->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);//settings->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);settings->setFontFamily(QWebSettings::FixedFont,"幼圆");ui->webView->setStyle(new CustomStyle());ui->webView->load(QUrl("qrc:/map.html"));connect(ui->webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(populateJavaScriptWindowObject()));}
void MainWindow::populateJavaScriptWindowObject()
{ui->webView->page()->mainFrame()->addToJavaScriptWindowObject("Mywebkit", this);
}
void MainWindow::onBtnCallJSClicked()
{QString strVal = QString("callfromqt(要传的参数);"));ui->webView->page()->mainFrame()->evaluateJavaScript(strVal);
}

2.4 智能闹钟模块

2.4.1 开启线程,检测时间

这里设置了四个闹钟,即在线程类里边设置了四个全局变量(闹钟时间)。当前时间戳等于设置的时间戳后设置蜂鸣器响起。

void TimeAlarmClock::run()
{while (1) {QDateTime time = QDateTime::currentDateTime();   //获取当前时间uint timeT = time.toTime_t();   //将当前时间转为时间戳
//        qDebug()<<timeT<<alarm_clocktime1;if(alarm_clocktime1==timeT){beep_on();
//            qDebug()<<"open";}else{}if(alarm_clocktime2==timeT){beep_on();}else{}if(alarm_clocktime3==timeT){beep_on();}else{}if(alarm_clocktime4==timeT){beep_on();}else{}}
}
void TimeAlarmClock::beep_on()
{int fd;struct input_event event;struct timeval time;fd = open("/dev/input/by-path/platform-beeper-event", O_RDWR);event.type = EV_SND;event.code = SND_TONE;event.value = 1000;time.tv_sec = 1;time.tv_usec = 0;event.time = time;write(fd, &event, sizeof(struct input_event));close(fd);
}

2.4.2 提交闹钟时间

使用QdateTimeEdit设置闹钟时间,点击按钮后,将闹钟时间设置到线程中的全局变量中。
void MainWindow::on_time_btn1_clicked()
{if(ui->time_btn1->text()==" "){ui->time_btn1->setText("\n");timeAlarmClock.alarm_clocktime1 = ui->dateTimeEdit_1->dateTime().toTime_t();}else{ui->time_btn1->setText(" ");timeAlarmClock.alarm_clocktime1 = 0;}
}

总结

此项目可在ubuntu下运行,也可通过交叉编译在ARM平台上运行。源码请私信

智能语音生活助手实现(QT)相关推荐

  1. HaaS云端一体智能语音交互方案

    1.方案背景 智能语音交互作为物联网领域的一个重要生态成员,是一种全新的交互方式,它能够解放双手,随时提供服务,无须借助任何按键.近年来智能家居逐渐走入千家万户,产业市场规模不断增长.智能家居产品种类 ...

  2. 贴近司机,感知生活:智能语音助手在滴滴车主端的设计与实践

    桔妹导读:基于网约车司机的职业特性,帮助与指引司机在各类复杂的场景下更安全.便捷地完成工作,并尽可能疏导与减轻他们因长时间处于封闭环境下的心理压力,一直是滴滴发力的一个方向.但现有的一些途径,如规则展 ...

  3. 如何快速搭建一个像“天猫精灵”的智能语音助手?

    不看这几篇好文,就别说自己了解物联网 天猫精灵相信大家都不陌生了,它是阿里巴巴于2017年7月5日发布的AI智能终端品牌.让用户以自然语言对话的交互方式,实现影音娱乐.购物.信息查询.生活服务等功能操 ...

  4. 标贝科技|智能语音助手+全息形象,会是下一个趋势吗

    现在,智能语音助手已经无处不在,手机.音箱.电视.汽车里都能寻得他们的踪迹.他们都有一些相似的点:能识别语音.说唤醒词就能开始对话.可以完成人们的各种指令,除了内在技能以外,在外表上,他们目前也都没有 ...

  5. ESP-Skainet智能语音助手,智能物联网方案,语音唤醒识别准确率高

    消费级智能硬件是最早显示出市场潜力的赛道,市场各方都在瞄准消费级智能交互终端.而智能终端的背后还有广阔的生态,包括语音开放平台.语音操作系统.内容等等. 近年行业正在经历从单一商业模式向多元化商业模式 ...

  6. 中国智能语音助手用户最担心安全和隐私问题

    埃森哲最新调研显示,有77%的受访中国消费者使用智能语音助手,为全球最高(全球平均比例50%).国内用户对于独立智能语音助手的满意度达到了97%,因而对其有着更高的期待,希望更多的家用设备与之实现集成 ...

  7. 中国智能语音助手企业案例研究报告(2018年)-笔记

    中国智能语音助手企业案例研究报告(2018年)-笔记 1 摘要 目前行业里的智能语音助手主要应用于消费级产品和专业级行业应用两大领域. 智能语音助手的卖点是:想通过语音操控从而解放双手,并且智能语音助 ...

  8. 钻石与小度:智能语音助手背后的“马斯洛需求模型”

    从软件到硬件,从辅助功能到产品核心,从前沿科技走向千万普通人的生活,智能语音助手的一路发展,经历了数次技术.形态.商业市场上的彻底蜕变.很多人都会好奇,智能语音助手的未来会走向何处? 其实这件事并不那 ...

  9. 今年CES最大亮点:智能语音助手正成为新趋势

    国外媒体本周刊文称,在今年CES上,智能语音助手正成为新趋势,而这也将成为科技行业未来的基石. 以下为文章全文: 今年的美国国际消费电子展(CES)上并没有任何"杀手级"产品发布, ...

最新文章

  1. Apache学习路线
  2. 实验三 JSP应用开发进阶
  3. 分布式文件系统—HDFS—Java API操作
  4. javascript简单介绍
  5. Nova虚拟机启动提示libvirtError
  6. 王道 —— 进程的定义、组成、组织方式、特征
  7. html页面乱码问题
  8. 如何通过Chrome中的代码设置JavaScript断点?
  9. using namespace cv
  10. Windows 下Redis客户端可视化工具-redis client
  11. QT界面美化与添加多个界面
  12. 基于单片机的功放protues_基于单片机的音乐播放器设计
  13. 淘宝订单API接口参数详解
  14. 2022最新whatsapp接收不到验证码解决方法
  15. Realtek 2.5G USB网卡RTL8156B-CG支持免驱简介
  16. 阿里云服务器云数据库免费体验(Java Web详细实例)
  17. Unity线性工作流下UI保持Gamma的解决方案收集
  18. regl fake-3d 静态图变动态图, 使用深度信息图片
  19. 7. Laravel5学习笔记:如何定义自己的视图组件
  20. 震惊!重新认识资本主义。

热门文章

  1. 并离网切换-双机并联逆变器自适应虚拟阻抗下垂控制(Droop)策略MATLAB仿真模型
  2. 一本通题解——1191:流感传染
  3. 动力电池热管理设计与仿真及整车热管理高级技术
  4. Binary XML file line #142 in xxx.xxx.xxx:layout/yyy: Binary XML file l
  5. 使用IEEE802.1Q VLAN实现单线复用之WiFi提速篇
  6. 利用vant组件上传照片 修改自定义上传照片样式 exif插件整理照片旋转 照片添加水印
  7. 达龙云电脑虚拟服务器,可以与索尼、英伟达一争高下的国产云游戏服务“达龙云电脑”简评...
  8. android面试宝典铁道出版社,关于Android开发的面试经验总结
  9. 计算机应用房地产,房地产管理中的计算机应用.pdf
  10. Android通过辅助功能实现抢微信红包原理简单介绍