def check_espeak(cls): """ Check whether ``espeak`` can be called. Return ``True`` on failure and ``False`` on success. :rtype: bool """ try: from aeneas.espeakwrapper import ESPEAKWrapper text = u"From fairest creatures we desire increase," language = u"eng" handler, output_file_path = gf.tmp_file(suffix=u".wav") espeak = ESPEAKWrapper() result = espeak.synthesize_single(text, language, output_file_path) gf.delete_file(handler, output_file_path) if result: gf.print_success(u"espeak OK") return False except: pass gf.print_error(u"espeak ERROR") gf.print_info( u" Please make sure you have espeak installed correctly") gf.print_info( u" and that its path is in your PATH environment variable") gf.print_info( u" You might also want to check that the espeak-data directory") gf.print_info( u" is set up correctly, for example, it has the correct permissions" ) return True
def step4(): on_info("Test 4/6 (espeak)...") try: on_info(" Trying to call espeak...") from aeneas.espeakwrapper import ESPEAKWrapper from aeneas.language import Language text = u"From fairest creatures we desire increase," language = Language.EN handler, output_file_path = tempfile.mkstemp(suffix=".wav") espeak = ESPEAKWrapper() result = espeak.synthesize(text, language, output_file_path) os.close(handler) os.remove(output_file_path) if result: on_info(" Trying to call espeak... succeeded.") return True else: on_error(" Unable to call espeak.") on_error( " Please make sure you have espeak installed correctly and that it is in your $PATH." ) except: on_error(" Unable to call espeak.") on_error( " Please make sure you have espeak installed correctly and that it is in your $PATH." ) return False
def main(): """ Entry point """ if len(sys.argv) < 4: usage() return text = sys.argv[1] language = sys.argv[2] output_file_path = sys.argv[3] synt = ESPEAKWrapper() synt.synthesize(text, language, output_file_path) print "[INFO] Created file '%s'" % output_file_path
def _select_tts_engine(self): """ Select the TTS engine to be used by looking at the rconf object. """ self.log(u"Selecting TTS engine...") if self.rconf[RuntimeConfiguration.TTS] == self.CUSTOM: self.log(u"TTS engine: custom") tts_path = self.rconf[RuntimeConfiguration.TTS_PATH] if not gf.file_can_be_read(tts_path): self.log_exc(u"Cannot read tts_path", None, True, OSError) try: import imp self.log([ u"Loading CustomTTSWrapper module from '%s'...", tts_path ]) imp.load_source("CustomTTSWrapperModule", tts_path) self.log([ u"Loading CustomTTSWrapper module from '%s'... done", tts_path ]) self.log(u"Importing CustomTTSWrapper...") from CustomTTSWrapperModule import CustomTTSWrapper self.log(u"Importing CustomTTSWrapper... done") self.log(u"Creating CustomTTSWrapper instance...") self.tts_engine = CustomTTSWrapper(rconf=self.rconf, logger=self.logger) self.log(u"Creating CustomTTSWrapper instance... done") except Exception as exc: self.log_exc(u"Unable to load custom TTS wrapper", exc, True, OSError) elif self.rconf[RuntimeConfiguration.TTS] == self.FESTIVAL: self.log(u"TTS engine: Festival") self.tts_engine = FESTIVALWrapper(rconf=self.rconf, logger=self.logger) elif self.rconf[RuntimeConfiguration.TTS] == self.NUANCETTSAPI: try: import requests except ImportError as exc: self.log_exc( u"Unable to import requests for Nuance TTS API wrapper", exc, True, ImportError) self.log(u"TTS engine: Nuance TTS API") self.tts_engine = NuanceTTSAPIWrapper(rconf=self.rconf, logger=self.logger) else: self.log(u"TTS engine: eSpeak") self.tts_engine = ESPEAKWrapper(rconf=self.rconf, logger=self.logger) self.log(u"Selecting TTS engine... done")
def synthesize(self, text_file, audio_file_path, quit_after=None, backwards=False): """ Synthesize the text contained in the given fragment list into a ``wav`` file. :param text_file: the text file to be synthesized :type text_file: :class:`aeneas.textfile.TextFile` :param audio_file_path: the path to the output audio file :type audio_file_path: string (path) :param quit_after: stop synthesizing as soon as reaching this many seconds :type quit_after: float :param backwards: synthesizing from the end of the text file :type backwards: bool """ # time anchors anchors = [] # initialize time current_time = 0.0 # waves is used to concatenate all the fragments WAV files waves = numpy.array([]) # espeak wrapper espeak = ESPEAKWrapper(logger=self.logger) if quit_after is not None: self._log(["Quit after reaching %.3f", quit_after]) if backwards: self._log("Synthesizing backwards") # for each fragment, synthesize it and concatenate it num = 0 num_chars = 0 fragments = text_file.fragments if backwards: fragments = fragments[::-1] for fragment in fragments: # synthesize and get the duration of the output file self._log(["Synthesizing fragment %d", num]) handler, tmp_destination = tempfile.mkstemp( suffix=".wav", dir=gf.custom_tmp_dir()) duration = espeak.synthesize(text=fragment.text, language=fragment.language, output_file_path=tmp_destination) # store for later output anchors.append([current_time, fragment.identifier, fragment.text]) # increase the character counter num_chars += fragment.characters # concatenate to buffer self._log(["Fragment %d starts at: %f", num, current_time]) if duration > 0: self._log(["Fragment %d duration: %f", num, duration]) current_time += duration data, sample_frequency, encoding = wavread(tmp_destination) # # TODO this might result in memory swapping # if we have a large number of fragments # is there a better way? # # NOTE since append cannot be in place, # it seems that the only alternative is pre-allocating # the destination array, # possibly truncating or extending it as needed # if backwards: waves = numpy.append(data, waves) else: waves = numpy.append(waves, data) else: self._log(["Fragment %d has zero duration", num]) # remove temporary file self._log(["Removing temporary file '%s'", tmp_destination]) os.close(handler) os.remove(tmp_destination) num += 1 if (quit_after is not None) and (current_time > quit_after): self._log( ["Quitting after reached duration %.3f", current_time]) break # output WAV file, concatenation of synthesized fragments self._log(["Writing audio file '%s'", audio_file_path]) wavwrite(waves, audio_file_path, sample_frequency, encoding) # return the time anchors # TODO anchors do not make sense if backwards == True self._log(["Returning %d time anchors", len(anchors)]) self._log(["Current time %.3f", current_time]) self._log(["Synthesized %d characters", num_chars]) return (anchors, current_time, num_chars)