API
 
Loading...
Searching...
No Matches
opentts_bridge.py
Go to the documentation of this file.
1from dataclasses import dataclass
2import os.path
3import subprocess
4import hashlib
5import logging
6import requests
7from urllib.parse import urljoin
8
9from .personality import Recording
10
11log = logging.getLogger(__name__)
12
14 return requests.head(api_url).status_code == 200
15
16def 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
26def 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:
51 log.debug(f"Cache written: {destination_path}")
52 else:
53 log.debug(f"Cache hit: {destination_path}")
54 return destination_path
55
56def 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)