📜 ⬆️ ⬇️

We learn the PC to talk

For those who at home have a desktop computer ala "home server". I bring to your attention one interesting function that can be realized by many.

Typical tasks for such a machine:
We will assign another task to him - to tell us various interesting things in a human voice ...

For example notify:


From words, let's get down to business, the task can be implemented on almost any platform under any OS.
I'll tell you how I implemented it on Ubuntu Server, which runs on my “server” on Intell Atom.
It is understood that you have a sound card that can work under Ubuntu and an audio system, my audio system is connected to the “server”. Anything will do for these purposes, even “computer speakers” for $ 7.
')

Installation Festival


Much has been written about this, for example , on Habré and in inters, I can only say what I did according to the instructions and did not encounter any problems.

Later I decided to compile myself and start the festival server, i.e. it weighs a demon and we connect to it with the help of a client and command it. Pros - significantly less response time, on the "smart" system and phrases like the current time, the delay is no more than 1-2 seconds.

We download all the source archives from the project page .
Unpacking to a folder such as / usr / local / bin / festival / ($ INST_DIR), you will not be able to install the product with the standard sudo make install, you need to build it where it will be as a result. Now the festival / and speech_tools / last will appear in our directory - the voice means library of The Edinburgh Speech Tools, the assembly should be started from it.

$cd speech_tools $ ./configure $make 

Will swear at the absence of libcurses
 $sudo aptitude install libncurses-dev 

and repeat the build

We collect the festival itself

 $cd ../festival $ ./configure $make 

In festival / bin /, among other things, festivale and festivale_client will appear - these are symlinks to binaries that are not immediately located nearby.

Launch festivale (indicating the path to our new file, otherwise the old one will start or nothing will start at all) and try to start the English text:
festival> (SayText "Hello World")
If I started talking, it’s small, if Linux: Can’t open / dev / dsp look here https://wiki.archlinux.org/index.php/Festival#can.27t_open_.2Fdev.2Fdsp (thanks RussianNeuroMancer )

Russify!

Download the Russian voice here: http://festlang.berlios.de/docu/doku.php?id=russianru
Unpacking msu_ru_nsh_clunits-0.5.tar.bz2 (at the time of writing this is the most recent version) in $ INST_DIR / festival / lib / voices / en / - the directory structure should be saved.

At the beginning of the $ INST_DIR / festival / lib / languages.scm file we write:
 (define (language_russian) "(language_russian) Set up language parameters for Russian." (set! male1 voice_msu_ru_nsh_clunits) (male1) (Parameter.set 'Language 'russian) ) 

We are looking for a block starting with the line:
 (define (select_language language) 

by analogy with other languages ​​add
  ((equal? language 'russian) (language_russian)) 


Check Russian language:
 echo "" | festival --tts --language russian 

If it says - fine, try to start the server:
 $INST_DIR/festival/bin/festival --server --language russian 
we will not run it into the background yet, let it hang in the terminal for the time of debugging.

We start the client in another terminal (the option who has alsa and aplay works fine)
 echo "" | $INST_DIR/festival/bin/festival_client -ttw | aplay 
the key -ttw means text to wave, you can run with the key -tts which means text to speech
 echo "" | $INST_DIR/festival/bin/festival_client -tts 


He speaks? - super! If not, we look at the terminal where the server is running, a message may appear stating that the Reject client is not in the list of allowed connections, then edit the $ INST_DIR / festival / lib / festival.scm file:
find the parameter
 (defvar server_access_list '("192.168.2.1" "127.0.0.1" localhost) 
and add the IP address of the host from which you are connecting (although I tried to connect through 127.0.0.1 the server cursed and identified the client as 192.168.2.1, the IP added was all OK). Obviously, they can steer from a remote host, by the way, port 1314 is used for connection, it can be changed both in this config and when launching the client and server with the --port key, of course the client and server ports should be the same.

For the Orthodox launch at system startup, I threw init-script:
 #!/bin/sh ### BEGIN INIT INFO # Provides: helius # Required-Start: $local_fs # Required-Stop: $local_fs # Should-Start: $network # Should-Stop: $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Festival server # Description: Start Festival daemon as server ### END INIT INFO . /lib/lsb/init-functions PATH=/sbin:/bin:/usr/sbin:/usr/bin NAME=festival DESC="Festivale Speech system" DAEMON=/home/eugene/src/festival_src/festival/bin/festival START_MPD= # Exit if the package is not installed [ -x "$DAEMON" ] || exit 0 fest_start () { log_daemon_msg "Starting $DESC" "$NAME" start-stop-daemon --start --quiet --oknodo \ --exec "$DAEMON" -- --server --language russian & log_end_msg $? } fest_stop () { log_daemon_msg "Stopping $DESC" "$NAME" start-stop-daemon --stop --quiet --oknodo --retry 5 \ --exec $DAEMON log_end_msg $? } case "$1" in start) fest_start ;; stop) fest_stop ;; restart|force-reload) fest_stop fest_start ;; force-start|start-create-db) FORCE_CREATE_DB=1 fest_start ;; force-restart) FORCE_CREATE_DB=1 fest_stop fest_start ;; *) echo "Usage: $0 {start|start-create-db|stop|restart}" exit 2 ;; esac 

Copy to /etc/init.d/ from root, do
 $sudo update-rc.d festivald defaults 

we start
 $sudo /etc/init.d/festivald start 

we check that the client connects normally - the phrases are pronounced, we make out the launch of the client in the script, enjoy! : D

In order for him to say something, it is enough to call him like this:
echo "Hello" | festival --tts --language russian
It is more convenient to arrange this in a script, and transfer the string to its standard input.

And what if we play music? What if the volume of the sound card synthesizer changes while listening to music? You do not want to jump in the morning from screaming, if you forgot to turn down the volume control in the evening? : D

My sound is played through Alsa, after reading the mana I found how to control the alsa-mixer by setting the desired volume. I use the player MOC (Music On Consol) which allows you to pause and start playback with uncomplicated commands (if you use another audio player, find out how to control it, pause - remove, or just remove these lines).

In this way:
1) pause the player
2) set a predetermined "comfortable" volume level
3) pronounce the phrase
4) return the volume level
5) remove the player with a pause

Here's what I got: the sayit script
#!/bin/bash <br/>
# <br/>
read str <& 0 <br/>
# <br/>
/ usr / bin / mocp -P <br/>
# <br/>
amixer -c 0 -- sset Master playback 40 <br/>
# <br/>
echo " $str " | festival --tts --language russian<br/>
# <br/>
amixer -c 0 -- sset Master playback 100 <br/>
# <br/>
/ usr / bin / mocp -U <br/>

#!/bin/bash <br/>
# <br/>
read str <& 0 <br/>
# <br/>
/ usr / bin / mocp -P <br/>
# <br/>
amixer -c 0 -- sset Master playback 40 <br/>
# <br/>
echo " $str " | festival --tts --language russian<br/>
# <br/>
amixer -c 0 -- sset Master playback 100 <br/>
# <br/>
/ usr / bin / mocp -U <br/>


We check mail


I use gmail, how to get a list of new letters already told on Habré, everything is simple with it, the algorithm is as follows:
1) we get the number of new letters
2) compare the count with the previously recorded file (so as not to chat, if there are no “new” unreads, but only after the appearance of another unread one)
3) if it is more recorded, we pronounce the phrase “You have a new letter”
4) if the recorded count is greater than zero (there are still unread), then output to the standard output "Unread $ Number"

Script:
#! /bin/bash <br/>
# - <br/>
Nmb = ` curl -u LOGIN:PASSWORD --silent "mail.google.com/mail/feed/atom" | grep -c "<entry>" ` <br/>
# - <br/>
OldNmb = ` cat / home / eugene / mail_count ` <br/>
# - <br/>
if ( ( $Nmb > $OldNmb ) ) <br/>
then <br/>
# , - <br/>
# "" <br/>
if ( ( $Nmb > 1 ) ) <br/>
then <br/>
echo " . " $Nmb | / home / eugene / .bin / sayit<br/>
else <br/>
echo " ." | / home / eugene / .bin / sayit<br/>
fi <br/>
fi <br/>
# - <br/>
echo " $Nmb " >/ home / eugene / mail_count<br/>
<br/>
#! /bin/bash <br/>
# - <br/>
Nmb = ` curl -u LOGIN:PASSWORD --silent "mail.google.com/mail/feed/atom" | grep -c "<entry>" ` <br/>
# - <br/>
OldNmb = ` cat / home / eugene / mail_count ` <br/>
# - <br/>
if ( ( $Nmb > $OldNmb ) ) <br/>
then <br/>
# , - <br/>
# "" <br/>
if ( ( $Nmb > 1 ) ) <br/>
then <br/>
echo " . " $Nmb | / home / eugene / .bin / sayit<br/>
else <br/>
echo " ." | / home / eugene / .bin / sayit<br/>
fi <br/>
fi <br/>
# - <br/>
echo " $Nmb " >/ home / eugene / mail_count<br/>
<br/>

Do not forget to substitute your LOGIN / PASSWORD! =)
Add to cron.

Temperature "outside the window"


Here, too, everything is quite simple, you just need to find any “weather” site that is easy to parse and pull out the current temperature, in Novosibirsk (where I am) there is www.ngs.ru on the main one with which the temperature “hangs”, well, get_cur_tmpr script:
1) we pull up the page wget,
2) pass through a regular expression,
3) return the temperature in “pure” form, for example, 16 or -9.

> #!/bin/bash <br/>
# c http://ngs.ru <br/>
wget -P / home / eugene / .tmp http: // ngs.ru -q <br/>
# UTF-8 - <br/>
stringZ = ` cat / home / eugene / .tmp / index.html | iconv -f CP1251 -t UTF- 8 ` <br/>
# <br/>
tmp_str = ` expr " $stringZ " : '.*</a></h2>:&nbsp;\(.........\).*$' ` <br/>
# <br/>
digit = ` expr " $tmp_str " : '^.*\([0-9]\{1,2\}\)' ` <br/>
# <br/>
sign = ` expr " $tmp_str " : '^\(.......\)' ` <br/>
# - "-" <br/>
if [ [ $sign = "&minus;" ] ] <br/>
then <br/>
tmpr = "-" <br/>
fi <br/>
tmpr = $tmpr $digit <br/>
# <br/>
echo $tmpr <br/>
# <br/>
rm / home / eugene / .tmp / index.html


It remains to execute this script on a schedule, adding the following command to cron
get_cur_tmpr | sayit

For example, it starts with me during the morning cup of coffee, so I know how to dress on the way to work.

Tomorrow forecast


This script is started by Cron th in the evening, before going to bed, so that I know which transport scheme to prefer on my way to work tomorrow and whether to go at all: D: D: D

It is not much different from the previous one, only as a source of information I use Yandex (I hope I do not violate anyone's rights =)). Yandex is smart, he knows where the page was requested from and will give a weather forecast for your area, so the script will work the same everywhere, that is, it will be different everywhere))

Script get_fut_tmpr:
#!/bin/bash <br/>
# <br/>
wget -P / home / eugene / .tmp http: // m.weather.yandex.ru / -q <br/>
# <br/>
stringZ = ` cat / home / eugene / .tmp / index.html<br/>
# <br/>
tmpr = " `expr "$stringZ" : '.*.*....\(..............\)'` " <br/>
# , <br/>
if [ -n " $tmpr " ] # <br/>
then <br/>
# ( : -9 -11) <br/>
tmprhi = ` echo $tmpr | egrep -o '^.?[0-9][0-9]?' ` <br/>
tmprlo = ` echo $tmpr | egrep -o '.?[0-9][0-9]?$' ` <br/>
# <br/>
if ( ( $tmprhi < 0 ) ) # <br/>
then <br/>
shi = "" <br/>
# <br/>
tmprhi = ` echo $tmprhi | egrep -o '[0-9][0-9]?' ` <br/>
else <br/>
shi = " " <br/>
fi <br/>
if ( ( $tmprlo < 0 ) ) # <br/>
then <br/>
slo = "" <br/>
# <br/>
tmprlo = ` echo $tmprlo | egrep -o '[0-9][0-9]?' ` <br/>
else <br/>
slo = " " <br/>
fi <br/>
else <br/>
echo " ." <br/>
exit 0 <br/>
fi <br/>
<br/>
echo " $shi $tmprhi $slo $tmprlo " <br/>
# <br/>
rm / home / eugene / .tmp / index.html
#!/bin/bash <br/>
# <br/>
wget -P / home / eugene / .tmp http: // m.weather.yandex.ru / -q <br/>
# <br/>
stringZ = ` cat / home / eugene / .tmp / index.html<br/>
# <br/>
tmpr = " `expr "$stringZ" : '.*.*....\(..............\)'` " <br/>
# , <br/>
if [ -n " $tmpr " ] # <br/>
then <br/>
# ( : -9 -11) <br/>
tmprhi = ` echo $tmpr | egrep -o '^.?[0-9][0-9]?' ` <br/>
tmprlo = ` echo $tmpr | egrep -o '.?[0-9][0-9]?$' ` <br/>
# <br/>
if ( ( $tmprhi < 0 ) ) # <br/>
then <br/>
shi = "" <br/>
# <br/>
tmprhi = ` echo $tmprhi | egrep -o '[0-9][0-9]?' ` <br/>
else <br/>
shi = " " <br/>
fi <br/>
if ( ( $tmprlo < 0 ) ) # <br/>
then <br/>
slo = "" <br/>
# <br/>
tmprlo = ` echo $tmprlo | egrep -o '[0-9][0-9]?' ` <br/>
else <br/>
slo = " " <br/>
fi <br/>
else <br/>
echo " ." <br/>
exit 0 <br/>
fi <br/>
<br/>
echo " $shi $tmprhi $slo $tmprlo " <br/>
# <br/>
rm / home / eugene / .tmp / index.html


“Yandex” is written exclusively for euphony, some words the synthesizer says crookedly, you have to experiment

What else can you think of, yes a lot! Report karma to Habré, rating on torrents, backups (especially negative), noticed an attack from the Internet, sum up visits to the home site in the evenings, I’m silent about site control (for web programmers). I present a picture, night, 3 hours, voice "on the xxx site some of the content is unavailable!"

There are a couple of unpleasant moments with the synthesizer:
1) I think for a long time before I utter a phrase (search in dictionaries, synthesis) how to defeat it, I did not find, everyone complains about it, apparently implementation features.
2) The dictionary leaves much to be desired in terms of the pronunciation of individual words, some words have to be replaced by synonyms, because they sound frankly awful: D

In general, if you “pick words” pronunciation is not even very bad! Well-made male voice.

The synthesis of speech and its use in “everyday” purposes is becoming more and more used, let’s get closer to the future in half a step!

Well, that's all I had to tell you, I hope I kindled someone interested in this issue!
Thanks for attention.

Source: https://habr.com/ru/post/88193/


All Articles