動画資料のための音声データ（ナレーション）を Google の Text-to-Speech に作成させる（C#とPythonのサンプル付き）

# 概要

Google が提供する音声合成サービス「**Cloud Text-to-Speech**」の導入メモです。APIサービスの有効化から、認証ファイルの取得、自作プログラム（C#またはPython）から呼び出して利用するまでの流れをできるだけ詳しく説明しました。

基本的には公式の「[クイックスタート：クライアント ライブラリの使用](https://cloud.google.com/text-to-speech/docs/quickstart-client-libraries?hl=ja)」の内容をスクリーンショット付きで解説したものです（なお、不要と思われるステップは飛ばしています）。


**Cloud Text-to-Speech** は、テキストデータ（日本語OK）から、**読みあげ音声データ** (.mp3) を生成してくるクラウドサービスです。かなり人間に近い自然な音声出力が可能です。品質については [こちら](https://cloud.google.com/text-to-speech?hl=ja) から、任意のテキスト（日本語もOK）を与えて確認することができます。

# Google Cloud Platform に登録

Google Cloud ( https://cloud.google.com/?hl=ja ) からユーザー登録します。

お手持ちの Googleカウント を使って無料トライアル利用が可能です。ただし、登録時にクレジットカードが必要です。とはいえ、期間終了後に、有料アカウントに自動移行されることも**ない**ので、また、有料カウントに移行しても料金は（個人的には）非常にリーズナブルだと思いますので、あまり構えずに登録しましょう。

<img width="747" alt="2020-04-30_10h18_41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/05d91c7a-119f-cfe4-0d88-c85fb889dc62.png">

## 利用料金の目安

- [Text-to-Speech の料金](https://cloud.google.com/text-to-speech/pricing?hl=ja)<br><img width="565" alt="2020-04-30_14h28_42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/c1970995-c98a-5d21-529d-23d894916cfb.png">

以下、Google Cloud に**登録済み**として説明を進めていきます。<br><img width="447" alt="2020-04-30_14h35_05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/6b8446a3-f877-a6c3-6cee-0a9b82cf1a81.png">

# Text-to-Speech のサービス有効化と認証ファイルの取得

[Google Cloud Platform](https://console.cloud.google.com/?hl=ja) にアクセして、ログインします。<br><img width="643" alt="2020-04-30_13h13_35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/142500a1-cdf3-0994-9e5f-46131288cf18.png">


ダイアログが表示されるので「**新しいプロジェクト**」を選択します。<br><img width="702" alt="2020-04-30_13h23_04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/09b93f08-3e05-efbc-4afe-69592ee2beb4.png">

適当なプロジェクト名（ここでは `Text To Speech 20xxx` とします）を入力して「**作成**」をクリックします。<br><img width="436" alt="2020-04-30_13h24_501.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/f226cdce-2968-e2eb-da2e-8244abcbaa14.png">


ダッシュボードに戻ってくるので、**いま作成したプロジェクトに切り替えます**。<br><img width="526" alt="2020-04-30_13h27_19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/cf450971-a9d1-56bb-ffb6-f448e79d0ab0.png">

左上のメニューをクリックして「**APIとサービス**」、「**ダッシュボード**」に進みます。<br><img width="526" alt="2020-04-30_13h32_01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/036008d0-227a-05e7-3a96-8374acc24e1a.png">


「**APIとサービスを有効化**」を選択します。<br><img width="591" alt="2020-04-30_13h34_24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/6e33d78b-45ad-6612-27cf-c541273b1d87.png">

テキストボックスに「Text to Speech」と入力します。<br><img width="549" alt="2020-04-30_13h36_53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/263cb822-b684-4d0b-31a1-621533fa7154.png">

「**Cloud Text-to-Speech API**」を選択します。
<img width="651" alt="2020-04-30_13h37_58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/7b3ed5b7-052c-e211-f1be-e19f67edc03e.png">

「**有効にする**」を選択します。<br><img width="540" alt="2020-04-30_13h39_35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/9d0b046f-4d9e-2c8e-4f0a-49edf6c89d66.png">

自作のプログラムからサービスを利用するために必要となる「**認証情報を作成**」を選択します。<br><img width="787" alt="2020-04-30_13h40_59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/8e38f0e0-7d57-c42b-1ee7-b6860906a9ca.png">

「**プロジェクトへの認証情報の追加**」という画面に移動するので、下記のドロップダウンリストから「**Cloud Text-to-Speech API**」を選択してから「**必要な認証情報**」をクリックします。

※ この画面は「APIとサービス」、「認証情報」、「認証情報を作成」、「＋認証情報を作成」、「ウィザードで選択」と選択していっても呼び出すことができます。
<img width="543" alt="2020-04-30_13h46_45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/39eefef8-fb76-a93a-ea98-5ad5f9a0d40f.png">

表示が切り替わるので「**いいえ、使用していません**」を選択して、再度「**必要な認証情報**」をクリックします。<br><img width="467" alt="2020-04-30_13h53_29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/ab754dad-3195-1ae1-826d-61d16f4cf7d9.png">

適当な**サービスアカウント名を入力**します（ここでは `test` としました）。**ロールは特に選択しません**。また「サービスアカウントID」は自動で生成されます。「**次へ**」を選択します。<br><img width="455" alt="2020-04-30_13h54_42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/ed2362d7-799a-48a7-9f30-c0635927858d.png">

次のようなダイアログが表示されますが「**ロールなしで作成**」を選択します。<br><img width="430" alt="2020-04-30_13h57_51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/eaf6b62b-a422-efad-f948-9906bc4d9fa2.png">

次のようなダイアログが表示されて、認証情報が入った**JSONファイル**が、PCにダウンロードされます。<br><img width="403" alt="2020-04-30_13h58_37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152805/2fc21664-805a-b102-2e43-6a543e27ac68.png">


このファイルの名前を「`credentials.json`」に変更して「`C:\Users\xxx\Desktop`」に配置するものとします。

なお、公式の[クイックスタート](https://cloud.google.com/text-to-speech/docs/quickstart-client-libraries?hl=ja) では、このファイルのパスを **環境変数** `GOOGLE_APPLICATION_CREDENTIALS` として登録し、プログラムでは環境変数経由で情報を参照するという方法を説明しています。一方、**<font color='red'>ここでは環境変数には登録せず、プログラムから直接パスを指定して情報を参照する方法をとります</font>**。

# C#（.NET Core）プログラムから呼び出す

VisualStudio を起動し［**ファイル**］－［**新規作成**］－［**プロジェクト**］で、「**Visual C#**」の「**コンソールアプリ（.NET Core）**」を選択します。

メニューの［**ツール**］－［**NuGetパッケージマネージャ**］－［**パッケージ マネージャー コンソール**］を選択します。コンソールに `Install-Package Google.Cloud.TextToSpeech.V1 -Pre` を入力して実行します。

```
PM> Install-Package Google.Cloud.TextToSpeech.V1 -Pre
```

`Program.cs` の内容を以下に書き換えます。

```cs:Program.cs
using System;
using System.IO;
using Google.Cloud.TextToSpeech.V1;
using System.Diagnostics;

public class QuickStart {
  public static void Main(string[] args) {

    var credentialsFilePath = @"C:\Users\xxx\Desktop\credentials.json";

    var textToSpeechClientBuilder = new TextToSpeechClientBuilder() {
      CredentialsPath = credentialsFilePath
    };
    var client = textToSpeechClientBuilder.Build();

    // 読み上げテキストの設定
    SynthesisInput input = new SynthesisInput {
      Text = "目的地は、日本橋です。"
    };

    // 音声タイプの設定
    VoiceSelectionParams voice = new VoiceSelectionParams {
      Name = "ja-JP-Wavenet-D",
      LanguageCode = "ja-JP",
      SsmlGender = SsmlVoiceGender.Neutral
    };

    // オーディオ出力の設定
    AudioConfig config = new AudioConfig {
      AudioEncoding = AudioEncoding.Mp3,
      Pitch = -2.0
    };

    // Text-to-Speech リクエストの生成
    var response = client.SynthesizeSpeech(new SynthesizeSpeechRequest {
      Input = input,
      Voice = voice,
      AudioConfig = config
    });

    // Text-to-Speech レスポンス（音声ファイル）の保存
    var fileName = DateTime.Now.ToString("yyyy-MM-dd_HHmmss") + ".mp3";
    using (Stream output = File.Create(fileName)) {
      response.AudioContent.WriteTo(output);
      Console.WriteLine($"音声コンテンツを '{fileName}' として保存しました。");
    }

    Console.WriteLine("ファイルを出力したフォルダを開きますか [Y]/n");
    var k = Console.ReadKey();
    if (k.Key != ConsoleKey.N && k.Key != ConsoleKey.Escape) {
      Process.Start("explorer.exe", Directory.GetCurrentDirectory());
    }
  }
}
```

実行すると「もくてきちは、にほんばしです。」という MP3 ファイルが生成されます。

なお、**音声合成マークアップ言語**（SSML）にも対応しており、以下のように変更すると
「もくてきちは、**にほんばし**ではなく、**にっぽんばし**です。」と読み上げてくれます。また、`<break time="200ms"/>` などにより **間** を挿入することもできます。

```cs:SSML形式
SynthesisInput input = new SynthesisInput {
  Ssml = "<speak>目的地は、日本橋、ではなく、<sub alias='にっぽんばし'>日本橋</sub>です。</speak>".Replace("'", "\"")
};
```

# Python プログラムから呼び出す

```
pip install --upgrade google-cloud-texttospeech
```

```py:
from datetime import datetime
from pytz import timezone
from google.cloud import texttospeech
from google.oauth2 import service_account

credentials = service_account.Credentials.from_service_account_file('credentials.json')
client = texttospeech.TextToSpeechClient(credentials=credentials)

synthesis_input = texttospeech.types.SynthesisInput(
  text='目的地は、秋葉原です。')

voice = texttospeech.types.VoiceSelectionParams(
  language_code='ja-JP',
  name='ja-JP-Wavenet-D',
  ssml_gender=texttospeech.enums.SsmlVoiceGender.NEUTRAL)

audio_config = texttospeech.types.AudioConfig(
  audio_encoding=texttospeech.enums.AudioEncoding.MP3,
  pitch = -2.0
  )

response = client.synthesize_speech(synthesis_input, voice, audio_config)

now = datetime.now(timezone('Asia/Tokyo'))
filename = now.strftime('%Y-%m-%d_%H%M%S.mp3')
with open(filename, 'wb') as out:
  out.write(response.audio_content)
  print(f'Audio content written to file {filename}')
```