Using QtTextToSpeech for speech synthesis

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

The Qt 5.8.0 library provided programmers with the ability to use a systemic speech synthesizer. A speech synthesizer is a program that converts text to speech. Speech synthesizers are an integral part of any modern operating system: Windows (version 7 and higher), Mac OS, Linux, iOS and Android. Cross-platform interface for managing speech synthesis provides QtTextToSpeech module Qt library.

  • To work with the QtTextToSpeech module on Windows OS, you must:
  • Install the Qt library with the QtTextToSpeech module for the Visual Studio 2015 compiler or older (mingw will not work);
  • Install the Visual Studio 2015 compiler;
  • Install the SAPI 5.1 library if, for some reason, it is not on your computer;
  • Set the voice for the speech synthesizer (if you do not have one).
  • Set the voice for the speech synthesizer (if you do not have one)....

If you compile the program, you see a message

Error loading text-to-speech plug-in "sapi"

then you did something wrong.

If you use Android, then by default you have an online synthesizer. For this you will pay a delay in the synthesis and spent traffic. If this does not suit you, then install the offline version. On Android 5.1, for this you need to go to "settings" - "special features" - "speech synthesis" - "Google speech synthesizer" - "voice data installation" - "Russian (Russia)" and click install and wait for completion. In addition, we prepare Qt Creator for creating Android applications.

Now you can start writing the program. Under the link you can download the project with the source code of the program described below. Create a new qtwidget project. In the project file, connect the necessary module

QT += texttospeech

We connect the synthesizer library of speech

#include <QtTextToSpeech>

Create a pointer to a QTextToSpeech class object

QTextToSpeech * speech ;

And then the object itself

speech = new QtextToSpeech ;

Now you can generate speech signals using the say () function, as the argument of which you need to convey the spoken text. The examples created by Qt Creator developers include a simple helloSpeech example. Consider it in order to better understand the capabilities of the module in question.

I'll move on to some more complicated things. The program, which you can download by reference, contains a widget of the Q TextEdit class for playback text, control buttons: start, stop, forward, ..., a window for selecting files, and windows for setting the synthesizer.

You can also play large text fragments for playback. However, this leads to unnecessary delays, and in the case of the online synthesizer on Android and to the hang of the program. Therefore, we break the text into fragments, the less, the better. First, I select the paragraph (int activeBlock) from the text and then break the line into a sheet of lines (QStringList readList) using the dots as a separator.

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);
    }
}

One line is sent to the synthesizer. Upon completion of its playback, speech generates a stateChanged signal. The speechStateChange slot connected to it is responsible for playing the next line.

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;
    }
}

Secondary functions

For the convenience of using the program as a reader, two auxiliary functions scrollTo () were written to scroll the text to the selected paragraph and textBlockSelection (QColor) to highlight the readable paragraph with the background color. Below is their source code.

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;
    }
}

Emphasis and Homographs

An important problem for a speech synthesizer is stress. Especially in cases where two words are written equally, but have different stresses (omographs). In this case, without the use of complex semantic algorithms, stress can only be set manually. And Windows (unlike Android) allows you to do this. To do this, put a "` "(on one key with the letter e). However, it was not possible to establish the exact mechanism of operation of this tool.

Virtual hosting with 10 percent discount
Virtual hosting with 10 percent discount
EVILEG offers reliable hosting with a 10% discount for virtual hosting and 5% for VPS

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

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

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

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Looking for a Job?
14,000.00 руб. - 40,000.00 руб.
Разработчик Qt
Annino, Moscow Oblast, Russia
5,000.00 руб. - 15,000.00 руб.
Дизайнер
Moskovskiy, Moscow, Russia
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

For registered users on the site there is a minimum amount of advertising

A
Aug. 22, 2019, 11:24 p.m.
Aleksandr73

Qt - Test 001. Signals and slots

  • Result:47points,
  • Rating points-6
Aug. 21, 2019, 10:23 a.m.
Andrej Ermoshin

C++ - Test 002. Constants

  • Result:58points,
  • Rating points-2
Aug. 21, 2019, 10:15 a.m.
Andrej Ermoshin

C++ - Test 001. The first program and data types

  • Result:86points,
  • Rating points6
Last comments
Aug. 19, 2019, 7:41 a.m.
Andrej Jankovich

это проблема дистрибутива, попробуйте установить через пакетный менеджер snap Суть проблемы: libQt5Core которая лежит в дистрибутиве требует версию glibc >= 2.25 у вас видимо …
b
Aug. 18, 2019, 6:09 a.m.
bbb116

cqtdeployer /home/aleks/CQtDeployer/bin/cqtdeployer: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.25' not found (required by /home/aleks/CQtDeployer/lib/libQt5Core.so.5) linux mint …
D
Aug. 17, 2019, 9:04 a.m.
Damir

github ChekableTView Правой групповая смена значения при перетаскивании левой как обычно.
Aug. 16, 2019, 1:03 p.m.
Evgenij Legotskoj

Потому, что в минуте 60 секунд
Aug. 16, 2019, 12:16 p.m.
Dmitrij

а почему делитель 60000, а не 1000?
Now discuss on the forum
Aug. 24, 2019, 7:21 a.m.
Evgenij Legotskoj

Не помню, давно уже с QML не работал, по-моему, обычно пишет в консоль, что не находит файл. В любом случае какую-то ошибку в консоль выкидывает. Но если честно, если у вас проект будет ак…
BG
Aug. 24, 2019, 4:27 a.m.
Brjus Gliff

Спасибо, вначале в документации было не понятно что к чему, теперь разобрался
I
Aug. 21, 2019, 8:36 a.m.
Intruder

Александр, мне не нужно перебирать. Вы говорите правильно, сначала я написал избыточный код просто не подумав. Задача такая, мне нужно просто переложить из QMap в атрибуты xml тега все, что там …
Aug. 21, 2019, 3:16 a.m.
nayk1982

Если Вы разрабатываете какую-то универсальную утилиту, которая вообще не привязана к логике, тогда как вариант: 1. Получить список таблиц через QSqlDatabase::tables 2. Для каждой табли…
EVILEG
About
Services
© EVILEG 2015-2019
Recommend hosting TIMEWEB