Как стать автором
Обновить

Комментарии 36

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Я имел в виду можете ли вы дать линк на Ютуб например который говорит именно тем голосом который вам больше всего нравится?
НЛО прилетело и опубликовало эту надпись здесь
Попробуйте ту же Татьяну из Ivona, можете приятно удивиться. Когда-то сравнивали как раз на книгах, и голоса от Nuance заметно им проигрывали, особенно в витиеватой художественной литературе. В т.ч. на телефоне неплохо работает.
НЛО прилетело и опубликовало эту надпись здесь
Мне мужские голоса в любом синтезе кажутся гораздо лучше…
Попробовал Ивону. Таки да, мужской голос лучше.

Причём что забавно: тестировал на «Белой берёзе», и Максим читает «стоИт берёза», а Татьяна читает «стОит берёза». Это заговор! :D Впрочем, без «ё» они одинаково ошибаются в определении слова.

Тестовый текст
Белая берёза
Под моим окном
Принакрылась снегом,
Точно серебром.

На пушистых ветках
Снежною каймой
Распустились кисти
Белой бахромой.

И стоит берёза
В сонной тишине,
И горят снежинки
В золотом огне.
Это мой первый go код, приветствую вашу критику.

Не стоит хардкорить пути и ключи прямо в исходники. Для этого есть flag и path/filepath (не стоит обходиться обычной конкатерацией). А в bufio есть сканнер для чтения по словам/строкам/символам, хотя и не принципиально для файлов среднего размера. io/ioutil.WriteFile может возвратить ошибку (например место кончилось или ещё чего) и её стоит обработать.

Парочка усовершенствований
package main

import (
	ivona "github.com/jpadilla/ivona-go"

	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const format = "tts%04d.ogg" // files like 0001.ogg

var dir = flag.String("dir", ".", "like /home/vitaly/Desktop/")
var textFile = flag.String("text", "", "path to text file, like /home/vitaly/Desktop/test.txt")
var key = flag.String("key", "GDNAICTDMLSLU5426OAA", "access key for ivona api")
var secret = flag.String("secret", "2qUFTF8ZF9wqy7xoGBY+YXLEu+M2Qqalf/pSrd9m", "secret key for ivona api")

func main() {
	flag.Parse()

	conf := os.Stdin // если нет конфига, но читаем стандартный ввод
	if *textFile != "" {
		conf, err := os.Open(*textFile)
		if err != nil {
			log.Fatal(err)
		}
		defer conf.Close()
	}

	client := ivona.New(*key, *secret)
	scanner := bufio.NewScanner(conf)
	for i := 1; scanner.Scan(); i++ {
		paragraph := strings.TrimSpace(scanner.Text())
		if paragraph == "" { // пропускаем пустые строки
			continue
		}
		log.Printf("process: %v\n", paragraph)

		options := ivona.NewSpeechOptions(paragraph)
		options.Voice.Language = "ru-RU"
		options.Voice.Name = "Maxim"
		options.Voice.Gender = "Male"
		options.OutputFormat.Codec = "OGG"

		r, err := client.CreateSpeech(options)
		if err != nil {
			log.Fatal(err)
		}

		file := filepath.Join(*dir, fmt.Sprintf(format, i))
		err = ioutil.WriteFile(file, r.Audio, 0644)
		if err != nil {
			log.Fatalln("writing result file:", err)
		}
	}

	if err := scanner.Err(); err != nil {
		log.Fatalln("reading text file:", err)
	}
}


diff
4d3
< 	"fmt"
5a5,8
> 
> 	"bufio"
> 	"flag"
> 	"fmt"
7a11,12
> 	"os"
> 	"path/filepath"
10a16,22
> const format = "tts%04d.ogg" // files like 0001.ogg
> 
> var dir = flag.String("dir", ".", "like /home/vitaly/Desktop/")
> var textFile = flag.String("text", "", "path to text file, like /home/vitaly/Desktop/test.txt")
> var key = flag.String("key", "GDNAICTDMLSLU5426OAA", "access key for ivona api")
> var secret = flag.String("secret", "2qUFTF8ZF9wqy7xoGBY+YXLEu+M2Qqalf/pSrd9m", "secret key for ivona api")
> 
12,15c24,32
< 	client := ivona.New("GDNAICTDMLSLU5426OAA", "2qUFTF8ZF9wqy7xoGBY+YXLEu+M2Qqalf/pSrd9m")
< 	text, err := ioutil.ReadFile("/home/vitaly/Desktop/test.txt")
< 	if err != nil {
< 		log.Fatal(err)
---
> 	flag.Parse()
> 
> 	conf := os.Stdin // если нет конфига, но читаем стандартный ввод
> 	if *textFile != "" {
> 		conf, err := os.Open(*textFile)
> 		if err != nil {
> 			log.Fatal(err)
> 		}
> 		defer conf.Close()
18,21c35,39
< 	arrayOfParagraphs := strings.Split(string(text), "\n")
< 	i := 0
< 	for _, paragraph := range arrayOfParagraphs {
< 		if len(paragraph) < 4 { // against empty lines
---
> 	client := ivona.New(*key, *secret)
> 	scanner := bufio.NewScanner(conf)
> 	for i := 1; scanner.Scan(); i++ {
> 		paragraph := strings.TrimSpace(scanner.Text())
> 		if paragraph == "" { // пропускаем пустые строки
24c42,43
< 		log.Printf("%v\n", paragraph)
---
> 		log.Printf("process: %v\n", paragraph)
> 
29a49
> 
35,37c55,63
< 		i++
< 		file := fmt.Sprintf("/home/vitaly/Desktop/ivona/tts%04d.ogg", i) // files like 0001.ogg
< 		ioutil.WriteFile(file, r.Audio, 0644)
---
> 		file := filepath.Join(*dir, fmt.Sprintf(format, i))
> 		err = ioutil.WriteFile(file, r.Audio, 0644)
> 		if err != nil {
> 			log.Fatalln("writing result file:", err)
> 		}
> 	}
> 
> 	if err := scanner.Err(); err != nil {
> 		log.Fatalln("reading text file:", err)

у вас только конфиг из файла никогда читаться не будет
И правда. Вот фикс:
	var err error
	if *textFile != "" {
		conf, err = os.Open(*textFile)
Спасибо.
Только Go всё-таки не скриптовый язык.
Сам сейчас периодически пользую go
и как ни странно, как скриптовый, это позволяет наличие большого количества либ. Да и запуск не такой уж и долгий. Хотя конечно лучше собирать. Но для изучения подойдет и просто go run
Тогда ждём статьи про C-скрипты, чего уж…
Вы удивитесь — bellard.org/tcc
C script supported: just add '#!/usr/local/bin/tcc -run' at the first line of your C source, and execute it directly from the command line.
С Go можно даже так
//usr/bin/go run $0 $@; exit $?
package main

import "fmt"

func main() {
	fmt.Println("Hello world!")
}


Однако, по моему разумению, слово скрипт указывает на скриптовый язык.
Зачем конвертировать если можно сразу читать голосом? На андроиде это умеют многие приложения, например fbreader. На iOS и того проще — чтение текста встроенная системная функция, можно активировать в настройках чтение (в любой программе) по двойному свайпу сверху вниз.
Голос так себе, не знаю почему автор его выбрал, есть получше (имею в виду русский)
Спасибо за IVONA, не слышал. Наличие Java API радует, заберу к себе в умный дом
Умеют ли современные синтезаторы речи решать проблему с е/ё?
Попробовал скрипт автора, и могу сказать что в опробованной книге кусочек из фразы: «Я и осел здесь, чтобы отвязаться от вас.» слово осел было прочитано как осёл. Т.е. проблему вроде как решают, но местами неправильно
У меня возник вопрос, а если в тексте встречается предложение в котором есть и русский текст и английский?
Один будет в пролете?
Будет прочитан весь текст, но не факт, что произношение будет правильным. У API Ivona есть возможность задавать лексиконы, которые позволяют подстроить произношение слова/фразы или произнести сокращения полностью. Я думаю, этим механизмом можно воспользоваться для подобных случаев.
Не знаю, как в Ivona, а в RHVoice, который я использовала с «Балаболкой», есть возмощность XML-тегами переключать язык произношения и другие параметры.
У них на сайте тестовый текст содержит фразы со смесью языков, вроде:
Я один из голосов программы преобразования текста в речь IVONA. Введите фразу здесь и нажмите Play.
Произносит без проблем.
Спасибо! Две недели назад как раз искала максимально качественный TTS. Пока лучшее из того, что нашла для русского языка — «Балаболка». Попробую поэкспериментировать с Ivona :)
if (len(paragraph) < 1) {

Скобки в Go не нужны.
log.Printf("%v\n", paragraph)

В принципе ок, особенно для скрипта. Но т.к. точно известно, что у вас строка, то быстрее будет с %s.
Наступил на грабли) Для пробы скачал с lib.ru наугад стихотворение Бунина, оказалось в старинной транскрипции, с ятями. Очень неожиданное прочтение получилось. А так — действительно впечатляет, хорошее звучание и интонации естественные (я специально стихи для пробы выбрал). Пожалуй попробую себе в машину что-нибудь сделать послушать.
Только вот извините, но хардкодить входные/выходные файлы — жуткий моветон. Я тоже go первый раз в жизни вижу, однако если вы разобрались с остальным, то узнать как передать параметры в командной строке уж совсем не проблема. Еще я не понял как оно работает с импортом модулей с гитхаба, мне пришлось руками ставить.
Интересное решение, но не проще ли использовать уже готовое решение с лучшим синтезом для русского языка chitatel.pro
Попробовать можно синтез от ЦРТ на: voicefabric.ru
Небольшой отрывок из Достоевского: «в начале июля, в чрезвычайно жаркое время, под вечер, один молодой человек вышел из своей каморки, которую нанимал от жильцов в С — м переулке»
Ивона: пОд вечер
Читатель: под вЕчер

И, ксати, к вопросу о женских голосах, рекомендую попробовать голос Юлия.
Я видел эти сайты и пробовал их до написания своего скрипта — на мой вкус голос Ivona лучше. Хотя логично было бы предположить что русский синтез должен быть лучше у русских компаний вроде Яндекса или Центра Речевых Технологий, наверняка в будущем и те и те улучшат свои продукты.
было бы интересно провести Mos-оценку. Синтезировать один и тот же текст Ivona и ЦРТ и выложить на голосование.
Да тут и сравнивать нечего, Ivona пока вне конкуренции
Статья, в которой приведено сравнение синтеза ЦРТ и Яндекса: habrahabr.ru/post/272655
https://www.ivona.com/us/about-us/voice-portfolio/
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории