AnyTech Engineer Blog

AnyTech Engineer Blogは、AnyTechのエンジニアたちによる調査や成果、Tipsなどを公開するブログです。

JARVIS(っぽい何か)を作ろう!第三回:返答を合成音声で喋らせる

JARVIS(っぽい何か)を作ろう!第三回:返答を合成音声で喋らせる

はじめに

本記事はおしゃべりAIをオフラインかつローカルで実装するシリーズ第三回です。 前回までは、耳となる音声認識、返答を返すtext to textを実装しました。 今回は口となる、合成音声という手法を使ってテキストを音声に変換し(.wavファイル)を生成するプログラムを書きます。

前回

tech.anytech.co.jp

シリーズ

こちらの手順を踏まえて、作っていきたいと思います。 ※ 本シリーズはローカルUbuntuマシンにGPUがある場合を想定しております。

今回の目次

  1. 合成音声モデルについて
  2. 合成音声モデルの実装

1. 合成音声モデルについて

概要

合成音声(voice synthesis)モデルはテキストを入力にし、音声を出力する仕組みを指します。 歴史はかなり古くからありますが、機械学習の普及により、より人間らしい声を出力することができるようになってきました。

モデル・サービスの例

text to textモデル同様、音声合成もAzureのテキスト読み上げなどAPI経由で可能なサービスがあります。 今回も、ローカル環境で動作する例でかつ日本語の読み上げに対応している例をご紹介します。

Tacotron2

テキストをメルスペクトログラム(周波数特性を二次元化したもの)へ変換し、そのメルスペクトログラムを音声に変換する2段階のモデルです。

ESPNet

Tacotron2をはじめ、有名な手法をまとめたツールとなります。 Tacotron2に対して処理速度で勝るFastSpeechも実装されています。 最近では、VITSのモデルも追加されました。

VOICEVOX

オープンソースでコマンドで合成音声の出力も可能です。 無料で利用でき、出力可能な声の種類が非常に豊富です。(利用規約が各キャラクターによって異なるためご注意ください)

VOICEPEAK

有料だが、感情(幸せ・楽しみ・怒り・悲しみ)の4パラメータを調節でき、こちらもコマンドラインから合成音声の出力が可能です。(筆者はMacOS・Ubuntuで動作確認できました)

今回は第一回:マイクからリアルタイムで音声認識するでも使用したESPNetを使用していきます。

2. 合成音声モデルの実装

環境構築

第一回:マイクからリアルタイムで音声認識すると同じ環境で実行します。

推論コードの実装

学習済みモデルをmodels/ttsにダウンロードして保存します。

cd models
mkdir tts
cd tts
wget https://zenodo.org/record/5521446/files/tts_finetune_full_band_jsut_vits_raw_phn_jaconv_pyopenjtalk_prosody_latest.zip
unzip /tts_finetune_full_band_jsut_vits_raw_phn_jaconv_pyopenjtalk_prosody_latest.zip

モデルの保存が完了後、作業ディレクトリに戻ります。

tools/voice_synthesis.py

import os
import soundfile as sf
import simpleaudio as sa
from espnet2.bin.tts_inference import Text2Speech


def load_tts(model_path):
    fs, lang = 44100, "Japanese"
    text2speech = Text2Speech(
        model_file=model_path,
        device="cuda",
        speed_control_alpha=1.2,
        noise_scale=0.333,
        noise_scale_dur=0.333,
    )
    return text2speech


def main():
    # Load espnet
    model_path = "models/tts/exp/tts_finetune_full_band_jsut_vits_raw_phn_jaconv_pyopenjtalk_prosody/100epoch.pth"
    text2speech = load_tts(model_path)

    # 読み上げる文章
    text = "こんにちは"

    # 推論
    wav = text2speech(text)["wav"]

    # 音声保存
    audio_path = "talk.wav"
    sf.write(audio_path, wav.data.cpu().numpy(), text2speech.fs, "PCM_16")

    # 保存した音声を再生
    wave_obj = sa.WaveObject.from_wave_file(audio_path)
    play_obj = wave_obj.play()
    play_obj.wait_done()


if __name__ == '__main__':
    main()

python tools/voice_synthesis.pyを実行

これで./talk.wavが作業ディレクトリに保存され、音声が再生されたかと思います!