TTS with https://pypi.org/project/TTS

List the French and English voices in the TTS package and synthesise speech with them.

2 min read Updated

The TTS package ships a range of pre-trained voices; this script lists the French and English models and synthesises speech with the one you pick. The script and the model lists are below.

FR models

json
[
  "tts_models/fr/css10/vits"
]

EN Models

json
[
  "tts_models/en/ek1/tacotron2",
  "tts_models/en/ljspeech/tacotron2-DDC",
  "tts_models/en/ljspeech/tacotron2-DDC_ph",
  "tts_models/en/ljspeech/glow-tts",
  "tts_models/en/ljspeech/speedy-speech",
  "tts_models/en/ljspeech/tacotron2-DCA",
  "tts_models/en/ljspeech/vits",
  "tts_models/en/ljspeech/vits--neon",
  "tts_models/en/ljspeech/fast_pitch",
  "tts_models/en/ljspeech/overflow",
  "tts_models/en/ljspeech/neural_hmm",
  "tts_models/en/vctk/vits",
  "tts_models/en/vctk/fast_pitch",
  "tts_models/en/sam/tacotron-DDC",
  "tts_models/en/blizzard2013/capacitron-t2-c50",
  "tts_models/en/blizzard2013/capacitron-t2-c150_v2",
  "vocoder_models/en/ek1/wavegrad",
  "vocoder_models/en/ljspeech/multiband-melgan",
  "vocoder_models/en/ljspeech/hifigan_v2",
  "vocoder_models/en/ljspeech/univnet",
  "vocoder_models/en/blizzard2013/hifigan_v2",
  "vocoder_models/en/vctk/hifigan_v2",
  "vocoder_models/en/sam/hifigan_v2"
]

tts.py

python
import os
import uuid
import pyaudio
import torch
import numpy as np

from TTS.api import TTS

from oremi.core.text import Text
from oremi.core.trace import trace
from oremi.core.utils import HiddenPrints
from oremi.core.audio import Player
from oremi.core.paths import TEMPORARY_DIR
from oremi.core.models import EngineModelSetting


class Text2Speech2:
  _tts: TTS

  def __init__(self, model: EngineModelSetting):
    self._player = Player()
    self.set_model(model)

  def set_model(self, model: EngineModelSetting):
    trace.info(f'Loading TTS model {model.tts.model}')

    self._model = model

    with HiddenPrints():
      self._tts = TTS(
        model_name = model.tts.model,
        progress_bar = False,
        gpu = torch.cuda.is_available(),
      )

  def _say(self, text: str):
    filename = os.path.join(TEMPORARY_DIR, f'{uuid.uuid1()}.wav')

    # Current TTS models cannot understand number.
    # So we need to translate number to words.
    text = Text.parse_numbers(text, language = self._model.language)

    trace.info('Saying "%s"', text)

    with HiddenPrints():
      self._tts.tts_to_file(text, file_path = filename)

    self._player.play(filename)

    return filename

  def say(self, text: str):
    filename = self._say(text)
    os.remove(filename)

  def say_stream(self, text: str):
    trace.info('Saying "%s"', text)

    paudio = pyaudio.PyAudio()

    with HiddenPrints():
      # Prevent trailing truncation
      text += '. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.'

      # Synthesize speech
      wav = self._tts.tts(text)

    wav = np.array(wav)
    wav_norm = wav * (32767 / max(0.01, np.max(np.abs(wav))))

    # Open audio stream
    device = paudio.get_default_output_device_info()
    output_sample_rate = int(self._tts.synthesizer.output_sample_rate) if self._tts.synthesizer else 16000
    stream = paudio.open(
      format = pyaudio.paInt16,
      channels = 1,
      rate = output_sample_rate,
      output = True,
      output_device_index = device.get('index'), # type: ignore
    )

    # Convert audio samples to bytes
    data = wav_norm.astype(np.int16)

    try:
      # Play audio
      stream.write(data) # type: ignore
    finally:
      # Close stream and release resources
      stream.stop_stream()
      stream.close()
      paudio.terminate()

  def say_and_wait(self, text: str):
    filename = self._say(text)

    while self._player.is_playing():
      pass

    os.remove(filename)

  def stop(self):
    self._player.stop()

Search articles

Type to filter articles. Use the arrow keys to move through results and Enter to open one. Press Escape to close.