ウェブページで音声合成エンジンを使う（CoefontAPI）


仕様変更でAPIはenterpriseアカウントのみになりました

ウェブ上で道案内アプリを作ってみたくなったのでAPIがある便利な音声合成エンジンであるCoefontを使ってみた。
#Coefont
オンラインで使える音声合成エンジン（ソフトウェアトーク）
だれでも声を登録できたりする。公式の音声のいくつかは無料で使える

https://coefont.cloud/

APIが提供されていて自作したソフトとかから便利に使える

https://docs.coefont.cloud/

#Pythonで使ってみる
APIKeyとAccessSecretの取得は[この記事](https://qiita.com/masaya3/items/2391c012d9c87c53680a)にやり方が書いてあるのでそちらを見てください

![CoefontDocument](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533947/a7b46bcc-d848-d065-0044-5857727e2703.png)

Pythonのコードは公式サイトに例があるのでそのまま使ってみる。Requestsをインストールしておく
`pip install requests`
今回はCoefontの公式のキャラクターであるアリアルを使用します。
実際の人物のCoefontとかを使用する際は規約に注意

![allial.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533947/baaaf9d6-3850-04a6-8a6c-f87d3ec0637a.png)

![resp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533947/84a0b544-4491-531d-0297-9fa3d0aa4ee4.png)

音声が生成された
#ウェブページで使う
Coefontは利用料として一文字0.05円ほどかかる有料のサービスなので、一般に公開するウェブページに直接APIKeyとAccessSecretがくっついているのはよろしくない。
そのためかCoefontAPIも、ウェブページから直接アクセスすることは想定されていないようす。
そこで今回はGoogle Cloud Fuction を使ってウェブページとCoefontAPIを仲介するスクリプトを作った

https://cloud.google.com/functions

![cloudFunc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533947/495b01fa-850e-924f-6d16-0f075ca333c5.png)

ここ押してアカウント登録とかする。有料のサービスだけど最初の12か月無料なのでその間に使って遊ぶ。たぶんGCFだけならそんなに値段はかからない。

https://cloud.google.com/functions/docs/quickstart-console

このページの**始める前に**の部分を進めておく
[Google Cloud Function](https://console.cloud.google.com/functions/list?_ga=2.102145729.1396872279.1645494741-1807891381.1645494741)のページを開く

![makeFunc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533947/c3a06b09-4a59-0bd3-85c6-122ef6ec1123.png)

関数の作成を押して、トリガーはデフォルトのまま保存し、次へをおす
ランタイムをpython3.9に変更、エントリポイントをrequestに変更。Httpでアクセスしたときに、エントリポイントの関数が実行される
``main.py``に以下を入力

```python:main.py
import hmac
import requests
import hashlib
import json
from datetime import datetime, timezone

access_key = "YOUR_ACCESS_KEY"
client_secret = "YOUR_CLIENT_SECRET"

def request(request):
    """Responds to any HTTP request.
    Args:
        request (flask.Request): HTTP request object.
    Returns:
        The response text or any set of values that can be turned into a
        Response object using
        `make_response <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>`.
    """
    if request.method == 'OPTIONS':
      headers = {
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'POST, OPTIONS',
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Max-Age': '3600',
        }
      return ('', 204, headers)
    
    headers = {
        'Access-Control-Allow-Origin': '*',
    }
    if(request.headers['content-type'] == 'application/json'):
      request_json = request.get_json(silent=True)
      if request_json and 'text' in request_json:
          text = request_json['text']
      else:
        return('', 400,headers)
      date: str = str(int(datetime.utcnow().replace(tzinfo=timezone.utc).timestamp()))
      data: str = json.dumps({
        'coefont': '46a81787-af54-4a91-8c5b-3b597066294e',
        'text': text
      })
      signature = hmac.new(bytes(client_secret, 'utf-8'), (date+data).encode('utf-8'), hashlib.sha256).hexdigest()

      response = requests.post('https://api.coefont.cloud/v1/text2speech', data=data, headers={
        'Content-Type': 'application/json',
        'Authorization': access_key,
        'X-Coefont-Date': date,
        'X-Coefont-Content': signature
      })
      if response.status_code == 200:
        return(response.url, 200 , headers)
      else:
        return(str(response.status_code), 500,headers)
    return('', 400,headers)
```

```python:main.py
    access_key = "YOUR_ACCESS_KEY"
    client_secret = "YOUR_CLIENT_SECRET"
```

自分のAPIkeyとClientSecretを入力

```python:main.py
    data: str = json.dumps({
        'coefont': '46a81787-af54-4a91-8c5b-3b597066294e',
        'text': text
    })
```

適当なCoefontIDを設定
``requirement.txt``に以下を入力してデプロイ

```text:reqirement.txt
# Function dependencies, for example:
# package>=version
requests==2.24.0
```

少し待つと作成した関数が使用可能になるので、関数を選択

![cF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533947/f79c72e5-dd24-1e89-f93a-1cadbc868039.png)

**テスト中**をクリックして、以下を入力すると

```json:test.json
{"text":"てすと"}
```

![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533947/7e3a11d1-afc4-318d-c861-2781b28c4684.png)

出力にURLが返ってくるのでこれにアクセスすると音声合成されたwavファイルをダウンロードできる
**トリガー**のタブから確認できるURLでこの関数にアクセスできるので、あとは自分のウェブページから先ほどの形式のjsonファイルをそのURLにPostし、帰ってきたURLにGetでアクセスする。そしてダウンロードできるwavを[Web Audio API](https://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API)などで再生すると、Web上で音声合成エンジンを利用できる

#おわりに
ウェブ上で自由に音声を再生したくて、APIが公開されているCoefont APIを利用してみました。これを利用すると、かなり多くの種類の音声が使用可能なので、好きな音声を見つけて使ってみてください。この記事上のコードは自由に改変して使用して問題ありません。この記事のおかしなところなど、コメント等歓迎です。