1. 程式人生 > >Qt:使用百度語音識別REST API,做全平臺語音識別

Qt:使用百度語音識別REST API,做全平臺語音識別

百度語音開發介紹文件:

使用語音識別,需要在百度申請一個應用,然後拿到API Key和Secret Key,然後才可以使用語音識別

ps:我的示例裡面有放了一組可用的Key,但是僅供各位測試使用,有需要開發App的請自行申請,放在示例中的Key我可能隨時會撤銷。

ps:編譯需要開啟C++11的支援

ps:我寫示例在OS X下是沒問題的。但是當我移植到Windows下的時候,在重新整理token那一步有問題,貌似和https有關,等到我想到解決方法的時候回來更新。

ps:示例裡,在重新整理token的地方我直接寫了apikey的明文字串,應該替換成m_apiKey,請手動替換。本頁面中我已經更改了。

直接上程式碼

.h標頭檔案部分

class BaiduVop: public QObject
{
    Q_OBJECT

private:
    QAudioDeviceInfo m_currentDevice;

    QString m_apiKey;
    QString m_secretKey;
    QString m_token;

    QAudioInput *m_audioInput = NULL;
    QByteArray m_buf;
    QBuffer *m_buffer = NULL;

    JasonQt_Net::HTTP m_http;

public:
    BaiduVop(const QString &apiKey, const QString &secretKey);

    void setDevice(const QAudioDeviceInfo &device);

public slots:
    bool refreshToken(void);

    bool start(void);

    std::pair<bool, QString> finish(void);
};

.cpp實現檔案
BaiduVop::BaiduVop(const QString &apiKey, const QString &secretKey):
    m_apiKey(apiKey),
    m_secretKey(secretKey)
{
    const auto &&availableDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
    if(!availableDevices.isEmpty())
    {
        m_currentDevice = availableDevices.first();

        QAudioFormat format;
        format.setSampleRate(8000);
        format.setChannelCount(1);
        format.setSampleSize(16);
        format.setSampleType(QAudioFormat::SignedInt);
        format.setByteOrder(QAudioFormat::LittleEndian);
        format.setCodec("audio/pcm");

        m_audioInput = new QAudioInput(m_currentDevice, format, this);
    }
}

void BaiduVop::setDevice(const QAudioDeviceInfo &device)
{
    m_currentDevice = device;
}

bool BaiduVop::refreshToken(void)
{
    QNetworkRequest request(QUrl(QString("https://openapi.baidu.com/oauth/2.0/token?")));
    QByteArray append = QString("grant_type=client_credentials&client_id=%1&client_secret=%2&").arg(m_apiKey, m_secretKey).toLatin1();
    QByteArray buf;

    request.setRawHeader("Content-Type", "application/json");

    const auto &&flag = m_http.post(request, append, buf, 15000);
    if(!flag) { return false; }

    const auto &&data = QJsonDocument::fromJson(buf).object();
    if(data.isEmpty() || !data.contains("access_token")) { return false; }

    m_token = data["access_token"].toString();
    return true;
}

bool BaiduVop::start(void)
{
    if(m_token.isEmpty())
    {
        qDebug("BaiduVop::start fail, Need refresh token befor start.");
        return false;
    }

    m_buffer = new QBuffer;
    m_buffer->open(QIODevice::ReadWrite);
    m_audioInput->start(m_buffer);

    return true;
}

std::pair<bool, QString> BaiduVop::finish(void)
{
    m_audioInput->stop();

    const auto &sendData = m_buffer->data();
    m_buffer->deleteLater();

    QNetworkRequest request(QUrl("http://vop.baidu.com/server_api"));
    QJsonObject append;

    request.setRawHeader("Content-Type", "application/json");

    append["format"] = "pcm";
    append["rate"] = 8000;
    append["channel"] = 1;
    append["token"] = m_token;
    append["lan"] = "zh";
    append["cuid"] = "JasonQt";
    append["speech"] = QString(sendData.toBase64());
    append["len"] = sendData.size();

    QByteArray buf;
    m_http.post(request, QJsonDocument(append).toJson(), buf, 15000);

    QJsonObject acceptedData(QJsonDocument::fromJson(buf).object());

    if(buf.isEmpty() || acceptedData.isEmpty() || !acceptedData.contains("result")) { return { false, buf }; }

    const auto &&message = acceptedData["result"].toArray()[0].toString();
    return { true, message.mid(0, message.size() - 1) };
}

其中有幾個http的介面已經被我封裝了,需要自行開發的請更改程式碼或者直接下載我的示例,裡面有完整的工程。

可以到下方連結中下載