**SOLVED** Looking for examples of python code using espeakng

Can anyone point me to some working examples of python code using espeakng with the GoPiGo3? Running the espeak-ng executable at a command line works

$ espeak-ng 'hello'                   # speaker says 'hello'

but the following python code does not work for me:

import espeakng
esng = espeakng.ESpeakNG()
esng.say('hello')                     # speaker says nothing

Thanks in advance!

Update: I figured it out. I needed to specify a voice (don’t know why there is not a default voice).

This worked:

import espeakng
esng = espeakng.ESpeakNG(voice='en-gb')
esng.say('hello')                     # speaker says 'hello' with a British accent

See this link here.

3 Likes

I developed a set of functions ( from before espeak became espeak-ng). Would be interested in a comparative analysis, but understand “a solution” is all that is needed.

There are times that it is desirable to speak while continuing on with the program. Does the Python espeakng package wait until speaking is complete or speak asynchronously?

3 Likes

Thanks for sharing! AFAIK, the espeakng say() function is blocking so the robot can’t “walk and talk” as it were.

A related ROS question - ROS nodes run asynchronously but, unless ROS is multithreaded, don’t node activities sometimes block each other? More specifically, if you had a ROS “speaker” node that gave a speech over speaker, wouldn’t all the other nodes just have to wait until the monolog was over? Conversely, if ROS is multithreaded then the robot really should be able to “walk and talk”.

3 Likes

Multi-processing and multi-threading in ROS vs ROS 2 and Python vs C++ are the deep abyss waiting to consume all available time - human and processors’.

I have had luck putting my multi-process TTS calls in the main of a ROS 2 node, but never in a callback or a function that calls spin().

..
import subprocess

--

def say(phrase,vol=100):

    phrase = phrase.replace("I'm","I m")
    phrase = phrase.replace("'","")
    phrase = phrase.replace('"',' quote ')
    phrase = phrase.replace('*',"")

    # Carl's voice
    # subprocess.check_output(['espeak-ng -s150 -ven-us+f5 -a'+str(vol)+' "%s"' % phrase], stderr=subprocess.STDOUT, shell=True)  
    # Dave's voice
    subprocess.check_output(['espeak-ng -s300 -a'+str(vol)+' "%s"' % phrase], stderr=subprocess.STDOUT, shell=True)


def main(args=None):
    rclpy.init(args=args)

    subscriber = Subscriber()
    publisher = Publisher()
    command = Twist()

    say("I'm Humble Dave. Starting Ross 2 wanderer",vol=200)
    time.sleep(2)  # Wait till done talking

    while 1:  # main loop. The robot goes forward until obstacle, and then turns until its free to advance, repeatedly.
        time.sleep(1)
        say("Going forward",vol=50)  # Walk and talk at the same time
        go_forward_until_obstacle(subscriber, publisher, command)
        say("Something too close", vol=50)
        rotate_until_clear(subscriber, publisher, command)
..

I think I have seen some examples of these in GitHub - Eventually, this is the correct architecture for using any robot resource. The TTS node should have both a listener and a service or action. The listener would provide asynchronous TTS, and the service would provide synchronous TTS. As an action, the TTS node could implement preempting one TTS stream with a more important TTS stream, and manage a queue of speech requests. This node would be complicated since the handler for a topic is a callback, and you don’t put long running things like TTS in callbacks.

3 Likes