見出し画像

Google Cloud Text to Speechで作る読み上げキャラクターボイスの作り方

こんにちは。丸ダイスです。

先日、 unity1week というオンラインゲームジャムでこんなゲームを作りました。

遊ぶと分かる通り、全てのセリフにボイスがついています。

ゲームデザイン上の理由で可能ならボイスを付けたかったので、開発期間中に検証してコマンド一発で全セリフの音声ファイルを出力する方法を検証しましたので紹介します。

上からやればゲーム中のテキストから読み上げ音声を自動生成する仕組みが大体組めるはず。

Google Cloud Text to Speech

Googleが提供している音声読み上げサービスです。100万語/月 の制限付きですが無料でも使え、HTTPリクエストで音声ファイル出力に対応しています。

デモサイトで試してみるとリクエスト用のjsonも表示でき、使い方のイメージが湧きます。

サービスの利用準備

コマンドラインからクエリを投げるにはアカウントの登録とSDKの初期化が必要です。

ぶっちゃけるとほぼこちらのサイトの通りにやっただけです。

Linux系バッシュを前提に書かれていますが、Windowsのコマンドラインでも可能でした。一部は読み替えが必要です。

・Google Cloud Platformの利用登録~Google Cloud SDK の初期化

上から順にやります。

SDKのインストールについてはWindows用のクイックスタートからインストーラが落とせるのがむしろ楽です。基本コマンドである gcloud もどこからでも実行可能なよう、いい感じにパスも通してくれます。

・認証情報の作成

環境変数の保存でexportは使えないので

export GOOGLE_APPLICATION_CREDENTIALS=<キーファイルのパス>

こうではなく

setx GOOGLE_APPLICATION_CREDENTIALS=<キーファイルのパス>

こうなります。

・Cloud Text-to-Speech API へのリクエスト実行

リクエストで使うcurlコマンドは問題ないですが、 $(gcloud auth application-default print-access-token) ←この形式でアクセストークンの出力をcurlコマンドに埋め込むのはWindowsのコマンドラインではやりづらいです。試すだけなら素直に、

gcloud auth application-default print-access-token

これの結果を$( ) の箇所にコピペして

curl -H "Authorization: Bearer "<アクセストークンをコピペ> \
-H "Content-Type: application/json; charset=utf-8" \
-d @<JSON ファイルのパス> \
https://texttospeech.googleapis.com/v1beta1/text:synthesize > synthesize-output.txt

こうした方が良いでしょう。

解説ページにある通り、.txtの中身の "audioContent"が目的の音声をテキストにエンコードしたもの(意味が分からなくてもOK)です。デコードのためのbase64はWindowsにはないので、

base64 synthesize-output-base64.txt --decode > synthetic-audio.mp3

これは

certutil -f -decode synthesize-output-base64.txt synthetic-audio.mp3

こう書き換えます。

Rubyで自動化

ここまで来れば、一連のコマンド実行をスクリプト化するだけです。私はRubyで書きました。

ExportVoiceFile.rb

require 'fileutils'
require 'optparse'
require 'json'

class ExportVoiceFile
 def initialize()
   @access_token = `gcloud auth application-default print-access-token`
   @access_token = @access_token.gsub("\n", "").gsub("\r","")
 end

 def execute()
   export_file("SampleText.txt")
 end

 def export_file(filepath)
   FileUtils.mkdir_p("Tmp")
   FileUtils.mkdir_p("Voice")
   lines = File.readlines(filepath)
   idx = 0
   lines.each do |line|
     line = line.gsub("\n", "").gsub("\r", "")
     next if line == ""
     doc = <<-EOS
{
 "audioConfig": {
   "audioEncoding": "MP3",
   "pitch": "4.4",
   "speakingRate": "1.30"
 },
 "input": {
   "text": "#{line}"
 },
 "voice": {
   "languageCode": "ja-JP",
   "name": "ja-JP-Wavenet-A"
 }
}
EOS
     File.open("Tmp/input.json", "wb") do |file|
       file.puts doc
     end
     cmd = "curl -H \"Authorization: Bearer \"#{@access_token} -H \"Content-Type: application/json; charset=utf-8\" -d @\"Tmp/input.json\" https://texttospeech.googleapis.com/v1beta1/text:synthesize > Tmp/output.txt"
     result = `#{cmd}`
     puts result
     json = JSON.parse(File.read("Tmp/output.txt"))
     File.open("Tmp/audio.txt", "wb") do |file|
       file.puts( json["audioContent"])
     end
     cmd = "certutil -f -decode \"Tmp/audio.txt\" \"Voice/voice#{idx}.mp3\""
     puts cmd
     result = `#{cmd}`
     puts result
     idx += 1
   end
 end
end

if $0 == __FILE__
begin
 ExportVoiceFile.new().execute()
 exit 0
rescue => e
 puts e.message
 puts e.backtrace
 exit 1
end
end

このRubyスクリプトの隣にこれ(Sample.txt)

勇者よ
勇者
伝説の
勇者
山の上に
棲みついた
ドラゴン

を置いて、Rubyをインストールしてから

ruby ExportVoiceFile.rb

と実行すれば動作します。Voiceフォルダが出来て、voice0.mp3, voice1.mp3, .... が出力されます。1行ごとに

「リクエスト用のjsonを出力→curlでリクエスト→結果からaudioContentを抽出→base64デコード」

これをしてるだけなので、PythonでもUnityのC#エディタ拡張でもお好みで(なぜエディタ拡張で書かなかったのか)。

Timelineでタイミングを合わせ、発話させる

Timelineから任意の関数を呼び出せるSignal Trackという機能で、画像のように1行ごとにしゃべるイベントをTimelineに打っていきます。

画像1

先ほどの音声は Resources/Audio/Voice/Cut1_0/voice0.mp3, .... と配置してあるので、1回シグナルが来るごとに

mVoiceIdx = 0;
..
public void SpeekSignal(){
    AudioClip clip = Resources.Load<AudioClip>($"Audio/Voice/Cut1_0/voice{mVoiceIdx}");
    mVoiceIdx++;
}

これで音声ファイルを読み込みます。勘のいい方はお気づきの通り、シグナルの打ち方を間違えると無が再生されたり、セリフと話者がズレます。

以上です。ゲームの中身が変わってもキャラクターボイスの自動生成として応用が効きそうですね。

実際に使った際の工夫

・入力ファイルと出力ファイルはそのままUnityプロジェクト内にしてます

・44の全カットシーンをまとめて実行してます

・セリフファイルにタグ行を入れて話者ごとにボイスパターンを変える

加えて、極端なピッチ変更(ドラゴン、偽物)は音量が小さくなったので音量を正規化したりしました。が、大慌てで泥臭くやったので紹介しません・・。

他に使える読み上げ音声サービス

結局、セリフテキストに対してコマンドで音声ファイルが出力出来ればなんでもいいので、好みで他のサービスを使っても良さそうです。

VOICEROID

有料で、今回は人物ごとにボイスを変えたかったのでキツそうでした。 キャラクター性が強く出てしまうのも役者の声としてはイマイチかも? アカネちゃんときりたんが好きです。

ボイロゲームジャムとかでは良さそうですね。

IBM WatsonText to Speech

Cloud Text to Speechとほぼ同等の機能のようです。ボイスのパターンが少ないと思ってGoogleにしました。

Microsoft Azure Text to Speech

これもほぼ同等。ボイスパターン的にもGoogleに負けてないかも? やり方紹介ページでWatson vs Google って競合紹介されてて気付かなかった・・。

いいなと思ったら応援しよう!