Всем привет! В этой статье будут рассмотрены открытые проекты по синтезу речи с поддержкой русского языка. Под словом «открытые» будем иметь в виду, что разработчики безвозмездно предоставляют в пользование результаты своих трудов (спасибо им за это большое). Также в обзоре вы найдете краткое описание решений с примерами генерации аудио по тексту и полезными ссылками для начального погружения в задачу text-to-speech. Приятного прочтения.
Первые опыты
Мое первое знакомство с аудионейросетями и одновременно их практическое применение началось с задачи дообучения англоговорящей нейросети на русском датасете. Основой модели была архитектура Fast Speech от coqui.ai, это один из популярных проектов в области TTS. Сама модель должна была стать частью телеграм-бота для технической поддержки пользователей (не будем задаваться вопросом зачем).
Неудивительно, что с первого раза сделать качественную нейросеть в ограниченные сроки не представилось возможным, но опыта было получено немерено.
Сегодня создавать с нуля такое решение уже необязательно, поскольку в открытом доступе есть множество моделей удовлетворительного качества. Конечно, количество решений для популярного английского языка значительно больше, но и для русского получилось кое-что найти.
Немножко про сам звук
Из теории звука (подробнее можно почитать тут) для дальнейшего понимания нам понадобятся частота дискретизации, амплитуда и способы его (звука) визуализации.
Частота дискретизации
Важным параметром при обучении нейросетей является частота дискретизации (sample rate по-английски) – количество измерений непрерывного сигнала, сделанных за одну секунду, измеряется в герцах (Гц). Частота дискретизации звука высокого разрешения составляет 192 кГц, но обычно частота дискретизации, используемая при обучении речевых моделей, составляет 16 или 24 кГц (ну и 22 050 Гц).
Частота дискретизации напрямую влияет на качество звука. При выборе модели генерации важно знать, какие частоты дискретизации она поддерживает и желательно какая была частота дискретизации у датасета для обучения.
Амплитуда звуковой волны
Другим важным параметром является амплитуда. Амплитуда определяет уровень звукового давления и измеряется в децибелах (дБ). Для человека амплитуда звука воспринимается как громкость. Децибельная шкала для реального звука начинается с 0 дБ, что соответствует самому тихому звуку, который может услышать человек, а звук громкостью 130 дБ и больше преодолевает болевой порог организма и может вызвать различные патологические процессы.
Часто, например, в электротехнике, можно увидеть отрицательную шкалу дБ, где сигнал в 0 дБ, наоборот, соответствует максимальной мощности, которую может выдать устройство, поэтому значения меньше максимального будут отрицательны.
Фаза звуковой волны
Фаза – это положение волны относительно нулевой амплитуды в определенный момент времени. Фаза, как и амплитуда, является характеристикой любых колебательных процессов, к которым относится и звук.
Визуализация звука
Амплитудный график и частотный спектр
Аудиосигнал можно визуализировать несколькими способами. Самый простой способ – смотреть зависимость амплитуды сигнала от времени.
Другим способом является построение частотного спектра (не связано с частотой дискретизации). Условно сигнал любой сложной формы можно представить в виде «суммы» простых гармонических колебаний различных частот. А строя частотный спектр сигнала (с помощью дискретного преобразования Фурье), можно визуально посмотреть на отдельные частоты, из которых он состоит.
Рассмотрим визуализацию на примере звука музыкальной трубы:
import matplotlib.pyplot as plt
import librosa.display
import librosa
# подгружаем звук
array, sampling_rate = librosa.load(librosa.ex("trumpet"))
array = array[:len(array)//2]
dft_input = array[:4096]
# рассчитаем ДПФ
window = np.hanning(len(dft_input))
windowed_input = dft_input * window
dft = np.fft.rfft(windowed_input)
# получим амплитудный спектр в децибелах
amplitude = np.abs(dft)
amplitude_db = librosa.amplitude_to_db(amplitude, ref=np.max)
# получим частотные столбцы
frequency = librosa.fft_frequencies(sr=sampling_rate, n_fft=len(dft_input))
# строим графики
fig, axis = plt.subplots(nrows=1, ncols=2, figsize = (16, 4))
librosa.display.waveshow(array, sr=sampling_rate, ax = axis[0])
axis[0].set_title("Амплитудный график", fontsize = 18)
axis[1].plot(frequency, amplitude_db)
# axis[1].set_xscale("log")
axis[1].set_title("Частотный спектр", fontsize = 18)
Спектрограмма
Для обучения нейросетей часто используются спектрограммы. Многие модели машинного обучения принимают на вход и выдают на выходе спектрограммы. Спектрограмма строится с применением оконного преобразования Фурье и представляет собой зависимость изменения частот звукового сигнала от времени. Она позволяет увидеть время, частоту и амплитуду на одном изображении.
Для того чтобы воспроизвести звук по спектрограмме, необходимо восстановить из нее волновую форму аудио, что можно сделать с помощью обратного преобразования Фурье. Однако при работе со спектрограммами теряется информация о фазе, и если спектрограмма была сгенерирована моделью машинного обучения, то она, как правило, выдает только амплитуды. В таком случае для восстановления формы волны из спектрограммы можно использовать классический алгоритм Гриффина – Лима или нейронную сеть, называемую вокодером.
Мел-спектрограмма
Мел-спектрограмма – это модификация спектрограммы, в которой частоты выражаются не в Гц, а в мелах. Поскольку слуховая система человека более чувствительна к изменениям на низких частотах, чем на высоких, и эта чувствительность уменьшается логарифмически с увеличением частоты, то шкалу мел применяют для аппроксимации нелинейной чувствительности человеческого слуха.
Подробнее про мел-спектрограммы
Построим спектрограммы отрывка аудио музыкальной трубы:
# строим спектрограммы
fig, axis = plt.subplots(nrows=1, ncols=2, figsize = (16, 4))
D = librosa.stft(array)
S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)
librosa.display.specshow(S_db, x_axis="time", y_axis="hz", ax = axis[0])
axis[0].set_title("Спектрограмма", fontsize = 20)
S = librosa.feature.melspectrogram(y=array, sr=sampling_rate, n_mels=128, fmax=8000)
S_dB = librosa.power_to_db(S, ref=np.max)
librosa.display.specshow(S_dB, x_axis="time", y_axis="mel", sr=sampling_rate, fmax=8000, ax = axis[1])
axis[1].set_title("Мел-спектрограмма", fontsize = 20)
plt.tight_layout()
Наглядное отличие представлено на рисунке ниже:
На этом с теорией звука все, переходим к обзору решений.
Задача TTS
Text-to-speech (TTS) – задача преобразования текста в речь, над решением которой люди работают уже достаточно долго (вспоминая того же Стивена Хокинга). Ранние методы имели в своей основе алгоритмы конкатенации предписанных фонем, однако сгенерированная таким образом речь не имела интонации, не передавала особенности голоса человека и в целом звучала неестественно. Сегодня машинные методы позволяют не только воспроизводить правильные интонации, но и копировать речь людей, хоть и не со 100%-ной схожестью, но с общими чертами и сохранением узнаваемости.
Общие подходы ML к решению TTS
Современные генеративные модели для синтеза звука либо состоят из нескольких логических компонентов, либо являются так называемыми end-to-end-моделями. Подробнее о развитии архитектур можно почитать в этой статье.
Возможные компоненты TTS
Акустические модели генерируют акустические параметры (наиболее часто используемым акустическим параметром является мел-спектрограмма) из лингвистических характеристик или напрямую из фонем или символов. Или, например, в end-to-end-пайплайне модели не требуют сопоставления между языковыми и акустическими фичами, они неявно выучивают данные закономерности и тем самым требуют меньше предварительной обработки.
Существующие решения
coqui.ai / TTS
Этот проект включает в себя множество уже обученных моделей для популярных языков, а также обширный репозиторий кода и документации для самостоятельного обучения. Тут есть и советы по созданию своего датасета, готовые ноутбуки для его проверки, а также «рецепты» по обучению с нуля.
В пределах предобученных моделей русский язык генерируется в мультиязычных моделях, таких как xtts_v1, xtts_v2, bark. Вот примеры генерации каждой из 3 моделей:
Исходя из качества генерации, наиболее подходящей является xtts_v2. Для генерации нового аудио модель может принимать на вход референсный голос или использовать один из 58 (!) встроенных голосов.
Качество выходного аудио сильно коррелирует с качеством референса. Как советует автор, референс должен быть длиной 4-6 секунд и не иметь посторонних шумов, кроме самого голоса.
Архитектура модели представлена в статье, и есть небольшой блог, который ведет разработчик. Вот что он говорит по поводу xtts_v1:
«Подход, используемый в xtts, включает использование диффузионных моделей для перевода выхода GPT-модели в фрейм спектрограммы, далее с помощью UnivNet происходит генерация окончательного аудиосигнала».
Во второй версии xtts разработчики применяют модель Perceiver для выделения латентного вектора, несущего информацию о спикере, а для генерации финальной аудиодорожки они перешли на популярный вокодер HifiGAN.
Для примера сгенерируем несколько голосов известных личностей:
В целом голос переносится +- похоже, общие черты улавливаются, однако специфические интонации речи не всегда реализуются в выходном аудио. Частично при переносе голоса переносятся и ярко выраженные интонации из отрывка референса (вскрики, эмоциональные восклицания или приглушенность речи), из-за этого на выходе могут получиться неровная речь и выделение интонацией в местах, где его быть не должно. Поэтому аудио для референса лучше подбирать со спокойной речью. Также при указании нескольких семплов референса качество выходного аудио улучшается, а при использовании студийной записи без фонового шума получается совсем хорошо!
Bark
Модель на основе трансформеров от компании Suno. Она может генерировать высокореалистичную мультиязычную речь, а также фоновый шум и звуковые эффекты.
Поскольку Bark является полностью генеративной text-to-audio-моделью и ее архитектура похожа на GPT, то и выходное аудио, которое генерируется с нуля, может иметь некоторые особенности. Например, разработчики заявляют, что выходное аудио может генерироваться в любом, в том числе и плохом качестве. Такой подход к разработке пайплайна text-to-speech имеет также и свои плюсы. Так как модель не прибегает к разложению текста на фонемы, то ее возможности генерации не ограничиваются только речью. При задании в промт текста определенных паттернов можно добиться генерации смеха, музыки или вздохов. Сами паттерны не являются чем-то, что задают разработчики, а представляют собой найденные эмпирическим способом команды, которые понимает и более или менее стабильно воспроизводит в аудио модель.
Вот примеры запуска модели с паралингвистическими и эмоциональными звуками:
Правда, во время их создания было переслушано много семплов плохого качества...
Как видим, паттерны не всегда срабатывают, качество генерации скачет, но произношение самих слов правильное и в основном без пропусков. Глобально, если говорить про смех, то подставляются или рандомный смешок, или психопатическая истерия. Иногда модель может предугадать логику текста, например, при передаче диалога озвучивает сам диалог, без имен действующих лиц.
Полагаться как на стабильный генератор аудио не стоит, однако за возможность генерации не только голоса ставим плюс этой модели.
Для русского языка представлены 10 спикеров-промтов, из которых 7 мужских голосов и 3 женских. Большинство из промтов имеет среднее качество, а также фоновый шум. Однако при указании промта модель работает более стабильно и выдержанно по качеству.
Один голос также периодически произносит «ээээ». Как утверждают авторы, больше промтов можно найти в их сообществе в Discord (правда, там вы найдете больше про генерацию песен).
Silero
Русскоязычный проект (кстати, у них есть еще блог на «Хабре», в котором можно еще более подробно ознакомиться с решением) активно развивается и поддерживается разработчиками. Проект открытый и бесплатный, но код для обучения и архитектуры моделей не представлены. В общем доступе расположен репозиторий с предобученными моделями. Список моделей крайне обширный, поражают наличие и качество моделей для языков, использующих специфическую кириллицу, например, узбекского или калмыцкого языков. Вот пример генерации калмыцкой речи:
На мой наполовину калмыцкий взгляд, звучит отлично. Слышно специфику калмыцкой речи, да и голос сам калмыцкий, что бы это ни значило.
У Silero поддерживается генерация на 3 частотах дискретизации (8000, 24 000, 48 000). Для сравнения:
Для 4-й версии модели представлены 5 голосов (aidar, baya, kseniya, xenia, eugene) и рандомный голос, который можно сохранить и использовать для дальнейшей генерации. Кроме того, Silero предоставляет также модель SSML для расстановки ударений и просодий.
Сравнение решений
coqui(xtts) | silero | bark | |
особенности | генерация голоса по референсу | поддержка расширенной кириллицы, генерация речи с акцентом (модели, обученные на голосах представителей различных национальностей России и СНГ) | генеративная модель с возможностями генерации неречевых звуков (смеха и т. п.), а также большим комьюнити |
стриминг | есть | нет | нет |
поддержка и документация | поддержка сайта закончилась, есть модель на Hugging face | сайт с документацией | сообщество в Discord |
тип модели | text-to-speech | text-to-speech | text-to-audio |
частоты дискретизации | 24 кГц | 8, 24, 48 кГц | 24 кГц |
встроенные голоса | на основе референса + 58 голосов | 5 голосов и random | 10 и random |
архитектура | диффузионная модель на основе GPT, Perceiver + HifiGAN | возможно, семейство Tacotron | GPT-архитектура |
характер генерации | авторегрессионный | - | end-to-end |
качество генерации | хорошее | хорошее | плохое |
файнюнинг | есть | нет | нет* |
Vosk-tts
Модель на основе VITS. Генерация как из командной строки, так и из Python API. Есть 5 русских голосов (3 женских и 2 мужских). Частота дискретизации 22 кГц. Генерирует относительно быстро.
Как слышим, с интонациями у модели в целом все нормально. Кроме того, есть подробный пайплайн для файнтюнинга модели на небольшом количестве данных. Так что у кого есть доступ хотя бы к одной видеокарте, можете попробовать обучить говорилку со своим голосом.
Sova-tts
Решение на архитектуре Tacotron 2. Представляет собой REST API сервис, быстро устанавливается. Минималистичный интерфейс, можно менять скорость, питч и громкость при генерации. По идее, можно обучить и добавить свои голоса в сервис. Примеры генерации:
Mimic3
Решение от MicrosoftAI на основе VITS. Есть модель для русского языка, поддерживает 1 женский и 2 мужских голоса. Из интересного: решение можно реализовать на Raspberry Pi. Качество генерации для русского языка – среднее. Есть документация, а также возможность добавления SSML-разметки к тексту.
При генерации можно регулировать скорость и т. п. Пример:
В целом генератор не пропускает и почти не коверкает слова, просто и со вкусом. В интонациях и ударениях ошибается, также обрезает звуки в конце предложения.
Подсказка: На текущий момент модели не подгружаются через lfs, поэтому сразу запустить не получится. Но найти и отдельно скачать эти модели можно на Hugging Face и все будет работать.
Piper
Еще одно решение, которое можно реализовать на Raspberry Pi от разработчика предыдущего проекта. Для русского языка представлено 3 мужских и 1 женский голос. Частота дискретизации – 22 050 Гц. Качество генерации примерно такое же, как у Mimic 3 (но по сравнению с ним не обрезает конец предложений).
SeamlessM4T-v2
Модель генерирует русский язык напрямую, так и реализует пайплайн TTS для русского языка путем генерации текста по английскому промту с дальнейшим переводом его на русский язык. В целом очень интересная реализация. Частота дискретизации – 16 кГц. На русском языке качество ниже среднего и, как мне показалось, переносится акцент.
ЗАКЛЮЧЕНИЕ
Модели по генерации голоса имеют множество архитектурных реализаций, у каждой из которых есть свои плюсы и минусы. Использовать реализованные уже кем-то модели – это зависеть от их решения и его доступности, предобученные модели зачастую будет сложно или невозможно зафайнтюнить самостоятельно. Однако если задача тривиальна и не будет требовать в будущем улучшений качества, скорости работы или дополнительной специфики, то представленные выше проекты потенциально подойдут для задач генерации русской речи.
P. S. Если у вас есть на уме хорошие проекты по генерации русской речи, которые вы не нашли в этой статье, то можете делиться ссылками на них в комментариях.