前言
随着社会的发展,科技的不断进步,中国特色社会主义进入新时代,我国社会主要矛盾已经转化为人民日益增长的美好生活需求......不好意思跑题了 咳咳,OK 话不多说,正式步入主题
目录
一、语音识别详细过程
1、使用QT自带音频类录取语音信息
.........此处省略一万字
2、将语音信息上传至百度AI进行识别(HTTP请求)
.........此处省略一万字
3、解析获取的语音识别结果(JSON解析)
.........此处省略一万字
——详情都在代码里
二、代码详情
1_0.音频获取—— .h文件
#ifndef AUDIO_H
#define AUDIO_H
#include <QObject>
#include <QAudioDeviceInfo> //查询音频设备
#include <QAudioInput> //音频输入
#include <QAudioFormat> //音频存储
#include <QFile>
#include <speech.h>
#include <QMessageBox>
#include <QDebug>
class Audio : public QObject
{
Q_OBJECT
public:
explicit Audio(QObject *parent = nullptr);
signals:
public slots:
public:
void startAudio(QString fileName);//初始化
void stopAudio();//停止录音
QString startSpeech();//开始录音并识别
private:
QString AudioFileName;//用于记录音频文件名
QFile *AudioFile;//用于操作音频文件
QAudioInput *AudioDevice;//音频设备对象
Speech *speech;//语音识别对象
};
#endif // AUDIO_H
1_1.音频获取—— .cpp文件
#include "audio.h"
Audio::Audio(QObject *parent) : QObject(parent)
{
speech = new Speech(this);
}
void Audio::startAudio(QString fileName)
{
if(fileName.isEmpty())
{
QMessageBox::warning(NULL,"警告(Audio)","无音频文件名");
return;
}
QAudioDeviceInfo device = QAudioDeviceInfo::defaultInputDevice();//用于检测音频设备状态信息
if(device.isNull())
{
QMessageBox::warning(NULL,"警告(Audio)","无音频设备");
}else{
/* 记录录音文件 */
AudioFileName = fileName;
/* 音频编码要求 */
QAudioFormat m_format;
/* 设置采样频率 */
m_format.setSampleRate(16000);
/* 设置通道数 */
m_format.setChannelCount(1);
/* 设置位深 */
m_format.setSampleSize(16);
/* 设置编码格式 */
m_format.setCodec("audio/pcm");//http上传推荐pcm格式;也可封装成json上传
/* 判断设备是否支持该格式 */
if(!device.isFormatSupported(m_format))
{
/* 寻找最接近的格式 */
m_format = device.nearestFormat(m_format);
}
//打开文件,创建一个音频文件
AudioFile = new QFile;
AudioFile->setFileName(fileName);
AudioFile->open(QIODevice::WriteOnly);
/* 创建录音对象 */
AudioDevice = new QAudioInput(m_format,this);
AudioDevice->start(AudioFile);
}
}
QString Audio::startSpeech()
{
if(AudioFileName.isEmpty())//检查录音文件是否存在
{
QMessageBox::warning(NULL,"警告","文件不存在");
return QString("");
}
return speech->speechIdentify(AudioFileName); //语音识别,并返回识别后的结果,调用speech中的函数
}
void Audio::stopAudio()
{
/* 停止录音 */
AudioDevice->stop();
/* 关闭文件 */
AudioFile->close();
/* 删除文件对象指针并置空 */
delete AudioFile;
AudioFile = nullptr;
}
2_0.语音识别请求——.h文件
#ifndef SPEECH_H
#define SPEECH_H
#include <http.h>
#include <QObject>
#include <QByteArray>
#include <QMessageBox>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QFile>
#include <QHostInfo>
#include <QDebug>
const QString BaiduSpeechUrl = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%1&client_secret=%2"; //获取token请求的Url
const QString BaiduSpeechClientID = "v0jaeF9X3Z7e0n5TsHaD5keZ"; //AK
const QString BaiduSpeechClientSecret = "Sm3pQ1ERXLu11RlRddnlpRBsHBdUNvVn"; //SK
//语音识别的Url
const QString BaiduSpeechSatrtUrl = "https://vop.baidu.com/pro_api?dev_pid=80001&cuid=%1&token=%2"; //80001识别普通话 %1:本机标识 %2:获取的token
/*
* 1.发送获取token值的Url,相当于向百度对接,获取通行证(token值)
* 2.发送语音识别的Url,进行语音识别
*/
class Speech : public QObject
{
Q_OBJECT
public:
explicit Speech(QObject *parent = nullptr);
signals:
public slots:
public:
QString speechIdentify(QString audioFile);//语音识别请求函数
private:
QString getJsonValue(QByteArray &data, QString &key);//json解析函数
private:
QString accessToken;//存放获取的token值
};
#endif // SPEECH_H
2_1.语音识别请求——.cpp文件
#include "speech.h"
Speech::Speech(QObject *parent) : QObject(parent)
{
}
/*Http请求函数*/
QString Speech::speechIdentify(QString audioFile)
{
if(audioFile.isEmpty())
{
QMessageBox::warning(NULL,"警告(speech)","录音文件不存在");
return QString("");
}
bool ret = false;
/* 组装access token的Url */
QString TokenUrl = QString(BaiduSpeechUrl).arg(BaiduSpeechClientID).arg(BaiduSpeechClientSecret);
/**************获取token值不用的参数,但自定义http函数需要传入**************/
QMap<QString, QString>header; //Content-Type: audio/pcm;rate=16000键值对 RAW方式上传音频
header.insert(QString("Content-Type"),QString("audio/pcm;rate=16000"));
QByteArray requestData;//存放上传的录音信息
QByteArray replyData;//存放语音识别返回的结果
/**************获取token值不用的参数,但自定义http函数需要传入**************/
//获取token值,获取一次使用30天
if(accessToken.isEmpty() == true)//如果token值为空,即未获取token值
{
//http请求,以获取token值
ret = Http::http_postRequst(TokenUrl, header, requestData, replyData);
if(ret)
{
QString key = "access_token";
accessToken = getJsonValue(replyData,key);
replyData.clear();
// qDebug() << "获取的token ——" << accessToken;
}
}
/* 将获取的token值组装到新的url中用于发送语音识别请求*/
QString speechUrl = QString(BaiduSpeechSatrtUrl).arg(QHostInfo::localHostName()).arg(accessToken);
/* 把文件转换成QByteArray */
QFile file;
file.setFileName(audioFile);//获取保存的录音文件
file.open(QIODevice::ReadOnly);
requestData = file.readAll();//读取录音文件中的内容
file.close();
if(requestData.isEmpty())
{
return QString("语音数据为空");
}
/* 再次发送http请求 进行语音识别 */
ret = Http::http_postRequst(speechUrl, header, requestData, replyData);
if(ret)
{
QString key = "result";
QString text = getJsonValue(replyData,key);//json解析,自定义函数将结果转换成QString
return text;
}else{
QMessageBox::warning(NULL,"警告(speech)","识别失败");
}
return QString("");
}
/*JSON解析函数*/
QString Speech::getJsonValue(QByteArray &data, QString &key)
{
QJsonParseError parseError;
QJsonDocument jsonDocument = QJsonDocument::fromJson(data,&parseError);
QString retStr = "";
if(parseError.error == QJsonParseError::NoError)
{
if(jsonDocument.isObject())
{
/* 将jsonDocument 转换成json对象 */
QJsonObject jsonObj = jsonDocument.object();
if(jsonObj.contains(key))
{
QJsonValue jsonVal = jsonObj.value(key);
if(jsonVal.isString())
{
return jsonVal.toString();
}
else if(jsonVal.isArray())//检查是否为数组
{
QJsonArray arr = jsonVal.toArray();
for(int index = 0; index<arr.size(); index++)
{
QJsonValue subValue = arr.at(index);
if(subValue.isString())
{
retStr += subValue.toString()+" ";
}
}
return retStr;
}
}
else
{
qDebug() << "不包含关键字:" << key;
}//contains(key)
}
else
{
qDebug() << "不是json对象";
}//isObject
}
else
{
qDebug() << "未成功解析JSON";
}//NoError
qDebug() << "未成功解析JSON:" << data.data();
return QString("");
}
3_0.HTTP请求——.h文件
#ifndef HTTP_H
#define HTTP_H
#include <QObject>
#include <QNetworkAccessManager> //发送请求
#include <QNetworkRequest> //请求内容
#include <QNetworkReply> //返回的结果
#include <QEventLoop>
class Http : public QObject
{
Q_OBJECT
public:
explicit Http(QObject *parent = nullptr);
signals:
public slots:
public:
static bool http_postRequst(QString Url, QMap<QString,QString>header, QByteArray &requestData, QByteArray &replyData);
};
#endif // HTTP_H
3_1.HTTP请求——.cpp文件
#include "http.h"
Http::Http(QObject *parent) : QObject(parent)
{
}
bool Http::http_postRequst(QString Url, QMap<QString, QString> header, QByteArray &requestData, QByteArray &replyData)
{
QNetworkAccessManager manager; //请求者
QNetworkRequest request; //请求内容
request.setUrl(Url); //获取token值时,参数只需要url和接收token值即可
QMapIterator<QString, QString> it(header);
while (it.hasNext()) {//判断header中是否有内容,并读取
it.next();
request.setRawHeader(it.key().toLatin1(),it.value().toLatin1());
}
/* 发送请求等待响应 */
QNetworkReply *Reply = manager.post(request,requestData);//发送请求
QEventLoop l;
connect(Reply,&QNetworkReply::finished,&l,&QEventLoop::quit); //等待响应
l.exec();//阻塞等待响应
if(Reply != nullptr && Reply->error() == QNetworkReply::NoError)
{
replyData = Reply->readAll();//读取获取的语音识别结果
return true;
}
return false;
}
效果展示
总结
通过调用 audio文件中的startAudio函数实现开始录音,stopAudio函数停止录音并使用startSpeech函数上传语音信息进行识别。
项目链接:
注:如果使用时出现以下情况,说明你的QT软件缺少OpenSSL库,建议去安装对应版本的库,不会装的话去网上搜索QT安装openSSL1.0.2教程