Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSML rendering not working #287

Open
colin-hue opened this issue Aug 2, 2023 · 1 comment
Open

SSML rendering not working #287

colin-hue opened this issue Aug 2, 2023 · 1 comment
Assignees

Comments

@colin-hue
Copy link

The engine.say method does not render SSML in espeak;; and there is no method to set the equivalent of the CLI espeak "-m" option to tell pyttsx3 that the content of the string is SSML and have it render properly. There is an argument that SSML rendering should be turned on by default - to do this the say function in espeak.py should be altered to OR _espeak.SSML with the other flags currently used.

@willwade willwade self-assigned this Oct 17, 2024
@willwade
Copy link
Collaborator

willwade commented Oct 17, 2024

Note to self.


def say(self, text, ssml=False):
    self._text_to_say = text
    self._ssml = ssml

Then in start synthesis we need to


flags = _espeak.ENDPAUSE | _espeak.CHARS_UTF8
if self._ssml:
    flags |= _espeak.SSML

But needs thought. We should have a flag that works in sapi and nsss too

And for ssml in sapi. Remember we need to work on other methods like save to file.

def say(self, text, ssml=False):
    self._proxy.setBusy(True)
    self._proxy.notify("started-utterance")
    self._speaking = True
    self._current_text = text
    # Use SVSFIsXML flag if SSML is enabled
    flags = SpeechLib.SVSFlagsAsync | (SpeechLib.SVSFIsXML if ssml else 0)
    self._tts.Speak(fromUtf8(toUtf8(text)), flags)

def save_to_file(self, text, filename, ssml=False):
    cwd = os.getcwd()
    stream = comtypes.client.CreateObject("SAPI.SpFileStream")
    stream.Open(filename, SpeechLib.SSFMCreateForWrite)
    temp_stream = self._tts.AudioOutputStream
    self._current_text = text
    self._tts.AudioOutputStream = stream
    # Use SVSFIsXML flag if SSML is enabled
    flags = SpeechLib.SVSFIsXML if ssml else 0
    self._tts.Speak(fromUtf8(toUtf8(text)), flags)
    self._tts.AudioOutputStream = temp_stream
    stream.close()
    os.chdir(cwd)

Small snag. I don't think ssml is supported in nsss. Annoying. I could be wrong.


import re

# Utility function to remove SSML tags
def strip_ssml(text):
    # This removes basic SSML tags. Expand as needed for specific tags
    return re.sub(r"<[^>]*>", "", text)

class NSSpeechDriver(NSObject):
    # Existing methods...

    @objc.python_method
    def say(self, text, ssml=False):
        self._proxy.setBusy(True)
        self._completed = True
        self._proxy.notify("started-utterance")
        self._current_text = strip_ssml(text) if ssml else text  # Process SSML if needed
        self._tts.startSpeakingString_(self._current_text)

    @objc.python_method
    def save_to_file(self, text, filename, ssml=False):
        self._proxy.setBusy(True)
        self._completed = True
        self._current_text = strip_ssml(text) if ssml else text  # Process SSML if needed
        url = Foundation.NSURL.fileURLWithPath_(filename)
        self._tts.startSpeakingString_toURL_(self._current_text, url)

However I think we should migrate all of macOS code to AVSpeechSynth

https://gist.github.com/willwade/93e709147d7ce9a5f80a3c3944f8e331

willwade added a commit to willwade/pyttsx3 that referenced this issue Oct 26, 2024
nateshmbhat#347 nateshmbhat#336

I think this is passing all the tests. Its far simpler than nsss and we can do thngs like ssml nateshmbhat#121 nateshmbhat#287
willwade added a commit to willwade/pyttsx3 that referenced this issue Nov 4, 2024
I think this is passing all the tests. Its far simpler than nsss and we can do thngs like ssml nateshmbhat#121 nateshmbhat#287
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants