def main(): args = arg_parser() play = Player(dummy=args.quiet) tts = TTS(threads=1) text_size_all = 0 reply_size_all = 0 reply_time_all = 0 full_time_all = 0 counts = 0 while True: text = args.file.read(args.chunks) if not text: break text_size = len(text) reply_size = 0 full_time = time.time() reply_time = None with tts.say(text, voice=args.voice, format_='wav') as say: for chunk in say: if reply_time is None: reply_time = time.time() - full_time reply_size += len(chunk) play.play_chunk(chunk) full_time = time.time() - full_time text_size_all += text_size reply_size_all += reply_size reply_time_all += reply_time full_time_all += full_time counts += 1 _print(text_size, reply_size, reply_time, full_time) args.file.close() play.close() tts.join() if counts: print('Summary:') _print(text_size_all, reply_size_all, reply_time_all / counts, full_time_all) print('bye.')
class Player(threading.Thread): def __init__(self): super().__init__() self.tts = TTS(threads=1, force_process=False) self._queue = queue.Queue() self._p_audio = pyaudio.PyAudio() self._stream = self._p_audio.open( format=self._p_audio.get_format_from_width(2), channels=1, rate=24000, output=True, start=False, ) self._sets = { 'absolute_rate': '50', 'absolute_pitch': '50', 'absolute_volume': '50', 'voice': ['anna'] } self._nums = 'min: 0, max 100' self._info = '{}: [{}] current: {}' self._work = True self._clear_queue = threading.Event() self.start() def volume(self, volume): if not volume: return self._info.format('Volume', self._nums, self._sets['absolute_volume']) else: return self._set_set('absolute_volume', volume) def rate(self, rate): if not rate: return self._info.format('Rate', self._nums, self._sets['absolute_rate']) else: return self._set_set('absolute_rate', rate) def pitch(self, pitch): if not pitch: return self._info.format('Pitch', self._nums, self._sets['absolute_pitch']) else: return self._set_set('absolute_pitch', pitch) def voice(self, voice): if not voice: return self._info.format('Voice', ', '.join(self.tts.voices), ', '.join(self._sets['voice'])) else: if isinstance(voice, str): voice = [voice] voice = voice[:2] return self._set_set('voice', voice) def _set_set(self, param, value): if self._sets[param] == value: return 'unchanged' if param == 'voice': return self._set_voice(value) else: n_value = _prepare_set(value) if n_value is None: return 'bad value: {}'.format(value) self._sets[param] = str(n_value) self.tts.set_params(**{param: _normalize_set(n_value)}) return 'success' def _set_voice(self, voice): for target in voice: if target not in self.tts.voices: return 'unknown voice: {}'.format(target) self._sets['voice'] = voice return 'success' def _text(self, text): for line in textwrap.wrap(text, 200): if not self._work: break line = line.strip('\n') if line: yield line def _clear(self): if self._clear_queue.is_set(): while self._queue.qsize(): try: self._queue.get_nowait() except queue.Empty: break self._clear_queue.clear() def clear(self): self._clear_queue.set() def stop(self): if self._work: self._work = False self._queue.put_nowait(None) self.join() self.tts.join() self._stream.stop_stream() self._stream.close() self._p_audio.terminate() def run(self): while self._work: self._clear() data = self._queue.get() if not data: break self._say(data) def say(self, text: str, print_=True): if not text: return if print_: print(text) self._queue.put_nowait(text) def _say(self, text): self._stream.start_stream() with self.tts.say(self._text(text), self._sets['voice'], 'pcm') as gen: for chunk in gen: if not self._work or self._clear_queue.is_set(): break self._stream.write(chunk) self._stream.stop_stream()