利用Ai語音合成介面,將文字轉成音訊

編譯環境:window 平臺下 工具:Qt creator 語言C++

下面僅列出核心程式碼,如需全部程式碼請 點選後面連結,自行下載。

原創不易,敬請珍惜

標頭檔案: ttswidget。h

#ifndef TTSWIDGET_H#define TTSWIDGET_H#include #include #include #include #include #include #include “ttshelperdef。h”#include “httpHelper/chttphelper。h”namespace Ui {class TtsWidget;}class TtsWidget : public QWidget{ Q_OBJECTpublic: explicit TtsWidget(QWidget *parent = 0); ~TtsWidget();protected: void paintEvent(QPaintEvent *);private: void InitTable(); void InitTableContent(); void InitControl(); //解析批次合成檔案 bool AnalysisXml(); //獲取token void GetToken(); //解析token響應 QString AnalyticalTokenRes(QString strRes); //合成音訊 bool Tts(QString strText,QString strFileName); //線上播放 bool OnLinePlay(QString strText); QString GetVoiceIndex(); bool getVectVoice(int iIndex,ST_VOICE_XML &strOut);private slots: //雙擊行 void slotRowDoubleClicked(const QModelIndex index); void slots_CurrTtsInfo(QString strText,QString strMp3Name); //選擇批次合成的目標檔案 void on_m_pBtnSelectFile_clicked(); //合成完成 void on_finished(QString strFileName); void on_error(QNetworkReply::NetworkError); //播放已經合成的音訊檔案 void on_m_pBtnPlayVoice_clicked(); //選擇輸出目錄 void on_m_pBtnSelectOutDir_clicked(); //合成 void on_m_pBtnTts_clicked(); //批次合成 void on_m_pBtnBatchTts_clicked(); void on_pushButton_clicked();private: Ui::TtsWidget *ui; QString m_strOutPath; QString m_strXmlFileName; QString m_strMp3OutDir; std::vector m_stXmVectorl; QStandardItemModel* m_model; QStandardItemModel* m_Exmpmodel; QString m_strAppID; QString m_strAPIKey; QString m_strSecretKey; QString m_strToken; QMediaPlayer *m_player; bool m_bIsAllTts; int m_iCurTtsIndex;private: CHttpHelper *m_pHttpHelper; QString m_url;};#endif // TTSWIDGET_H

cpp檔案:ttswidget。cpp

#include “ttswidget。h”#include “ui_ttswidget。h”#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;#pragma execution_character_set(“utf-8”)TtsWidget::TtsWidget(QWidget *parent) : QWidget(parent), ui(new Ui::TtsWidget){ ui->setupUi(this); setFixedSize(1170,600); m_bIsAllTts = false; m_strAppID = “14537614”;//此處我用的是百度的介面 可換成自己的 m_strAPIKey=“53fw6KrAQM6kUqxiCU2iTDj3”; m_strSecretKey=“A3dZCgvAiAYBKleGAIfcl2TaFDy8Z3N4”; m_player=new QMediaPlayer; m_pHttpHelper = new CHttpHelper; InitControl(); GetToken(); //下載完響應finished訊號 connect(m_pHttpHelper, SIGNAL(signalfinished(QString)), this, SLOT(on_finished(QString))); connect(m_pHttpHelper, SIGNAL(signalerror(QNetworkReply::NetworkError)) , this, SLOT(on_error(QNetworkReply::NetworkError)));}TtsWidget::~TtsWidget(){ delete ui;}void TtsWidget::paintEvent(QPaintEvent *){ QString strSkin_name(“。/Config/Res/18。jpg”); QPainter painter(this); painter。drawPixmap(rect(), QPixmap(strSkin_name));}void TtsWidget::on_m_pBtnTts_clicked(){ QString strName = ui->outMp3NamelineEdit->text(); if(strName。isEmpty()) { QMessageBox message(QMessageBox::NoIcon, “Title”, “請選擇生成檔名”); message。exec(); return ; } m_strOutPath =strName; ui->labelTip->setText(“”); QString strText = ui->WilltextEdit->toPlainText(); QString strFileName= ui->outMp3NamelineEdit->text(); Tts(strText,strFileName);}QString TtsWidget::AnalyticalTokenRes(QString strRes){ QString strRet; QJsonParseError jsonError; QJsonDocument doucment = QJsonDocument::fromJson(strRes。toLatin1(), &jsonError); if (jsonError。error != QJsonParseError::NoError) { qDebug() << QStringLiteral(“解析Json失敗”); return false; } // 解析Json if (doucment。isObject()) { QJsonObject obj = doucment。object(); QJsonValue value; if (obj。contains(“access_token”)) { value = obj。take(“access_token”); if (value。isString()) { QString data = value。toString(); strRet = data; m_strToken = data; qDebug()<<“strToken:”<m_YuShuCommBox->currentIndex(); int iYinDiao = ui->m_YinDiaoComboBox->currentIndex(); int iYinLiang = ui->m_YinLiangComboBox->currentIndex(); QString strYushu = QString(“%1”)。arg(iYushu); QString strYinDiao = QString(“%1”)。arg(iYinDiao); QString strYinLiang = QString(“%1”)。arg(iYinLiang); query。addQueryItem(“spd”, strYushu);//語速 query。addQueryItem(“pit”, strYinDiao);//音調 query。addQueryItem(“vol”, strYinLiang);//音量 QString strVoice = GetVoiceIndex(); query。addQueryItem(“per”, strVoice);//度小宇=1,度小美=0,度逍遙=3,度丫丫=4 //度博文=106,度小童=110,度小萌=111,度米朵=103,度小嬌=5 query。addQueryItem(“aue”, “zh”);//3為mp3格式(預設); 4為pcm-16k;5為pcm-8k;6為wav(內容同pcm-16k); url。setQuery(query); qDebug()<HttpDownload_Get(url。toString(),strFileName); return true;}bool TtsWidget::OnLinePlay(QString strText){ QByteArray url=“http://tsn。baidu。com/text2audio?”; QString strParam = QString(“&lan=zh&cuid=12345678&ctp=1&tok=%1&pit=8&per=3” )。arg(m_strToken。toLatin1()。data()); url。append(strParam); url。append(“&tex=”); url。append(QUrl::toPercentEncoding(strText)); qDebug()<setMedia(QUrl::fromLocalFile(url)); m_player->play(); return true;}void TtsWidget::slotRowDoubleClicked(const QModelIndex index){ //透過Model獲取一行 if (index。isValid()) { qDebug() <<“row = ”<itemFromIndex(index); if(0 == index。column()) { ui->WilltextEdit->setText(aItem->text()); } else if(1 == index。column()) { QString strTemp = QString(“/%1/%2”)。arg(m_strMp3OutDir)。arg(aItem->text()); ui->outMp3NamelineEdit->setText(strTemp); } }}bool TtsWidget::AnalysisXml(){ if(m_strXmlFileName。isEmpty()) { return false; } QFile file( m_strXmlFileName ); if( !file。open(QFile::ReadOnly | QFile::Text) ) { qDebug()<tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->tableView->setSelectionMode( QAbstractItemView::SingleSelection); m_Exmpmodel = new QStandardItemModel(); QStringList labels = QObject::trUtf8(“content,mp3”)。simplified()。split(“,”); m_Exmpmodel->setHorizontalHeaderLabels(labels); InitTableContent(); ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//所有列都擴充套件自適應寬度,填充充滿整個螢幕寬度 ui->tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);//對第0列單獨設定固定寬度 ui->tableView->setColumnWidth(0,600);}void TtsWidget::InitTableContent(){ std::vector::iterator itor = m_stXmVectorl。begin(); for(int i = 0;itor != m_stXmVectorl。end();itor++,i++) { ST_VOICE_XML stTemp = *itor; QStandardItem* item = new QStandardItem(QString(“%1”)。arg(stTemp。strText)); m_Exmpmodel->setItem(i,0,item); QStandardItem* item2 = new QStandardItem(QString(“%1”)。arg(stTemp。strMp3Name)); m_Exmpmodel->setItem(i,1,item2); } ui->tableView->setModel(m_Exmpmodel);}void TtsWidget::InitControl(){ m_strMp3OutDir = “D://”; ui->outMp3NamelineEdit->setText(“D://defalut。mp3”); m_strOutPath = “D://defalut。mp3”; //度小宇=1,度小美=0,度逍遙=3,度丫丫=4 //度博文=106,度小童=110,度小萌=111,度米朵=103,度小嬌=5 ui->m_VoiceSetcomboBox->addItem(“小美”); ui->m_VoiceSetcomboBox->addItem(“小宇”); ui->m_VoiceSetcomboBox->addItem(“逍遙”); ui->m_VoiceSetcomboBox->addItem(“丫丫”); ui->m_VoiceSetcomboBox->addItem(“博文”); ui->m_VoiceSetcomboBox->addItem(“小嬌”); ui->m_VoiceSetcomboBox->addItem(“小童”); ui->m_VoiceSetcomboBox->addItem(“小萌”); ui->m_VoiceSetcomboBox->addItem(“米朵”); ui->m_VoiceSetcomboBox->setCurrentIndex(3); for(int i=0;i<15;i++) { QString strTemp = QString(“%1”)。arg(i); ui->m_YinDiaoComboBox->addItem(strTemp); ui->m_YuShuCommBox->addItem(strTemp); ui->m_YinLiangComboBox->addItem(strTemp); } ui->m_YinDiaoComboBox->setCurrentIndex(5); ui->m_YuShuCommBox->setCurrentIndex(5); ui->m_YinLiangComboBox->setCurrentIndex(5); ui->tableView->setMouseTracking(true); connect(ui->tableView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(slotRowDoubleClicked(const QModelIndex &)));}QString TtsWidget::GetVoiceIndex(){ //度小宇=1,度小美=0,度逍遙=3,度丫丫=4 QString strRet=“5”; QString strVoice = ui->m_VoiceSetcomboBox->currentText(); if(strVoice == “小美”) { strRet = “0”; } if(strVoice == “小宇”) { strRet = “1”; } if(strVoice == “逍遙”) { strRet = “3”; } if(strVoice == “丫丫”) { strRet = “0”; } //度博文=106,度小童=110,度小萌=111,度米朵=103,度小嬌=5 if(strVoice == “小嬌”) { strRet = “5”; } if(strVoice == “米朵”) { strRet = “103”; } if(strVoice == “小萌”) { strRet = “111”; } if(strVoice == “小童”) { strRet = “110”; } if(strVoice == “博文”) { strRet = “106”; } return strRet;}void TtsWidget::GetToken(){ QString strUrl = “https://openapi。baidu。com/oauth/2。0/token”; QUrl url(strUrl); // key-value 對 QUrlQuery query; query。addQueryItem(“grant_type”, “client_credentials”); query。addQueryItem(“client_id”, m_strAPIKey); query。addQueryItem(“client_secret”, m_strSecretKey); url。setQuery(query); qDebug()<HttpGet(url。toString()); AnalyticalTokenRes(strRet);}bool TtsWidget::getVectVoice(int iIndex,ST_VOICE_XML &stOut){ bool bRet = false; if(iIndex < m_stXmVectorl。size()) { stOut = m_stXmVectorl。at(iIndex); bRet = true; } return bRet;}void TtsWidget::on_m_pBtnBatchTts_clicked(){ m_bIsAllTts = true; m_iCurTtsIndex = 0; ST_VOICE_XML stTemp; bool bRet = getVectVoice(m_iCurTtsIndex,stTemp); if(bRet) { QString strFileName = QString(“%1/%2”)。arg(m_strMp3OutDir)。arg(stTemp。strMp3Name); Tts(stTemp。strText,strFileName); }}void TtsWidget::on_m_pBtnSelectOutDir_clicked(){ m_strMp3OutDir = QFileDialog::getExistingDirectory(this, tr(“Open File”), “”); if(!m_strMp3OutDir。isEmpty()) { QString strTemp = QString(“%1/defalut。mp3”)。arg(m_strMp3OutDir); ui->outMp3NamelineEdit->setText(strTemp); }}void TtsWidget::slots_CurrTtsInfo(QString strText, QString strMp3Name){ ui->WilltextEdit->setText(strText); ui->outMp3NamelineEdit->setText(strMp3Name);}void TtsWidget::on_m_pBtnSelectFile_clicked(){ m_strXmlFileName = QFileDialog::getOpenFileName(this, tr(“Open File”), “”, tr(“*。xml”)); if(m_strXmlFileName。isEmpty()) { return ; } AnalysisXml();}//網路響應結束void TtsWidget::on_finished(QString strFileName){ QFile file(strFileName); int isize = file。size(); qDebug()<<“file size:”< 0) { strShow = strFileName + “ 語音合成完成”; } else { strShow = strFileName + “ 語音合成失敗”; } ui->labelTip->setText(strShow); if(m_bIsAllTts) { m_iCurTtsIndex +=1; if(m_iCurTtsIndex >= m_stXmVectorl。size()) { m_bIsAllTts = false; } else { ST_VOICE_XML stTemp; bool bRet = getVectVoice(m_iCurTtsIndex,stTemp); if(bRet) { QString strFileName = QString(“%1/%2”)。arg(m_strMp3OutDir)。arg(stTemp。strMp3Name); Tts(stTemp。strText,strFileName); } } }}void TtsWidget::on_error(QNetworkReply::NetworkError error){ qDebug()<<“error:”<labelTip->setText(“合成出錯”);}void TtsWidget::on_m_pBtnPlayVoice_clicked(){ m_strOutPath = ui->outMp3NamelineEdit->text(); if(m_strOutPath。isEmpty()) { if(m_strOutPath。isEmpty()) { QMessageBox message(QMessageBox::NoIcon, “Title”, “請選擇播放的檔名”); message。exec(); return ; } } m_player->setMedia(QUrl::fromLocalFile(m_strOutPath)); m_player->play();}void TtsWidget::on_pushButton_clicked(){}

執行效果圖:

利用Ai語音合成介面,將文字轉成音訊

批次合成配置:VoiceGuid。xml

<?xml version=“1。0” encoding=“utf-8”?>