Use speaker names as well as ids
This commit is contained in:
parent
fb9cd71919
commit
3b730bfd9a
3 changed files with 64 additions and 19 deletions
|
|
@ -21,7 +21,23 @@ speaker = SSMLSpeaker(tts)
|
|||
# ssml = '<speak><voice name="uk_UK/m-ailabs_low"><s><w>бажав</w></s></voice></speak>'
|
||||
# ssml = '<speak><s><w>Hello</w><w>World</w></s></speak>'
|
||||
# ssml = '<speak><s>Hello world</s></speak>'
|
||||
ssml = '<speak><s><voice name="el_GR/rapunzelina_low"><say-as interpret-as="characters">12</say-as></voice></s></speak>'
|
||||
# ssml = '<speak><s><voice name="el_GR/rapunzelina_low"><say-as interpret-as="characters">12</say-as></voice></s></speak>'
|
||||
ssml = '''
|
||||
<speak>
|
||||
<voice name="en_US/amy_low">
|
||||
<s>
|
||||
Today is 1/2.
|
||||
<break time="1s" />
|
||||
</s>
|
||||
</voice>
|
||||
|
||||
|
||||
<voice name="es_ES/carlfm_low">
|
||||
<s>Soy el <say-as interpret-as="number" format="ordinal">1</say-as>.</s>
|
||||
</voice>
|
||||
</speak>
|
||||
'''
|
||||
|
||||
|
||||
wav_file: wave.Wave_write = wave.open("out.wav", "wb")
|
||||
params_set = False
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ from opentts_abc import (
|
|||
|
||||
from mimic3_tts.config import TrainingConfig
|
||||
from mimic3_tts.utils import audio_float_to_int16
|
||||
from mimic3_tts.voice import Mimic3Voice
|
||||
from mimic3_tts.voice import Mimic3Voice, SPEAKER_TYPE
|
||||
|
||||
_DIR = Path(__file__).parent
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ class Mimic3Settings:
|
|||
voice: typing.Optional[str] = None
|
||||
language: typing.Optional[str] = None
|
||||
voices_directories: typing.Optional[typing.Iterable[typing.Union[str, Path]]] = None
|
||||
speaker_id: typing.Optional[int] = None
|
||||
speaker: typing.Optional[SPEAKER_TYPE] = None
|
||||
length_scale: float = 1.0
|
||||
noise_scale: float = 0.667
|
||||
noise_w: float = 0.8
|
||||
|
|
@ -81,26 +81,24 @@ class Mimic3TextToSpeechSystem(TextToSpeechSystem):
|
|||
@voice.setter
|
||||
def voice(self, new_voice: str):
|
||||
if new_voice != self.settings.voice:
|
||||
# Clear speaker id on voice change
|
||||
self.speaker_id = None
|
||||
# Clear speaker on voice change
|
||||
self.speaker = None
|
||||
|
||||
self.settings.voice = new_voice
|
||||
|
||||
if "#" in self.settings.voice:
|
||||
# Split
|
||||
voice, speaker_id_str = self.settings.voice.split("#", maxsplit=1)
|
||||
voice, speaker = self.settings.voice.split("#", maxsplit=1)
|
||||
self.settings.voice = voice
|
||||
|
||||
# TODO: Use speaker map
|
||||
self.speaker_id = int(speaker_id_str)
|
||||
self.speaker = speaker
|
||||
|
||||
@property
|
||||
def speaker_id(self) -> typing.Optional[int]:
|
||||
return self.settings.speaker_id
|
||||
def speaker(self) -> typing.Optional[SPEAKER_TYPE]:
|
||||
return self.settings.speaker
|
||||
|
||||
@speaker_id.setter
|
||||
def speaker_id(self, new_speaker_id: typing.Optional[int]):
|
||||
self.settings.speaker_id = new_speaker_id
|
||||
@speaker.setter
|
||||
def speaker(self, new_speaker: typing.Optional[SPEAKER_TYPE]):
|
||||
self.settings.speaker = new_speaker
|
||||
|
||||
@property
|
||||
def language(self) -> str:
|
||||
|
|
@ -154,12 +152,15 @@ class Mimic3TextToSpeechSystem(TextToSpeechSystem):
|
|||
for sent_phonemes in voice.text_to_phonemes(text, text_language=text_language):
|
||||
self._results.append(
|
||||
Mimic3Phonemes(
|
||||
current_settings=deepcopy(self.settings), phonemes=sent_phonemes,
|
||||
current_settings=deepcopy(self.settings),
|
||||
phonemes=sent_phonemes,
|
||||
)
|
||||
)
|
||||
|
||||
def _speak_sentence_phonemes(
|
||||
self, sent_phonemes, settings: typing.Optional[Mimic3Settings] = None,
|
||||
self,
|
||||
sent_phonemes,
|
||||
settings: typing.Optional[Mimic3Settings] = None,
|
||||
) -> AudioResult:
|
||||
settings = settings or self.settings
|
||||
voice = self._get_or_load_voice(settings.voice or self.voice)
|
||||
|
|
@ -169,7 +170,7 @@ class Mimic3TextToSpeechSystem(TextToSpeechSystem):
|
|||
|
||||
audio = voice.ids_to_audio(
|
||||
sent_phoneme_ids,
|
||||
speaker=self.speaker_id,
|
||||
speaker=self.speaker,
|
||||
length_scale=settings.length_scale,
|
||||
noise_scale=settings.noise_scale,
|
||||
noise_w=settings.noise_w,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
import csv
|
||||
import itertools
|
||||
import logging
|
||||
import time
|
||||
|
|
@ -24,6 +25,7 @@ PHONEME_MAP_TYPE = typing.Dict[PHONEME_TYPE, typing.List[PHONEME_TYPE]]
|
|||
|
||||
SPEAKER_NAME_TYPE = str
|
||||
SPEAKER_ID_TYPE = int
|
||||
SPEAKER_TYPE = typing.Union[SPEAKER_NAME_TYPE, SPEAKER_ID_TYPE]
|
||||
SPEAKER_MAP_TYPE = typing.Dict[SPEAKER_NAME_TYPE, SPEAKER_ID_TYPE]
|
||||
|
||||
DEFAULT_LANGUAGE = "en_US"
|
||||
|
|
@ -137,7 +139,19 @@ class Mimic3Voice(metaclass=ABCMeta):
|
|||
speaker_id = 0
|
||||
if isinstance(speaker, SPEAKER_NAME_TYPE):
|
||||
if self.speaker_map:
|
||||
speaker_id = self.speaker_map.get(speaker, speaker_id)
|
||||
maybe_speaker_id = self.speaker_map.get(speaker)
|
||||
if maybe_speaker_id is None:
|
||||
try:
|
||||
# Interpret as speaker id
|
||||
speaker_id = int(speaker)
|
||||
except ValueError:
|
||||
_LOGGER.warning(
|
||||
"Unable to find a speaker with the name '%s'. Falling back to first speaker.",
|
||||
speaker,
|
||||
)
|
||||
pass
|
||||
else:
|
||||
speaker_id = maybe_speaker_id
|
||||
elif speaker is not None:
|
||||
speaker_id = speaker
|
||||
|
||||
|
|
@ -198,7 +212,18 @@ class Mimic3Voice(metaclass=ABCMeta):
|
|||
with open(phoneme_map_path, "r", encoding="utf-8") as map_file:
|
||||
phoneme_map = phonemes2ids.utils.load_phoneme_map(map_file)
|
||||
|
||||
# TODO: Load speaker map
|
||||
# id -> speaker | alias | alias ...
|
||||
speaker_map: typing.Optional[SPEAKER_MAP_TYPE] = None
|
||||
speaker_map_path = voice_dir / "speaker_map.csv"
|
||||
if speaker_map_path.is_file():
|
||||
_LOGGER.debug("Loading speaker map from %s", speaker_map_path)
|
||||
with open(speaker_map_path, "r", encoding="utf-8") as map_file:
|
||||
reader = csv.reader(map_file, delimiter="|")
|
||||
speaker_map = {}
|
||||
for row in reader:
|
||||
speaker_id = int(row[0])
|
||||
for alias in row[1:]:
|
||||
speaker_map[alias] = speaker_id
|
||||
|
||||
if config.phonemizer == Phonemizer.GRUUT:
|
||||
return GruutVoice(
|
||||
|
|
@ -206,6 +231,7 @@ class Mimic3Voice(metaclass=ABCMeta):
|
|||
onnx_model=onnx_model,
|
||||
phoneme_to_id=phoneme_to_id,
|
||||
phoneme_map=phoneme_map,
|
||||
speaker_map=speaker_map,
|
||||
)
|
||||
|
||||
if config.phonemizer == Phonemizer.ESPEAK:
|
||||
|
|
@ -214,6 +240,7 @@ class Mimic3Voice(metaclass=ABCMeta):
|
|||
onnx_model=onnx_model,
|
||||
phoneme_to_id=phoneme_to_id,
|
||||
phoneme_map=phoneme_map,
|
||||
speaker_map=speaker_map,
|
||||
)
|
||||
if config.phonemizer == Phonemizer.SYMBOLS:
|
||||
return SymbolsVoice(
|
||||
|
|
@ -221,6 +248,7 @@ class Mimic3Voice(metaclass=ABCMeta):
|
|||
onnx_model=onnx_model,
|
||||
phoneme_to_id=phoneme_to_id,
|
||||
phoneme_map=phoneme_map,
|
||||
speaker_map=speaker_map,
|
||||
)
|
||||
|
||||
raise ValueError(f"Unsupported phonemizer: {config.phonemizer}")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue