parent
2a530d49ff
commit
777a026277
@ -0,0 +1,38 @@
|
|||||||
|
# This is the parameter configuration file for TTS server.
|
||||||
|
|
||||||
|
##################################################################
|
||||||
|
# TTS SERVER SETTING #
|
||||||
|
##################################################################
|
||||||
|
host: '0.0.0.0'
|
||||||
|
port: 8692
|
||||||
|
|
||||||
|
##################################################################
|
||||||
|
# ACOUSTIC MODEL SETTING #
|
||||||
|
# am choices=['speedyspeech_csmsc', 'fastspeech2_csmsc',
|
||||||
|
# 'fastspeech2_ljspeech', 'fastspeech2_aishell3',
|
||||||
|
# 'fastspeech2_vctk']
|
||||||
|
##################################################################
|
||||||
|
am: 'fastspeech2_csmsc'
|
||||||
|
am_config:
|
||||||
|
am_ckpt:
|
||||||
|
am_stat:
|
||||||
|
phones_dict:
|
||||||
|
tones_dict:
|
||||||
|
speaker_dict:
|
||||||
|
spk_id: 0
|
||||||
|
|
||||||
|
##################################################################
|
||||||
|
# VOCODER SETTING #
|
||||||
|
# voc choices=['pwgan_csmsc', 'pwgan_ljspeech', 'pwgan_aishell3',
|
||||||
|
# 'pwgan_vctk', 'mb_melgan_csmsc']
|
||||||
|
##################################################################
|
||||||
|
voc: 'pwgan_csmsc'
|
||||||
|
voc_config:
|
||||||
|
voc_ckpt:
|
||||||
|
voc_stat:
|
||||||
|
|
||||||
|
##################################################################
|
||||||
|
# OTHERS #
|
||||||
|
##################################################################
|
||||||
|
lang: 'zh'
|
||||||
|
device: paddle.get_device()
|
@ -0,0 +1,143 @@
|
|||||||
|
# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
import argparse
|
||||||
|
import base64
|
||||||
|
|
||||||
|
import librosa
|
||||||
|
import numpy as np
|
||||||
|
import soundfile as sf
|
||||||
|
import yaml
|
||||||
|
from engine.base_engine import BaseEngine
|
||||||
|
|
||||||
|
from paddlespeech.cli.log import logger
|
||||||
|
from paddlespeech.cli.tts.infer import TTSExecutor
|
||||||
|
|
||||||
|
__all__ = ['TTSEngine']
|
||||||
|
|
||||||
|
|
||||||
|
class TTSServerExecutor(TTSExecutor):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.parser = argparse.ArgumentParser(
|
||||||
|
prog='paddlespeech.tts', add_help=True)
|
||||||
|
self.parser.add_argument(
|
||||||
|
'--conf',
|
||||||
|
type=str,
|
||||||
|
default='./conf/tts/tts.yaml',
|
||||||
|
help='Configuration parameters.')
|
||||||
|
|
||||||
|
|
||||||
|
class TTSEngine(BaseEngine):
|
||||||
|
"""TTS server engine
|
||||||
|
|
||||||
|
Args:
|
||||||
|
metaclass: Defaults to Singleton.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, name=None):
|
||||||
|
"""Initialize TTS server engine
|
||||||
|
"""
|
||||||
|
super(TTSEngine, self).__init__()
|
||||||
|
self.executor = TTSServerExecutor()
|
||||||
|
|
||||||
|
config_path = self.executor.parser.parse_args().conf
|
||||||
|
with open(config_path, 'rt') as f:
|
||||||
|
self.conf_dict = yaml.safe_load(f)
|
||||||
|
|
||||||
|
self.executor._init_from_path(
|
||||||
|
am=self.conf_dict["am"],
|
||||||
|
am_config=self.conf_dict["am_config"],
|
||||||
|
am_ckpt=self.conf_dict["am_ckpt"],
|
||||||
|
am_stat=self.conf_dict["am_stat"],
|
||||||
|
phones_dict=self.conf_dict["phones_dict"],
|
||||||
|
tones_dict=self.conf_dict["tones_dict"],
|
||||||
|
speaker_dict=self.conf_dict["speaker_dict"],
|
||||||
|
voc=self.conf_dict["voc"],
|
||||||
|
voc_config=self.conf_dict["voc_config"],
|
||||||
|
voc_ckpt=self.conf_dict["voc_ckpt"],
|
||||||
|
voc_stat=self.conf_dict["voc_stat"],
|
||||||
|
lang=self.conf_dict["lang"])
|
||||||
|
|
||||||
|
logger.info("Initialize TTS server engine successfully.")
|
||||||
|
|
||||||
|
def postprocess(self,
|
||||||
|
wav,
|
||||||
|
original_fs: int,
|
||||||
|
target_fs: int=16000,
|
||||||
|
volume: float=1.0,
|
||||||
|
speed: float=1.0,
|
||||||
|
audio_path: str=None,
|
||||||
|
audio_format: str="wav"):
|
||||||
|
"""Post-processing operations, including speech, volume, sample rate, save audio file
|
||||||
|
|
||||||
|
Args:
|
||||||
|
wav (numpy(float)): Synthesized audio sample points
|
||||||
|
original_fs (int): original audio sample rate
|
||||||
|
target_fs (int): target audio sample rate
|
||||||
|
volume (float): target volume
|
||||||
|
speed (float): target speed
|
||||||
|
"""
|
||||||
|
|
||||||
|
# transform sample_rate
|
||||||
|
if target_fs == 0 or target_fs > original_fs:
|
||||||
|
target_fs = original_fs
|
||||||
|
wav_tar_fs = wav
|
||||||
|
else:
|
||||||
|
wav_tar_fs = librosa.resample(
|
||||||
|
np.squeeze(wav), original_fs, target_fs)
|
||||||
|
|
||||||
|
# transform volume
|
||||||
|
wav_vol = wav_tar_fs * volume
|
||||||
|
|
||||||
|
# transform speed
|
||||||
|
# TODO
|
||||||
|
target_wav = wav_vol.reshape(-1, 1)
|
||||||
|
|
||||||
|
# save audio
|
||||||
|
if audio_path is not None:
|
||||||
|
sf.write(audio_path, target_wav, target_fs)
|
||||||
|
logger.info('Wave file has been generated: {}'.format(audio_path))
|
||||||
|
|
||||||
|
# wav to base64
|
||||||
|
base64_bytes = base64.b64encode(target_wav)
|
||||||
|
base64_string = base64_bytes.decode('utf-8')
|
||||||
|
wav_base64 = base64_string
|
||||||
|
|
||||||
|
return target_fs, wav_base64
|
||||||
|
|
||||||
|
def run(self,
|
||||||
|
sentence: str,
|
||||||
|
spk_id: int=0,
|
||||||
|
speed: float=1.0,
|
||||||
|
volume: float=1.0,
|
||||||
|
sample_rate: int=0,
|
||||||
|
save_path: str=None,
|
||||||
|
audio_format: str="wav"):
|
||||||
|
|
||||||
|
lang = self.conf_dict["lang"]
|
||||||
|
|
||||||
|
self.executor.infer(
|
||||||
|
text=sentence, lang=lang, am=self.conf_dict["am"], spk_id=spk_id)
|
||||||
|
|
||||||
|
target_sample_rate, wav_base64 = self.postprocess(
|
||||||
|
wav=self.executor._outputs['wav'].numpy(),
|
||||||
|
original_fs=self.executor.am_config.fs,
|
||||||
|
target_fs=sample_rate,
|
||||||
|
volume=volume,
|
||||||
|
speed=speed,
|
||||||
|
audio_path=save_path,
|
||||||
|
audio_format=audio_format)
|
||||||
|
|
||||||
|
return lang, target_sample_rate, wav_base64
|
Loading…
Reference in new issue