知是行的主意,行是知的功夫。这篇文章主要讲述AI语音识别-我给浏览器加了个语音搜索功能相关的知识,希望能为你提供帮助。
1. 前言随着物联网的发展,语音识别技术受到越来越多的关注,语音识别技术正积极推动信息通信领域的革命,语音拨号,语音邮件,语音输入乃至语音操控等以语音识别为基础的人机交互日益普及.尽管生物识别方式不断增多,语音识别方式仍是主流方式.与其他生物识别技术相比,语音识别技术不仅具有非接触,非侵入性,使用方便,不会遗失和忘记,不需记忆等特点。
本篇文章就采用华为云提供的在线语音识别服务给浏览器设计一个语音自动搜索的功能,编程语言采用C++,软件框架采用QT设计,浏览器内核采用QWebEngineView,在QT5.7以后,QT里就不支持webkit了,目前自带的浏览器内核是QWebEngineView,只能使用MSVC编译编译,mingw要使用浏览器可以单独下载webkit的库,或者使用COM组件调用IE浏览器,当前文章里使用的浏览器是QWebEngineView,编译器采用VS2017,32bit。
语音采集功能使用QT的QAudioInput类来实现,采集声卡的PCM数据,保存起来,通过华为云的语音识别HTTP接口完成文字识别,得到文字后再通过浏览器进行搜索文字相关内容。
实现效果如下:

文章图片
点击界面上的 ”开始语音采集“按钮,就可以说话,说完点击停止采集,然后调用华为云的语音识别接口进行语音识别,在下面的显示框上显示识别到的文字,然后再完成浏览器自动搜索。
【AI语音识别-我给浏览器加了个语音搜索功能】

文章图片

文章图片
2. 创建语音服务器 2.1 使用语音服务
登录华为云官网: https://www.huaweicloud.com/
选择产品-人工智能-语音交互服务-一句话识别。

文章图片
短语音识别地址: https://www.huaweicloud.com/product/asr.html
短语音识别是将口述音频转换为文本,通过API调用识别不超过一分钟的不同音频源发来的音频流或音频文件。适用于语音搜索、人机交互等语音交互识别场景。 支持免费试用。

文章图片
免费试用每日500次。

文章图片

文章图片

文章图片

文章图片

文章图片
2.2 HTTP接口使用介绍
文档地址: https://support.huaweicloud.com/api-sis/sis_03_0094.html

文章图片
在线调试接口地址: https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=SIS&api=RecognizeShortAudio
几个重要的参数:
本地音频采集的频率、通道数都得与参数匹配。

文章图片

文章图片
2.3 接口地址总结
请求地址: "https://endpoint/v1/project_id/asr/short-audio"请求数据:"config":
"audio_format": "ulaw8k8bit",
"property": "chinese_8k_common",
"add_punc": "yes",
"digit_norm": "yes",
"need_word_info": "yes"
,
"data": "/+MgxAAUeHpMAUkQAANhuRAC..."请求头里要带: X-Auth-Token 参数
请求数据里的参数在前面截图里介绍了,data就是音频文件的base64编码数据。
请求地址里的endpoint字段、project_id字段、还有X-Auth-Token字段只要是访问华为云的任何API接口都需要填,获取方法看这里: https://bbs.huaweicloud.com/blogs/317759翻到2.3小节。

文章图片
识别成功返回的数据:
"trace_id": "567e8537-a89c-13c3-a882-826321939651",
"result":
"text": "欢迎使用语音云服务。",
"score": 0.9,
"word_info": ["start_time": 150,
"end_time": 570,
"word": "欢迎"
,"start_time": 570,
"end_time": 990,
"word": "使用"
,"start_time": 990,
"end_time": 1380,
"word": "语音"
,"start_time": 1380,
"end_time": 1590,
"word": "云"
,"start_time": 1590,
"end_time": 2070,
"word": "服务"]
其中的text字段就是识别的文本数据。
3. 项目代码示例下面列出核心的代码,主要是就是字符串拼接格式,拼接完发送http请求即可。
3.1 语音转文字请求代码
//语音转文本
void Widget::audio_to_text(QByteArray data)function_select=0;
QString requestUrl;
QNetworkRequest request;
//存放文件的BASE64编码
QString base64_Data;
//设置请求地址
QUrl url;
//一句话识别的请求地址
requestUrl = QString("https://sis-ext.%1.myhuaweicloud.com/v1/%2/asr/short-audio")
.arg(SERVER_ID)
.arg(PROJECT_ID);
qDebug()<
<
"requestUrl:"<
<
requestUrl;
//设置数据提交格式
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
//将图片进行Base64编码
base64_Data = https://www.songbingjia.com/android/QString(data.toBase64());
//设置token
request.setRawHeader("X-Auth-Token",Token);
//构造请求
url.setUrl(requestUrl);
request.setUrl(url);
//设置采样率
QString post_param=QString
(""
"\\"config\\": "
"\\"audio_format\\": \\"%1\\","
"\\"property\\": \\"%2\\","
"\\"add_punc\\": \\"yes\\","
"\\"digit_norm\\": \\"yes\\","
"\\"need_word_info\\": \\"yes\\""
","
"\\"data\\": \\"%3\\""
"").arg("pcm16k16bit").arg("chinese_16k_common").arg(base64_Data);
/*
chinese_16k_common支持采样率为16k的中文普通话语音识别。
pcm16k16bit16k16bit单通道录音数据。
*/
//发送请求
manager->
post(request, post_param.toUtf8());
3.2 更新token代码
/*
功能: 获取token
*/
void Widget::GetToken()//表示获取token
function_select=3;
QString requestUrl;
QNetworkRequest request;
//设置请求地址
QUrl url;
//获取token请求地址
requestUrl = QString("https://iam.%1.myhuaweicloud.com/v3/auth/tokens")
.arg(SERVER_ID);
//自己创建的TCP服务器,测试用
//requestUrl="http://10.0.0.6:8080";
//设置数据提交格式
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json;
charset=UTF-8"));
//构造请求
url.setUrl(requestUrl);
request.setUrl(url);
QString text =QString("\\"auth\\":\\"identity\\":\\"methods\\":[\\"password\\"],\\"password\\":"
"\\"user\\":\\"domain\\": "
"\\"name\\":\\"%1\\",\\"name\\": \\"%2\\",\\"password\\": \\"%3\\","
"\\"scope\\":\\"project\\":\\"name\\":\\"%4\\"")
.arg(MAIN_USER)
.arg(IAM_USER)
.arg(IAM_PASSWORD)
.arg(SERVER_ID);
//发送请求
manager->
post(request, text.toUtf8());
3.3 华为云返回的结果处理
//解析反馈结果
void Widget::replyFinished(QNetworkReply *reply)QString displayInfo;
int statusCode = reply->
attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
//读取所有数据
QByteArray replyData = https://www.songbingjia.com/android/reply->
readAll();
qDebug()<
<"状态码:"<
<
statusCode;
qDebug()<
<
"反馈的数据:"<
<
QString(replyData);
//更新token
if(function_select==3)displayInfo="token 更新失败.";
//读取HTTP响应头的数据
QList<
QNetworkReply::RawHeaderPair>
RawHeader=reply->
rawHeaderPairs();
qDebug()<
<
"HTTP响应头数量:"<
<
RawHeader.size();
for(int i=0;
i<
RawHeader.size();
i++)QString first=RawHeader.at(i).first;
QString second=RawHeader.at(i).second;
if(first=="X-Subject-Token")Token=second.toUtf8();
displayInfo="token 更新成功.";
//保存到文件
SaveDataToFile(Token);
break;
qDebug()<
<
displayInfo;
return;
//判断状态码
if(200 != statusCode)//解析数据
QJsonParseError json_error;
QJsonDocument document = QJsonDocument::fromJson(replyData, &
json_error);
if(json_error.error == QJsonParseError::NoError)//判断是否是对象,然后开始解析数据
if(document.isObject())QString error_str="";
QJsonObject obj = document.object();
QString error_code;
//解析错误代码
if(obj.contains("error_code"))error_code=obj.take("error_code").toString();
error_str+="错误代码:";
error_str+=error_code;
error_str+="\\n";
if(obj.contains("error_msg"))error_str+="错误消息:";
error_str+=obj.take("error_msg").toString();
error_str+="\\n";
//显示错误代码
qDebug()<
<
error_str;
return;
//语音识别
if(function_select==0)//解析数据
QJsonParseError json_error;
QJsonDocument document = QJsonDocument::fromJson(replyData, &
json_error);
if(json_error.error == QJsonParseError::NoError)//判断是否是对象,然后开始解析数据
if(document.isObject())QString error_str="";
QJsonObject obj = document.object();
QString error_code;
if(obj.contains("result"))QJsonObject obj2=obj.take("result").toObject();
if(obj2.contains("text"))QString text=obj2.take("text").toString();
qDebug()<
<
"识别的文本:"<
<
text;
ui->
lineEdit_text_display->
setText(text);
//浏览器搜索
QString url="https://www.baidu.com/s?ie=UTF-8&
wd="+text;
m_webView->
load(QUrl(url));
//显示错误代码
qDebug()<
<
error_str;
推荐阅读
- Java反序列化漏洞——反射与反序列化基础
- Physical Layer
- 计算机硬件与虚拟机的安装
- MySQL开发篇,存储引擎选择真的很重要吗()
- 使用程序生成要部署的实体和目标环境实体的差别
- Redis入门到实践,由持久化引发的思考
- VMware Tools 启动脚本未能在虚拟机中成功运行。如果您在此虚拟机中配置了自定义启动脚本,请确保该脚本没有错误。您也可以提交支持请求,报告此问题。
- #yyds干货盘点# Redis键过期策略详解
- 虚拟机的安装与使用