Source code for sic_framework.devices.common_desktop.desktop_text_to_speech

import subprocess

from sic_framework import SICActuator, SICComponentManager
from sic_framework.core.connector import SICConnector
from sic_framework.core.message_python2 import (
    AudioMessage,
    SICConfMessage,
    SICMessage,
    TextMessage,
    TextRequest,
)

[docs] class TextToSpeechConf(SICConfMessage): """ Parameters for espeak. """
[docs] def __init__( self, amplitude=100, pitch=50, speed=175, gap=0, voice="en", ): """ Initialize espeak configuration. :param amplitude: Volume (0-200), default 100 :param pitch: Pitch adjustment (0-99), default 50 :param speed: Speed in words per minute, default 175 :param gap: Word gap in 10ms units, default 0 :param voice: Voice to use (e.g., 'en', 'en-us', 'en+f3'), default 'en' """ self.amplitude = amplitude self.pitch = pitch self.speed = speed self.gap = gap self.voice = voice
[docs] class DesktopTextToSpeechActuator(SICActuator): """ Desktop text to speech actuator. Requires espeak to be installed. """
[docs] def __init__(self, *args, **kwargs): super(DesktopTextToSpeechActuator, self).__init__(*args, **kwargs) # Check if espeak is available try: subprocess.run(['espeak', '--version'], capture_output=True, check=True, timeout=5) self.logger.info("espeak is available") except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired) as e: self.logger.warning("espeak not found or not working: {}".format(e)) self.logger.warning("Please install espeak: 'sudo apt-get install espeak' (Linux) or 'brew install espeak' (macOS)")
[docs] @staticmethod def get_conf(): return TextToSpeechConf()
[docs] @staticmethod def get_inputs(): return [TextMessage, TextRequest]
[docs] @staticmethod def get_output(): return SICMessage
[docs] def _speak(self, text): """Use espeak subprocess to speak the text.""" try: # Build espeak command with parameters cmd = [ 'espeak', '-a', str(self.params.amplitude), # amplitude (volume) '-p', str(self.params.pitch), # pitch '-s', str(self.params.speed), # speed '-g', str(self.params.gap), # word gap '-v', self.params.voice, # voice text ] self.logger.debug("Running espeak command: {}".format(' '.join(cmd))) # Run espeak and wait for completion subprocess.run(cmd, check=True, timeout=30) except subprocess.CalledProcessError as e: self.logger.error("espeak command failed: {}".format(e)) except subprocess.TimeoutExpired: self.logger.error("espeak command timed out") except FileNotFoundError: self.logger.error("espeak not found. Please install espeak.")
[docs] def on_request(self, request): self.logger.debug("Saying: " + request.text) self._speak(request.text) return SICMessage()
[docs] def on_message(self, message): self.logger.debug("Saying: " + message.text) self._speak(message.text)
[docs] def stop(self, *args): self._stopped.set() super(DesktopTextToSpeechActuator, self).stop(*args)
[docs] class DesktopTextToSpeech(SICConnector): component_class = DesktopTextToSpeechActuator
if __name__ == "__main__": SICComponentManager([DesktopTextToSpeechActuator])