Text to speech in BGE

Is there any way to use/include a text to speech in a BGE game ?

https://pythonprogramminglanguage.com/text-to-speech/

I’ve done text to speech where i pre-recorded some files but ^ is the realtime way to do it

Hi guys,

I want to leave an experiment here, which I did a few years ago.

Disclaimer: It’s WINDOWS only. :point_up:

In an attempt to produce a “talking clock”, I was trying to figure out how to make the BGE talk - I did not know about the module which @Nicholas_A mentioned. So I stripped down a VBS script (I think from Peter Bennett) which I called with a subprocess from Python and fed it with a text file containing the string which should be handed over to the text-to-speech module from Windows.

Instructions:
0.) Make sure you are running this on WINDOWS.
1.) Download these two files in a folder, where you have write access

2.) Open the *.blend and run it in BGE
3.) Press SPACE
4.) A magic voice should tell you what time it is

Here is a screenshot:

Let me know if this works for someone else, it has never left my PC.
Enjoy!

1 Like

Not working.

expandPath(//) needs to be used in the f,open line and also in the popen.
changed cscript to wscript and also changed < to – in the popen.

then the only result i get is an error no script engine to run .vbs,

dutch error

Microsoft ® Windows Script Host versie 5.812
Copyright © Microsoft Corporation. Alle rechten voorbehouden.

Invoerfout: Er is geen script-engine voor bestandsextensie .vbs’).

while double clicking the file works fine so there is something not right.

adjusted part of script
def Talk():
    sens = bge.logic.getCurrentController().sensors['Bla']
    
    if sens.positive:
        f = open(bge.logic.expandPath('//tmp.txt'), 'w')
        f.write(time.strftime("%H:%M:%S"))
        print ("say")
        f.write(time.strftime(""))
        f.close()
        sens = bge.logic.getCurrentController().sensors['Bla']
        own = bge.logic.getCurrentController().owner
        
        str = "wscript bge.logic.expandPath('//ptts.vbs')  --bge.logic.expandPath('//tmp.txt')"
        subprocess.Popen(str,shell=True)
    return

maybe you know an solution, this would be a nice option to have working.

Hi Cotaks,

Hmm, on my machine it works flawlessly. I am running BGE 2.79b on Win 10 (1803). Some hints:

  1. expandPath: I don’t need the expandPath anywere - fopen just dumps the temporary file right next to the *blend. I am not sure why you added it.
  2. cscript: The *.vbs states explicitly that it shall be called with cscipt - Line 160: “Usage: cscript ptts.vbs [options]”… can you check in the terminal if typing cscripts gives an output?
  3. Your string (str for subprocess) is wrong. If you print it, you’ll se the bge.logic terms given to the vbs script - it does not get expanded.

Can you check points 2 and 3 again?

without expand path:

Python script error - object 'Plane.001', controller 'Python.001':
Traceback (most recent call last):
  File "D:\Nieuwe map\BGE_TextToSpeech.blend\Say.py", line 21, in Talk
PermissionError: [Errno 13] Permission denied: 'tmp.txt

(i have never ever had this error before, and i have written tons of scripts)
expand path at fopen fixes this

then we get this problem:

say

Het systeem kan het opgegeven bestand niet vinden. (can't find path to file)

we fix this by chaning < to – in the popen

then we get the next error:

say
Microsoft (R) Windows Script Host versie 5.812
Copyright (C) Microsoft Corporation. Alle rechten voorbehouden.

Invoerfout: Kan scriptbestand C:\Program Files\Blender Foundation\Blender\ptts.vbs niet vinden.
(can't find ptts.vbs)

we fix this error by adding expandPath to the Popen line

I know it should print it because it’s in a string thats why i wonder why it does find the file, other wise you get buffer errors.

and cscript or wscript is wscript is the program you call with cscript, cscript prints the error in the console while wscript gives an popup window with that error.

Can you try again with the updated file in my main post?
It could not find the temporary file in you case because the filename for the vbs has to be inbetween two "s. At least this worked for me.

I still haven’t touched your changes from cscript to wscript and < to - though.

D:\Nieuwe map\tmp.txt
cscript ptts.vbs < "D:\Nieuwe map\tmp.txt"
Microsoft (R) Windows Script Host versie 5.812
Copyright (C) Microsoft Corporation. Alle rechten voorbehouden.

Invoerfout: Kan scriptbestand C:\Program Files\Blender Foundation\Blender\ptts.vbs niet vinden.

input error can’t find ptts.vbs (wrong path as you see).

yall know you can use pip to install inside blender eh?

blender/.../python.exe -m ensurepip
blender/.../python.exe -m pip install pyttsx

I knew that pip can be added and additional modules can be installed. However, I usually went the route via get-pip.py described on stackexchange. The ensurepip way (just tested it) is indeed a little shorter. Thanks!

@Cotaks: I don’t understand why it is seaching the ptts.vbs in Blenders folder.
Can you please describe exactly, where you put the both files I prepared for download?

I expected them to be in some folder which is NOT the Blender folder. The only reason I see for you error would be that you somehow have still the expandpath in your call…

@BluePrintRandom Besides that, I just tried pyttsx. However, the 1:1 script from did not work for me on 2.79b, it complained about some missing dependency.

Python script error - object 'Cube', controller 'Python':
Traceback (most recent call last):
  File "Text", line 1, in <module>
  File "C:\Blender\2.79\python\lib\site-packages\pyttsx\__init__.py", line 18, in <module>
    from engine import Engine
ImportError: No module named 'engine'

I tried with pyttsx3 instead, which had two other dependencies I had to install

python.exe -m ensurepip
python.exe -m pywin32 pypiwin32 pyttsx3

Then, the TextToSpeech_pyttsx3.blend (476.5 KB) was talking to me in a minimal example taken from here.

I noticed two things:

  1. The voice output blocks the game loop (my rotating cube stops)
  2. It only works once. Stopping and restarting fills up the terminal with junk I was not motivated enough to investigate. See right side in screenshot

Maybe there are solutions to both. My *.vbs version did not block the game loop at least.

@BluePrintRandom: In case have a minimal example of pyttsx / bytssx3 working in the BGE, please leave it here.

I think @WKnight02 has a example of opening a subthread in bge.

Made a new folder, put all in it, opened blend, hit play, resulting in that.

#edit

haha in blender timer works speech don’t
in upbge timer don’t work but speech does (with latest files)

#edit2

hmm… if i open upbge then open file, it does not work. if i double click the file (wich opens upbge) it works perfectly. Pretty strange

I reproduced and fixed it by expandig the scriptname as well. It was a typical path problem. Original post is updated. I was assuming that Pythons current working directoriy is automatically the one of the *.blend, which was the case in my tests.

However, this seems to be different depending on the way you open the file, which explains your #edit 2 . With respect to your other observation:

@Cotaks
haha in blender timer works speech don’t
in upbge timer don’t work but speech does (with latest files)

This makes sense as well, because I used the “classic” bitmap text, which for some reaon got kicked in UPBGE as far as I know.

Summing up: After playing around with both solutions (vbs & pttsx), I personally prefer the *.vbs one due to simplicity, as one does not have to modify with Blenders Python installation, threading modules and it works on each “Press P” iteration.

Well, (1) you use a function named runAndAwait, so indeed it might block for the duration of the call. Using a thread is not very hard, just make sure that persistent ones are made to exit when the game exits as well (else it will leak into the editor).

(2) you seem to use engine = pyttsx3.init()
https://pyttsx3.readthedocs.io/en/latest/engine.html#the-engine-factory
Blender keeps some piece of the Python environment through the game and the editor, so maybe something is messing up here. But a game ultimately should be published as a standalone, in which case you should/would not initialize things twice.

But nice that you could use pyttsx3! :slight_smile:

Still getting an

error

C:\Users\Cotaks\Desktop\Nieuwe map\tmp.txt
cscript C:\Users\Cotaks\Desktop\Nieuwe map\ptts.vbs < “C:\Users\Cotaks\Desktop\Nieuwe map\tmp.txt”
Microsoft ® Windows Script Host versie 5.812
Copyright © Microsoft Corporation. Alle rechten voorbehouden.

Invoerfout: Er is geen bestandsextensie in C:\Users\Cotaks\Desktop\Nieuwe.

But the user can easily fix this error by not using spaces in the folders name.
Other then that runs good now, nice work.

also your string can just be:

str = "cscript " + vbsFile + "<" +  tmpFile

no need to escape anything (the empty space after cscript is needed else it won’t work)