{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "6LWsNd3_M3MP"
   },
   "source": [
    "# Converting Pytorch models to Tensorflow and TFLite by CoquiTTS"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "FAqrSIWgLyP0"
   },
   "source": [
    "This is a tutorial demonstrating Coqui TTS capabilities to convert \n",
    "trained PyTorch models to Tensorflow and Tflite.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "MBJjGYnoEo4v"
   },
   "source": [
    "# Installation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Ku-dA4DKoeXk"
   },
   "source": [
    "### Download TF Models and configs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 162
    },
    "colab_type": "code",
    "id": "jGIgnWhGsxU1",
    "outputId": "b461952f-8507-4dd2-af06-4e6b8692765d",
    "tags": []
   },
   "outputs": [],
   "source": [
    "!gdown --id 1dntzjWFg7ufWaTaFy80nRz-Tu02xWZos -O data/tts_model.pth.tar\n",
    "!gdown --id 18CQ6G6tBEOfvCHlPqP8EBI4xWbrr9dBc -O data/config.json"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 235
    },
    "colab_type": "code",
    "id": "4dnpE0-kvTsu",
    "outputId": "f67c3138-bda0-4b3e-ffcc-647f9feec23e",
    "tags": []
   },
   "outputs": [],
   "source": [
    "!gdown --id 1Ty5DZdOc0F7OTGj9oJThYbL5iVu_2G0K -O data/vocoder_model.pth.tar\n",
    "!gdown --id 1Rd0R_nRCrbjEdpOwq6XwZAktvugiBvmu -O data/config_vocoder.json\n",
    "!gdown --id 11oY3Tv0kQtxK_JPgxrfesa99maVXHNxU -O data/scale_stats.npy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "3IGvvCRMEwqn"
   },
   "source": [
    "# Model Conversion PyTorch -> TF -> TFLite"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "tLhz8SAf8Pgp"
   },
   "source": [
    "## Converting PyTorch to Tensorflow\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "colab_type": "code",
    "id": "Xsrvr_WQ8Ib5",
    "outputId": "dae96616-e5f7-41b6-cdb9-5026cfcd3214",
    "tags": []
   },
   "outputs": [],
   "source": [
    "# convert TTS model to Tensorflow\n",
    "!python ../TTS/bin/convert_tacotron2_torch_to_tf.py --config_path data/config.json --torch_model_path data/tts_model.pth.tar --output_path data/tts_model_tf.pkl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "colab_type": "code",
    "id": "VJ4NA5If9ljv",
    "outputId": "1520dca8-1db8-4e07-bc0c-b1d5941c775e",
    "tags": []
   },
   "outputs": [],
   "source": [
    "# convert Vocoder model to Tensorflow\n",
    "!python ../TTS/bin/convert_melgan_torch_to_tf.py --config_path data/config_vocoder.json --torch_model_path data/vocoder_model.pth.tar --output_path data/vocoder_model_tf.pkl"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "7d5vTkBZ-BYQ"
   },
   "source": [
    "## Converting Tensorflow to TFLite"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 927
    },
    "colab_type": "code",
    "id": "33hTfpuU99cg",
    "outputId": "8a0e5be1-23a2-4128-ee37-8232adcb8ff0",
    "tags": []
   },
   "outputs": [],
   "source": [
    "# convert TTS model to TFLite\n",
    "!python ../TTS/bin/convert_tacotron2_tflite.py --config_path data/config.json --tf_model data/tts_model_tf.pkl --output_path data/tts_model.tflite"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 364
    },
    "colab_type": "code",
    "id": "e00Hm75Y-wZ2",
    "outputId": "42381b05-3c9d-44f0-dac7-d81efd95eadf",
    "tags": []
   },
   "outputs": [],
   "source": [
    "# convert Vocoder model to TFLite\n",
    "!python ../TTS/bin/convert_melgan_tflite.py --config_path data/config_vocoder.json --tf_model data/vocoder_model_tf.pkl --output_path data/vocoder_model.tflite"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Zlgi8fPdpRF0"
   },
   "source": [
    "# Run Inference with TFLite "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "f-Yc42nQZG5A"
   },
   "outputs": [],
   "source": [
    "def run_vocoder(mel_spec):\n",
    "  vocoder_inputs = mel_spec[None, :, :]\n",
    "  # get input and output details\n",
    "  input_details = vocoder_model.get_input_details()\n",
    "  # reshape input tensor for the new input shape\n",
    "  vocoder_model.resize_tensor_input(input_details[0]['index'], vocoder_inputs.shape)\n",
    "  vocoder_model.allocate_tensors()\n",
    "  detail = input_details[0]\n",
    "  vocoder_model.set_tensor(detail['index'], vocoder_inputs)\n",
    "  # run the model\n",
    "  vocoder_model.invoke()\n",
    "  # collect outputs\n",
    "  output_details = vocoder_model.get_output_details()\n",
    "  waveform = vocoder_model.get_tensor(output_details[0]['index'])\n",
    "  return waveform \n",
    "\n",
    "\n",
    "def tts(model, text, CONFIG, p):\n",
    "    t_1 = time.time()\n",
    "    waveform, alignment, mel_spec, mel_postnet_spec, stop_tokens, inputs = synthesis(model, text, CONFIG, use_cuda, ap, speaker_id, style_wav=None,\n",
    "                                                                             truncated=False, enable_eos_bos_chars=CONFIG.enable_eos_bos_chars,\n",
    "                                                                             backend='tflite')\n",
    "    waveform = run_vocoder(mel_postnet_spec.T)\n",
    "    waveform = waveform[0, 0]\n",
    "    rtf = (time.time() - t_1) / (len(waveform) / ap.sample_rate)\n",
    "    tps = (time.time() - t_1) / len(waveform)\n",
    "    print(waveform.shape)\n",
    "    print(\" > Run-time: {}\".format(time.time() - t_1))\n",
    "    print(\" > Real-time factor: {}\".format(rtf))\n",
    "    print(\" > Time per step: {}\".format(tps))\n",
    "    IPython.display.display(IPython.display.Audio(waveform, rate=CONFIG.audio['sample_rate']))  \n",
    "    return alignment, mel_postnet_spec, stop_tokens, waveform"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "ZksegYQepkFg"
   },
   "source": [
    "### Load TF Models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "oVa0kOamprgj"
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import torch\n",
    "import time\n",
    "import IPython\n",
    "\n",
    "from TTS.tts.tf.utils.tflite import load_tflite_model\n",
    "from TTS.tts.tf.utils.io import load_checkpoint\n",
    "from TTS.utils.io import load_config\n",
    "from TTS.tts.utils.text.symbols import symbols, phonemes\n",
    "from TTS.utils.audio import AudioProcessor\n",
    "from TTS.tts.utils.synthesis import synthesis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "EY-sHVO8IFSH"
   },
   "outputs": [],
   "source": [
    "# runtime settings\n",
    "use_cuda = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "_1aIUp2FpxOQ"
   },
   "outputs": [],
   "source": [
    "# model paths\n",
    "TTS_MODEL = \"data/tts_model.tflite\"\n",
    "TTS_CONFIG = \"data/config.json\"\n",
    "VOCODER_MODEL = \"data/vocoder_model.tflite\"\n",
    "VOCODER_CONFIG = \"data/config_vocoder.json\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "CpgmdBVQplbv"
   },
   "outputs": [],
   "source": [
    "# load configs\n",
    "TTS_CONFIG = load_config(TTS_CONFIG)\n",
    "VOCODER_CONFIG = load_config(VOCODER_CONFIG)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 471
    },
    "colab_type": "code",
    "id": "zmrQxiozIUVE",
    "outputId": "21cda136-de87-4d55-fd46-7d5306103d90",
    "tags": []
   },
   "outputs": [],
   "source": [
    "# load the audio processor\n",
    "TTS_CONFIG.audio['stats_path'] = 'data/scale_stats.npy'\n",
    "ap = AudioProcessor(**TTS_CONFIG.audio)         "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "8fLoI4ipqMeS"
   },
   "outputs": [],
   "source": [
    "# LOAD TTS MODEL\n",
    "# multi speaker \n",
    "speaker_id = None\n",
    "speakers = []\n",
    "\n",
    "# load the models\n",
    "model = load_tflite_model(TTS_MODEL)\n",
    "vocoder_model = load_tflite_model(VOCODER_MODEL)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Ws_YkPKsLgo-"
   },
   "source": [
    "## Run Sample Sentence"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 134
    },
    "colab_type": "code",
    "id": "FuWxZ9Ey5Puj",
    "outputId": "535c2df1-c27c-458b-e14b-41a977635aa1",
    "tags": []
   },
   "outputs": [],
   "source": [
    "sentence =  \"Bill got in the habit of asking himself “Is that thought true?” and if he wasn’t absolutely certain it was, he just let it go.\"\n",
    "align, spec, stop_tokens, wav = tts(model, sentence, TTS_CONFIG, ap)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "Tutorial_Converting_PyTorch_to_TF_to_TFlite.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
