音声認識AIに言葉を覚えさせよう!!　(COTOHA音声認識)

# COTOHA APIとは??
NTTが長年頑張って得たノウハウを詰め込んだ、NTTコミュニケーションズが提供する自然言語処理のAPIサービスになります!!  
**サービスの詳細** は[こちら](https://api.ce-cotoha.com/contents/index.html)を見て頂くとして、これまでは<font color="Tomato">構文解析</font>や<font color="Tomato">ユーザ属性推定</font>などのテキスト解析のサービスを提供していました。    

- Python初心者 :hand:
- COTOHA API 初心者 :hand:

"[自然言語処理を簡単に扱えると噂のCOTOHA APIをPythonで使ってみた](https://qiita.com/gossy5454/items/83072418fb0c5f3e269f)"で、テキスト解析で遊んでもらってからこの記事を見て頂くことをオススメします!!

**リファレンス** は[こちら](https://api.ce-cotoha.com/contents/reference.html#api-Speech-recognition)
**GitHub** は[こちら](https://github.com/cotoha-api-group)


さて本題に入りましょう!!

# 今回はテキストではなく... <font color="Tomato">音声認識</font> !!
今までCOTOHAは、テキストしか相手にしてくれませんでした... :disappointed:

しかし、音声認識APIが2019年3月にリリースされCOTOHA君が音声言語を理解するようになりました!!しかも、入力フォーマットが

- <font color="Tomato">音声ファイル形式</font>
- <font color="DodgerBlue">ストリーミング音声形式</font>

の2パターンで提供しているため、様々なユースケースで音声認識をお試し頂けます!

![vr_arch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467283/3734a489-27a2-ba73-38af-9f671ebc5fdf.png)


## さらに! COTOHAは，固有名詞を覚えることも !!! :flushed:

このCOTOHA君<font color="DodgerBlue">**単語登録**</font>ができるため、固有名詞を教えることもできます。   
例えば，<font color="DodgerBlue">**COTOHA**</font> と言って，音声認識しても，<font color="DodgerBlue">**ことは**</font>・<font color="DodgerBlue">**事は**</font> など，同音異義語で認識されてしまったりします． 
そこに辞書登録を行うことで， <font color="DodgerBlue">**COTOHA**</font> が出る<font color="Tomato">確率を増やして</font>，認識精度を向上させることができます．

実際のところ、
- 自社の商品名を認識させたい :smirk:
- 思ったフレーズが出ないので出やすくしたい! :yum:

といった場面で、大活躍な機能となっています!!  
しかも、この単語登録には<font color="Tomato">実際の単語文字</font>と<font color="Tomato">読み方の文字(カタカナ)</font>のペアがあれば良いので、わざわざ音声を収録して登録なんて面倒なことが必要ありません!!

![dictionary.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467283/b48b27c5-2ce0-ff88-d843-a974717593b2.png)


# 音声認識やってみましょう !
では，実際にやってみましょう!!  
今回は，Pythonを使ってファイル音声認識を行います．

## サンプルコード on GitHub
**GitHub** にサンプルコードを

- [Python版](https://github.com/cotoha-api-group/speech_recognition-python-sample)
- [Node.js版](https://github.com/cotoha-api-group/speech_recognition-js-sample)

を公開していますので，そちらを参考にしてください!!

## APIアカウント認証

認証情報ファイルは、json形式でまとめています。
<details><summary><font color="DodgerBlue">Source Code | クリックしてください</font></summary>
<div>

```json
{
    "client_id":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "client_secret":"YYYYYYYYYYYYYYYY",
    "domain_id":"ZZZZZZZZ"
}
```

</div>
</details>

## ファイル音声認識


### ライブラリのインポート & プロパティ情報

<details><summary><font color="DodgerBlue">Source Code | クリックしてください</font></summary>
<div>

```py
import requests
import json
import sys
import wave

args = sys.argv
audio_name = args[1]    # 音声ファイルのパス
json_name = args[2]     # 認証情報ファイルパス
oauth_url = 'https://api.ce-cotoha.com/v1/oauth/accesstokens'
model_id = 'ja-gen_tf-16'
hostname = 'https://api.ce-cotoha.com/api/'
url = hostname + 'asr/v1/speech_recognition/' + model_id

with open(json_name) as f:
    credential = json.load(f)
client_id = credential['client_id']
client_secret = credential['client_secret']
domain_id = credential['domain_id']
Interval = 0.24  # 1メッセージあたり240msの音声データ
wf = wave.open(audio_name, 'rb')
rate = wf.getframerate()
wf.close()
```
</div>
</details>

### アクセストークンの取得
<details><summary><font color="DodgerBlue">Source Code | クリックしてください</font></summary>
<div>

```py
headers = {"Content-Type": "application/json;charset=UTF-8"}
obj = {'grantType': 'client_credentials', 'clientId': client_id, 'clientSecret': client_secret}
data_json = json.dumps(obj).encode("utf-8")
response = requests.post(url=oauth_url, data=data_json, headers=headers)
access_token = response.json()['access_token']
```
</div>
</details>

### Requestの作成 & 送信
<details><summary><font color="DodgerBlue">Source Code | クリックしてください</font></summary>
<div>

```py
### MIME_TYPE設定 & ヘッダー作成
MIMETYPE_JSON = 'application/json'
MIMETYPE_AUDIO = 'application/octet-stream'
headers = {'Authorization': 'Bearer '+access_token}

### パラメータパート作成: 音声認識開始要求パート
request_json = {
        "msg": {
            "msgname": "start"
        },
        "param": {
            "baseParam.samplingRate": rate,
            "recognizeParameter.domainId": domain_id,
            "recognizeParameter.enableContinuous": True
        }
}

### 音声データパート作成: バイナリ音声データを送信パート
wf = wave.open(audio_name, 'rb')
fileDataBinary = wf.readframes(wf.getnframes())
wf.close()

### コマンドパート: 音声認識終了要求パート
command_json = {
        "msg": {
            "msgname": "stop"
        }
}

### マルチパートエンコード → 辞書型オブジェクトに変換
files = [
        ('parameter', (None, json.dumps(request_json), MIMETYPE_JSON)),
        ('audio', (None, fileDataBinary, MIMETYPE_AUDIO)),
        ('command', (None, json.dumps(command_json), MIMETYPE_JSON))
]

### POSTリクエスト
response = request.post(url, headers=headers, files=files)
```

</div>
</details>


### 認識結果の出力
<details><summary><font color="DodgerBlue">Source Code | クリックしてください</font></summary>
<div>

```py
# statusが200のときのみresponseにjsonが含まれる
if response.status_code == 200:
    for res in response.json():
        # type=2ではsentenceの中身が空の配列の場合がある
        if res['msg']['msgname'] == 'recognized' and res['result']['sentence'] != []:
            print(res['result']['sentence'][0]['surface'])

else:
    print("STATUS_CODE:", response.status_code)
    print(response.text)
```

</div>
</details>

# 辞書登録による精度向上

本記事の<font color="Tomato">**メインテーマ**</font>です．  
COTOHA君に，言葉を覚えていただきましょう!!

今，音声認識して，<font color="DodgerBlue">Slack Webhook API</font>で投稿する簡単なアプリを作ってます．  ↓↓↓

![vrg_demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467283/f461f665-ea7d-32fe-990d-5fd0dd46d9a3.gif)


**しかし**，COTOHAが <font color="DodgerBlue">COTOHA</font>という自分の名前すら認識しない...  
そこで，<font color="Tomato">**辞書登録**</font>を使いましょう．

## 辞書登録
### 辞書ファイル
辞書データのフォーマットは <font color="Tomato">TSV</font>ファイルで記述します．  

```
[表示して欲しい文字列]`<TAB>`[読み方(全角カタカナ)]
```
の形式で以下のように記述します

```tsv
COTOHA  コトハ
エヌ・ティ・ティコミュニケーションズ株式会社	エヌティティコミュニケーションズカブシキガイシャ
```

### 辞書登録
実際に辞書登録します
<details><summary><font color="DodgerBlue">Source Code | クリックしてください</font></summary>
<div>

```py
url = "https://api.ce-cotoha.com/api/asr/v1/speech_words/upload?domainid=" + domainid
### ヘッダー設定
headers = {"Authorization":"Bearer " + access_token}
### tsv_name : 辞書TSVファイルのパスを指定
file = {"cascadeword": open(tsv_name, 'rb')}

### リクエスト送信
res = requests.post(self.url, files=file, headers=headers)

### レスポンス出力
print(res.text)
```
#### レスポンス結果
以下のように，登録が成功したらsuccessとレスポンスが返ってきます．  

```bash
--Boundary_3_1519969759_1562293676854
Content-Type: text/plain
Content-Disposition: form-data; name="status"

code : 200
message : OK
detail : success

--Boundary_3_1519969759_1562293676854
Content-Type: text/plain
Content-Disposition: form-data; name="cascadeword"

COTOHA  コトハ  M       -3.0
エヌ・ティ・ティコミュニケーションズ株式会社    エヌティティコミュニケーションズカブシキガイシャ    M-3.0

--Boundary_3_1519969759_1562293676854--
```
</div>
</details>

## 辞書更新の結果

<img width="710" alt="after_dict.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467283/a84b11e4-e05e-8084-9cd7-5c45a5546791.png">


しっかり，<font color="DodgerBlue">**COTOHA**</font>と<font color="DodgerBlue">**エヌ・ティ・ティコミュニケーションズ**</font>の固有名詞が出るようになりました!!


## 注意!! : 辞書の更新の仕組み・タイミング
COTOHA君は，<font color="Tomato">1時間に1回更新のタイミング</font>で行なっていますので，最後の辞書更新・辞書クリアのリクエストに応じて辞書更新が行われます．

![dict_ponch.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467283/d4704a80-e31f-4520-6147-2ceea3e132aa.jpeg)



## まとめ
COTOHA音声認識に言葉を覚えさせてみました!!  
それによって，<font color="Tomato">専門用語</font>や<font color="Tomato">略称</font>なども音声認識可能になります．  
現在は，<font color="DodgerBlue">Enterprise版</font>のみの提供となっておりますが，  
<font color="Tomato">3ヶ月無料枠</font>があるので，そちらでお試しください!!