From c7a880924f86539f73cf2db7c14db76e71219d0c Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Thu, 17 Nov 2022 21:38:14 -0500 Subject: [PATCH] Add max_decoder_steps, streamline Dockerfile --- .gitignore | 29 ++++++++---- Dockerfile | 100 ++++++++++++++++++++++++++++++++++++++--- tts/tacotron2/model.py | 3 ++ tts/vocodes_common.py | 11 +++++ tts/vocodes_server.py | 16 ++++++- 5 files changed, 144 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index bcbe63b..b6b8c03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,36 @@ -*.pyc -*.swo -*.swp +# Dot env (and secrets!) *secret*sh -*~ .env .env-secrets -.idea/ -__pycache__/ -models/Wav2Lip/python/ -models/tacotron2/python/ production_database_secret_connect.sh production_database_secret_query.sh secrets.toml secrets.yaml + +# Vim cruft +*.swo +*.swp +*~ + +# Python cruft +*.pyc +__pycache__/ + +# Virtual environments +models/Wav2Lip/python/ +models/tacotron2/python/ +tts/python/ + +# Rust build target/ +# IntelliJ +.idea/ + # Models for testing future-todo/ControllableTalkNet/models tts/hifigan/hifisr # Other garbage to prune/remove tts/hifigan/LJSpeech-1.1/ + diff --git a/Dockerfile b/Dockerfile index 5b79466..039d55a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,91 @@ # ==================== Python Build Base ==================== -FROM ghcr.io/storytold/docker-base-images-nvidia-cuda-experimental:080f96bc7087 as pybuild-base +# Experimental NVidia CUDA +# - ubuntu 20.04 +# - nvidia-384 +# - multiple python versions (3.6, 3.8) +# THIS IS NOT VERIFIED TO WORK YET (2021-05-30) + +#FROM nvidia/cuda:10.1-devel-ubuntu18.04 as pybuild-base +FROM nvidia/cuda:11.3.0-devel-ubuntu20.04 as pybuild-base + +# tzdata install hangs without presetting the time zone +ENV TZ=UTC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# NB(2021-05-30): This is the image that Tacotron 2's Dockerfile specifies. +# I have not tried this, but it might be necessary. +#FROM pytorch/pytorch:nightly-devel-cuda10.0-cudnn7 +#ENV PATH /usr/local/nvidia/bin:/usr/local/cuda/bin:${PATH} + +# NB: https://github.com/NVIDIA/nvidia-docker/issues/864#issuecomment-439848887 +# NB: We do not install ffmpeg, since the version is 3.8.* series and we need 4.2.* +# +# NB(2021-05-30): We need to install `cython3` for building modern Tacotron 2 +# dependencies (ie. protoc) on old Ubuntu +# RUN apt-get update \ +# && apt-get install -y \ +RUN apt-get update +#RUN apt-cache search python3.8 + +# NB: Here we install nvidia drivers +# NB: Avoid keyboard prompt +RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \ + nvidia-384 \ + --no-install-recommends + +# Notes on packages: +# * software-properties-common - needed for `apt-add-repository` +# * pciutils - needed for `lspci | grep -i nvidia` +RUN apt-get install -y \ + build-essential \ + curl \ + cython3 \ + ffmpeg \ + g++-7 \ + gcc-7 \ + git \ + htop \ + imagemagick \ + libc++-7-dev \ + libffi-dev \ + libgcc-7-dev \ + libmagic1 \ + libsm6 \ + libsndfile1 \ + libssl-dev \ + libxext6 \ + libxrender-dev \ + netcat \ + pciutils \ + pkg-config \ + python-dev \ + python3-pip \ + python3.8 \ + python3.8-dev \ + python3.8-venv\ + redis-tools \ + silversearcher-ag \ + software-properties-common \ + sox \ + tmux \ + unzip \ + vim \ + wget + +# Wav2Lip needs Python3.6 +# NB: we install python3-virtualenv as `python3.6 -m venv` won't work anymore +RUN add-apt-repository ppa:deadsnakes/ppa +RUN apt-get update +RUN apt-get install -y \ + python3.6 \ + python3.6-dev \ + python3.6-venv + +RUN python3.6 --version +RUN python3.8 --version + +#FROM ghcr.io/storytold/docker-base-images-nvidia-cuda-experimental:080f96bc7087 as pybuild-base ## Authenticating with GHCR locally: ## https://docs.github.com/en/packages/working-with-a-github-packages-registry/migrating-to-the-container-registry-from-the-docker-registry @@ -117,7 +202,10 @@ FROM pybuild-base as pybuild-requirements WORKDIR / -COPY ./tts ./models/tts +RUN mkdir -p /models/tts + +COPY ./tts/requirements-tacotron-python36.txt ./models/tts + WORKDIR models/tts # NB: Not sure if we need Python3.6 for Tacotron2, but Python3.8 gave me trouble. @@ -129,11 +217,10 @@ RUN . python/bin/activate \ && pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113 \ && deactivate - - # Final image # FROM ubuntu:xenial -FROM pybuild-requirements as final +#FROM pybuild-requirements as final + WORKDIR / #COPY scripts/ ./scripts @@ -189,3 +276,6 @@ RUN pip3 install gdown # NB(echelon,2022-07-14): Run a newer version of pytorch which will support RTX3090. # Fixes bug, "NVIDIA GeForce RTX 3080 with CUDA capability sm_86 is not compatible with the current PyTorch installation." #RUN pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113 + + +COPY ./tts ./models/tts diff --git a/tts/tacotron2/model.py b/tts/tacotron2/model.py index 8f15d25..7010216 100644 --- a/tts/tacotron2/model.py +++ b/tts/tacotron2/model.py @@ -469,6 +469,9 @@ class Tacotron2(nn.Module): self.encoder = Encoder(hparams) self.decoder = Decoder(hparams) self.postnet = Postnet(hparams) + + def fakeyou_set_max_decoder_steps(self, max_decoder_steps): + self.decoder.max_decoder_steps = max_decoder_steps def parse_batch(self, batch): text_padded, input_lengths, mel_padded, gate_padded, \ diff --git a/tts/vocodes_common.py b/tts/vocodes_common.py index 0762e11..87dae19 100644 --- a/tts/vocodes_common.py +++ b/tts/vocodes_common.py @@ -99,6 +99,14 @@ ENGLISH_ESPEAK_PIPELINE = EspeakPipeline(lang='en') ENGLISH_PIPELINE_V1 = EnglishPipelineV1(EnglishPhonetization(CMUDict(DEFAULT_CMUDICT_PATH))) LEGACY_FAKEYOU_PIPELINE = LegacyFakeYouPipeline() +def parse_int_or_default(maybe_int, default_int): + if maybe_int: + try: + return int(maybe_int) + except: + pass + return default_int + def preprocess_text(raw_user_text: str, text_pipeline_type: str): integer_sequence = [] @@ -278,6 +286,7 @@ class TacotronWaveglowPipeline: assert('output_audio_filename' in args) assert('output_spectrogram_filename' in args) assert('output_metadata_filename' in args) + assert('max_decoder_steps' in args) LOGGER.info(f"raw inference text: {args['raw_text']}") @@ -285,6 +294,8 @@ class TacotronWaveglowPipeline: tacotron = self.tacotron_model_cache[args['synthesizer_checkpoint_path']] + tacotron.fakeyou_set_max_decoder_steps(args['max_decoder_steps']) + LOGGER.info("running inference...") with torch.no_grad(): diff --git a/tts/vocodes_server.py b/tts/vocodes_server.py index 51e5de0..e6e5ab4 100755 --- a/tts/vocodes_server.py +++ b/tts/vocodes_server.py @@ -25,10 +25,11 @@ from falcon_multipart.middleware import MultipartMiddleware from wsgiref import simple_server from vocodes_common import TacotronWaveglowPipeline -from vocodes_common import print_gpu_info +from vocodes_common import load_hifigan_model from vocodes_common import load_tacotron_model from vocodes_common import load_waveglow_model -from vocodes_common import load_hifigan_model +from vocodes_common import parse_int_or_default +from vocodes_common import print_gpu_info from logger import LOGGER @@ -221,6 +222,8 @@ class ApiHandler(): LOGGER.info(f"TTS Request: {raw_data}") + # ========== RUST SERVICE ARGUMENTS ========== + # Request parameters synthesizer_checkpoint_path = raw_data.get('synthesizer_checkpoint_path') text_pipeline_type = raw_data.get('text_pipeline_type') @@ -233,10 +236,15 @@ class ApiHandler(): output_spectrogram_filename = raw_data.get('output_spectrogram_filename') output_metadata_filename = raw_data.get('output_metadata_filename') + # Temporarily optional request parameters + maybe_max_decoder_steps = raw_data.get('max_decoder_steps') + # Optional request parameters maybe_clear_synthesizer_checkpoint_path = \ raw_data.get('maybe_clear_synthesizer_checkpoint_path') + # ========== INFERENCE ========== + pipeline.maybe_load_waveglow_model(waveglow_vocoder_checkpoint_path) pipeline.maybe_load_hifigan(hifigan_vocoder_checkpoint_path) pipeline.maybe_load_hifigan_super_resolution(hifigan_superres_vocoder_checkpoint_path) @@ -246,6 +254,9 @@ class ApiHandler(): pipeline.maybe_load_tacotron_model_to_cache(synthesizer_checkpoint_path) + # NB: 1000 is the default and is roughly 12 seconds. + max_decoder_steps = parse_int_or_default(maybe_max_decoder_steps, 1000) + inference_args = { 'raw_text': inference_text, 'synthesizer_checkpoint_path': synthesizer_checkpoint_path, @@ -254,6 +265,7 @@ class ApiHandler(): 'output_audio_filename': output_audio_filename, 'output_spectrogram_filename': output_spectrogram_filename, 'output_metadata_filename': output_metadata_filename, + 'max_decoder_steps': max_decoder_steps, } LOGGER.info(f"running inference with args: {inference_args}")