QtSpeech是一个Qt封装的跨平台TTS(文本变成语音输出)API,在不同平台下利用系统自带的TTS引擎。
【1】在Windows下使用SAPI; 【2】在Mac下使用SpeechSynthesis; 【3】而在Linux下使用 Festival;
需要的类:QTextToSpeech
需要引入的模块:QT +=texttospeech
函数基类:QObjeck
请在.pro项目中添加文本转语音模块 -》texttospeech
为了促进理解,将ui设计界面先奉上,根据界面的信息,整个项目的实现不难理解
main.cpp
#include "mainwindow.h"
#include
#include
int main(int argc, char *argv[])
{
//解决中文乱码
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec);
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
先介绍头文件,将所需的头文件和变量说明清楚
保存语言和国家 目前只有中国和美国为例
QVector voices;
QTextToSpeech *my_tospeech;//说话对象
本次项目第一步通过读取文件内容添加进QPlainTextEdit文本框,然后语音读取里面的内容,语音分为中英文,有男女语音,以在Windows平台为例,低配的某些电脑可能语音无法收听,在Linux平台的需要安装对应的包,这里就不深究了,实际想了解者,可自行修炼。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include //文本转语音类
#include //数组容器类
#include //说话类
#include //日志记录类
#include
#include //文件IO
#include //文件对话框
#include //目录
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public :
void speak();//说话
void Speakstop();//停止
void speakPause();//暂停说话
void speakContinue();//继续说话
void setRate(int );//语速
void setPitch(int );//音高
void setVolume(int );//男 女
void stateChanged(QTextToSpeech::State state);//状态改变
void engineSelected(int index);//引擎选择
void languageSelected(int language);//语言选择
void voiceSelected(int index);//语音选择
void localeChanged(const QLocale &locale);//本地改变
private slots:
void on_PB_speak_2_clicked();//打开文件 写入文本框
private:
Ui::MainWindow *ui;
QVector <QVoice> voices;//保存音量值
QTextToSpeech *my_tospeech;//说话对象
};
#endif // MAINWINDOW_H
配置应该通过一组规则来启用哪些类别和消息类型。 如果在安装程序过滤器()中安装了自定义类别过滤器, 或者如果用户定义了QT_LOGGING_CONF或QT_LOGGING_RULES环境变量,则可能会忽略这些规则。
QStringLiteral: 宏在编译时从字符串文字str中生成QString的数据。在这种情况下,
从它创建一个QString是免费的,生成的字符串数据存储在已编译的对象文件的只读段中。
//日志记录类 安装过滤规则
QLoggingCategory::setFilterRules(QStringLiteral("qt.speech.tts=true \n qt.speech.tts.*=true"));
在本次项目中,信号与槽的初始化使用直接引用地址方式,其于几种自行修炼。
信号与槽可以看作调用函数的地址实现,在以下第二种,就是典型的函数指针类型,static_cast(&QComboBox::currentIndexChanged),其中static_cast代表强制类型转换,里面的参数就是转换类型:
返回值:void
指针:QComboBox:: *
参数:int
需要转化的类型:&QComboBox::currentIndexChanged
`
信号的发送者 :ui->PB_speak
信号函数 :clicked()
信号的接收者 :this
接收槽函数 :speak()
`
connect(ui->PB_speak,&QPushButton::clicked,this,&MainWindow::speak);
//以下这种需要介绍以下
connect(ui->com_language, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &MainWindow::languageSelected);
使用状态栏显示每个阶段的任务,本次添加了-》语速、音量、语言、音高等设置项,内容繁多但在本仙师的运作下,每个阶段皆可柳暗花明。
QTextToSpeech在进行读取 、暂定、停止、继续等阶段,只要按钮按下,QTextToSpeech里面得到枚举值会自动设置,并且QTextToSpeech的信号stateChanged(QTextToSpeech::State state)会触发以下槽函数,所以每次点击按钮显示以下信息不要受到惊吓
//状态改变 读 暂停 继续 停
void MainWindow::stateChanged(QTextToSpeech::State state)
{
if (state == QTextToSpeech::Speaking) {
ui->statusBar->showMessage("正在读取...");
}
else if (state == QTextToSpeech::Ready)
ui->statusBar->showMessage("读取停止...");
else if (state == QTextToSpeech::Paused)
ui->statusBar->showMessage("读取暂停...");
else
ui->statusBar->showMessage("读取错误!!!");
}
头文件和主函数上面已经介绍完毕,这里介绍实现的.cpp文件
内容还是比较繁多,经我折腾一上午,通过qDebug()打印出数据,一切自然明了,每个按钮皆可触发对应的信号与槽,根据函数的先后执行顺序进行理解即可
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),my_tospeech(0) //参数列表初始化
{
ui->setupUi(this);
qDebug()<<"my_tospeech="<<my_tospeech<<endl;
//配置应该通过一组规则来启用哪些类别和消息类型。
//如果在安装程序过滤器()中安装了自定义类别过滤器,
//或者如果用户定义了QT_LOGGING_CONF或QT_LOGGING_RULES环境变量,则可能会忽略这些规则
/*QStringLiteral:宏在编译时从字符串文字str中生成QString的数据。在这种情况下,
* 从它创建一个QString是免费的,生成的字符串数据存储在已编译的对象文件的只读段中。*/
QLoggingCategory::setFilterRules(QStringLiteral("qt.speech.tts=true \n qt.speech.tts.*=true"));
//填充引擎选择列表
ui->com_engine->addItem("Default",tr("Default"));
//获取当前受支持的区域设置的向量。[引擎]
foreach(QString engineList, QTextToSpeech::availableEngines())
{//后一个所有值依次给前面的字符串
ui->com_engine->addItem(engineList, engineList);
qDebug()<<"engineList="<<engineList<<endl;
}
ui->com_engine->setCurrentIndex(0);//默认显示第一项
/*============================================================================*/
engineSelected(0);//填充引擎选择
/*============================================================================*/
//信号与槽
connect(ui->PB_speak,&QPushButton::clicked,this,&MainWindow::speak);
connect(ui->PB_pause,&QPushButton::clicked,this,&MainWindow::speakPause);
connect(ui->PB_continue,&QPushButton::clicked,this,&MainWindow::speakContinue);
connect(ui->PB_stop,&QPushButton::clicked,this,&MainWindow::Speakstop);
connect(ui->horizontalSlider_pitch,&QSlider::valueChanged,this,&MainWindow::setPitch);
connect(ui->horizontalSlider_rate,&QSlider::valueChanged,this,&MainWindow::setRate);
connect(ui->horizontalSlider_volume,&QSlider::valueChanged,this,&MainWindow::setVolume);
//设置QComboBox信号与槽 这里使用函数指针
connect(ui->com_engine,static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),this,&MainWindow::engineSelected);
}
MainWindow::~MainWindow()
{
delete ui;
}
//说话啊 靓仔
void MainWindow::speak()
{
my_tospeech->say(ui->plainTextEdit->toPlainText());//读取文本
ui->PB_stop->setStyleSheet("color:#000000");
ui->PB_speak->setStyleSheet("color:#FF0000");
ui->PB_continue->setStyleSheet("color:#000000");
ui->PB_pause->setStyleSheet("color:#000000");
}
//先暂停下
void MainWindow::speakPause()
{
my_tospeech->pause();
ui->PB_stop->setStyleSheet("color:#000000");
ui->PB_speak->setStyleSheet("color:#000000");
ui->PB_continue->setStyleSheet("color:#000000");
ui->PB_pause->setStyleSheet("color:#FF0000");
}
//继续说话
void MainWindow::speakContinue()
{
qDebug()<<"继续说话";
my_tospeech->resume();
ui->PB_stop->setStyleSheet("color:#000000");
ui->PB_speak->setStyleSheet("color:#000000");
ui->PB_continue->setStyleSheet("color:#FF0000");
ui->PB_pause->setStyleSheet("color:#000000");
}
//停止说话
void MainWindow::Speakstop()
{
my_tospeech->stop();
ui->PB_stop->setStyleSheet("color:#FF0000");
ui->PB_speak->setStyleSheet("color:#000000");
ui->PB_continue->setStyleSheet("color:#000000");
ui->PB_pause->setStyleSheet("color:#000000");
}
//设置语速
void MainWindow::setRate(int rate)
{
qDebug()<<"rate ="<<rate;
my_tospeech->setRate(rate);
}
//设置音高
void MainWindow::setPitch(int pitch)
{
qDebug()<<"pitch ="<<pitch;
my_tospeech->setPitch(pitch);
}
//设置音量
void MainWindow::setVolume(int volume)
{
qDebug()<<"volume ="<<volume;
my_tospeech->setVolume(volume);
}
//引擎 索引改变时触发
void MainWindow::engineSelected(int index)
{
qDebug()<<"index ="<<index<<endl;
QString engineName = ui->com_engine->itemData(index).toString();//获取数据
qDebug()<<"engineName ="<<engineName<<endl;
my_tospeech->deleteLater();//删除
if(engineName == "Default")
my_tospeech = new QTextToSpeech(this);//第一个构造函数
else
my_tospeech = new QTextToSpeech(engineName,this);//第二个构造函数
//此时语言不可连接
disconnect(ui->com_language,static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),this,&MainWindow::languageSelected);;
ui->com_language->clear();
//在连接其信号之前,先填充语言组合框。
//QLocale类在各种语言中的数字及其字符串表示之间进行转换。
QVector<QLocale>locales = my_tospeech->availableLocales();//[语言]
qDebug()<<"locales="<<locales<<endl;
//此属性保存正在使用的当前区域设置。默认情况下,将使用系统区域设置。
QLocale curLocale = my_tospeech->locale();
qDebug()<<"curLocale="<<curLocale<<endl;
foreach (const QLocale &locale, locales) {
QString name = QString("%1 (%2)").arg(QLocale::languageToString(locale.language()))
.arg(QLocale::countryToString(locale.country()));
QVariant localeVal(locale);
ui->com_language->addItem(name,localeVal);
qDebug()<<"name="<<name<<"localeVal="<<localeVal<<endl;
if(locale.name() == curLocale.name())
{
curLocale = locale;
}
}
//设置
setRate(ui->horizontalSlider_rate->value());//语速
setVolume(ui->horizontalSlider_volume->value());//音量
setPitch(ui->horizontalSlider_pitch->value());//音高
connect(my_tospeech, &QTextToSpeech::stateChanged, this, &MainWindow::stateChanged);
connect(my_tospeech, &QTextToSpeech::localeChanged, this, &MainWindow::localeChanged);
//可以选择语言
connect(ui->com_language, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &MainWindow::languageSelected);
/*===============================================================================*/
localeChanged(curLocale);//设置当前语言和国家
/*===============================================================================*/
return;
}
//状态改变 读 暂停 继续 停
void MainWindow::stateChanged(QTextToSpeech::State state)
{
if (state == QTextToSpeech::Speaking) {
ui->statusBar->showMessage("正在读取...");
}
else if (state == QTextToSpeech::Ready)
ui->statusBar->showMessage("读取停止...");
else if (state == QTextToSpeech::Paused)
ui->statusBar->showMessage("读取暂停...");
else
ui->statusBar->showMessage("读取错误!!!");
}
//男女语音 根据语言和国家改变
void MainWindow::localeChanged(const QLocale &locale)
{
qDebug()<<"当前的语言和国家="<<locale<<endl;
ui->statusBar->showMessage("男女语音 国家和语言改变");
QVariant localeVal(locale);
ui->com_language->setCurrentIndex(ui->com_language->findData(localeVal));
//说话类型
disconnect(ui->com_name, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &MainWindow::voiceSelected);
ui->com_name->clear();
voices = my_tospeech->availableVoices();//保存国家和语言在矢量数组
QVoice currentVoice = my_tospeech->voice();
foreach (const QVoice &voice, voices) {
ui->com_name->addItem(QString("%1 - %2 - %3").arg(voice.name())//语音读字人
.arg(QVoice::genderName(voice.gender()))//女性 male:男性的
.arg(QVoice::ageName(voice.age())));//成年的
if (voice.name() == currentVoice.name())
ui->com_name->setCurrentIndex(ui->com_name->count() - 1);
}
connect(ui->com_name, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &MainWindow::voiceSelected);
}
//当前的语言选择
void MainWindow::languageSelected(int language)
{
QLocale locale1 = ui->com_language->itemData(language).toLocale();
qDebug()<<"当前的语言选择="<<ui->com_language->itemText(language)<<endl;
my_tospeech->setLocale(locale1);//设置语言
}
//男女 说话类型
void MainWindow::voiceSelected(int index)
{
qDebug()<<"当前的语音类型="<<ui->com_name->itemText(index)<<endl;
my_tospeech->setVoice(voices.at(index));
}
//打开要读取的文件
void MainWindow::on_PB_speak_2_clicked()
{
ui->plainTextEdit->clear();
QString curPath = QDir::currentPath();
QString Title1 ="打开一个文件";
//文件过滤器
QString filter1 = "文本文件(*.txt);;程序文件(*.cpp *.h);;WPS(*.docx *.xlsx);;所有文件(*.*)";
//获取文件绝对路径
QString filename =QFileDialog::getOpenFileName(this,Title1,curPath,filter1);
if(filename.isEmpty())
return;
qDebug()<<"filename="<<filename<<endl;
//打开文件 读取内容
QFile file(filename);
if(!file.exists())
{
qDebug()<<file.errorString();
return;
}
if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
return;
QByteArray alldata = file.readAll();
QString data(alldata);
ui->plainTextEdit->appendPlainText(tr("%1").arg(data));//将文件内容写入文本框
file.close();
return;
}
语音转文字已不再新奇,也成为了生活必不可少的一部分,音量范围0~99 ,语速也可0~99,不过设置为0即可,不然快到让你意想不到,中文阅读是女士发音,在英文时,有男女发音,可切换多次进行校验,本尊以亲测,皆可使用
【1】打开文件时的效果
【2】说话时的效果
【3】选择英文时的效果,并且选择了男生语音
其他项,实现的效果相差无几,不在过多解释,说话类型和引擎这些选项获取的是电脑支持的类型,可能电脑不同,略有差异,不过能播放语音即可
就不再分享源码了,因为以上便是,推荐各位使用Qt版本5.9.0或者5.9.1功能完善,具有自动补齐功能,不过也有缺点,有些隐含错误不会提示,各有差异,用客自行选择即可,好的咋们下会见。