Русский
Русский
English
Статистика
Реклама

Text-to-speech

Пишем расширение-читалку для Habr

12.02.2021 08:05:33 | Автор: admin

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

В данной статье я хочу показать, как можно совместить утренние сборы на работу с прочтением статей на Habr. Для этого мы напишем простое расширение для браузеров на базе chromium (в частности, Chrome и Opera), которое будет зачитывать для нас вслух открытый во вкладке пост на Habr.

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

Автор туториалаАвтор туториала

Шаг 1. Определим состав расширения

Наше расширение будет состоять из нескольких частей:

  • манифест-файл manifest.json с описанием самого расширения, указанием его основных разрешений, прописыванием путей к иконкам, фоновым скриптами т.д.;

  • HTML-страница popup.html и CSS-файл style.css для popup-формы, на которой будет расположена панель управления воспроизведением аудио;

  • фоновый JavaScript-файл content.js, который будет обращаться к странице с открытым постом и воспроизводить её текстовое содержимое;

  • JavaScript-файл popup.js для popup-формы, с помощью которого фоновому скрипту будут передаваться команды пользователя, заданные через popup-форму;

  • иконки расширения 3 размеров: 128x128, 48x48, 16x16 пикселей.

В итоге получаем примерно такую структуру:

Структура проектаСтруктура проекта

Шаг 2. Подготавливаем манифест-файл

С помощью манифеста мы:

  • сообщаем о том, что мы сделали за расширение;

  • указываем, где хранятся его иконки;

  • запрашиваем доступы к вкладкам;

  • сообщаем о том, что будем выполнять фоновые скрипты;

  • указываем, какой popup мы будем использовать.

Здесь также присутствует разрешение на использование localStorage, если вы захотите менять и сохранять настройки без модификации кода. Пример расширения с применением настроек есть у меня на GitHub.

Содержимое manifest.json
{  "manifest_version": 2,  "name": "Habr Reader",  "description": "Расширение позволяет воспроизводить текст на странице со статьей на Хабре с возможностью изменения языка и скорости воспроизведения",  "version": "1.01",  "developer": {    "name": "Enji Rouz",    "url": "https://github.com/EnjiRouz/Habr-Reader-Extension"  },  "icons": {    "16": "res/icon16.png",    "48": "res/icon48.png",    "128": "res/icon128.png"  },  "permissions": [    "storage",    "http://*/*",    "https://*/*",    "tabs",    "contextMenus"  ],  "background": {    "scripts": ["js/content.js"],    "persistent": true  },  "browser_action": {    "default_icon": "res/icon128.png",    "default_popup": "popup.html",    "icon_128": "res/icon128.png"  },  "content_scripts": [{    "matches": ["<all_urls>"],    "js": ["js/content.js"]  }],  "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';"}

Шаг 3. Делаем popup-форму для управления воспроизведением

С помощью данной формы мы будем ненапрямую:

  • запускать проигрывание синтезированной речи;

  • ставить воспроизведение на паузу;

  • полностью останавливать воспроизведение;

  • менять скорость воспроизведения;

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

Для этого нам потребуется сделать в popup.html несколько кнопок для управления воспроизведением, поле для ввода скорости и переключатель для языков. К странице мы привяжем файл стилей style.css, а также скрипт popup.js, который мы будем запускать после того, как форма полностью загрузится. Для этого добавим после его определения ключевое слово defer.

Содержимое popup.html
<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <link rel="stylesheet" href="css/style.css" type="text/css"/>     <script type="text/javascript" src="js/popup.js" defer></script>     <title>Habr Reader</title> </head> <body> <div class="tool-bar">     <ul>         <li>             <button id="play-button"></button>         </li>         <li>             <button id="pause-button"></button>         </li>         <li>             <button id="stop-button"></button>         </li>         <li>             <label for="speed">Speed</label>             <input type="number" name="speed" id="speed" placeholder="1" value="1" min="0.5" max="2.0"                    step="0.1">         </li>             <li>             <label><input type="radio" name="speech-language" value="ru-RU" id="ru" checked>ru-RU</label>         </li>         <li>             <label><input type="radio" name="speech-language" value="en-US" id="en">en-US</label>         </li>     </ul> </div> </body> </html>
Содержимое style.css
body{    width:180px;    height:60px;    font-family: arial, serif;    font-size: 12px;}.tool-bar{    display: block;    width: 180px;    height: 60px;    line-height: 30px;    background-color: #242424;}.tool-bar ul{    list-style-type: none;    margin: 0;    padding: 0;}.tool-bar ul li{    display: inline-block;    margin: 0;    padding: 0;}button{    background: none;    color: inherit;    border: none;    padding: 0;    font: inherit;    cursor: pointer;    outline: inherit;}.tool-bar ul li button, label{    padding: 0 4px;    text-decoration: none;    color: #FFFFFF;}.tool-bar ul li button:hover{    text-decoration: underline;}input {    width:30px;    padding: 6px 0 4px 10px;    border: 1px solid #9e9e9e;    background: #242424;    border-radius: 4px;    color: #FFFFFF;}

Итоговый вид нашей popup-формы довольно прост и лаконичен. Здесь продемонстрировано, как форма будет отображаться при нажатии на иконку расширения:

Раскрытая popup-форма расширенияРаскрытая popup-форма расширения

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

Упаковку самого расширения мы рассмотрим в конце.

Шаг 4. Передаём управление фоновому скрипту из popup-формы

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

Для этого на каждое событие мы добавим обращение к активной вкладке текущего окна, в котором передадим сообщение. В нём мы укажем следующее:

  • название команды, которую нужно выполнить, например, todo: "play", чтобы сообщить, что мы хотим начать либо продолжить воспроизведение;

  • значения переменных, которые нужны будут для выполнения этой команды, например, newSpeed: speed.value, lang: language,где мы передадим новое значение скорости и языка.

Содержимое popup.js
// определение кнопокconst playButton = document.getElementById("play-button");const pauseButton = document.getElementById("pause-button");const stopButton = document.getElementById("stop-button");// определение полей вводаconst speed = document.getElementById("speed");// назначение действий на соответствующие кнопки/поляif(playButton)    playButton.addEventListener("click", play);if(pauseButton)    pauseButton.addEventListener("click", pause);if(stopButton)    stopButton.addEventListener("click", stop);if(speed)    speed.addEventListener("input", changeSpeed);// применение настроек на странице происходит при помощи их передачи в сообщении,// предназначенном для background скриптаfunction play(){    // определение выбранного языка воспроизведения    let language = document.querySelector('input[name="speech-language"]:checked').value;    chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {        chrome.tabs.sendMessage(tabs[0].id, {todo: "play", newSpeed: speed.value, lang: language});    });}function pause(){    chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {        chrome.tabs.sendMessage(tabs[0].id, {todo: "pause"});    });}function stop(){    chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {        chrome.tabs.sendMessage(tabs[0].id, {todo: "stop"});    });}function changeSpeed(){    chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {        chrome.tabs.sendMessage(tabs[0].id, {todo: "changeSpeed", newSpeed: speed.value});    });}

Шаг 5. Пишем фоновый скрипт для синтеза речи

На самом деле,браузер уже содержит встроенные возможности для синтеза речи. Их мы и будем использовать.

Кстати, если вам хочется побаловаться с браузерным синтезом речи, вот мой проект на GitHub и страница для тестирования, которая будет работать даже со смартфона (за исключением некоторых встроенных в приложения браузеров).

Вот, что будет происходить в нашем фоновом скрипте:

  1. При загрузке страницы, содержащей элемент с ID "post-content-body", скрипт будет рекурсивно складывать содержимое текстовых элементов внутри родительского, чтобы сформировать текст для будущего синтеза (это гораздо проще, чем запрашивать разрешение на использование Habr API, но стоит учитывать, что однажды этот ID может поменяться);

  2. По окончании обхода элементов будет выдано сообщение о том, что пост готов к прочтению (но вы можете вместо этого модифицировать код так, чтобы воспроизведение аудио начиналось сразу после подготовки текста);

  3. Далее ожидается действие пользователя через popup-форму. Как только фоновый скрипт получит сообщение от popup-формы с командой и/или значением переменных, то он инициализирует переменные внутри себя и запустит соответствующие функции, например, найдёт голос для нужного языка, а затем начнёт синтез речи в случае нажатия на кнопку воспроизведения.

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

Далее вы можете модифицировать код на своё усмотрение.

Содержимое content.js
// создание средства синтеза речи и получение списка голосовconst synthesis = window.speechSynthesis;const voices = synthesis.getVoices();const utterance = new SpeechSynthesisUtterance();// текущий символ, который синтезируется в данный момент времениlet currentCharacter;// назначение события на момент, когда речь перестанет проигрыватьсяutterance.addEventListener("end", () => {    currentCharacter = null;});// получение символа, который синтезируется в данный моментutterance.addEventListener("boundary", event => {    currentCharacter = event.charIndex;});// переменные: язык речи, скорость проигрывания аудио, воспроизводимый текстlet speechLanguage = "ru-RU";let playerSpeed = 1;let textToPlay = "Открой статью, а потом уже нажимай сюда";/** * Рекурсивно прибавляет текстовое содержимое дочерних элементов для формирования текста поста * @param elementForSearchingIn - родительский элемент, в котором будет осуществляться поиск текстовых нодов */function joinTextNodes(elementForSearchingIn) {    if (elementForSearchingIn.hasChildNodes()) {        elementForSearchingIn.childNodes.forEach(function (node) {            joinTextNodes(node)        });    } else if (elementForSearchingIn.nodeType === Text.TEXT_NODE) {        textToPlay += " " + elementForSearchingIn.textContent;    }}/** * Поиск голоса для заданного языка речи * @param lang - заданный язык речи * @returns {null|SpeechSynthesisVoice} */function findVoice(lang) {    for (let i = 0; i < voices.length; i++) {        if (voices[i].lang === lang)            return voices[i];    }    return null;}/** * Проигрывание синтезированного высказывания */function playTextToSpeech() {    // если проигрывание речи было поставлено на паузу - происходит продолжение проигрывания    if (synthesis.paused && synthesis.speaking)        return synthesis.resume();    if (synthesis.speaking) return;    // определение параметров синтезируемой речи    utterance.text = textToPlay;    utterance.rate = playerSpeed || 1;    utterance.lang = speechLanguage;    utterance.voice = findVoice(utterance.lang);    // проигрывание речи    synthesis.speak(utterance);}/** * Установка проигрывания синтезированной речи на паузу */function pauseTextToSpeech() {    if (synthesis.speaking)        synthesis.pause();}/** * Остановка (прекращение) проигрывания синтезированной речи */function stopTextToSpeech() {    synthesis.resume();    synthesis.cancel();}/** * Изменение скорости речи в режиме реального времени */function changeSpeed() {    if (synthesis.paused && synthesis.speaking) return;    if (currentCharacter === null) return;    stopTextToSpeech();    playTextToSpeech(utterance.text.substring(currentCharacter));}/** * Осуществление взаимодействия pop-up формы с background скриптом при помощи отправки-получения сообщений * в активной вкладке с передачей в них необходимых для работы параметров. * Переданные параметры перезаписывают предыдущие настройки */chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {    switch (request.todo) {        case "play":            playerSpeed = request.newSpeed;            speechLanguage = request.lang;            playTextToSpeech();            break;        case "changeSpeed":            playerSpeed = request.newSpeed;            changeSpeed();            break;        case "pause":            pauseTextToSpeech();            break;        case "stop":            stopTextToSpeech();            break;    }    sendResponse({        response: "Message received"    });});// подготовка текста поста к чтениюwindow.onload = function () {    let contentBody = document.getElementById("post-content-body");    if (contentBody) {        textToPlay = "";        joinTextNodes(contentBody);        alert("Текст поста готов к чтению")    }};

Шаг 6. Упаковка и установка расширения

Я опишу упаковку и установку для Opera и Chrome. В других браузерах процесс, скорее всего, будет аналогичным, поскольку основные действия мы будем делать через стандартный раздел браузера "Расширения".

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

  • Opera Меню Расширения Расширения включить Режим Разработчика Упаковка расширения

  • Google Chrome Дополнительные инструменты Расширения включить Режим Разработчика Упаковка расширения

На выходе вы получите crx-файл расширения, который, по факту, представляет собой архив с запакованным проектом.

Расширение можно установить через раздел "Расширения" двумя путями:

  • если модификация не требуется - для ряда браузеров достаточно перетащить подготовленный crx-файл из папки с проектом в окно с открытым разделом расширений и нажать на "Установить";

  • если была сделана модификация кода и требуется тестирование перед упаковкой(или браузер блокирует установку), то в окне с разделом расширений требуется нажать на "Загрузить распакованное расширение" и выбрать в диалоговом окне папку с проектом (предварительно убедитесь, что у вас включен режим разработчика).

Заключение

На этом мой небольшой туториал подошёл к концу.

Если у вас есть собственные расширения, которыми вы хотите поделиться - оставляйте в комментариях ссылки на них вместе с кратким описанием.

Кстати, мой хороший товарищ сделал на основе моего проекта расширение для того, чтобы оставлять для себя комментарии к объявлениям на Avito. Кому интересно - код и релиз вы найдёте на его GitHub.

Документированные исходники моего расширения и его запакованную версию можно найти здесь.

Спасибо за внимание! До новых встреч!

Подробнее..

Мы Опубликовали Качественный, Простой, Доступный и Быстрый Синтез Речи

30.03.2021 08:23:00 | Автор: admin

fiona


Вокруг темы синтеза речи сейчас много движения: на рынке есть огромное число тулкитов для синтеза, большое число закрытых коммерческих решений за АПИ (как на современных технологиях, так и на более старых, т.е. "говорилки") от условных GAFA компаний, большое количество американских стартапов, пытающихся сделать очередные аудио дипфейки (voice transfer).


Но мы не видели открытых решений, которые бы удовлетворяли одновременно следующим критериям:


  • Приемлемый уровень естественности речи;
  • Большая библиотека готовых голосов на разных языках;
  • Поддержка синтеза как в 16kHz так и в 8kHz из коробки;
  • Наличие своих собственных голосов у авторов решения, не нарушающих чужие права и лицензии;
  • Высокая скорость работы на "слабом" железе. Достаточная скорость работы на 1 потоке / ядре процессора;
  • Не требует GPU, команды ML инженеров или какой-либо дополнительной тренировки или для использования;
  • Минимализм и отсутствие зависимостей / использование в 1 строчку / не надо ничего собирать или чинить;
  • Позиционируется именно как готовое решение, а не очередной фреймворк / компиляция чужих скриптов / тулкитов для сбора плюсиков;
  • Решение никак не связано и не аффилировано с закрытыми экосистемами и продуктами Гугла / Сбера / Яндекса / вставить нужное;

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


Краткий Обзор Решений


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


  • Конкатенативные модели (появившиеся до DL бума). Из того, что хоть как-то поддерживается и живо и можно запустить "as-is" без археологических раскопок, я нашел только rhvoice (я глубоко не копал, но есть целые форумы, посвященные использованию голосов из Windows, но вряд ли это можно назвать поддерживаемым решением). На момент, когда я пользовался проектом ради интереса, он по сути был заброшен, но потом у него появился новый "хозяин". К плюсам такого рода решений можно отнести их скорость и нетребовательность к ресурсам (исключая ресурсы, чтобы заставить это работать). Очевидный и основной минус звучит как говорилка. Менее очевидный минус довольно тяжело оценить стоимость обладания. Качество звучания: 3+ по пятибалльной шкале;


  • DL-based модели в основном разделяют end-to-end TTS задачу на подзадачи: текст -> фичи и фичи -> речь (вокодинг). Практически повсеместно для первой подзадачи используется Tacotron2. Выделим следующие сочетания моделей в соответствии с их эффективностью и простотой использования:


    • Tacotron2 + WaveNet (оригинальный WaveNet принимал на вход лингвофичи, но для такотрона поменяли на более удобные мелспектрограммы). Основная проблема очень медленный инференс ввиду авторегрессионности модели и необходимость запретительно большого количества ресурсов и времени. Качество звучания: 4+;


    • Tacotron2 + WaveRNN (тоже с переходом от лингвофичей к спектрограммам). Вокодер заметно быстрее предыдущего: при использовании всех хаков можно получить даже риалтайм синтез без GPU, правда естественность звука несколько просядет. Качество звучания: 3.5-4;


    • Tacotron2 + Parallel WaveNet. Упомянутый выше медленный вокодер был использован в качестве учителя для получения новой довольно быстрой параллельной модели вокодера: с ней стал возможен синтез быстрее риалтайма, но все еще на мощных GPU. Из недостатков дистилляция требует качественную учительскую модель и соответствующую схему обучения. Качество звучания: 4+;


    • Tacotron2 + multi-band WaveRNN. Тоже развитие предыдущих идей, тоже распараллеливание в некотором смысле здесь доступен синтез быстрее риалтайма уже на CPU. Однако, не слишком популярная работа, меньше имплементаций и поддержки, хотя некоторые подходы хороши и были успешно использованы в более поздних моделях; Качество звучания: 3.5-4+;


    • Tacotron2 + LPCNet. Интересная идея про сочетание DL и классических алгоритмов, что может дать буст по скорости до подходящего для продакшена уровня и на CPU, но требует вдумчивого допиливания для качественных результатов. Качество звучания: 3.5-4+;


    • Многочисленные решения на базе Tacotron2 + Waveglow от Nvidia как нынешний стандарт для задачи синтеза речи. Никто не пишет про свой "секретный соус" (например как 15.ai делает голос по 15 минутам и сколько там моделей в цепочке). Есть много имплементаций и репозиториев, которые "копируют" чужой код. Может звучать на cherry-picked примерах неотличимо от живых людей, но когда смотришь реальные модели от комьюнити, качество заметно варьируется, а детали улучшенных решений не раскрываются. Архитектурно к такотрону и его аналогам по скорости и цене обладания претензий нет, но Waveglow очень прожорлив к ресурсам как на тренировке, так и в продакшене, что делает его использование по сути нецелесообразным. Качество звучания: 3.5-4+;


    • Замена Tacotron2 => FastSpeech / FastSpeech 2 / FastPitch, то есть уход к более простой сетке (на базе forced-align от такотрона и миллион более хитрых и сложных вариантов). Из полезного дает контроль темпа речи и высоты голоса, что неплохо, вообще упрощает и делает более модульной конечную архитектуру. Немаловажно, что сетка перестает быть рекуррентной, что открывает просторы для оптимизаций по скорости. Качество звучания: 3.5-4+;




Оценки Качества и Примеры Аудио


Чтобы не вдаваться в дебри, мы поступили максимально просто: синтезировали аудио из валидационной выборки датасетов (~200 файлов на спикера), смешали с оригинальными аудио этой же выборки и дали группе из 24 людей для оценки качества звучания по пятибалльной шкале. Для 8kHz и 16kHz оценки собирали раздельно, градация оценок [1, 2, 3, 4-, 4, 4+, 5-, 5] с большей детализацией для более качественного звука.


Всего было поставлено 37,403 оценок. 12 человек сделали оценку полностью. Еще 12 людей успели проставить только от 10% до 75% оценок. Дальше для каждого спикера мы просто посчитали среднее (в скобочках приведено стандартное отклонение). Расчет среднего от медиан по каждому аудио завышает средние оценки на 0.1 0.2 балла, но не влияет на отношения. Показательны естественно скорее отношения средних баллов друг к другу. Дисперсия довольно высокая, но оценки пользователей отличались сильно и мы решили не выбрасывать никакие, т.к. оценки одного пользователя были консистентными друг с другом. По ряду соображений мы провели такую оценку только на своих уникальных голосах:


Спикер Оригинал Синтез Отношение Примеры
aidar_8khz 4.67 (.45) 4.52 (.55) 96.8% link
baya_8khz 4.52 (.57) 4.25 (.76) 94.0% link
kseniya_8khz 4.80 (.40) 4.54 (.60) 94.5% link
aidar_16khz 4.72 (.43) 4.53 (.55) 95.9% link
baya_16khz 4.59 (.55) 4.18 (.76) 91.1% link
kseniya_16khz 4.84 (.37) 4.54 (.59) 93.9% link

Мы просили людей в первую очередь оценивать естественность звучания речи (а не качество звука). Нас удивило, что по расспросам обычные люди на своих ежедневных дивайсах не особо слышат разницу между 8 kHz и 16 kHz (что подтверждается оценками)! Самые низкие абсолютные оценки и самое низкое отношение у Байи. Самые высокие абсолютные оценки у Ксении, а относительные у Айдара. Тут важно отметить, что у Байи меньше поставлен голос, но поэтому он звучит более по-человечески за счет этого. У Байи также выше дисперсия оценок.


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


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


Сравнение Хуже Одинаково Лучше
16k против 8k, оригинал 957 4811 1512
16k против 8k, синтез 1668 4061 1551
Оригинал против синтеза, 8k 816 3697 2767
Оригинал против синтеза, 16k 674 3462 3144

Тут напрашивается несколько выводов:


  • В 66% случаев люди не слышат разницы между 8k и 16k;
  • В синтезе, 8k немного помогает скрыть ошибки;
  • Примерно в 60% случаев люди считают, что синтез не хуже оригнала по естественности;
  • Показательно, что два последних вывода не особо зависят от частоты дискретизации (8k имеет небольшое преимущество);

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


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


Айдар:





Байя:





Ксения:





Еще раз обращаю внимание, что это не cherry-picked примеры, а реальное звучание синтеза.


Бенчмарки по Скорости


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


  • RTF (Real Time Factor) какую долю длительности аудио занимает синтез этого аудио;
  • RTS = 1 / RTF (Real Time Speed) насколько синтез "быстрее" риалтайма;

Метрики мы снимали на двух устройствах с помощью встроенных в PyTorch 1.8 утилит:


  • CPU Intel i7-6800K CPU @ 3.40GHz;
  • GPU 1080 Ti;
  • При снятии метрик на CPU мы также ограничивали число используемых потоков;

Для моделей 16 kHz получаются такие показатели:


Батч Устройство RTF RTS
1 CPU 1 thread 0.7 1.4
1 CPU 2 threads 0.4 2.3
1 CPU 4 threads 0.3 3.1
4 CPU 1 thread 0.5 2.0
4 CPU 2 threads 0.3 3.2
4 CPU 4 threads 0.2 4.9
--- ----------- --- ---
1 GPU 0.06 16.9
4 GPU 0.02 51.7
8 GPU 0.01 79.4
16 GPU 0.008 122.9
32 GPU 0.006 161.2
--- ----------- --- ---

Для моделей 8 kHz получаются такие показатели:


Батч Устройство RTF RTS
1 CPU 1 thread 0.5 1.9
1 CPU 2 threads 0.3 3.0
1 CPU 4 threads 0.2 4.2
4 CPU 1 thread 0.4 2.8
4 CPU 1 threads 0.2 4.4
4 CPU 4 threads 0.1 6.6
--- ----------- --- ---
1 GPU 0.06 17.5
4 GPU 0.02 55.0
8 GPU 0.01 92.1
16 GPU 0.007 147.7
32 GPU 0.004 227.5
--- ----------- --- ---

Также при расчетах скорости мы были удивлены ряду вещей:


  • Процессоры AMD показали себя сильно хуже;
  • Удивительно, но бутылочным горлышком в нашем случае оказался именно такотрон а не вокодер (то еще остается существенный потенциал ускорения всей системы в 3-4 раза, а может даже и в 10 раз, если получится квантизация и дополнительное сжатие);
  • Более чем 4 потока CPU не помогают, равно как и батч больше 4;

Список Доступных моделей и Ссылки на Датасеты


Для просты мы решили опубликовать все наши модели в рамках проекта silero-models. Список актуальных моделей всегда можно найти в этом yaml файле.


На момент написания этой статьи доступны следующие голоса (доступны _16khz и _8khz версии голосов):


Спикер Пол Язык Источник Лицензия Датасета Примеры Colab
aidar m ru Silero Private 8000 / 16000 Open In Colab
baya f ru Silero Private 8000 / 16000 Open In Colab
ksenia f ru Silero Private 8000 / 16000 Open In Colab
irina f ru Private contribution TBD 8000 / 16000 Open In Colab
natasha f ru source CC BY 4.0 8000 / 16000 Open In Colab
ruslan m ru source CC BY-NC-SA 4.0 8000 / 16000 Open In Colab
lj f en source Public Domain 8000 / 16000 Open In Colab
thorsten m de source Creative Commons Zero v1.0 Universal 8000 / 16000 Open In Colab
gilles m fr source Public Domain 8000 / 16000 Open In Colab
tux m es source Public Domain 8000 / 16000 Open In Colab

Как Попробовать


Все модели опубликованы в репозитории silero-models, там также есть примеры запуска синтеза в colab. Для полноты приведем минималистичный пример (да, это действительно так просто):


import torchlanguage = 'ru'speaker = 'kseniya_16khz'device = torch.device('cpu')(model, symbols, sample_rate, example_text, apply_tts) = torch.hub.load(repo_or_dir='snakers4/silero-models',                                          model='silero_tts',                                          language=language,                                          speaker=speaker)model = model.to(device)  # gpu or cpuaudio = apply_tts(texts=[example_text],                  model=model,                  sample_rate=sample_rate,                  symbols=symbols,                  device=device)

На данный момент поддерживаются следующие спец-символы: !\'(),.:;?. Кроме того, для большинства спикеров русского языка в тексте для озвучивания были использованы метки ударения (символ + перед ударной гласной, при тестировании таких моделей пока еще нужно ставить ударение вручную):


Спикер С ударением
aidar да
baya да
ksenia да
irina да
natasha да
ruslan да
lj нет
thorsten нет
gilles нет
tux нет

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


Философия, Лицензия и Мотивация


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


  • Голоса из внешних источников приведены исключительно в целях демонстрации и будут удалены;
  • Любые из описанных выше моделей нельзя использовать в коммерческих продуктах;
  • Репозиторий silero-models опубликован под лицензией GNU A-GPL 3.0. Де-юре это не запрещает коммерческое использование, но по факту мы еще не встречали коммерческие решения с полностью открытым кодом, чего требует эта лицензия;
  • Если вы ставите своей целью некоммерческое использование наших моделей во благо общества мы будем рады помочь вам с интеграцией моделей в ваше решение;
  • Если вы планируете использование наших моделей в личных целях (по фану или для озвучки каких-то текстов), то делитесь результатами своих экспериментов в репозитории;
  • Если вы планируете использование наших моделей в некоммерческих продуктах для людей с нарушениями речи или зрения обращайтесь, мы поможем с интеграцией, чем умеем;

Делая этот проект мы ставили своей целью ценой многочисленных компромиссов показать, что современный TTS, удовлетворяющий описанным выше критериям, возможен. И для этого не нужно заложником закрытых экосистем корпораций.


Дальнейшая Работа


Мы планируем постоянно развивать и улучшать свое решение, в частности:


  • Рано или поздно добавить поддержку изменения скорости и высоты голоса;
  • Продолжать работать над качеством и естественностью звучания и расширять библиотеку голосов;
  • Мы оцениваем, что есть еще запас ускорения всего пайплайна в целом примерно в 3-4 раза (возможно даже до 10 раз, если повезет);
  • Маловероятно но не исключено, что рано или поздно мы сможем добавить мульти-спикерную модель или voice-transfer;

Скороговорки


И в качестве бонуса, немного скороговорок.


Русский язык:






Другие языки:





Подробнее..

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

18.06.2021 14:19:30 | Автор: admin

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 torchlanguage = 'ru'speaker = 'kseniya_v2'sample_rate = 16000device = 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 cpuaudio = model.apply_tts(texts=[example_text],                        sample_rate=sample_rate)

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


import osimport torchdevice = 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 = 16000audio_paths = model.save_wav(texts=example_batch,                             sample_rate=sample_rate)

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


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


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


Количество аудио Тип старта Результат
15 20 часов с холодного модели в репозитории
5-6 часов с холодного заводится, нормальное качество, примеры ниже
3 часа с холодного заводится, но речь уже не очень членораздельна
1 час с холодного не заводится совсем
-------------------------- ------------------------ ---------------------------------------------------------
5-6 часов с теплого, похожий голос заводится чуть быстрее, нормальное качество, примеры ниже
5-6 часов с теплого, другой пол заводится, нормальное качество, примеры ниже
5-6 часов с теплого старта с теплого, другой язык заводится, нормальное качество, примеры ниже
3 часа с теплого, похожий голос заводится, качество чуть хуже, примеры ниже
1 час с теплого, похожий голос заводится, качество чуть хуже, примеры ниже
3 15 минут с теплого, похожий голос заводится, на 3 минутах уже сильно проседает качество

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




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



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


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



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



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


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



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


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



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


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





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


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


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


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



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


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


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


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





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


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


Ну и напоследок попробуем заставить Ксению говорить по-немецки. Например, вот эту фразу: Mein Knig, das Fichtenbaum, Bundesausbildungsfrderungsgesetz, die Ubng..



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


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


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

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


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


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













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


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


photo_2021-05-17_18-05-35


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


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


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


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


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


Модель 8 kHz 16 kHz
v1 только вокодер, 1 поток 18 8
v2 только вокодер, 1 поток 70 35

Это великолепный результат, но теперь осталось подтянуть все остальное. Но тут уже технически нам не хватает ресурсов, чтобы все 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+ раз);
  • Эмоции, управление интонацией;
  • Еще большее снижение требований по данным;
  • Добавление новых голосов по мере появления открытых голосов на других языках;
  • Добавление малых языков и языков народностей России и СНГ по мере сбора датасетов;
Подробнее..

Веб-клиент Google Cloud Text to Speech за завтраком в бастионе Сен-Жерве

13.04.2021 04:20:54 | Автор: admin

С самых юных лет, с самого первого прочтения залпом "Трех мушкетеров" автор неколебимо убежден, что оптимальный способ обучения чему-либо - практика. Теорию в дальнейшем можно подучить и подточить, друзья-мушкетеры "покажут несколько славных приемов", не проблема. Но, если верить досточтимому мэтру Дюма (а автор ему верит), оптимальный способ интеграции в любую новую для себя сущность - сходу погрузиться в нее с головой, а там как пойдет. Где наша не пропадала, да и, как известно, любой гасконец с детства академик.

Вообще, если интерес возникнет, то это всегда 90% успеха, поверьте... ну, а если не возникнет, что ж. Сэкономите время: стало быть, не ваше. Сейчас, таким образом, самонадеянный и скорый на подъем аффтор, всегда готовый выхватить шпагу при виде гнусного тролля на любом интернет-форуме - предлагает всем dbutants потратить всего лишь полчаса-час на то, чтобы заинтересоваться сразу несколькими технологиями, в числе которых язык программирования Ruby, API Google Cloud Text to Speech, облачная PaaS-платформа Heroku и git.

К слову. Предвидя сделанные на языке растреклятых англичан, исконных врагов любого истинного француза комментарии в стиле "Is ruby dead?", в том смысле, а есть ли смысл вообще этим заниматься... автор предлагает всем любителям потрепаться-ни-о-чем-в-инете временно оставить эту животрепещущую тематику, сменив ее на рекомендации по изготовлению чудодейственного бальзама, наподобие того, что дала в путь-дорогу д`Артаньяну любящая его матушка, и который помог бы, в духе дня, раз и навсегда избавиться от спама за подписью того или иного эйчара, русскоговорящего или европейца/американца, несколько раз в неделю присылающих абсолютно ненужные автору инвайты на позицию Ruby Developer. Ненужные не потому, что автор, вволю напрактиковавшись и слегка "подточив" теорию, привык получать приглашения исключительно и самолично из рук аж самого CTO Armand-Jean du Plessis, duc de Richelieu... а потому, что за все годы работы - ни одного проекта, ни одной должности от HR он не получил, так уж сложилось.

Чего и вам от души желает. Если какой-либо институт и мертв, то это почти наверняка Human Resource, по крайней мере, у нас в России (как с этим обстоят дела у Бекингема - Бог весть, не знаю). Все остальное покамест работает... это была, так сказать, литературная прелюдия, ну а теперь сходу к практике, с места в карьер. "Сударь, вы ошиблись! Нас не трое, нас четверо!"

Итак. Цель сегодняшних наших упражнений - построение приложения, работающего с API Google Cloud Text to Speech, иными словами - конвертера текста в звук, и с очень неплохим качеством. Правда, все чаще раздаются голоса, дескать, IBM Text-to-Speech API круче, но это мы оставим, с вашего позволения, для следующей статьи... "голоса" обычно не скрывают, что IBM API обходится недешево, гугловский же сервис возможно использовать практически бесплатно (находим и внимательно читаем Terms of Service). Но вам понадобится волшебный ключ, нечто в стиле "то, что сделал предъявитель сего, сделано по моему приказанию и для блага государства" в формате JSON, для получения которого, вполне возможно, придется засветить ваш MasterCard здесь. Может быть, даже заморозят на недельку кровный ваш $1, ничего? - ну всяко это не так страшно, как в военное де-факто время совершать вояж за линию фронта, будучи вдохновленным одним лишь лукавым взглядом г-жи Бонасье, согласитесь.

Также зарегистрируйте Free account Heroku, куда мы с вами намереваемся пушить ваше первое приложение на основе фреймворка Ruby on Rails, скачайте и установите git и Heroku toolbelt для своей OS.

Немного о структуре приложения. Как уже сказано выше, это rails-app, полноценный веб-интерфейс для API Google Cloud Text to Speech: аутентификация реализована посредством device (полистайте доку, там немало интересного на случай, если захотите что-то изменить в предлагаемом техническом решении), сконфигурированного таким образом, что возможен лишь один пользователь. Что нам и нужно: сразу после деплоя приложения на Heroku вы зарегистрируетесь в нем, подтвердив указанный вами email, и дальнейшие регистрации будут невозможны (изменить или сбросить пароль вы, при необходимости, сможете).

Интерфейс выполнен в духе минимализма, под которым автор понимает Bootstrap 4 и кое-какие джаваскрипты; информационные flash-сообщения панели управления - средствами ajax, благо он как никто родной для Ruby on Rails. Заказчик-киевлянин, для которого был выполнен этот rails-app, он же старый мой приятель, скупой как кардинал Мазарини - очень просил "без излишеств, можно вообще без стилей", ну и вот... впрочем, помимо ожидания, получилось вполне элегантно. Представленный далее короткий ролик не самый новый, с момента его создания приложение было рефакторено и получило новые свойства, но какое-то визуальное представление способен дать.

Да, и "о фичах". На момент публикации этого материала Google-Cloud-TTS-Rails способен работать с текстом (также поддерживается SSML) на любом из 18 языков, конвертируя в один из следующих, по желанию, форматов: MP3 (MPEG Audio Layer III), WAV (LINEAR16) and OGG (OGG_OPUS), поддерживаются оба доступных voice type: WaveNet и Basic. Также интерфейс приложения позволяет корректировать скорость произношения...

...с чего, пожалуй, и начнем этот краткий экскурс в программный код. Меню регулировки скорости реализовано как хелпер, посредством которого получаем в HTML выпадающее меню (drop-down list), диапазон значений от 0.25 до 4.0 (обусловлено API), шаг 0.25, значение по-дефолту 1.0. Привыкайте, это рельсы:

module SoundHelper  def speaking_rate    select_tag 'speaking_rate', options_for_select(      0.25.step(by: 0.25, to: 4.0), selected: '1.0'    ), { class: 'btn' }  endend

Да, к слову. Те, кто не хотят вникать в код, возможно, им это сто лет не нужно... имеют возможность пропустить вышесказанное/поименованное мимо, соответственно, ушей и глаз, равно как и еще парочку фрагментов кода, воспоследующих далее. Имеете полное право, почему нет. Я сейчас сделаю краткую паузу на то, чтобы in two words рассказать, как залить из гитхаба на Heroku полностью готовое к работе приложение, вам понадобятся на вашем рабочем компе лишь Heroku CLI и git, как уже и говорил. Ruby и postgreSQL в этом случае без надобности.

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

git clone https://github.com/cmirnow/Google-Cloud-TTS-Rails.gitcd Google-Cloud-TTS-Rails

Бросьте файл, содержащий ваш персональный ключ YOUR_KEY_NAME.json, в корень директории приложения (название значения не имеет). Далее:

git add .   git commit -m "my first commit"heroku creategit push heroku masterheroku run rake db:migrate

Откройте панель администрирования Heroku, YOUR_NEW_APPLICATION -> 'Settings' -> 'Reveal Config Vars', и введите следующие пары key/value:


key: GOOGLE_APPLICATION_CREDENTIALS value: YOUR_KEY_NAME.json

key: DOMAIN_NAME value: YOUR_HEROKU_DOMAIN ### i.e 'https://***************.herokuapp.com' without quotes.

key: GMAIL_USER_NAME value: YOUR_GMAIL_LOGIN

key: GMAIL_PASSWORD value: YOUR_GMAIL_PASSWORD ### (An App Password is a 16-digit passcode that gives an app or device restricted access to your Google Account without having to divulge your personal password and complete access to your Google Account).


Как видите, потребуется указать доступ к почтовому серверу, чтобы Google-Cloud-TTS-Rails смог отослать вам письмо в ходе регистрации аккаунта, также на случай необходимости сброса забытого пароля. И - на этом все, после регистрации приложение полностью готово к работе. Лимит текста "за один раз" - 5000 знаков, обусловлено Google. Надеюсь, вам понравится.

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

class Validationinclude ActiveModel::Modelattr_accessor :requestvalidates :request, presence: true, length: {in:3..4999}end

Контроллер, как ему и предназначено судьбой, служит связующим звеном между интерфейсом пользователя и собсно сервисом, вызывая метод класса TtsConversion со следующими параметрами:

  def conversion    audio_format = TtsConversion.index(client, synthesis_input, voice, audio, params[:codec])    success_info(audio_format)  end  def client    Google::Cloud::TextToSpeech.text_to_speech  end  def synthesis_input    { params[:text_or_ssml] => params[:request] }  end  def voice    { language_code: params[:lang], name: params[:voicename] }  end  def audio    { audio_encoding: params[:codec], speaking_rate: params[:speaking_rate].to_f }  end
class TtsConversion  def self.index(*args)    response = args[0].synthesize_speech input: args[1], voice: args[2], audio_config: args[3]    File.open 'public/output/output.' + audio_format(args[4]).to_s, 'wb' do |file|      file.write response.audio_content      audio_format(args[4]).to_s    end  end  def self.audio_format(codec)  case codec  when "LINEAR16"  'wav'    when "OGG_OPUS"      'ogg'  else  'mp3'  end  endend

Всю работу свершает, по сути, gem 'google-cloud-text_to_speech', передавая конвертируемый текст и выбранные параметры в API Google Cloud Text to Speech и получая обратно звук в цифре. Вот, пожалуй, и все.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru