Мы сделали наш публичный синтез речи еще лучше

6cc6e0011d4d26aeded6f052080b1890

Мы были очень рады, что наша прошлая статья понравилась Хабру. Мы получили много позитивной и негативной обратной связи. Также в ней мы сделали ряд обещаний по развитию нашего синтеза.

Мы достигли существенного прогресса по этим пунктам, но ультимативный релиз со всеми новыми фичами и спикерами может занять относительно много времени, поэтому не хотелось бы уходить в радиомолчание надолго. В этой статье мы ответим на справедливую и не очень критику и поделимся хорошими новостями про развитие нашего синтеза.

Если коротко:


  • Мы сделали наш вокодер в 4 раза быстрее;
  • Мы сделали пакетирование моделей более удобным;
  • Мы сделали мультиспикерную / мультязычную модель и «заставили» спикеров говорить на «чужих» языках;
  • Мы добавили в наши русские модели возможность автопростановки ударений и буквы ё с некоторыми ограничениями;
  • Теперь мы можем сделать голос с нормальным качеством на 15 минутах — 1 часе (с теплого старта в принципе заводилось даже на 3–7 минутах) или на 5 часах аудио (с холодного старта). Но тут все очень сильно зависит от качества самого аудио и ряда деталей;
  • Мы привлекли коммьюнити к работе, и нам помогли сделать удобный интерфейс для записи. Мы начали работу над голосами на языках народностей СНГ (украинский, татарский, башкирский, узбекский, таджикский). Если вы хотите увидеть свой язык в числе спикеров — пишите нам;
  • Мы продолжаем собирать обратную связь по применимости нашей системы для экранных интерфейсов чтения, и пока кажется, что нужно где-то еще всё ускорить в 5–10 раз, чтобы наши модели закрывали и этот кейс;

Справедливая критика

Люди верно заметили, что в первом релизе иностранные языки не содержали ударений вообще, а в русском не было автоматической простановки ударений и буквы ё. Мы просто банально не успели этого сделать. Для русского и украинского мы это наконец сделали. Для других языков — тоже сделаем по мере поиска словарей и надобности (зачастую там и так нормально все работает).

Также стали всплывать известные артефакты используемых нейросетей, например потеря алайна такотроном (симптом — генерация длинного аудио с тишиной в конце). В большинстве случаев это решалось… постановкой точки в конце фразы. Мы внесли соответствующую микроправку.

Хотя мы вроде явно написали про это и даже сделали warning в коде про то, что модель принимает только предложения (а не целые тексты или книги), все равно основной поток комментариев был именно про это. Также мало кто обратил внимание на раздел статьи про скорость работы моделей и батчи (если вы не видели его, прочитайте).

Я привел в комментариях к статье пару простейших примеров в виде ответов на вопросы (раз, два, три, четыре), но чтобы не возвращаться к этому правильный алгоритм работы с моделью такой:


  • Сначала текст надо разбить на предложения оптимальным способом для вашего домена;
  • Потом надо проставить ударения (новые модели русского языка автоматически проставляют ударение и там, где его нет, и букву ё, но можно поставить и руками);
  • Далее надо кормить модель батчами в соответствии с оптимальным сайзингом (например на 2 ядрах процессора оптимальнее всего использовать батч-сайз 1–2);

Упрощаем запуск

Вспоминая опыт с silero-vad, чтобы не множить сущности, мы опубликовали наш синтез в нашем репозитории silero-models. Это имело очевидные плюсы, но и ряд минусов:


  • Если запускать модель через интерфейс с torch.hub, то нахождение в одном репозитории с моделями распознавания речи требовало установки двух библиотек (omegaconf для парсинга yaml-конфига и torchaudio для чтения аудио). Сам синтез не имеет внешних зависимостей кроме стандартной библиотеки питона и PyTorch. Но, если судить только по гневным комментариям и сообщениям в личку, это оказалось слишком сложным даже если дисконтировать радикальные мнения (мне всерьез писали в личку люди, c энтузиазмом стремящиеся доказать что «питон говно»). Люди в итоге не обращали внимание как на интерактивное демо в colab, так и на standalone примеры. По этой причине через какое-то время я добавил пример # Minimal Example to Run Locally;
  • Вообще конечно в идеале для полностью независимого оффлайнового запуска нужно было просто скачать модель, взять этот скрипт загрузки модели, дополнить его своими функциями и убрать лишнее. Но это тоже оказалось слишком сложным и неочевидным;

С учетом того, что механизм вызова моделей сильно усложнился (добавились мульти-язычная модель и автопростановка ударений и буквы ё для русского языка), мы решили довести вопрос с пакетированием до конца и просто использовать новый механизм пакетирования моделей из PyTorch 1.9. По сути единственное реальное отличие состоит в том, что утилиты для каждой модели теперь упакованы вместе с самой моделью и дистрибутив вместе с утилитами теперь можно скачать одним файлом.

Если вызов через torch.hub по сути особо и не изменился:

import torch

language = 'ru'
speaker = 'kseniya_v2'
sample_rate = 16000
device = torch.device('cpu')

model, example_text = torch.hub.load(repo_or_dir='snakers4/silero-models',
                                     model='silero_tts',
                                     language=language,
                                     speaker=speaker)
model.to(device)  # gpu or cpu

audio = model.apply_tts(texts=[example_text],
                        sample_rate=sample_rate)

То полностью standalone вызов стал сильно проще:

import os
import torch

device = torch.device('cpu')
torch.set_num_threads(4)
local_file = 'model.pt'

if not os.path.isfile(local_file):
    torch.hub.download_url_to_file('https://models.silero.ai/models/tts/ru/v2_kseniya.pt',
                                   local_file)  

model = torch.package.PackageImporter(local_file).load_pickle("tts_models", "model")
model.to(device)

example_batch = ['В недрах тундры выдры в г+етрах т+ырят в вёдра ядра кедров.',
                 'Котики - это жидкость!',
                 'М+ама М+илу м+ыла с м+ылом.']
sample_rate = 16000

audio_paths = model.save_wav(texts=example_batch,
                             sample_rate=sample_rate)

Снижение требований по количеству часов и расширение базы голосов

Не секрет, что записывать 15 — 20 часов аудио это тяжелая и кропотливая работа. Мы проверили некоторые исследования, чтобы понять, сколько часов нужно реально для того, чтобы сделать адекватный голос. Например системы синтеза прошлого поколения требуют около 2–3 часов аудио.

У нас получились такие результаты:


С холодного старта, 6 часов:



С теплого старта, 6 часов:


С холодного старта, 3 часа:

Тут уже понятно, что для холодного старта 3 часов маловато.


С теплого старта, 3 часа:


С холодного старта, 1 час:

На холодном старте 1 час вообще уже не работает и генерирует хрип вместо голоса.


С теплого старта, 1 час:

На 1 часу с теплого старта продолжает работать.


С теплого старта, 3 — 15 минут:

И тут нам стало интересно, а какой же минимальный порог после которого с теплого старта перестает работать? На похожем голосе получилось, что нижняя граница лежит где-то в районе 3 минут.




На моем голосе из голосового чата:

Тут у нас закралась мысль, а может в наших экспериментах что-то подтекает или есть ошибки (то есть мы выдаем желаемое за действительное).

Мы просто попробовали взять мой голос из голосового чата с относительно скверным качеством, чтобы точно удостовериться, что все правда работает.

И чудо, оно завелось, но предсказуемо качество аудио очень сильно влияет на конечный результат.


Не секрет, что на рынке есть большое количество американских стартапов, пытающихся продавать свои коммерческие админки для клонирования голоса. Мы пробовали некоторые из них и качество было так себе. Тут в принципе и понятно, почему так происходит. Для синтеза очень важна чистота аудио, чего достичь, просто записывая в шумных условиях в некачественный микрофон, тяжело.

Как и в случае с видео дипфейками, новостное поле искажает их реальный потенциал и возможности, и скорее ограничением на массовое создание «поддельного» контента является даже не столько спорная этическая и финансовая составляющая (я не уверен какой будет LTV у сервиса с поздравлениями, но это скорее всё-таки не про наш рынок), сколько банальное количество усилий, которое надо все равно вложить, чтобы получить хорошее звучание.

Немного усложним задачу:

Давайте теперь попробуем теплый старт на немецком языке, с непохожего голоса другого пола и с непохожего голоса с другого языка:




Хм, все работает с некими оговорками.

Прочие эксперименты:

Ну и напоследок попробуем заставить Ксению говорить по-немецки. Например, вот эту фразу: Mein König, das Fichtenbaum, Bundesausbildungsförderungsgesetz, die Ubüng..


Звучит как ученик на первом уроке немецкого языка. Но мы знаем как сделать это лучше. Кстати одна из небольших фич текущего релиза, что можно заставлять спикеров говорить на других языках. Это пока сильно неидеально работает, но все равно уже прикольно.

Чтобы не разбегались мысли подведем некоторый итог:


  • Для более менее качественного синтеза точно достаточно 5–6 часов качественного аудио (особенно, если новый язык сильно не похож на имеющиеся);
  • Если записи очень качественные и язык похож на имеющиеся, то в принципе можно опускаться и ниже, вплоть до 15 минут — 1 часа;
  • Естественно интонации и эмоции модель выучивает из записанного корпуса, искусственно управлять интонациями мы пока не научились;
  • Именно качество аудиозаписей является критическим моментом для качества синтеза;
  • Мы пока не понимаем как добиться качества и интонаций сравнимых с Алисой, но есть подозрение, что дело в количестве часов (40 — 100 часов) и чистоте аудио;

Мультиязычная модель

После успешных экспериментов нам показалось, что стоит попробовать сделать мультиязычную мультиспикерную модель и «заставить» всех спикеров говорить по-русски. Вот результат. Обратите внимание на то, с какими акцентами говорят спикеры и попробуйте угадать какой язык для них родной.

У этой модели несколько хуже качество, но мы все равно опубликовали ее ради прикола.













Записываем голоса языков народностей СНГ

Также я был приятно удивлен тем, что нам помогли сделать удобный интерфейс для записи голоса и нашлись люди, записавшие / готовые записать спикера на украинском, азербайджанском, башкирском и татарском языках.

photo_2021-05-17_18-05-35

Собственно по причине наличия удобного интерфейса и снижения требований к количеству часов приглашаем всех, кто хочет записать свой голос. Особенно актуально это будет для малых языков допустим для озвучки мультиков и с целью их сохранения. Коллеги из Украины, Башкирии, Азербайджана и Татарстана уже присоединились к процессу.

Поскольку мы научились эффективно тренировать модели даже на небольшом количестве часов и качество аудио является критичным, то только активное и неравнодушное комьюнити тут может помочь сделать голоса на все языки нашей страны.


Ускорение модели

Изначально мы полагали, что именно вокодер будет основной проблемой по скорости в синтезе. Неудивительно, ведь он работает с «длинными» данными. На практике мы были удивлены, что сейчас бутылочным горлышком у нас является не вокодер, но его ускорение останется «про запас».

В текущей итерации у нас получилось ускорить вокодер примерно в 4 раза почти без потери качества (на глаз потеря 0.1 — 0.2 MOS в среднем) и достичь примерно таких цифр:


Это великолепный результат, но теперь осталось подтянуть все остальное. Но тут уже технически нам не хватает ресурсов, чтобы все 10 вещей делать одновременно. В релизе v2 также немного пришлось пожертвовать качеством отдельных моделей в силу ограниченности ресурсов.


Автоматическая простановка ударений

По итогу релиза нам посоветовали несколько публичных проектов, но качество или поддержка их всех были не очень (как правило это все классическое академическое abandonware). Мы прошли большую часть пути с ударениями, но при тестировании на все более сложных или приближенных к реальности кейсах появляются новые моменты, и мы долгое время находились в стадии «финишной прямой».

Основные проблемы:


  • Слов в русских и украинских языках реально много. Словарь может весить 100 — 200 мегабайт. Нужно не только добиться приемлемого качества и скорости работы моделей, но и высокой степени сжатия моделей по сравнению со словарем;
  • В отличие от словаря, модели обладают хоть какой-то генерализацией;
  • У слов в языке сильно отличается частотность и надо соблюсти баланс между размером всей системы, точностью на всех когортах и стоимостью обладания системой;

На текущий момент мы смогли решить задачу простановки ударений, например для русского языка, следующим образом:


  • Для самых популярных слов и словоформ (их примерно 130 тысяч), мы ставим ударение с точностью 99.9%;
  • Для слов со средней популярностью (их примерно 540 тысяч), мы ставим ударение с точностью 99.9%;
  • Примерно 1,300 слов мы включаем в словарь исключений (ошибки на остальных словах из этих когорт);
  • Для слов с низкой популярностью (длинный хвост, примерно 2 миллиона), мы ставим ударение с точностью 99%;
  • В каждой из этих категорий есть примерно 3% слов-омографов, которые мы пока не можем обработать (например зАмок — замОк, хлОпок — хлопОк). Такие слова наша модель специально пропускает, тем самым перенося бремя по простановке усредненного ударения на нашу модель синтеза;

Мы знаем как решить эти 3% в простановке ударений, но нам нужен большой корпус, в котором были бы размечены ударения в предложениях целиком (а не просто отдельные слова). Если вы знаете, где найти такой корпус — будем признательны за наводку. Так мы сможем окончательно решить этот вопрос для синтеза.

Задача простановки буквы ё была также решена с некоторыми оговорками:


  • Омографы, связанные с буквой ё (например все — всё, колеса — колёса), не пропускаются, как в случае с ударениями. Выбрать подобные омографы из корпуса оказалось нетривиальной задачей (часто буква ё на письме игнорируется, поэтому отделить омограф от hard negative сложно без специально размеченных данных);
  • На словаре буквы ё мы ставим её с точностью 99% (как для hard positive, так и для hard negative слов);
  • Модель немного генерализовалась на слова, которых она не видела при обучении. Но всё-таки общее поведение на незнакомых словах — не ставить ё;
  • Случается, что модель предсказывает ударение и букву ё на разные позиции. В таких ситуациях буква ё не будет проставлена;

Есть ещё одна проблема, не решённая на данном этапе: слова с побочными ударениями или несколькими буквами ё (например авиаметеослужба, премьер-министр, трёхколёсный).
Сейчас модель проставляет только одно ударение (и одну ё) в таких словах, но мы планируем в будущем исправить эти кейсы.


Несправедливая критика

По большей части критики конечно просто не понимали, что любые открытые и бесплатные продукты надо воспринимать как «подарок», какое количество усилий и работы было вложено в релиз, и что требовать от открытого продукта наличия упакованных клиентов и интеграций под каждую платформу и приложение как минимум странно.

Если перечислить самые популярные претензии:


  • Нет middleware под конкретный домен или платформу;
  • Нет приложения / интеграции в какое-то другое существующее приложение под какую-то платформу;
  • Слишком сложно, невозможно разобраться;
  • Алиса звучит лучше;

На первые ответ довольно простой — middleware делаются на заказ как часть коммерческого продукта. Если вы хотите поддерживаемый клиент / интеграцию под какую-то платформу, то цена вопроса — цена на поиск + зарплата команды разработки (1–2 человека), умноженная на требуемый срок поддержки.

Насчет Алисы — вы сами выбираете дарить ли свои персональные данные корпорациям. Практика показывает, что де-факто никакой защиты от их недобросовестного поведения нет кроме сил конкуренции. Как говорится: «Если подписал — не удивляйся». Также мы примерно приценивались к «звездным» голосам, там только бюджет на запись голоса уже в разы больше бюджета на весь некоммерческий релиз целиком (нам называли оценки в районе 0.25 — 0.5 миллиона долларов только за запись голоса).

Насчет сложности — мы довели синтез до того, что он вызывается и запускается 1 строчкой кода и фактически требует только только 1 библиотеки и при этом ест очень мало ресурсов при вменяемом качестве. В прошлой версии были некоторые издержки, так как он опубликован в репозитории вместе с STT и мы выбрали радикальную простоту вместо пакетирования. Всегда можно еще сильнее улучшить пакетирование, добавить гайдов под конкретные платформы и улучшить и упростить документацию. Но с учетом количества усилий, которые были вложены в релиз (и продолжают вкладываться в следующие релизы), мое личное мнение — что это уже задача для комьюнити.

Многие из этих причин и в принципе более высокий чем я ожидал уровень шума повлияли на наше решение несколько сместить приоритеты в этом релизе.

Если вы готовы поддержать проект грантом, профинансировать какие-то конкретные фичи или заказать голос для своего проекта — мы всегда будем этому рады. Если вам нужно супер качество, какие-то особенные фичи и интеграции — то это уже следует делать в рамках отдельных проектов.


Дальнейшие планы

Текущий релиз:


  • Ускорение вокодера в 4 раза;
  • Многоязычная мультиспикерная модель (и возможность говорить на другом языке с акцентом);
  • Снижено количество файлов и упрощено пакетирование;
  • Добавление автоматической простановки ударений и простановки буквы ё;
  • Снижение требований по количеству данных и начало работы над голосами народностей СНГ;

Следующие релизы:


  • Высота голоса и скорость;
  • Радикальное ускорение моделей (10+ раз);
  • Эмоции, управление интонацией;
  • Еще большее снижение требований по данным;
  • Добавление новых голосов по мере появления открытых голосов на других языках;
  • Добавление малых языков и языков народностей России и СНГ по мере сбора датасетов;

© Habrahabr.ru