Forum Archive

Can't install pyttsx3 module

lyubomyr83

I install stash, and after in stash console try:
pip install pyttsx3

I receive
........
........
Running setup file ...
PermissionError(1, 'Operation not permitted')
Failed to run setup.py
Fall back to directory guessing ...
Error: Cannot locate packages. Manual installation required.

When installed wikipedia all was ok.
Please help solve.

sulcud

This is not a solution for the installation but maybe it can help you, Pythonista has an already TTS module called “speech” and it works well


import speech

speech.say('hello')

lyubomyr83

Thank's a lot. You help me.

lyubomyr83

@sulcud
In iOS 12 russian language work well. But in iOS 13 russian words pronounce terrible with english mix. What's wrong in iOS13?

sulcud

I don’t speak Russian so I can’t confirm is the Russian pronunciation Is wrong, but maybe you are running the “say” function with the language “en-US”; this function has this parameters:

text -> text you want to say
language -> (optional) the language that you want to speak with
rate -> (optional) the speed of the voice

Maybe you are trying this, I don’t know

import speech

speech.say(some_russian_text)

You should try

import speech

speech.say("привет друг", "ru-RU")
cvp

If not yet ok, you could try speech via ObjectiveC

lyubomyr83

@sulcud
Thank's again. Setting "ru-RU" working good in iOS13.

def say(text):

settings = read_settings()

if settings["sound"] == 'yes':
    # windows
    if os.name == 'nt':
        engine = pyttsx3.init()

        en_voice_id = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_EN-US_ZIRA_11.0"
        ru_voice_id = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_RU-RU_IRINA_11.0"

        # use russian sound
        engine.setProperty('voice', ru_voice_id)
        engine.say(text)
        engine.runAndWait()
    # iOS, Android
    elif os.name == 'posix':
        speech.say(text, "ru-RU")
    else:
        pass
lyubomyr83

@sulcud
Maybe you know how to change default voice from female to male?
And how can i print all availible voices?

ccc

@lyubomyr83 said:

how can i print all availible voices?

https://forum.omz-software.com/topic/4706/how-to-use-speech-say-in-different-voice/2

sulcud

@lyubomyr83, I made this class to make it easier to work with the reference @ccc is pointing to, all could be done thanks to the work of @JonB


import objc_util
import re


class SpeechModule(object):
    def __init__(self):
        self.__AVSpeechUtterance = objc_util.ObjCClass('AVSpeechUtterance')
        self.__AVSpeechSynthesizer = objc_util.ObjCClass('AVSpeechSynthesizer')
        self.__AVSpeechSynthesisVoice = objc_util.ObjCClass('AVSpeechSynthesisVoice')
        self.__synthesizer = self.__AVSpeechSynthesizer.new()

    def get_synthesis_languages(self) -> list:
        return self.__AVSpeechSynthesisVoice.speechVoices()

    def say(self, msg: str, language: objc_util.ObjCInstance, rate=0.5):

        utterance = self.__AVSpeechUtterance.speechUtteranceWithString_(msg)
        utterance.rate = rate
        utterance.voice = voice
        utterance.useCompactVoice = False
        self.__synthesizer.speakUtterance_(utterance)

    def is_speaking(self) -> bool:
        return self.__synthesizer.isSpeaking()

    def is_paused(self) -> bool:
        return self.__synthesizer.isPaused()

    def pause(self) -> bool:
        return self.__synthesizer.pauseSpeakingAtBoundary_(True)

    def stop(self) -> bool:
        return self.__synthesizer.stopSpeakingAtBoundary_(True)

    def continue_speaking(self):
        self.__synthesizer.continueSpeaking()

Here is an example how to use it


import time

speech_ = SpeechModule()

available_voices = speech_.get_synthesis_languages()

us_english_voices = tuple(filter(lambda voice: "en-US" in str(voice), available_voices))

voice = us_english_voices[0]

speech_.say('Hello friend! how are you?', voice, 0.3)

time.sleep(1)
speech_.stop()
print(speech_.is_speaking())
speech_.say("nevermind", voice)

For some reason I can’t make that pause function to work correctly, anyway, it is an idea for your project and maybe my class could be buggy, so objc gurus invocation (@cvp @mikael @JonB @ccc )

cvp

@sulcud 👍 perfect except the fact to include me in a gurus list 😢

cvp

@sulcud said:

For some reason I can’t make that pause function to work correctly,

Parameter of pauseSpeakingAtBoundary_ is not a Boolean but an integer, see AVSpeechBoundary , try 0=Immediately instead ofTrue

sulcud

@cvp, you are right, using 0 fixes it, did you find anyway to fix the false positives that is_paused and is_speaking functions return?

cvp

@sulcud I don't have tested your code thus I didn't know there were some problems, except this one you described. I'll try later, sorry

cvp

@sulcud First, parameter of stopSpeakingAtBoundary_ is also integer...

cvp

@sulcud said:

did you find anyway to fix the false positives that is_paused and is_speaking functions return?

No, sorry

JonB

Haven't tried, but often objc_util.on_main_thread fixes problems like is_paused not reporting correct no values.

Note is_speaking will return true even if paused...

cvp

@JonB nothing changed for is_speaking, as you did foresee

JonB

Discussion
Returns YES if the synthesizer is speaking or has utterances enqueued to speak, even if it is currently paused. Returns NO if the synthesizer has finished speaking all utterances in its queue or if it has not yet been given an utterance to speak.

So if you want to know when speaking stops, one would want to check if not speaking, or speaking and paused.

Because of threading and such, it might be more reliable to implement the delegate, and then keep track of state within the delegate object, that can then be queried in python code.

mikael

@sulcud, looking at this putting a wrapper around the delegate as @JonB suggests looks like the best way to get fine control over the speech, being able to highlight individual words as they are spoken etc.

Such a wrapper could also include synchronous methods, so that it would be easy to just say something and move on after the talking is done.

lyubomyr83

@sulcud
I was remove speech module in my iOS. How to recover???

sulcud

I think that erasing a Pythonista build-in module is not possible, remember that python has a weird importing system so if you have a script/folder called speech in the same folder of your main script maybe you are importing it instead of the build in one. (python import order is: current dir, ... , site-packages, build-in) but If that is not the case, I think a fresh install of Pythonista could work

lyubomyr83

@sulcud fresh install doesn't helped. I was delete speech module before over stash(((. Now i can't recover.

JonB

Make sure you don't have a speech.py in site-packages, or in the same folder as the main script you are running. Also make sure you don't have any folders called speech inside site-packages, that includes an init file.

As a check, in the console, try

import speech

If that fails, look at the traceback to show you what failed, which should include a path to the module it was trying to import.

cvp

You can also try

import speech
import inspect
print(inspect.getfile(speech)) 

Either you will get an error module 'speech' (built-in)> is a built-in module
Either you will get its path if another speech module is imported

lyubomyr83

@cvp
get an error module 'speech' (built-in)> is a built-in module

cvp

@lyubomyr83 thus, you did not remove it...

JonB

@lyubomyr83 why do you think you deleted the speech module? What error do you get when you try to use it?

Or, are you talking the SpeechModule script that was shared?

In that case, just copy the code again, paste into the editor, and name it something other than speech...

lyubomyr83

@JonB i have two same 3rd generation ipads, run the same program and have voice in one of them and not in another one. Yes, voice is on ))) in settings. And i have not errors.

cvp

@lyubomyr83 could you try the iOS Shortuts app with "speak text" command, only to check if the problem could come from the hardware and not from Pythonista

lyubomyr83

@cvp in iOS settings/speech i hear sound when i change speed (Turtle)

cvp

@lyubomyr83 ok, but did you try the shortcut ?

And is your script as short as

import speech
speech.say("привет друг", "ru-RU")  # hello friend
JonB

@lyubomyr83 check that the mute alarms is not set in the pull down settings. If you have a physical mute switch, make sure it is not set to mute. If you have a physical switch that you toggled to lock rotation, then make sure the swipe settings doesn't show mute.

Even when volume is turned up, pythonista honors the mute setting for some sounds.