Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save taroushirani/3e54d01e9e85674dbb8eaa7e0e457acd to your computer and use it in GitHub Desktop.
Save taroushirani/3e54d01e9e85674dbb8eaa7e0e457acd to your computer and use it in GitHub Desktop.
nnsvs_ofuton_p_utagoe_db_official_recipe
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "nnsvs_ofuton_p_utagoe_db_official_recipe",
"provenance": [],
"toc_visible": true,
"authorship_tag": "ABX9TyPb8X+CoOvCkD9P7+VP79cH",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/taroushirani/3e54d01e9e85674dbb8eaa7e0e457acd/nnsvs_ofuton_p_utagoe_db_official_recipe.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "SckYElka6vig"
},
"source": [
"# NNSVS で おふとんP歌声データベースを使う\n",
"\n",
"ここでは[おふとんP歌声データベース](https://sites.google.com/view/oftn-utagoedb/%E3%83%9B%E3%83%BC%E3%83%A0)をNNSVSで使用する方法について解説します.\n",
"\n",
"*おふとんP歌声データベース用のレシピは2020年11月4日にNNSVSにマージされました. 公式のレシピを使用してください.*\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "F2jKaqy261xm"
},
"source": [
"## 基本的な環境構築"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gl4rXIZ26295"
},
"source": [
"### Google Colaboratoryの設定\n",
"Google Colaboratory の基本的な使い方に関しては割愛します. \n",
"画面上のメニューから「編集」-「ノートブックの設定」を選びハードウェアアクセラレータを None から GPU に変更するのを忘れないようにしてください."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "OIUAuyLp6487"
},
"source": [
"### NumPy, Cythonのアップグレード\n",
"NumPy, Cythonは最初からColaboratoryにインストールされていますが, 最新版にアップグレードしておきます."
]
},
{
"cell_type": "code",
"metadata": {
"id": "FCY9PjEUXT5i"
},
"source": [
"! pip install -U numpy cython"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "AH88sLL87Mxq"
},
"source": [
"### hts_engine_API, sinsy のビルド\n",
"\n",
"NNSVS は楽譜 (musicxml ファイル) から歌声合成に必要な情報が書かれたラベルファイル (lab ファイル) に変換するために [Sinsy](http://sinsy.sourceforge.net/) の python wrapper である Pysinsy を使います. Pysinsy のインストールに必要な [hts_engine_API](http://hts-engine.sourceforge.net/), Sinsy をビルドしますが, それぞれ公式からのリリースではなく NN-SVS の作者である Ryuichi Yamamoto 氏の fork を使います."
]
},
{
"cell_type": "code",
"metadata": {
"id": "iV4ghgxzXaNt"
},
"source": [
"! git clone -q https://github.com/r9y9/hts_engine_API\n",
"! cd hts_engine_API/src && mkdir -p build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=/usr/ .. && make -j > hts_engine_API_build.log 2>&1 && make install\n",
"! git clone -q https://github.com/r9y9/sinsy\n",
"! cd sinsy/src/ && mkdir -p build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=/usr/ .. && make -j > sinsy_build.log 2>&1 && make install"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "Tq4lOIeM7RiV"
},
"source": [
"### Pysinsy, nnmnkwii, NNSVS, jaconv のインストール\n",
"\n",
"NNSVS は音声合成システムを作るためのライブラリである [nnmnkwii](https://github.com/r9y9/nnmnkwii) 上に構築されています. Pysinsy, nnmnkwii, NNSVS をインストールします. また, おふとんP歌声データベースのレシピがjaconvを必要とするのでインストールします. "
]
},
{
"cell_type": "code",
"metadata": {
"id": "UdRQ5pMuYtFj"
},
"source": [
"! git clone -q https://github.com/r9y9/pysinsy\n",
"! cd pysinsy && export SINSY_INSTALL_PREFIX=/usr/ && pip install -q .\n",
"! git clone -q https://github.com/r9y9/nnmnkwii\n",
"! cd nnmnkwii && pip install -q .\n",
"! git clone -q https://github.com/r9y9/nnsvs \n",
"! cd nnsvs && pip install -q .\n",
"! pip install -q jaconv"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "8IeUCMD47jj-"
},
"source": [
"これでNN-SVSを使う準備が出来ました."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cIgUd0Ky7lrF"
},
"source": [
"## データとレシピの準備"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "X3JjXC9r7ovw"
},
"source": [
"### お布団P 歌声データベースのダウンロード\n",
"\n",
"[おふとんP 歌声データベース配布所](https://sites.google.com/view/oftn-utagoedb/%E3%83%9B%E3%83%BC%E3%83%A0) から利用規約に同意して OFUTON_P_UTAGOE_DB.zip をダウンロードします. ダウンロードされたファイルを Google Drive 上にアップロードします."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "QZNj6tW372kV"
},
"source": [
"### Google Driveのマウント\n",
"\n",
"Google Drive にアップロードしたファイルを Colaboratory から使うために Google Drive を Colaboratory にマウントします. 以下のセルを実行し, 表示されたリンクをクリックして Google アカウントへのアクセスを許可してください. 表示されたコードをコピーして Colaboratory 上に戻ってセル中の\"Enter your authorization code:\"の下の欄にペーストします."
]
},
{
"cell_type": "code",
"metadata": {
"id": "XpoUEOtIWx9X"
},
"source": [
"from google.colab import drive\n",
"drive.mount('/content/drive')"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "mWPMr9VS77qI"
},
"source": [
"一部のシェルスクリプトはファイル名にスペースが含まれていると上手く動作しないことがあります. /content/gdrive から Google Drive 上のファイルにアクセスできるようシンボリックリンクを貼ります."
]
},
{
"cell_type": "code",
"metadata": {
"id": "Je5Q0bGx762-"
},
"source": [
"!ln -s \"/content/drive/My Drive\" /content/gdrive"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "VVQ1z7Es7_dE"
},
"source": [
"これでさきほどアップロードした OFUTON_P_UTAGOE_DB.zip に /content/gdrive/Natsume_Singing_DB.zip からアクセスできるようになりました."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "1REHzy0S8ENe"
},
"source": [
"### おふとんP 歌声データベースの解凍\n",
"\n",
"セルに以下のように入力して OFUTON_P_UTAGOE_DB.zip を解凍します."
]
},
{
"cell_type": "code",
"metadata": {
"id": "_QhtzUCKfvjc"
},
"source": [
"! cd /content/gdrive && unzip -u /content/gdrive/OFUTON_P_UTAGOE_DB.zip"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "M4H71qSR8OGM"
},
"source": [
"### レシピのダウンロード\n",
"おふとん P 歌声データベース用のレシピは2020年11月4日に NNSVS 本家にマージされました. nnsvs_ofuton_p_utagoe_db をダウンロードする必要はもうありません."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "jEEfwwpF8VOZ"
},
"source": [
"おふとんP 歌声データベース用のレシピがあるディレクトリに変数 RECIPE_ROOT でアクセスできるようにします."
]
},
{
"cell_type": "code",
"metadata": {
"id": "m-TVJk1SGW_n"
},
"source": [
"RECIPE_ROOT=\"/content/nnsvs/egs/ofuton_p_utagoe_db/svs-world-conv/\""
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "95XENn3-8bBD"
},
"source": [
"### \\$RESIPE_ROOT/config.yaml の編集\n",
"おふとんP歌声データベース用のレシピは実際には $RECIPE_ROOT/run.sh というシェルスクリプトの形で提供されます. レシピに展開した OFUTON_P_UTAGOE_DB の場所を設定します. \n",
"\n",
"画面右端にある「ファイル」アイコンから /content/nnsvs/egs/ofuton_p_utagoe_db/00-svs-world/config.yaml を開き, 10 行目の db_root を直接編集するか, 以下のセルを実行します. \n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "hT4crM1wgCd7"
},
"source": [
"! sed -i 's#\\~\\/data#\\/content\\/gdrive#g' $RECIPE_ROOT/config.yaml "
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "JEpswCqI8pNo"
},
"source": [
"## おふとんP歌声データベース用レシピを試す"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "268rdmMN8sWo"
},
"source": [
"### ステージ-1(データのダウンロード) の実行\n",
"ここからは基本的にレシピの提供するステージに沿って実行していきます. NNSVSではステージ-1はデータのダウンロードですが, ライセンスの関係でこのレシピではデータを自動的にダウンロードするようにはしていません. 予め上記の指示に従って OFUTON_P_UTAGOE_DB.zip をダウンロードしておいてください.\n",
"\n",
"データのダウンロードを行わない代わりに, db_rootで設定された場所に解凍されたOFUTON_P_UTAGOE_DBが見つからない場合はダウンロードを促すメッセージを出力するように変更してあります."
]
},
{
"cell_type": "code",
"metadata": {
"id": "Veas7tJiGj8E"
},
"source": [
"! cd $RECIPE_ROOT && bash run.sh --stage -1 --stop-stage -1"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZOAZ03o-83NY"
},
"source": [
"### ステージ0(データの準備)の実行\n",
"\n",
"おふとんP歌声データベースのデータをNNSVSで扱いやすい形に整えます. Colaboratory の CPU はそれほど高速ではないので時間がかかります."
]
},
{
"cell_type": "code",
"metadata": {
"id": "8Ce6Fq2fGt17"
},
"source": [
"! cd $RECIPE_ROOT && bash run.sh --stage 0 --stop-stage 0"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "JJ-i--oa89NS"
},
"source": [
"### ステージ 1 (タイムラグ, 継続長, 言語特徴量, 音響特徴量の抽出) の実行\n",
"\n",
"歌声合成に必要なタイムラグ, 継続長, 言語特徴量, 音響特徴量を抽出します. この処理もかなりの時間がかかるので, 何度も歌声合成の実験を行う場合はレシピを Google Drive 以下に移動して Colaboratory のインスタンスが初期化されてもデータが残るようにすると良いかもしれません."
]
},
{
"cell_type": "code",
"metadata": {
"id": "tmI-uuTPGxxO"
},
"source": [
"! cd $RECIPE_ROOT && bash run.sh --stage 1 --stop-stage 1"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "XI0dCyUM9BqG"
},
"source": [
"### ステージ 2-4 (タイムラグモデル, 継続長モデル, 音響モデルの学習) の実行\n",
"ここまでは特に GPU を必要としない処理でしたが, ここからは GPU が使えると処理が高速になります. ハードウェアアクセラレータの設定を None から GPU に変更するのを忘れていた場合は, 画面上のメニューから「編集」-「ノートブックの設定」を選びハードウェアアクセラレータをGPUに変更してください(ここで変更した場合は残念ながら最初からやり直しになります).\n",
"\n",
"ステージ 2 がタイムラグモデル, ステージ 3 が継続長モデル, ステージ 4 が音響モデルの学習になります."
]
},
{
"cell_type": "code",
"metadata": {
"id": "ulblx4TgbU_d"
},
"source": [
"! cd $RECIPE_ROOT && bash run.sh --stage 2 --stop-stage 4"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "oLDHtqBq9LX_"
},
"source": [
"### ステージ 5-6 (歌声合成) の実行\n",
"\n",
"ステージ 5 は学習したモデルの出力, ステージ 6 がそのモデルを使った歌声合成になります. \n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "YnPWRwTgqUhg"
},
"source": [
"! cd $RECIPE_ROOT && bash run.sh --stage 5 --stop-stage 6"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "BrRngrY_9T0y"
},
"source": [
"ステージ6を実行すると, 学習の評価用に設定されている曲(本レシピでは kagome_kagome, haruga_kita)の歌声が合成されます. 合成結果は $RECIPE_ROOT/exp/natsumeyuuri/synthesis 以下に出力されます. Colaboratory からインタラクティブに視聴するにはセルに以下のように入力します.\n",
"\n",
"注意 この処理は非常に重くColaboratoryの接続が切れる場合があるようです. 画面左端の[ファイル]からファイルをダウンロードしてローカルで視聴することをお勧めします."
]
},
{
"cell_type": "code",
"metadata": {
"id": "w_Wy9DNLQhLv"
},
"source": [
"#import IPython\n",
"#from IPython.display import Audio\n",
"#from glob import glob\n",
"#from os.path import join\n",
"#sample_rate=48000\n",
"#synthesized_wav_paths = sorted(glob(join(RECIPE_ROOT, \"exp/**/*.wav\"), recursive=True))\n",
"\n",
"#for wav_path in synthesized_wav_paths:\n",
"# print(wav_path)\n",
"# IPython.display.display(Audio(wav_path, rate=sample_rate))"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "yhY9e01X9Zco"
},
"source": [
"### 学習したモデルから任意の歌声を合成する\n",
"レシピを見るとわかりますが NNSVS では nnsvs-synthesis に学習した各種パラメータと合成するラベルファイル(音素の位置指定に使用する単音素のラベルファイルではなく楽譜から生成されたHTSフルコンテキストラベルファイル)のリストを渡すことで歌声合成を行います.\n",
"\n",
"Google Drive に sample フォルダを作成し歌声合成したい曲の楽譜をアップロードしてみましょう(Colaboratoryからは/content/gdrive/sampleに見えます).\n",
"\n",
"Pysinsyを用いて楽譜をHTSフルコンテキストラベルファイルに変換します."
]
},
{
"cell_type": "code",
"metadata": {
"id": "uPPsi7pHbSXL"
},
"source": [
"import pysinsy\n",
"from os.path import basename, join, splitext\n",
"from glob import glob\n",
"sample_dir=\"/content/gdrive/sample\"\n",
"song_list_file=join(sample_dir, \"song_list.txt\")\n",
"\n",
"sinsy = pysinsy.sinsy.Sinsy()\n",
"# Set language to Japanese\n",
"assert sinsy.setLanguages(\"j\", join(RECIPE_ROOT, \"../../_common/no2\", \"dic\"))\n",
"\n",
"song_list = []\n",
"musicxml_files = glob(join(sample_dir, \"*.*xml\"))\n",
"for musicxml_file in musicxml_files:\n",
" assert sinsy.loadScoreFromMusicXML(musicxml_file)\n",
" is_mono = False\n",
" labels = sinsy.createLabelData(is_mono, 1, 1).getData()\n",
" song_name = splitext(basename(musicxml_file))[0]\n",
" song_list.append(song_name)\n",
" lab_file_path = join(sample_dir, song_name + \".lab\")\n",
" with open(lab_file_path, \"w\") as f:\n",
" f.write(\"\\n\".join(labels))\n",
"\n",
" sinsy.clearScore()\n",
"\n",
"with open(song_list_file, \"w\") as f:\n",
" f.write(\"\\n\".join(song_list))"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "1VdJQkwI9e9j"
},
"source": [
"nnsvs-synthesisに先ほど学習したモデルと, 合成したい曲のリストを渡します. 出力先は out_dirで指定します. 今回は $RECIPE_ROOT/exp/synthesis/sample にしました."
]
},
{
"cell_type": "code",
"metadata": {
"id": "RPzBOcckZqaM"
},
"source": [
"spk=\"ofuton_p\"\n",
"exp_dir=join(RECIPE_ROOT, \"exp\", spk)\n",
"dump_dir=join(RECIPE_ROOT, \"dump\")\n",
"dump_org_dir=join(dump_dir, spk, \"org\")\n",
"dump_norm_dir=join(dump_dir, spk, \"norm\")\n",
"conf_dir=join(RECIPE_ROOT, \"../../_common/hed\")\n",
"out_dir=join(exp_dir, \"synthesis/sample\")\n",
"\n",
"! nnsvs-synthesis question_path=$conf_dir/jp_qst001_nnsvs.hed \\\n",
"timelag.checkpoint=$exp_dir/timelag/latest.pth \\\n",
"timelag.in_scaler_path=$dump_norm_dir/in_timelag_scaler.joblib \\\n",
"timelag.out_scaler_path=$dump_norm_dir/out_timelag_scaler.joblib \\\n",
"timelag.model_yaml=$exp_dir/timelag/model.yaml \\\n",
"duration.checkpoint=$exp_dir/duration/latest.pth \\\n",
"duration.in_scaler_path=$dump_norm_dir/in_duration_scaler.joblib \\\n",
"duration.out_scaler_path=$dump_norm_dir/out_duration_scaler.joblib \\\n",
"duration.model_yaml=$exp_dir/duration/model.yaml \\\n",
"acoustic.checkpoint=$exp_dir/acoustic/latest.pth \\\n",
"acoustic.in_scaler_path=$dump_norm_dir/in_acoustic_scaler.joblib \\\n",
"acoustic.out_scaler_path=$dump_norm_dir/out_acoustic_scaler.joblib \\\n",
"acoustic.model_yaml=$exp_dir/acoustic/model.yaml \\\n",
"utt_list=$song_list_file \\\n",
"in_dir=$sample_dir \\\n",
"out_dir=$out_dir \\\n",
"ground_truth_duration=false"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "0Fp4fVCK9lWs"
},
"source": [
" Colaboratory からインタラクティブに視聴するにはセルに以下のように入力します.\n",
"\n",
" 注意 この処理は非常に重くColaboratoryの接続が切れる場合があるようです. 画面左端の[ファイル]からファイルをダウンロードしてローカルで視聴することをお勧めします."
]
},
{
"cell_type": "code",
"metadata": {
"id": "Jii5-1XotKUz"
},
"source": [
"#synthesized_wav_paths = sorted(glob(join(out_dir, \"*.wav\"), recursive=True))\n",
"\n",
"#for wav_path in synthesized_wav_paths:\n",
"# print(wav_path)\n",
"# IPython.display.display(Audio(wav_path, rate=sample_rate))"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "bDAwpETLWEhl"
},
"source": [
"## 学習したモデルを保存する\r\n",
"NNSVSの学習済みモデルの実体は \\$RECIPE_ROOT/exp/ofuton_p/{timelag,duration,acousitc}/{best_loss,latest}.pth です. \r\n",
"また合成時には学習中に正規化したデータを元に戻すために \\$RECIPE_ROOT/dump/ofuton_p/norm/{in,out}_{timelag,duration,acoustic}_scaler.joblib も必要になります. つまり, \\$RECIPE_ROOT/exp と \\$RECIPE_ROOT/dump が保存されていれば次回からは学習を省略できます. また再度学習する場合でも \\$RECIPE_ROOT/dump が保存されていれば時間のかかる音響特徴量の抽出を省略できます."
]
},
{
"cell_type": "code",
"metadata": {
"id": "VSp-z29iWLNQ"
},
"source": [
"! tar zcf /content/gdrive/nnsvs_ofuton_p_utagoe_db_data.tar.gz $RECIPE_ROOT/data $RECIPE_ROOT/dump $RECIPE_ROOT/exp"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "QB2pvE2OWNEj"
},
"source": [
"tar: Removing leading `/' from member names というメッセージが表示されますが無視して大丈夫です. zip で保存したい場合には次のように入力します"
]
},
{
"cell_type": "code",
"metadata": {
"id": "Acix756sWPPN"
},
"source": [
"! zip -9 /content/gdrive/nnsvs_ofuton_p_utagoe_db_data.zip -r $RECIPE_ROOT/data $RECIPE_ROOT/dump $RECIPE_ROOT/exp"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "7z0FZV_vWQxX"
},
"source": [
"学習のために展開したデータ($RECIPE_ROOT/dump)まで含めるとファイルサイズが非常に大きくなる(2GB程度)ため, Google Driveの空き容量に注意してください.\r\n",
"\r\n",
"保存した学習済みモデルを使用するには, RECIPE_ROOT の設定が終わった後に次のように入力します(先頭の#を外して使用してください)."
]
},
{
"cell_type": "code",
"metadata": {
"id": "VIucGrYqWYJ6"
},
"source": [
"# tar.gz の場合\r\n",
"#! tar zxf /content/gdrive/nnsvs_ofuton_p_utagoe_db_data.tar.gz -C / \r\n",
"\r\n",
"# zip の場合\r\n",
"#! unzip /content/gdrive/nnsvs_ofuton_p_utagoe_db_data.zip -d /"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "rpUzxqwbWT29"
},
"source": [
"これでステージ0から6までを省略でき, 任意の楽譜で歌声を合成するから始めることができます."
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment