Библиотека Qt 5.8.0 предоставила программистам возможность использовать системный синтезатор речи. Синтезатор речи - это программа, преобразующая текст в речь. Синтезаторы речи является неотъемлемой частью любой современной операционной системы: Windows (версии 7 и выше), Mac OS, Linux, iOS и Android. Кроссплатформенный интерфейс для управления синтезом речи предоставляет модуль QtTextToSpeech библиотеки Qt.
Для работы с модулем QtTextToSpeech на ОС Windows необходимо:
- установить библиотеку Qt c модулем QtTextToSpeech для компилятора Visual Studio 2015 или старше ( mingw работать не будет );
- установить компилятор Visual Studio 2015 ;
- установить библиотеку SAPI 5.1 , если по какой-то причине она отсутствует на вашем компьютере;
- установить голоса для синтезатора речи (если у вас они отсутствуют).
- При сборке проекта необходимо использовать теневую сборку.
Описание
Если при компиляции программы Вы видите сообщение
Error loading text-to-speech plug-in "sapi"
то вы сделали что-то неправильно.
Если вы используете Android , то по умолчанию у вас работает online синтезатор. За это вы расплатитесь задержкой при синтезе и потраченным трафиком. Если это вас не устраивает, то устанавливайте offline версию. На Android 5.1 для этого необходимо перейти в «настройки» - «специальные возможности» - «синтез речи» - «синтезатор речи Google » - «установка голосовых данных» - «русский (Россия)» и жмём установить и ожидаем завершения. Кроме того, подготавливаем Qt Creator для создания Android приложений.
Теперь можно приступать к написанию программы. По ссылке вы можете скачать проект с исходным кодом программы, описанной ниже. Создаём процесс новый проект qtwidget. В файл проекта подключает необходимый модуль
QT += texttospeech
Подключаем библиотеку синтезатора речи
#include <QtTextToSpeech>
Создаём указатель на объект класса QTextToSpeech
QTextToSpeech* speech;
а затем и сам объект
speech = new QtextToSpeech;
Теперь можно генерировать речевые сигналы с помощью функции say(), в качестве аргумента которой нужно передать произносимый текст. В примерах созданных разработчиками Qt Creator приведён простой пример helloSpeech. Рассмотрите его для того, чтобы лучше понять возможности рассматриваемого модуля.
Я перейду к некоторым более сложным вещам. Программа, которую вы можете скачать по ссылке, содержит виджет класса QTextEdit для воспроизводимого текста , управляющие кнопки: старт, стоп, вперёд назад, …, окно для выбора файлов, и окна для настройки синтезатора.
void MainWindow::start(bool checked)
Запускать на воспроизведение можно и большие текстовые фрагменты. Однако это приводит к необязательным задержкам, а в случае online синтезатора на Android и к зависанию программы. Поэтому дробим текст на фрагменты, чем меньше, тем лучше. Для начала я выделяю из текста абзац ( int activeBlock ), а затем разбиваю строку на лист строк ( QStringList readList ) использую точки в качестве разделителя.
void MainWindow::start(bool checked) { if(checked) { if(readList.isEmpty()) { readList = ui->textEdit->document()->findBlockByNumber( activeBlock ).text().split("."); } if(!readList.isEmpty()) { readString = readList.first(); readList.removeFirst(); if(!readString.contains(QRegularExpression("[A-Z]|[a-z]|[0-9]|[А-Я]|[а-я]"))) { readString = ".";//windows не читает точки if(QSysInfo::productType() == "android") readString = " "; } speech->say( readString ); scrollTo(); ui->textEdit->setReadOnly(true); } } else { readList.prepend(readString);// speech->stop(); ui->textEdit->setReadOnly(false); } }
void MainWindow::speechStateChange(QTextToSpeech::State state)
На синтезатор передаётся одна строчка. После завершения её воспроизведения speech генерирует сигнал stateChanged. Подключенный к ней слот speechStateChange отвечает за воспроизведение очередной строки.
void MainWindow::speechStateChange( QTextToSpeech::State state) { QString mes; switch(state) { case QTextToSpeech::Ready: if(ui->pushButtonStart->isChecked()) { textBlockSelection(colorClean); if(readList.isEmpty()) { if( setActiveBlock( activeBlock+1 ) ) start(); else stop(); } else { start(); } } mes = "ready"; break; case QTextToSpeech::Speaking: textBlockSelection(Qt::green); mes = "speaking"; break; case QTextToSpeech::Paused: mes = "paused"; break; case QTextToSpeech::BackendError: mes = "error"; break; } }
Вспомогательные функции
Для удобства использования программы в качестве читалки были написаны две вспомогательные функции scrollTo() для прокручивания текста до выбранного абзаца и textBlockSelection( QColor ) для выделения читаемого абзаца цветом фона. Ниже приведён их исходный код.
void MainWindow::scrollTo()
void MainWindow::scrollTo() { if(ui->textEdit->verticalScrollBar()->maximum() == 0) return; QTextDocument *textDoc = ui->textEdit->document(); int value = 0; for(int i = 0; i < activeBlock; i++) { value +=textDoc->findBlockByNumber(i).layout()->lineCount() * textDoc->findBlockByNumber(i).layout()->lineAt(0).height() + textDoc->findBlockByNumber(i).blockFormat().bottomMargin(); } if(value <= ui->textEdit->verticalScrollBar()->maximum()) ui->textEdit->verticalScrollBar()->setValue(value); }
bool MainWindow::setActiveBlock(int blockNumber, bool scroll)
bool MainWindow::setActiveBlock(int blockNumber, bool scroll) { readList.clear(); textBlockSelection(colorClean); if(blockNumber < 0) { activeBlock = 0; if(scroll) scrollTo(); return false; } if(blockNumber >= ui->textEdit->document()->blockCount()) { activeBlock = ui->textEdit->document()->blockCount()-1; if(scroll) scrollTo(); return false; } else { activeBlock = blockNumber; if(scroll) scrollTo(); return true; } }
Ударение и Омографы
Существенной проблемой для синтезатора речи является ударение. Особенно в тех случаях, когда два слова пишутся одинаково, но имеют разные ударения (омографы). В таком случае, без применения сложных семантических алгоритмов, ударение может быть выставлено только в ручную. И Windows ( в отличии от Android) позволяет это сделать. Для этого нужно поставить знак «`» ( на одной клавиши с буквой ё ). Однако точного механизма работы этого инструмента установить не удалось.
Если вы знаете простой способ для извлечения текста из pdf или djv файлов напишите в ответе.
Лично я простого не знаю способа. В обоих случаях понадобится использовать сторонние библиотеки.