Bash: Make Your Time Talk

πŸ“… June 20, 2024
Would you like to enjoy the thrill of having your computer speak the time in a mechanical, computerized voice?

You do? Great! This is completely possible in bash from the command line or a script.

We are not talking about any fancy GUI-based voice assistance. We are talking about typing a command that tells time, and we will look at two ways of achieving this using espeak and saytime.

Install espeak and saytime

We will need these programs, so let’s install them now.

sudo apt install espeak saytime

Let’s look at the espeak technique first.

espeak

First, be able to generate a time of your choosing using date. Here is one example:

date '+%A, %B %d, %Y, %I:%M %p'

Output

Thursday, June 20, 2024, 10:19 AM

To make this talk, pipe the output to espeak.

date '+%A, %B %d, %Y, %I:%M %p' | espeak

Oooh! Was that not beautiful? If espeak and your Linux audio are working correctly, you should hear a harsh, 1980’s mechanical, impersonal voice speak the date and time to you.

Let’s make the speech more fitting.

date '+%A, %B %d, %Y, %I:%M %p...Shall we play a game?' | espeak

Aaah! That is better. Not sure about you, but I know which game I will select if a text-based BBS menu appears…

Altering date’s format string will change the text that is spoken.

Controlling espeak

The default espeak might talk a little fast, so man espeak will display a large variety of options to alter the speech.

date '+%A, %B %d, %Y, %I:%M %p...Shall we play a game?' | espeak -v other/en-n -g 15

This speaks the time with a slight accent on the English. English systems will use a default English voice, but other voices are possible. Voice files are located in /usr/lib/x86_64-linux-gnu/espeak-data/voices, so peruse them to see what is available.

Voices use country codes. en is for English, fr is for French, and so on. Using fr (French) only adds a French accent to the English speech for text that cannot be translated into French. It does not perform a 100% translation between languages unless your locale is French, for example.

To use a voice with espeak, add the -v option with a relative path to the voice file. Here is the time spoken in English with a French accent:

date '+%A, %B %d, %Y, %I:%M %p...Shall we play a game?' | espeak -v fr -g 15

Umm…I think. Some of that sounded like gibberish on my system, so I might not have all necessary voice files. Trial and error is necessary here.

Some voice files are located in subdirectories within /usr/lib/x86_64-linux-gnu/espeak-data/voices. To use one, such as Russian, provide the relative path europe/ru so espeak can locate the ru file.

date '+%A, %B %d, %Y, %I:%M %p...Shall we play a game?' | espeak -v europe/ru -g 15

Output

Full dictionary is not installed for 'ru'

This is an example of not having all language files installed for a given locale. espeak will still try its best, but it will default to English or whatever your current locale might be.

Some voices alter the speech audio. For example, mb/mb-af1-en sounds like a grumpy bullfrog.

date '+%A, %B %d, %Y, %I:%M %p...Shall we play a game?' | espeak -v mb/mb-af1-en -g 15

Output

mbrola: mbrola: No such file or directory
mbrowrap error: mbrola exited with status 1
mbrola voice not found

The -g option controls the duration gap between words for better understanding. 10ms is the default. 15 represents 15ms to add more delay.

Partial Translation

Numbers, dates, and times, are usually translated and spoken in the specified language voice when possible, but English text remains English text if the system locale is English. By altering the date string, we can hear a different translation for the given day and time.

Begin with the date string you want to read to make sure that it is printable.

date '+%A, %l:%M'

Then, pipe to espeak.

date '+%A, %l:%M' | espeak -v en-us -g 15 -s 130

This voices the day and time in American English. By default, my system defaults to British English, so the accent between the two voices sounds different.

-g slows down the word gap duration to 15ms, and -s slows the spoken word speed to better understand the speech. Now, let’s try this in a few different languages by specifying different voices.

date '+%A, %l:%M' | espeak -v de -g 15 -s 130Β      # German
date '+%A, %l:%M' | espeak -v fr -g 15 -s 130      # French
date '+%A, %l:%M' | espeak -v en -g 15 -s 130      # British English
date '+%A, %l:%M' | espeak -v asia/zh -g 15 -s 130 # Chinese
date '+%A, %l:%M' | espeak -v asia/fa-en-us -g 15 -s 130 # Iranian (fa) English?
date '+%A, %l:%M' | espeak -v europe/cy -g 15 -s 130 # Welsh
date '+%A, %l:%M' | espeak -v test/gd -g 15 -s 130 # Scottish?

Consult the espeak-ng documentation for a full list of espeak languages to understand what the codes mean.

Notice that sometimes the day is spoken in a different language and other times it defaults to English. As I understand, the system needs the proper locale installed for a given language for full day/month name translation. Numbers, such as the time, are usually spoken in the target language. Anything that cannot be translated defaults to your system locale, which is British English in this example.

saytime

Another program dedicated to speaking the current system time is saytime. (You probably never knew that this existed, did you?)

Just run saytime to hear it in action.

saytime

Hmm. That was okay, but you might see a number of error messages as each phrase is spoken. This is especially noticeable if you are using S/PDIF optical output for your audio connection. (This also happens with espeak.)

sox WARN alsa: can't encode 0-bit Unknown or not applicable

Try specifying the output type with -t alsa.

saytime -t alsa

Much better. The voice sounds like an uncertain baseball sports announcer who knows nothing about baseball and has to consult his premade script, but the voice is much more understandable and natural than espeak.

Customizing saytime

We can customize the time format a little similar to date. By default, saytime uses %P%l%M%S as its default format string. Suppose we just want the hour and minutes.

saytime -t alsa -f %l%M

This omits the “The time is” spoken prefix, which is represented by %P.

If you want to hear a 24-hour clock, use the %k option.

saytime -t alsa -f %P%k%M%S

saytime only reports the current system time and does not perform any language translation like espeak does.

Changing Voices

The saytime voice sounds better than espeak in my opinion, but it is not as customizable.

Voice files for saytime are .au files located in /usr/share/saytime. That is all. In theory, you should be able to create your own sound files and use those with the -d option, but I have not tried this. Other than that, saytime is English, and no other default voices are available. Still a good program if all you need is the current time spoken in English.

Repeating Time

If you want to make yourself climb a wall and pray for somebody to rescue form self-induced torture, try using the -r1 option to repeat saytime nonstop.

saytime -t alsa -f %P%k%M%S -r1

This runs saytime as a background process, so you will need to kill the process to make it stop.

ps aux | egrep saytime
kill 370223   # Replace 370223 with the PID of saytime

 

Conclusion

There you have it! Two ways of making Linux speak the current time from a terminal. If it works from a terminal, then it will work from a script too…maybe.

espeak is more flexible because it speaks whatever text you feed to it and will even translate a few things to other languages, but it sounds metallic and impersonal — like a malicious computer that wants to take over your life.

saytime is a simple program that only reports the current time in a much more friendly, understandable voice, but it cannot be customized the way espeak can.

Either option adds a little flair to the command line and can add unexpected fun for unsuspecting users.

Enjoy!

 

 

 

, , ,

  1. Leave a comment

Leave a comment