原需求:
需要实现文字转语音功能,最开始采用的技术方法是QTextToSpeech,但是无法获取进度,导致出现很多的问题。
后面就改了方案,使用Windows自带的SAPI将文字转为音频,保存本地。
然后使用QMediaPlayer来播放音频。
QMediaPlayer比较强大,支持所有的需求(进度条、播放、暂停、继续播放、设置语速、设置音量)
Demo:
#ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug>#include <QMediaPlayer> #include <QMediaPlaylist>#include <QDir> #include <QStandardPaths>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();public slots:void fn_play();void fn_test();void fn_setRate(int rate);void fn_position(qint64 pos);void fn_duration(qint64 duration);private:Ui::Widget *ui;QMediaPlayer* player = nullptr; }; #endif // WIDGET_H
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 加载本地音频文件(不支持mp3,支持wmv)QString dir_path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);QString file_path = dir_path + "/1.wmv";player = new QMediaPlayer;player->setMedia(QUrl::fromLocalFile(file_path));connect(player, &QMediaPlayer::durationChanged, this, &Widget::fn_duration);connect(player, &QMediaPlayer::positionChanged, this, &Widget::fn_position);connect(ui->radioButton, &QRadioButton::clicked, this, [=](){fn_setRate(0);});connect(ui->radioButton_2, &QRadioButton::clicked, this, [=](){fn_setRate(1);});connect(ui->radioButton_3, &QRadioButton::clicked, this, [=](){fn_setRate(2);});connect(ui->pushButton, &QPushButton::clicked, this, &Widget::fn_bofang);connect(ui->pushButton_2, &QPushButton::clicked, this, &Widget::fn_test); }Widget::~Widget() {delete ui; }void Widget::fn_bofang() {if(player->state() == QMediaPlayer::StoppedState){ player->play(); }else if(player->state() == QMediaPlayer::PlayingState){ player->pause(); }else if(player->state() == QMediaPlayer::PausedState){ player->play(); } }void Widget::fn_test() {qDebug() << "rate:" << player->playbackRate();qDebug() << "state:" << player->state(); }void Widget::fn_setRate(int rate) {if(rate == 0 ){player->setPlaybackRate(0.8);}if(rate == 1 ){player->setPlaybackRate(1.0);}if(rate == 2 ){player->setPlaybackRate(1.2);} }void Widget::fn_position(qint64 pos) {qDebug() << "pos:" << pos;ui->horizontalSlider->setValue(pos); }void Widget::fn_duration(qint64 duration) {qDebug() << "duration:" << duration;ui->horizontalSlider->setMinimum(0);ui->horizontalSlider->setMaximum(duration); }
我的实际项目是根据QTextEdit的文字转的语音,QTextEdit的文字改变后,需要重新生成音频,播放新的音频。
播放新的音频,需要先把Media置空,然后在设置新的音频,这样才能生效,不然一直播放的是之前的音频。
if(player->state() == QMediaPlayer::StoppedState){player->stop();player->setMedia(QMediaContent());QString file_name = QDir::tempPath() + "/tts.wmv";if(QFile::exists(file_name)){bool ret = QFile::remove(file_name);qDebug() << "remove:" << ret;}QString file_path = fn_textToAudio(true);player->setMedia(QUrl::fromLocalFile(file_path));player->play();}