Дмитрий10 июля 2017 г. 3:19

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

Библиотека 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) позволяет это сделать. Для этого нужно поставить знак «`» ( на одной клавиши с буквой ё ). Однако точного механизма работы этого инструмента установить не удалось.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Если вы знаете простой способ для извлечения текста из pdf или djv файлов напишите в ответе.

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

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

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Timeweb

Позвольте мне порекомендовать вам отличный хостинг, на котором расположен EVILEG.

В течение многих лет Timeweb доказывает свою стабильность.

Для проектов на Django рекомендую VDS хостинг

Посмотреть Хостинг
СК

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

  • Результат:47баллов,
  • Очки рейтинга-6
ВА

C++ - Тест 001. Первая программа и типы данных

  • Результат:13баллов,
  • Очки рейтинга-10
М
  • Макс
  • 18 сентября 2022 г. 7:04

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:70баллов,
  • Очки рейтинга1
Последние комментарии
F

Инженерное решение кубического уравнения с помощью тригонометрической формулы Виета

красивое домашнее порно анал https://sexs-foto.com/ порно молодых русских бесплатно без регистрации порно знакомства онлайн порно блондинка с большой попой …

Qt/C++ - Урок 035. Скачивание файла по HTTP с помощью QNetworkAccessManager

Попробуйте просто вызвать метод getData в конструкторе класса

Qt/C++ - Урок 035. Скачивание файла по HTTP с помощью QNetworkAccessManager

Здравствуйте! Подскажите, пожалуйста, как сделать так, чтобы программа срабатыала без нажатия кнопки? Ну чисто при загрузке формы... Я так понимаю, надо что-то поменять в этой строчке con…
Р5

Qt/C++ - Урок 051. QMediaPlayer - Аудио плеер на Qt

Здравствуйте. Подскажите пожалуйста, как решить проблему multimedia модуль не распознается

Qt/C++ - Урок 009. QTimer или Как работать с таймером в Qt?

Да, именно так. Но в коде без this написано - это ошибка в статье.
Сейчас обсуждают на форуме
АБ

Sorting the added QML elements in the ListModel

I am writing an alarm clock in QML, I am required to sort the alarms in ascending order (depending on the date or time (if there are several alarms on the same day). I've done the sorting …

Вопрос по Qt Creator

Добрый день. Не знаю, подобную проблему я не решал.

Задать другой класс div-у

Добрый день. Попробуйте использовать Selenium. Это библиотека есть в виде Python модуля и она позволяет загружать страницу и манипулировать html элементами. Как я понимаю, в ней можно…
АЧ

Списки на QML

Вопрос решен с применением базы данных. Кому интересно, можете поюзать проект:) Отдельное спасибо Евгению за помощь)))Вход под админом Логин:1, пароль:1Вход под диспетчером Логин:22, пароль:2Вх…

Хочу переместить QMenuBar

Просто взять и заменить в пару строчек не получится. Qt предусматривает крайне ограниченный функционал по работе с обрамлением окон, к которому относится заголовок окна. Вообще это фу…
О нас
Услуги
© EVILEG 2015-2022
Рекомендует хостинг TIMEWEB