1. 前言
随着物联网的发展,语音识别技术越来越受到重视。语音识别技术正在积极推动基于语音识别的人机交互,如语音拨号、语音邮件、语音输入甚至语音控制.虽然生物识别方法越来越多,但语音识别方法仍然是主流方法.与其它生物识别技术相比,语音识别技术不仅具有非接触、非侵入性、使用方便、不会丢失和忘记,不需要记忆和其他特征。
本文采用华为云提供的在线语音识别服务,为浏览器设计语音自动搜索功能,编程语言采用C ,采用软件框架QT浏览器内核采用设计QWebEngineView,在QT5.7以后,QT里就不支持webkit目前自带浏览器内核是QWebEngineView,只能使用MSVC编译编译,mingw使用浏览器可以单独下载webkit库,或使用COM组件调用IE浏览器,当前文章中使用的浏览器是QWebEngineView,编译器采用VS2017,32bit。
使用语音采集功能QT的QAudioInput实现类别,收集声卡PCM通过华为云的语音识别保存数据HTTP接口完成文本识别,然后通过浏览器搜索文本相关内容。
点击界面 开始语音采集按钮,然后单击停止采集,然后调用华为云的语音识别界面进行语音识别,在下面的显示框上显示识别文本,然后完成浏览器的自动搜索。
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 = 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的中文普通话语音识别。 pcm16k16bit 16k16bit单通道录音数据。 */
//发送请求
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 = 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;
}
}
}
}