1 from dataclasses
import dataclass
7 from urllib.parse
import urljoin
9 from .personality
import Recording
11 log = logging.getLogger(__name__)
14 return requests.head(api_url).status_code == 200
16 def speak(speech, default_voice, api_url, cache_dir):
17 if isinstance(speech, Recording):
18 wav_path = speech.path
20 log.debug(
"Generating speech (or using cache)...")
21 wav_path =
ssml_to_wav(speech.markup, default_voice, api_url, cache_dir)
22 log.debug(
"Playing audio...")
24 log.debug(
"Speech spoken.")
26 def ssml_to_wav(ssml_text, default_voice, api_url, cache_dir):
27 cache_key = hashlib.md5(ssml_text.encode(
'utf-8')).hexdigest()
28 cache_filename = f
"{default_voice}_{cache_key}.wav"
29 destination_path = os.path.join(cache_dir, cache_filename)
30 if not os.path.exists(destination_path):
32 raise RuntimeError(f
"No OpenTTS at {api_url}, cannot generate speech")
33 endpoint = urljoin(api_url,
"/api/tts")
37 'voice': default_voice,
40 'denoiserStrength': 0.03,
49 with open(destination_path,
'wb')
as fh:
50 fh.write(resp.content)
51 log.debug(f
"Cache written: {destination_path}")
53 log.debug(f
"Cache hit: {destination_path}")
54 return destination_path
57 subprocess.check_call(f
"XDG_RUNTIME_DIR=/run/user/$(id -u xsup) pacat --rate=22050 --channels=1 {wav_path}", shell=
True)
def check_opentts_service_status(api_url)
def speak(speech, default_voice, api_url, cache_dir)
def ssml_to_wav(ssml_text, default_voice, api_url, cache_dir)