Issues 356 - Refactoring TTS
parent
885fe0a1cf
commit
e76c1b7d21
|
@ -16,18 +16,10 @@
|
||||||
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
|
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
import logging
|
from abc import ABCMeta, abstractmethod
|
||||||
|
|
||||||
import abc
|
|
||||||
from os.path import dirname, exists, isdir
|
from os.path import dirname, exists, isdir
|
||||||
|
|
||||||
from mycroft.configuration import ConfigurationManager
|
from mycroft.configuration import ConfigurationManager
|
||||||
from mycroft.tts import espeak_tts
|
|
||||||
from mycroft.tts import fa_tts
|
|
||||||
from mycroft.tts import google_tts
|
|
||||||
from mycroft.tts import mary_tts
|
|
||||||
from mycroft.tts import mimic_tts
|
|
||||||
from mycroft.tts import spdsay_tts
|
|
||||||
from mycroft.util.log import getLogger
|
from mycroft.util.log import getLogger
|
||||||
|
|
||||||
__author__ = 'jdorleans'
|
__author__ = 'jdorleans'
|
||||||
|
@ -42,15 +34,17 @@ class TTS(object):
|
||||||
It aggregates the minimum required parameters and exposes
|
It aggregates the minimum required parameters and exposes
|
||||||
``execute(sentence)`` function.
|
``execute(sentence)`` function.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
def __init__(self, lang, voice, filename='/tmp/tts.wav'):
|
def __init__(self, lang, voice, validator):
|
||||||
super(TTS, self).__init__()
|
super(TTS, self).__init__()
|
||||||
self.lang = lang
|
self.lang = lang
|
||||||
self.voice = voice
|
self.voice = voice
|
||||||
self.filename = filename
|
self.filename = '/tmp/tts.wav'
|
||||||
|
self.validator = validator
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abstractmethod
|
||||||
def execute(self, sentence, client):
|
def execute(self, sentence):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,48 +55,61 @@ class TTSValidator(object):
|
||||||
It exposes and implements ``validate(tts)`` function as a template to
|
It exposes and implements ``validate(tts)`` function as a template to
|
||||||
validate the TTS engines.
|
validate the TTS engines.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, tts):
|
||||||
pass
|
self.tts = tts
|
||||||
|
|
||||||
def validate(self, tts):
|
def validate(self):
|
||||||
self.__validate_instance(tts)
|
self.validate_instance()
|
||||||
self.__validate_filename(tts.filename)
|
self.validate_filename()
|
||||||
self.validate_lang(tts.lang)
|
self.validate_lang()
|
||||||
self.validate_connection(tts)
|
self.validate_connection()
|
||||||
|
|
||||||
def __validate_instance(self, tts):
|
def validate_instance(self):
|
||||||
instance = self.get_instance()
|
clazz = self.get_tts_class()
|
||||||
if not isinstance(tts, instance):
|
if not isinstance(self.tts, clazz):
|
||||||
raise AttributeError(
|
raise AttributeError('tts must be instance of ' + clazz.__name__)
|
||||||
'tts must be instance of ' + instance.__name__)
|
|
||||||
LOGGER.debug('TTS: ' + str(instance))
|
|
||||||
|
|
||||||
def __validate_filename(self, filename):
|
def validate_filename(self):
|
||||||
|
filename = self.tts.filename
|
||||||
if not (filename and filename.endswith('.wav')):
|
if not (filename and filename.endswith('.wav')):
|
||||||
raise AttributeError(
|
raise AttributeError('file: %s must be in .wav format!' % filename)
|
||||||
'filename: ' + filename + ' must be a .wav file!')
|
|
||||||
dir_path = dirname(filename)
|
dir_path = dirname(filename)
|
||||||
|
|
||||||
if not (exists(dir_path) and isdir(dir_path)):
|
if not (exists(dir_path) and isdir(dir_path)):
|
||||||
raise AttributeError(
|
raise AttributeError('filename: %s is not valid!' % filename)
|
||||||
'filename: ' + filename + ' is not a valid file path!')
|
|
||||||
LOGGER.debug('Filename: ' + filename)
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abstractmethod
|
||||||
def validate_lang(self, lang):
|
def validate_lang(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abstractmethod
|
||||||
def validate_connection(self, tts):
|
def validate_connection(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abstractmethod
|
||||||
def get_instance(self):
|
def get_tts_class(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TTSFactory(object):
|
class TTSFactory(object):
|
||||||
|
from mycroft.tts.espeak_tts import ESpeak
|
||||||
|
from mycroft.tts.fa_tts import FATTS
|
||||||
|
from mycroft.tts.google_tts import GoogleTTS
|
||||||
|
from mycroft.tts.mary_tts import MaryTTS
|
||||||
|
from mycroft.tts.mimic_tts import Mimic
|
||||||
|
from mycroft.tts.spdsay_tts import SpdSay
|
||||||
|
|
||||||
|
CLASSES = {
|
||||||
|
"mimic": Mimic,
|
||||||
|
"google": GoogleTTS,
|
||||||
|
"marytts": MaryTTS,
|
||||||
|
"fatts": FATTS,
|
||||||
|
"espeak": ESpeak,
|
||||||
|
"spdsay": SpdSay
|
||||||
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create():
|
def create():
|
||||||
"""
|
"""
|
||||||
|
@ -116,28 +123,18 @@ class TTSFactory(object):
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logging.basicConfig()
|
from mycroft.tts.remote_tts import RemoteTTS
|
||||||
config = ConfigurationManager.get().get('tts')
|
config = ConfigurationManager.get().get('tts', {})
|
||||||
name = config.get('module')
|
module = config.get('module', 'mimic')
|
||||||
lang = config.get(name).get('lang')
|
lang = config.get(module).get('lang')
|
||||||
voice = config.get(name).get('voice')
|
voice = config.get(module).get('voice')
|
||||||
|
clazz = TTSFactory.CLASSES.get(module)
|
||||||
|
|
||||||
if name == mimic_tts.NAME:
|
if issubclass(clazz, RemoteTTS):
|
||||||
tts = mimic_tts.Mimic(lang, voice)
|
url = config.get(module).get('url')
|
||||||
mimic_tts.MimicValidator().validate(tts)
|
tts = clazz(lang, voice, url)
|
||||||
elif name == google_tts.NAME:
|
|
||||||
tts = google_tts.GoogleTTS(lang, voice)
|
|
||||||
google_tts.GoogleTTSValidator().validate(tts)
|
|
||||||
elif name == mary_tts.NAME:
|
|
||||||
tts = mary_tts.MaryTTS(lang, voice, config[name + '.url'])
|
|
||||||
mary_tts.MaryTTSValidator().validate(tts)
|
|
||||||
elif name == fa_tts.NAME:
|
|
||||||
tts = fa_tts.FATTS(lang, voice, config[name + '.url'])
|
|
||||||
fa_tts.FATTSValidator().validate(tts)
|
|
||||||
elif name == espeak_tts.NAME:
|
|
||||||
tts = espeak_tts.ESpeak(lang, voice)
|
|
||||||
espeak_tts.ESpeakValidator().validate(tts)
|
|
||||||
else:
|
else:
|
||||||
tts = spdsay_tts.SpdSay(lang, voice)
|
tts = clazz(lang, voice)
|
||||||
spdsay_tts.SpdSayValidator().validate(tts)
|
|
||||||
|
tts.validator.validate()
|
||||||
return tts
|
return tts
|
||||||
|
|
|
@ -20,14 +20,12 @@ import subprocess
|
||||||
|
|
||||||
from mycroft.tts import TTS, TTSValidator
|
from mycroft.tts import TTS, TTSValidator
|
||||||
|
|
||||||
__author__ = 'seanfitz'
|
__author__ = 'seanfitz', 'jdorleans'
|
||||||
|
|
||||||
NAME = 'espeak'
|
|
||||||
|
|
||||||
|
|
||||||
class ESpeak(TTS):
|
class ESpeak(TTS):
|
||||||
def __init__(self, lang, voice):
|
def __init__(self, lang, voice):
|
||||||
super(ESpeak, self).__init__(lang, voice)
|
super(ESpeak, self).__init__(lang, voice, ESpeakValidator(self))
|
||||||
|
|
||||||
def execute(self, sentence, client):
|
def execute(self, sentence, client):
|
||||||
subprocess.call(
|
subprocess.call(
|
||||||
|
@ -35,20 +33,19 @@ class ESpeak(TTS):
|
||||||
|
|
||||||
|
|
||||||
class ESpeakValidator(TTSValidator):
|
class ESpeakValidator(TTSValidator):
|
||||||
def __init__(self):
|
def __init__(self, tts):
|
||||||
super(ESpeakValidator, self).__init__()
|
super(ESpeakValidator, self).__init__(tts)
|
||||||
|
|
||||||
def validate_lang(self, lang):
|
def validate_lang(self):
|
||||||
# TODO
|
# TODO
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def validate_connection(self, tts):
|
def validate_connection(self):
|
||||||
try:
|
try:
|
||||||
subprocess.call(['espeak', '--version'])
|
subprocess.call(['espeak', '--version'])
|
||||||
except:
|
except:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'ESpeak is not installed. Run on terminal: sudo apt-get '
|
'ESpeak is not installed. Run: sudo apt-get install espeak')
|
||||||
'install espeak')
|
|
||||||
|
|
||||||
def get_instance(self):
|
def get_tts_class(self):
|
||||||
return ESpeak
|
return ESpeak
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
|
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from mycroft.tts import TTSValidator
|
from mycroft.tts import TTSValidator
|
||||||
|
@ -25,8 +23,6 @@ from mycroft.tts.remote_tts import RemoteTTS
|
||||||
|
|
||||||
__author__ = 'jdorleans'
|
__author__ = 'jdorleans'
|
||||||
|
|
||||||
NAME = 'fatts'
|
|
||||||
|
|
||||||
|
|
||||||
class FATTS(RemoteTTS):
|
class FATTS(RemoteTTS):
|
||||||
PARAMS = {
|
PARAMS = {
|
||||||
|
@ -39,7 +35,8 @@ class FATTS(RemoteTTS):
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, lang, voice, url):
|
def __init__(self, lang, voice, url):
|
||||||
super(FATTS, self).__init__(lang, voice, url, '/say')
|
super(FATTS, self).__init__(lang, voice, url, '/say',
|
||||||
|
FATTSValidator(self))
|
||||||
|
|
||||||
def build_request_params(self, sentence):
|
def build_request_params(self, sentence):
|
||||||
params = self.PARAMS.copy()
|
params = self.PARAMS.copy()
|
||||||
|
@ -50,23 +47,23 @@ class FATTS(RemoteTTS):
|
||||||
|
|
||||||
|
|
||||||
class FATTSValidator(TTSValidator):
|
class FATTSValidator(TTSValidator):
|
||||||
def __init__(self):
|
def __init__(self, tts):
|
||||||
super(FATTSValidator, self).__init__()
|
super(FATTSValidator, self).__init__(tts)
|
||||||
|
|
||||||
def validate_lang(self, lang):
|
def validate_lang(self):
|
||||||
# TODO
|
# TODO
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def validate_connection(self, tts):
|
def validate_connection(self):
|
||||||
try:
|
try:
|
||||||
resp = requests.get(tts.url + "/info/version", verify=False)
|
resp = requests.get(self.tts.url + "/info/version", verify=False)
|
||||||
content = json.loads(resp.content)
|
content = resp.json()
|
||||||
if content['product'].find('FA-TTS') < 0:
|
if content.get('product', '').find('FA-TTS') < 0:
|
||||||
raise Exception('Invalid FA-TTS server.')
|
raise Exception('Invalid FA-TTS server.')
|
||||||
except:
|
except:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'FA-TTS server could not be verified. Check your connection '
|
'FA-TTS server could not be verified. Check your connection '
|
||||||
'to the server: ' + tts.url)
|
'to the server: ' + self.tts.url)
|
||||||
|
|
||||||
def get_instance(self):
|
def get_tts_class(self):
|
||||||
return FATTS
|
return FATTS
|
||||||
|
|
|
@ -23,12 +23,10 @@ from mycroft.util import play_wav
|
||||||
|
|
||||||
__author__ = 'jdorleans'
|
__author__ = 'jdorleans'
|
||||||
|
|
||||||
NAME = 'gtts'
|
|
||||||
|
|
||||||
|
|
||||||
class GoogleTTS(TTS):
|
class GoogleTTS(TTS):
|
||||||
def __init__(self, lang, voice):
|
def __init__(self, lang, voice):
|
||||||
super(GoogleTTS, self).__init__(lang, voice)
|
super(GoogleTTS, self).__init__(lang, voice, GoogleTTSValidator(self))
|
||||||
|
|
||||||
def execute(self, sentence, client):
|
def execute(self, sentence, client):
|
||||||
tts = gTTS(text=sentence, lang=self.lang)
|
tts = gTTS(text=sentence, lang=self.lang)
|
||||||
|
@ -37,20 +35,20 @@ class GoogleTTS(TTS):
|
||||||
|
|
||||||
|
|
||||||
class GoogleTTSValidator(TTSValidator):
|
class GoogleTTSValidator(TTSValidator):
|
||||||
def __init__(self):
|
def __init__(self, tts):
|
||||||
super(GoogleTTSValidator, self).__init__()
|
super(GoogleTTSValidator, self).__init__(tts)
|
||||||
|
|
||||||
def validate_lang(self, lang):
|
def validate_lang(self):
|
||||||
# TODO
|
# TODO
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def validate_connection(self, tts):
|
def validate_connection(self):
|
||||||
try:
|
try:
|
||||||
gTTS(text='Hi').save(tts.filename)
|
gTTS(text='Hi').save(self.tts.filename)
|
||||||
except:
|
except:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'GoogleTTS server could not be verified. Please check your '
|
'GoogleTTS server could not be verified. Please check your '
|
||||||
'internet connection.')
|
'internet connection.')
|
||||||
|
|
||||||
def get_instance(self):
|
def get_tts_class(self):
|
||||||
return GoogleTTS
|
return GoogleTTS
|
||||||
|
|
|
@ -23,8 +23,6 @@ from mycroft.tts.remote_tts import RemoteTTS
|
||||||
|
|
||||||
__author__ = 'jdorleans'
|
__author__ = 'jdorleans'
|
||||||
|
|
||||||
NAME = 'marytts'
|
|
||||||
|
|
||||||
|
|
||||||
class MaryTTS(RemoteTTS):
|
class MaryTTS(RemoteTTS):
|
||||||
PARAMS = {
|
PARAMS = {
|
||||||
|
@ -37,7 +35,8 @@ class MaryTTS(RemoteTTS):
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, lang, voice, url):
|
def __init__(self, lang, voice, url):
|
||||||
super(MaryTTS, self).__init__(lang, voice, url, '/process')
|
super(MaryTTS, self).__init__(lang, voice, url, '/process',
|
||||||
|
MaryTTSValidator(self))
|
||||||
|
|
||||||
def build_request_params(self, sentence):
|
def build_request_params(self, sentence):
|
||||||
params = self.PARAMS.copy()
|
params = self.PARAMS.copy()
|
||||||
|
@ -48,22 +47,22 @@ class MaryTTS(RemoteTTS):
|
||||||
|
|
||||||
|
|
||||||
class MaryTTSValidator(TTSValidator):
|
class MaryTTSValidator(TTSValidator):
|
||||||
def __init__(self):
|
def __init__(self, tts):
|
||||||
super(MaryTTSValidator, self).__init__()
|
super(MaryTTSValidator, self).__init__(tts)
|
||||||
|
|
||||||
def validate_lang(self, lang):
|
def validate_lang(self):
|
||||||
# TODO
|
# TODO
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def validate_connection(self, tts):
|
def validate_connection(self):
|
||||||
try:
|
try:
|
||||||
resp = requests.get(tts.url + "/version", verify=False)
|
resp = requests.get(self.tts.url + "/version", verify=False)
|
||||||
if resp.content.find('Mary TTS server') < 0:
|
if resp.content.find('Mary TTS server') < 0:
|
||||||
raise Exception('Invalid MaryTTS server.')
|
raise Exception('Invalid MaryTTS server.')
|
||||||
except:
|
except:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'MaryTTS server could not be verified. Check your connection '
|
'MaryTTS server could not be verified. Check your connection '
|
||||||
'to the server: ' + tts.url)
|
'to the server: ' + self.tts.url)
|
||||||
|
|
||||||
def get_instance(self):
|
def get_tts_class(self):
|
||||||
return MaryTTS
|
return MaryTTS
|
||||||
|
|
|
@ -16,11 +16,10 @@
|
||||||
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
|
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
from os.path import join
|
|
||||||
import re
|
|
||||||
import random
|
import random
|
||||||
import os
|
import os
|
||||||
import time
|
|
||||||
|
from os.path import join
|
||||||
|
|
||||||
from mycroft import MYCROFT_ROOT_PATH
|
from mycroft import MYCROFT_ROOT_PATH
|
||||||
from mycroft.tts import TTS, TTSValidator
|
from mycroft.tts import TTS, TTSValidator
|
||||||
|
@ -31,9 +30,7 @@ __author__ = 'jdorleans'
|
||||||
|
|
||||||
config = ConfigurationManager.get().get("tts", {})
|
config = ConfigurationManager.get().get("tts", {})
|
||||||
|
|
||||||
NAME = 'mimic'
|
BIN = config.get("path", join(MYCROFT_ROOT_PATH, 'mimic', 'bin', 'mimic'))
|
||||||
BIN = config.get(
|
|
||||||
"mimic.path", join(MYCROFT_ROOT_PATH, 'mimic', 'bin', 'mimic'))
|
|
||||||
|
|
||||||
# Mapping based on Jeffers phoneme to viseme map, seen in table 1 from:
|
# Mapping based on Jeffers phoneme to viseme map, seen in table 1 from:
|
||||||
# http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.221.6377&rep=rep1&type=pdf
|
# http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.221.6377&rep=rep1&type=pdf
|
||||||
|
@ -49,7 +46,7 @@ BIN = config.get(
|
||||||
class Mimic(TTS):
|
class Mimic(TTS):
|
||||||
|
|
||||||
def __init__(self, lang, voice):
|
def __init__(self, lang, voice):
|
||||||
super(Mimic, self).__init__(lang, voice)
|
super(Mimic, self).__init__(lang, voice, MimicValidator(self))
|
||||||
self.args = ['-voice', self.voice]
|
self.args = ['-voice', self.voice]
|
||||||
stretch = config.get('duration_stretch', None)
|
stretch = config.get('duration_stretch', None)
|
||||||
if stretch:
|
if stretch:
|
||||||
|
@ -151,19 +148,19 @@ class Mimic(TTS):
|
||||||
|
|
||||||
|
|
||||||
class MimicValidator(TTSValidator):
|
class MimicValidator(TTSValidator):
|
||||||
def __init__(self):
|
def __init__(self, tts):
|
||||||
super(MimicValidator, self).__init__()
|
super(MimicValidator, self).__init__(tts)
|
||||||
|
|
||||||
def validate_lang(self, lang):
|
def validate_lang(self):
|
||||||
|
# TODO
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def validate_connection(self, tts):
|
def validate_connection(self):
|
||||||
try:
|
try:
|
||||||
subprocess.call([BIN, '--version'])
|
subprocess.call([BIN, '--version'])
|
||||||
except:
|
except:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Mimic is not installed. Make sure install-mimic.sh ran '
|
'Mimic is not installed. Run install-mimic.sh to install it.')
|
||||||
'properly.')
|
|
||||||
|
|
||||||
def get_instance(self):
|
def get_tts_class(self):
|
||||||
return Mimic
|
return Mimic
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from requests_futures.sessions import FuturesSession
|
from requests_futures.sessions import FuturesSession
|
||||||
|
|
||||||
from mycroft.tts import TTS
|
from mycroft.tts import TTS
|
||||||
|
@ -38,8 +37,8 @@ class RemoteTTS(TTS):
|
||||||
whole sentence into small ones.
|
whole sentence into small ones.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, lang, voice, url, api_path):
|
def __init__(self, lang, voice, url, api_path, validator):
|
||||||
super(RemoteTTS, self).__init__(lang, voice)
|
super(RemoteTTS, self).__init__(lang, voice, validator)
|
||||||
self.api_path = api_path
|
self.api_path = api_path
|
||||||
self.url = remove_last_slash(url)
|
self.url = remove_last_slash(url)
|
||||||
self.session = FuturesSession()
|
self.session = FuturesSession()
|
||||||
|
|
|
@ -22,12 +22,10 @@ from mycroft.tts import TTS, TTSValidator
|
||||||
|
|
||||||
__author__ = 'jdorleans'
|
__author__ = 'jdorleans'
|
||||||
|
|
||||||
NAME = 'spdsay'
|
|
||||||
|
|
||||||
|
|
||||||
class SpdSay(TTS):
|
class SpdSay(TTS):
|
||||||
def __init__(self, lang, voice):
|
def __init__(self, lang, voice):
|
||||||
super(SpdSay, self).__init__(lang, voice)
|
super(SpdSay, self).__init__(lang, voice, SpdSayValidator(self))
|
||||||
|
|
||||||
def execute(self, sentence, client):
|
def execute(self, sentence, client):
|
||||||
subprocess.call(
|
subprocess.call(
|
||||||
|
@ -35,20 +33,20 @@ class SpdSay(TTS):
|
||||||
|
|
||||||
|
|
||||||
class SpdSayValidator(TTSValidator):
|
class SpdSayValidator(TTSValidator):
|
||||||
def __init__(self):
|
def __init__(self, tts):
|
||||||
super(SpdSayValidator, self).__init__()
|
super(SpdSayValidator, self).__init__(tts)
|
||||||
|
|
||||||
def validate_lang(self, lang):
|
def validate_lang(self):
|
||||||
# TODO
|
# TODO
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def validate_connection(self, tts):
|
def validate_connection(self):
|
||||||
try:
|
try:
|
||||||
subprocess.call(['spd-say', '--version'])
|
subprocess.call(['spd-say', '--version'])
|
||||||
except:
|
except:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'SpdSay is not installed. Run on terminal: sudo apt-get'
|
'SpdSay is not installed. Run: sudo apt-get install '
|
||||||
'install speech-dispatcher')
|
'speech-dispatcher')
|
||||||
|
|
||||||
def get_instance(self):
|
def get_tts_class(self):
|
||||||
return SpdSay
|
return SpdSay
|
||||||
|
|
Loading…
Reference in New Issue