Реклама

Использование модуля QtTextToSpeech для синтеза речи

qttexttospeech, Qt, синтезатор речи, qt speech, qt читалка

Библиотека 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. Рассмотрите его для того, чтобы лучше понять возможности рассматриваемого модуля.

Я переду к некоторым более сложным вещам. Программа, которую вы можете скачать по ссылке, содержит виджет класса Q TextEdit для воспроизводимого текста , управляющие кнопки: старт, стоп, вперёд назад, …, окно для выбора файлов, и окна для настройки синтезатора.

Запускать на воспроизведение можно и большие текстовые фрагменты. Однако это приводит к необязательным задержкам, а в случае 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);
    }
}

На синтезатор передаётся одна строчка. После завершения её воспроизведения 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()
{
    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)
{
    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 файлов напишите в ответе.

Лично я простого не знаю способа. В обоих случаях понадобится использовать сторонние библиотеки.

В случае с pdf - это будет либа, которая работает с pdf, какой-нибудь poppler-qt.
В случае же с djvu - это уже либа по распознаванию текста в изображениях.
Но за пример такой работы ничего не скажу, не занимался таким.

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
  • MinusNol
  • 18 октября 2017 г. 16:09

C++ - Тест 003. Условия и циклы

  • Результат - 85 баллов
  • MinusNol
  • 18 октября 2017 г. 15:41

C++ - Тест 002. Константы

  • Результат - 58 баллов
  • loctyr
  • 18 октября 2017 г. 10:25

Qt - Тест 001. Сигналы и слоты

  • Результат - 94 баллов
Последние комментарии
  • EVILEG
  • 18 октября 2017 г. 14:45

QML - Урок 031. Отключаем системное обрамление окна в QML и пишем код для обработки перемещения и ресайза окна

Задать свои property в окне и проверять их в методах изменения размера для topArea, bottomArea, rightArea, leftArea. В обработчиках onMouseYChanged, onMouseXChanged. Из-за отключен...

  • Troffe
  • 18 октября 2017 г. 14:35

QML - Урок 031. Отключаем системное обрамление окна в QML и пишем код для обработки перемещения и ресайза окна

После отключения системного обрамления не работают minimumHeight и minimumWidth. Что делать?

  • cordsac
  • 17 октября 2017 г. 15:29

Qt/C++ - Урок 045. SvgReader на Qt. Восстановление данных из файла SVG в QGraphicsScene

Sir I post is as a topic,please help me to solve this problem

  • EVILEG
  • 17 октября 2017 г. 11:44

Qt/C++ - Урок 045. SvgReader на Qt. Восстановление данных из файла SVG в QGraphicsScene

I think You have another version of SVG file. First, need to see content of SVG file. It is simple XML-format, therefore just need to research content. Do You want just open SVG file or ...

  • cordsac
  • 17 октября 2017 г. 2:09

Qt/C++ - Урок 045. SvgReader на Qt. Восстановление данных из файла SVG в QGraphicsScene

Sir,I tried your code for open ellipse item.but my program not open ellipse item.what should I need to do? here is my code : readsvg.cpp QL...

Сейчас обсуждают на форуме
  • cordsac
  • 17 октября 2017 г. 19:28

How can I open SVG file through QT

Okay,Thank you sir :)

  • EVILEG
  • 16 октября 2017 г. 20:34

Qt, Загрузка изображения в QImage

Сам view нужно поместить в внутри окна, а не просто создать его. Можете создать в графическом редакторе Qt Creator`а окно, набросать там QGraphicsView и потом посмотреть в сгенерированном...

  • mihenze
  • 15 октября 2017 г. 21:30

Рисуем линию QGraphicsItem за мышью

Большое спасибо!

  • EVILEG
  • 15 октября 2017 г. 18:58

Описание класса С++ в QtCreator

Для начала добавьте недостающие методы и участники для Q_PROPERTY. Для этого вызовите контекстное меню через ПКМ у Q_PROPERTY, там будет пункт "добавить недостающие члены". Автоматически...

  • EVILEG
  • 15 октября 2017 г. 15:34

Qt+Google Drive

Добрый день! Как-то не занимался этим, поэтому такого примера у меня нет в загашниках.