Google Cloud Text-to-SpeechをGoogle Cloud SDKなしのpythonで実行する

[link-01]:https://cloud.google.com/
[link-02]:https://cloud.google.com/text-to-speech/

#はじめに
[Google Cloud Platform(GCP)][link-01]に登録して1年半余り。2018年3月に[Text-to-Speech][link-02]が[リリースされていた](https://cloudplatform-jp.googleblog.com/2018/03/introducing-Cloud-Text-to-Speech-powered-by-Deepmind-WaveNet-technology.html)が、ようやく試してみた。

なるべく汎用なライブラリでコードを書きたいので、[Cloud SDK](https://cloud.google.com/sdk/)は使わずに記述した。

ラズパイでも何でも、python環境と必要なライブラリがインストールできていれば動く。

#pythonプラグラム

##参考文献

[Text-to-Speech][link-02]のjson記述を参考にしたが、下手に自分のうまくいっている別プログラムを流用したことで正しく実装できず、、、

いろいろ情報を探すと、curlで成功している事例を見つけたので、そこからjsonがらみのコードを起こした。curlの記述をpythonコードに変換してくれる情報をググったらドンピシャのサイトがあって、大前進。

結局、[Text-to-Speech][link-02]で参照できるjson記述を素直に使えばよかったというオチ。。。

- [Google Cloud Text-to-Speech API - permission error](https://stackoverflow.com/questions/49800921/google-cloud-text-to-speech-api-permission-error)
- [Convert curl syntax to Python, Node.js, R, PHP, Go](https://curl.trillworks.com/)

##ライブラリ

ライブラリはrequestsを使用。音を鳴らすために、mpg321をラズパイにインストールした。

```shell-session:
sudo apt install mpg321
```

##auth key情報

[GCP][link-01]の自分のAPI key情報を、gcpapikey.pyに記載する。

```gcpapikey.py
str_api_key = "1234567890ABCDEFGHIJKLMNOPQRSTUVXYZ"
```

メインプログラム側で、gcpapikey.pyの変数をimportする。

```python
from gcpapikey import(
    str_api_key
)
```

##[GCP][link-01]アクセス

お決まりの記述があり、使用するAPIでURLが変わる。**key=**の後ろにAPI key情報をつけるのがお約束。このURLとヘッダの記述は、[参考文献](https://stackoverflow.com/questions/49800921/google-cloud-text-to-speech-api-permission-error)で分かった。

```python
    str_url = "https://texttospeech.googleapis.com/v1beta1/text:synthesize?key="
    str_headers = {'Content-Type': 'application/json; charset=utf-8'}
    url = str_url + str_api_key
```

##jsonデータ

ここが一番悩んだところ。以下でOKになった。これは日本語の発話用。**audioEncoding**はLINEAR16もあるようだが、試していない。

```python
    str_json_data = {
        'input':{
            'text':text
        },
        'voice':{
            'languageCode': 'ja-JP',
            'name': 'ja-JP-Wavenet-A',
            'ssmlGender':'FEMALE'
        },
        'audioConfig':{
            'audioEncoding':'MP3'
        }
    }
```

##リクエストを投げる

これもお決まりの記述。jsonデータを整形して、指定のURLにヘッダをつけて投げる。この書式は大体のものに使えるのが分かってきた。

```python
    jd = json.dumps(str_json_data)
    #print(jd)
    print("begin request")

    s = requests.Session()
    r = requests.post(url, data=jd, headers=str_headers)

    print("status code : ", r.status_code)
    print("end request")
```

##音声ファイルの再生

ステータスコードが200ならアクセス成功！　jsonデータの**audioContent**を抜き出して、base64でデコード、**data.mp3**に保存してmpg321に渡す。

```python
    if r.status_code == 200:
        parsed = json.loads(r.text)
        with open('data.mp3', 'wb') as outfile:
            outfile.write(base64.b64decode(parsed['audioContent']))
            mpg321 = ['mpg321','data.mp3']
            wr = subprocess.Popen(mpg321)

        return r.text
    else:
        return "error"
```

##作成結果

プログラム全体は以下。あらかじめ準備したテキストファイルを読み込んで、読み上げる。

```gglt2s.py
#coding:utf-8
import base64
import json
import requests
import sys
import subprocess

from gcpapikey import(
    str_api_key
)

def getRecogSpeech(text):

    str_url = "https://texttospeech.googleapis.com/v1beta1/text:synthesize?key="
    str_headers = {'Content-Type': 'application/json; charset=utf-8'}
    url = str_url + str_api_key

    str_json_data = {
        'input':{
            'text':text
        },
        'voice':{
            'languageCode': 'ja-JP',
            'name': 'ja-JP-Wavenet-A',
            'ssmlGender':'FEMALE'
        },
        'audioConfig':{
            'audioEncoding':'MP3'
        }
    }

    """
    # save to file:
    with open('postdata.json', 'w') as f:
        json.dump(str_json_data, f)
    """

    jd = json.dumps(str_json_data)
    #print(jd)
    print("begin request")

    s = requests.Session()
    r = requests.post(url, data=jd, headers=str_headers)

    print("status code : ", r.status_code)
    print("end request")
    
    if r.status_code == 200:
        parsed = json.loads(r.text)
        """
        print (r.text)
        print (parsed)
        print('parsed:{}'.format(parsed['audioContent']))
        with open('data.json', 'w') as outfile:
            json.dump(parsed, outfile, sort_keys=True, indent=2)
        """
        with open('data.mp3', 'wb') as outfile:
            outfile.write(base64.b64decode(parsed['audioContent']))
            mpg321 = ['mpg321','data.mp3']
            wr = subprocess.Popen(mpg321)

        return r.text
    else:
        return "error"

if __name__ == '__main__':

    args =sys.argv
    
    if len(args) < 2:
        print("Usage: python gglt2s.py <text file>")
        exit()
    else:
        pass

    text = open(args[1], 'r').read()
    getRecogSpeech(text)
```

##発話

以下を実行し、テキストファイル**testj.txt**に記載した文章が発話されることを確認した。英単語や固有名詞も、自然なイントネーションでうまく読めていた。発話はgoogleのスマートスピーカと同等の品質のはず。

```sh
$ python3 gglt2s.py testj.txt
```

##さいごに

[Text-to-Speech][link-02]で発話できるようになったので、IoTデバイスの情報や画像認識結果を音声で伝えるとか、出力のインターフェースが広がった。

[GCP][link-01]の[Cloud Vision API](https://cloud.google.com/vision/)を使って、ラズパイカメラで画像認識、結果を発話するとか、できそう。