QT 使用百度语音识别--生成文本

1. 工程.pro 配置:

QT += multimedia texttospeech network

2.用windows上可用的麦克风进行录音:

audio.h 文件:

cpp 复制代码
#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

audio.cpp文件:

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;


}
  1. 通过把录音文件 通过http请求百度云语音库的方式 ,进行语音转文字

http.h文件:

cpp 复制代码
#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:
    static bool http_postRequst(QString Url, QMap<QString,QString>header, QByteArray &requestData, QByteArray &replyData);
};

#endif // HTTP_H

http.cpp文件:

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();//读取http请求后的结果
        return true;
    }
    return false;
}

请求语句的实现与replyData的解析 :

speech.h文件:

cpp 复制代码
#ifndef SPEECH_H
#define SPEECH_H

#include <QObject>

#include "http.h"

#include <QFile>

#include <QMap>

#include <QByteArray>
#include <QMessageBox>

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>

#include <QHostInfo>

#include <QDebug>

#include <QMessageBox>

const QString BaiduSpeechUrl = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%1&client_secret=%2"; //获取token请求的Url,注册百度语音识别可获得,免费180天
const QString BaiduSpeechClientID = "5VAJlZ5OMInnkkfzLlaWDktx";                                 //AK
const QString BaiduSpeechClientSecret = "JWNha3VuBFpotrXBag2Tf3ALWUCOwFuO";     //SK

//语音识别的Url
//const QString BaiduSpeechSatrtUrl = "https://vop.baidu.com/server_api?dev_pid=80001&cuid=%1&token=%2";//短语音识别极速版
const QString BaiduSpeechSatrtUrl = "https://vop.baidu.com/server_api?dev_pid=1537&cuid=%1&token=%2";  //短语音识别标准版
//80001识别普通话  %1:本机唯一标识(本机标识)  %2:获取的token

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);

private:
    QString accessToken;

};

#endif // SPEECH_H

speech.cpp文件:

cpp 复制代码
#include "speech.h"

Speech::Speech(QObject *parent) : QObject(parent)
{

}

QString Speech::speechIdentify(QString audioFile)
{
    if(audioFile.isEmpty())
    {
        QMessageBox::warning(NULL,"警告(speech)","文件不存在");
        return QString("");
    }

    /* 组装access token的Url */
    QString TokenUrl = QString(BaiduSpeechUrl).arg(BaiduSpeechClientID).arg(BaiduSpeechClientSecret);

    /**************获取token值时不用参数,但自定义http函数需要传入**************/
    QMap<QString, QString>header; 
    header.insert(QString("Content-Type"),QString("audio/pcm;rate=16000"));//Content-Type: audio/pcm;rate=16000键值对       PCM方式上传音频

    QByteArray requestData;//用于存放上传的数据,即录音信息
    QByteArray replyData;//定义存放Http请求结果的字节数组
    /**************获取token值不用的参数,但自定义http_postRequst函数需要传入**************/

    //获取token值,获取一次使用30天
    if(accessToken.isEmpty() == true)//如果还未获取token值
    {
        bool 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);

    qDebug()<<"speechUrl"<<speechUrl;

    /* 把录音文件转换成QByteArray */
    QFile file;
    file.setFileName(audioFile);//获取保存的录音文件
    file.open(QIODevice::ReadOnly);
    requestData = file.readAll();//读取录音文件中的内容
    file.close();

    if(requestData.isEmpty())
    {
        return QString("语音数据为空");
    }

    /* 再次发送请求       语音识别请求 */
    bool ret = Http::http_postRequst(speechUrl, header, requestData, replyData);
    if(ret)
    {
        QString key = "result";
        //解析获取的json信息为QString
          qDebug()<<"hello xjh "<<replyData;
        QString text = getJsonValue(replyData,key);//自定义函数,下方
        return text;//返回识别后的结果
    }else{
        QMessageBox::warning(NULL,"警告(speech)","识别失败");
    }
    return QString("");
}


QString Speech::getJsonValue(QByteArray &data, QString &key)    //自定义json解析函数
{
    QJsonParseError parseError;//json错误判定对象
    QJsonDocument jsonDocument = QJsonDocument::fromJson(data,&parseError);//转换成json文档
    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("");
}

4.主窗体上实现申明调用:

头文件:

#include <QTextToSpeech>

#include <QVoice>

#include "audio.h"//语音识别

申明:

Audio *my_audio;

QTextToSpeech *my_say;

初始化:

复制代码
 my_audio = new Audio;//语音识别对象
 my_say = new QTextToSpeech;//文字转语音 播放

按键实现调用:

void MainWindow::on_btnStartSpeak_clicked()

{

if(speakStatus==false)//开始

{

ui->btnStartSpeak->setText("结束语音");

ui->btnStartSpeak->setStyleSheet(ui->btnStartSpeak->styleSheet()+ "QToolButton{ color: red;}");

speakStatus=true;

my_audio->startAudio("audiofile");

ui->textEditReco->setText("");

}

else

{

ui->btnStartSpeak->setText("开始语音");

ui->btnStartSpeak->setStyleSheet(ui->btnStartSpeak->styleSheet()+ "QToolButton{color: blue;}");

speakStatus=false;

my_audio->stopAudio();

QString retStr = my_audio->startSpeech();//识别结果

my_say->say(retStr);//播放出来

qDebug() << retStr;

ui->textEditReco->setText(retStr);//显示出来

}

}

实验效果:

相关推荐
肖遥Janic6 分钟前
Stable Diffusion绘画 | 插件-Deforum:动态视频生成(上篇)
人工智能·ai·ai作画·stable diffusion
robinfang201914 分钟前
AI在医学领域:Arges框架在溃疡性结肠炎上的应用
人工智能
给自己一个 smile18 分钟前
如何高效使用Prompt与AI大模型对话
人工智能·ai·prompt
魔力之心1 小时前
人工智能与机器学习原理精解【30】
人工智能·机器学习
Hiweir ·1 小时前
NLP任务之文本分类(情感分析)
人工智能·自然语言处理·分类·huggingface
百里香酚兰1 小时前
【AI学习笔记】基于Unity+DeepSeek开发的一些BUG记录&解决方案
人工智能·学习·unity·大模型·deepseek
sp_fyf_20242 小时前
[大语言模型-论文精读] 更大且更可指导的语言模型变得不那么可靠
人工智能·深度学习·神经网络·搜索引擎·语言模型·自然语言处理
肖遥Janic3 小时前
Stable Diffusion绘画 | 插件-Deforum:商业LOGO广告视频
人工智能·ai·ai作画·stable diffusion
我就是全世界4 小时前
一起了解AI的发展历程和AGI的未来展望
人工智能·agi
colorknight4 小时前
1.2.3 HuggingFists安装说明-MacOS安装
人工智能·低代码·macos·huggingface·数据科学·ai agent