API
opentts_bridge.py
Go to the documentation of this file.
1 from dataclasses import dataclass
2 import os.path
3 import subprocess
4 import hashlib
5 import logging
6 import requests
7 from urllib.parse import urljoin
8 
9 from .personality import Recording
10 
11 log = logging.getLogger(__name__)
12 
14  return requests.head(api_url).status_code == 200
15 
16 def speak(speech, default_voice, api_url, cache_dir):
17  if isinstance(speech, Recording):
18  wav_path = speech.path
19  else:
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...")
23  play_wav(wav_path)
24  log.debug("Speech spoken.")
25 
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):
31  if not check_opentts_service_status(api_url):
32  raise RuntimeError(f"No OpenTTS at {api_url}, cannot generate speech")
33  endpoint = urljoin(api_url, "/api/tts")
34  resp = requests.get(
35  endpoint,
36  params={
37  'voice': default_voice,
38  'text': ssml_text,
39  'vocoder': 'high',
40  'denoiserStrength': 0.03,
41  'cache': False,
42  'ssml': True,
43  'ssmlNumbers': True,
44  'ssmlDates': True,
45  'ssmlCurrency': True,
46  },
47  timeout=10,
48  )
49  with open(destination_path, 'wb') as fh:
50  fh.write(resp.content)
51  log.debug(f"Cache written: {destination_path}")
52  else:
53  log.debug(f"Cache hit: {destination_path}")
54  return destination_path
55 
56 def play_wav(wav_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)