Google Cloud Speech API を動かしてみた！

Google Cloud Speech API という便利そうなサービスを知ったので手元で動かしてみました。

## Google Cloud Speech API とは

> Google Cloud Speech API では、使いやすい API で高度なニューラル ネットワーク モデルを適用し、音声をテキストに変換できます。API は 110 以上の言語と方言を認識し、グローバルなユーザーベースをサポートします。アプリケーションのマイクから入力された音声をテキストに変換する、音声による制御を行う、音声ファイルをテキストに変換するなど、さまざまな機能を利用できます。Google が自身のサービスで利用している技術を利用して、リクエストでアップロードされた音声を認識し、Google Cloud Storage の音声ストレージに統合できます。

> https://cloud.google.com/speech/?hl=ja CLOUD SPEECH API より引用

ざっくり言うと、音声の発話を文字に起こして返してくれる API です！

## 使ってみた

### 前提
- さくっと試してみたかったので [Google Cloud Shell](https://cloud.google.com/shell/docs/?hl=ja) を使用
- Speech API を使用する関係上 [Google Cloud Storage](https://cloud.google.com/storage/?hl=ja) も使用
- Speech API を使用するには、大きく分けて以下の 2 つの方法がある
  - API キーを使用する方法
  - サービスアカウントを作成して、そこから生成したアクセストークンを使用する方法

### 事前準備
- [Google Cloud Platform Dashboard](https://console.cloud.google.com/home/dashboard) から API キーの発行か、サービスアカウントの作成（jsonファイルをダウンロードする）を行う
- 解析するために必要な設定を書いた json ファイルを用意する

```json:request-gcs.json
{
  "config": {
      "encoding": "FLAC",
      "sampleRateHertz": 16000,
      "languageCode": "en-US",
      "enableWordTimeOffsets": false
  },
  "audio": {
      "uri":"gs://cloud-samples-tests/speech/brooklyn.flac"
  }
}           
```

上記のパラメータの詳細については公式サイトの [こちら](https://cloud.google.com/speech/docs/basics?hl=ja#synchronous-requests) を参考に設定。
実際の音声ソース（brooklyn.flac）に合わせてパラメータを調整する必要があります。
[使用制限](https://cloud.google.com/speech/limits?hl=ja) や [オーディオエンコーディングの制約](https://cloud.google.com/speech/docs/basics?hl=ja#audio-encodings) もあるので注意。

### コマンドラインで実行

APIを叩く2つの方法と同期／非同期リクエストの仕方についてまとめてみました。

#### 同期リクエスト

##### APIキーVersion

- リクエスト

```bash
$ curl -s -X POST -H "Content-Type: application/json" -d @request-gcs.json "https://speech.googleapis.com/v1/speech:recognize?key=[APIキー]"
```

- レスポンス

```json
{
  "results": [
    {
      "alternatives": [
        {
          "transcript": "how old is the Brooklyn Bridge",
          "confidence": 0.9840146
        }
      ]
    }
  ]
}
```

##### アクセストークンVersion
- アクセストークンの発行

```bash
$ gcloud auth activate-service-account --key-file=[ダッシュボードから発行したサービスアカウントのjsonファイルを指定].json
$ gcloud auth application-default print-access-token
xxxxx
```

- リクエスト

```bash
$ curl -s -H "Content-Type: application/json" \
    -H "Authorization: Bearer [print-access-tokenで出力されたアクセストークンのxxxxxを指定]" \
    https://speech.googleapis.com/v1/speech:recognize \
    -d @request-gcs.json
```

- レスポンス

```json
{
  "results": [
    {
      "alternatives": [
        {
          "transcript": "how old is the Brooklyn Bridge",
          "confidence": 0.9840146
        }
      ]
    }
  ]
}
```


#### 非同期リクエスト

##### APIキーVersion

- 解析リクエスト

```bash
$ curl -s -X POST -H "Content-Type: application/json" -d @request-gcs.json "https://speech.googleapis.com/v1/speech:longrunningrecognize?key=[APIキー]"
```

- 解析キューのレスポンス

```json
{
  "name": "xxx"
}
```

- 解析結果取得リクエスト

```bash
$ curl -s https://speech.googleapis.com/v1/operations/[解析キューのレスポンスのnameを指定]?key=[APIキー]
```

- 解析結果のレスポンス

```json
{
  "name": "xxx",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeMetadata",
    "progressPercent": 100,
    "startTime": "2018-02-08T08:14:15.515093Z",
    "lastUpdateTime": "2018-02-08T08:14:17.243671Z"
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeResponse",
    "results": [
      {
        "alternatives": [
          {
            "transcript": "how old is the Brooklyn Bridge",
            "confidence": 0.9840146
          }
        ]
      }
    ],
    "totalBilledTime": "15s",
    "s3Condition": "longform"
  }
}
```

##### アクセストークンVersion

- アクセストークン発行

```bash
$ gcloud auth activate-service-account --key-file=[ダッシュボードから発行したサービスアカウントのjsonファイルを指定].json
$ gcloud auth application-default print-access-token
xxxxx
```

- 解析リクエスト

```bash
$ curl -s -H "Content-Type: application/json" \
    -H "Authorization: Bearer [print-access-tokenで出力されたアクセストークンのxxxxxを指定]" \
    https://speech.googleapis.com/v1/speech:longrunningrecognize \
    -d @request-gcs.json
```

- 解析キューレスポンス

```json
{
  "name": "xxx"
}
```

- 解析結果の取得リクエスト

```bash
$ curl -s -H "Authorization: Bearer [print-access-tokenで出力されたアクセストークンのxxxxxを指定]" \
    https://speech.googleapis.com/v1/operations/[解析キューのレスポンスのnameを指定]
```

- 解析結果のレスポンス

```json
{
  "name": "xxx",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeMetadata",
    "progressPercent": 100,
    "startTime": "2018-02-08T08:25:41.247285Z",
    "lastUpdateTime": "2018-02-08T08:25:42.995156Z"
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeResponse",
    "results": [
      {
        "alternatives": [
          {
            "transcript": "how old is the Brooklyn Bridge",
            "confidence": 0.9840146
          }
        ]
      }
    ],
    "totalBilledTime": "15s",
    "s3Condition": "longform"
  }
}
```

色々と制約を気にせずにさくっと試したいのなら、非同期リクエストの API キー Version がオススメです。

## 日本語で使ってみた

音声には、弊社 YouTuber の[やまださん](https://www.youtube.com/channel/UC55Ugnz0PjMsfyZ1LCFDZTA)がナレーションをしているランキング解説動画の元データを使用しました。
解析に使用した元データと同じ動画がこちらの [YouTube](https://www.youtube.com/watch?v=VQIh3d6LcJA) からも視聴可能となっています。

- Cloud Storage
元データから flac にエンコードしたファイルをアップロードする

- Config
解析するために必要な設定を書いた json ファイルを用意する

```json:request-ja_JP-gcs.json
{
  "config": {
      "encoding": "FLAC",
      "sampleRateHertz": 48000,
      "languageCode": "ja-JP",
      "enableWordTimeOffsets": false
  },
  "audio": {
      "uri": "gs://path/filename.flac"
  }
}
```

- 解析リクエスト

```bash
curl -s -X POST -H "Content-Type: application/json" -d @request-ja_JP-gcs.json "https://speech.googleapis.com/v1/speech:longrunningrecognize?key=[APIキー]"
```

- 解析キューレスポンス

```json
{
  "name": "xxx"
}
```

-  解析結果取得リクエスト

```
curl -s https://speech.googleapis.com/v1/operations/[解析キューのレスポンスのnameを指定]?key=[APIキー] > result.txt
```

- 解析結果レスポンス

```json
{
  "name": "xxx",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeMetadata",
    "progressPercent": 100,
    "startTime": "2018-02-09T02:58:18.388640Z",
    "lastUpdateTime": "2018-02-09T03:01:13.347083Z"
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeResponse",
    "results": [
      {
        "alternatives": [
          {
            "transcript": "アプリストアに行く前にゲームウィズで探そうのゲームウィズの山田です今月もやってまいりました新作アプリランキング最近リリースされたアプリゲームの中で注目度の高いおすすめゲームトップ5小隊新しいゲームを探してる方にピッタリの内容となっております紹介したゲームが好きになった方は動画の概要欄からゲームのレビュー記事をチェックしてみてください今回のランキングは2016年2月から3月上旬までにリリースされた新作トートゲームウィズ一押しの切符を買い方+1の経路を紹介していきます今月のランキング第5位メダルマスターズカジュアルなのに連絡出来ネクソンが送る会夫婦 RPG プレイヤーは召喚主となりメダルに込められた英雄たちと共に魔王の率いる軍勢と戦って行くバトルシステムは編成した英雄",
            "confidence": 0.98472136
          }
        ]
      },
      {
        "alternatives": [
          {
            "transcript": "自動で行ってくれるセミオートバトルユニットをタップして使うスキルアップタイミングがずれると効果半減やりごたえとお手軽さが両立したゲームとなっている可愛すぎるキャラにほっこりしたのはご愛嬌ランコムは持って帰りたいねむしろを食べちゃいたいなにこの口調第4位逆転オセロ解析ボードゲームが超進化ドラマチック逆転バトルプレイヤーは相手の駒をひっくり返す回復やわなカウンターなどコマごとに設定されたスキルを使って安定バトルを行っていくトレーディングカード屋パズルゲームのように頭を使うゲームが好きな方にもってこいのこちらのゲーム離れた人や近くの友達とのリアルタイムでも可能どっちが振動セロニア待ったのか白黒ハッキリつけようぜオセロだけに入れる",
            "confidence": 0.9841474
          }
        ]
      },
      {
        "alternatives": [
          {
            "transcript": "なんかすいません代替イノセントベインキャラの数だけドラマがある DMM のお手軽ひっぱりアクションプレイヤーは異能者センターを操り次元の狭間から進行してくるストレンジャーたちを倒して行くバトルシステムは簡単操作の3d ひっぱりアクションタイプの違うキャラを使い分けて戦う追跡者たちにはそれぞれ意味に飲めるが用意されておりイノセントベインの世界観をより深く知ることができるキュートなキャラデザにアニメ尿のオープニングそしてそれを彩る豪華声優陣トップ&おはじきゲーイノセントベインご賞味あれ第二ブレスオブファイア6カプコンの名作 bof シリーズがスマホアプリに殴り込みプレイヤーは翼の生えた少女ニーナとともに龍の一族をめぐる冒険へと旅立つバトルではビールロー自由に動き回り仲間と連携して敵を撃破して行く BO",
            "confidence": 0.98392004
          }
        ]
      },
      {
        "alternatives": [
          {
            "transcript": "おなじみの要素いう返信焼き鳥は本作でも健在オリジナリティを残しつつたいたんだモデルチェンジを行ったブレスオブファイア6例えるなら人生からママと妊娠した小倉優子さんグラインド止め天神この例えがピンと来る人は結構テレビっ子ということでランキング5位から2位まで発表したままに入る前今月のゲームウィズ市押野一本の紹介のコーナーに入ろうと思います前回のオクラソース付きまして今回もゲームのレビュー原商会さんとウルトラ登場してくださいただ逢いゲームズの加藤ですはいしますよろしくお願いします英語日本紹介してくださいメタルスラッグアタックメダル暗くなる女",
            "confidence": 0.9853694
          }
        ]
      },
      {
        "alternatives": [
          {
            "transcript": "深く感謝とか平氏とかばばばばーすで迎えたアプリに入ったダンスバトル全然違う全然違う全然違う的なんですけどはいはいはいはいちんちんタミヤ中国外貨のままお餅ってことは今までの方メタルスラッグ韓国まで行っても楽しめるような感じになってなるほど送ってよね僕ら",
            "confidence": 0.9869373
          }
        ]
      },
      {
        "alternatives": [
          {
            "transcript": "世代じゃないですよねちょっと上ですよね僕らの入っちゃえばお兄ちゃんとか先輩世代がゲーセンでがっつりやってるみたいだ先月でさを暗くなるほどなーこれ瑞鳳が喋れ送信がいいのかなにかやつぐだそうだよねほんとねーなんて他の子と竹彦怖い話厳選てよかった歌詞やだよねこれはまだちょっとまだわかるんですよそのメタルスラッグスマホでできるとそうですって書いてあるじゃない肌だから今までも",
            "confidence": 0.9854467
          }
        ]
      },
      {
        "alternatives": [
          {
            "transcript": "好きな人が空いた時切り替えがもともとメタルスラッグシリーズてきたなるほど英語になるゲームの事を語る時本当に難しいゲームが好きなんですかねと北の方ですねはいはいはいはいはーいランキングをに戻ろうと思います1ねどんなサイトになってるのか楽しみですねすぐ1が発表につきましょうとどうぞ",
            "confidence": 0.9864882
          }
        ]
      },
      {
        "alternatives": [
          {
            "transcript": "マーベルツムツムアメコミキャラ大集結かっこかわいいパズルゲーム感情爆発的人気を誇るアプリディズニーツムツムの後継作として登場したその名の通りアイアンマン家キャプテンアメリカなどマーベルキャラのツムツムをつなげてハイスコアを目指すアブルアクション3体一組のチーム編成やボットのバトル協力プレイマベツムからの新要素も盛り沢山ディズニーツムツムとは一味違った楽しみ方ができるようになっていますツムツムが流行っているけど離れた時にやるの恥ずかしいなぁとか思っていた男性色どんな悩みは今日で解決マーベルツムツムで心ゆくまでツムツムガイコツ鹿児島新作乙女ゲームトップファイターができたでしょが今回紹介したゲームが気になった方は動画の概要欄だらゲームズのレビュー記事をチェックしてみてください今回の動画この辺で終わろうと思いますまた次回のランキング",
            "confidence": 0.98428494
          }
        ]
      },
      {
        "alternatives": [
          {
            "transcript": "ありがとうございました",
            "confidence": 0.9914967
          }
        ]
      }
    ]
  }
}
```


### 文字起こし

`"アプリストアに行く前にゲームウィズで探そうのゲームウィズの山田です今月もやってまいりました新作アプリランキング最近リリースされたアプリゲームの中で注目度の高いおすすめゲームトップ5小隊新しいゲームを探してる方にピッタリの内容となっております紹介したゲームが好きになった方は動画の概要欄からゲームのレビュー記事をチェックしてみてください今回のランキングは2016年2月から3月上旬までにリリースされた新作トートゲームウィズ一押しの切符を買い方+1の経路を紹介していきます今月のランキング第5位メダルマスターズカジュアルなのに連絡出来ネクソンが送る会夫婦 RPG プレイヤーは召喚主となりメダルに込められた英雄たちと共に魔王の率いる軍勢と戦って行くバトルシステムは編成した英雄",`

`"自動で行ってくれるセミオートバトルユニットをタップして使うスキルアップタイミングがずれると効果半減やりごたえとお手軽さが両立したゲームとなっている可愛すぎるキャラにほっこりしたのはご愛嬌ランコムは持って帰りたいねむしろを食べちゃいたいなにこの口調第4位逆転オセロ解析ボードゲームが超進化ドラマチック逆転バトルプレイヤーは相手の駒をひっくり返す回復やわなカウンターなどコマごとに設定されたスキルを使って安定バトルを行っていくトレーディングカード屋パズルゲームのように頭を使うゲームが好きな方にもってこいのこちらのゲーム離れた人や近くの友達とのリアルタイムでも可能どっちが振動セロニア待ったのか白黒ハッキリつけようぜオセロだけに入れる",`

`"なんかすいません代替イノセントベインキャラの数だけドラマがある DMM のお手軽ひっぱりアクションプレイヤーは異能者センターを操り次元の狭間から進行してくるストレンジャーたちを倒して行くバトルシステムは簡単操作の3d ひっぱりアクションタイプの違うキャラを使い分けて戦う追跡者たちにはそれぞれ意味に飲めるが用意されておりイノセントベインの世界観をより深く知ることができるキュートなキャラデザにアニメ尿のオープニングそしてそれを彩る豪華声優陣トップ&おはじきゲーイノセントベインご賞味あれ第二ブレスオブファイア6カプコンの名作 bof シリーズがスマホアプリに殴り込みプレイヤーは翼の生えた少女ニーナとともに龍の一族をめぐる冒険へと旅立つバトルではビールロー自由に動き回り仲間と連携して敵を撃破して行く BO",`

`"おなじみの要素いう返信焼き鳥は本作でも健在オリジナリティを残しつつたいたんだモデルチェンジを行ったブレスオブファイア6例えるなら人生からママと妊娠した小倉優子さんグラインド止め天神この例えがピンと来る人は結構テレビっ子ということでランキング5位から2位まで発表したままに入る前今月のゲームウィズ市押野一本の紹介のコーナーに入ろうと思います前回のオクラソース付きまして今回もゲームのレビュー原商会さんとウルトラ登場してくださいただ逢いゲームズの加藤ですはいしますよろしくお願いします英語日本紹介してくださいメタルスラッグアタックメダル暗くなる女",`

`"深く感謝とか平氏とかばばばばーすで迎えたアプリに入ったダンスバトル全然違う全然違う全然違う的なんですけどはいはいはいはいちんちんタミヤ中国外貨のままお餅ってことは今までの方メタルスラッグ韓国まで行っても楽しめるような感じになってなるほど送ってよね僕ら",`

`"世代じゃないですよねちょっと上ですよね僕らの入っちゃえばお兄ちゃんとか先輩世代がゲーセンでがっつりやってるみたいだ先月でさを暗くなるほどなーこれ瑞鳳が喋れ送信がいいのかなにかやつぐだそうだよねほんとねーなんて他の子と竹彦怖い話厳選てよかった歌詞やだよねこれはまだちょっとまだわかるんですよそのメタルスラッグスマホでできるとそうですって書いてあるじゃない肌だから今までも",`


`"好きな人が空いた時切り替えがもともとメタルスラッグシリーズてきたなるほど英語になるゲームの事を語る時本当に難しいゲームが好きなんですかねと北の方ですねはいはいはいはいはーいランキングをに戻ろうと思います1ねどんなサイトになってるのか楽しみですねすぐ1が発表につきましょうとどうぞ",`

`"マーベルツムツムアメコミキャラ大集結かっこかわいいパズルゲーム感情爆発的人気を誇るアプリディズニーツムツムの後継作として登場したその名の通りアイアンマン家キャプテンアメリカなどマーベルキャラのツムツムをつなげてハイスコアを目指すアブルアクション3体一組のチーム編成やボットのバトル協力プレイマベツムからの新要素も盛り沢山ディズニーツムツムとは一味違った楽しみ方ができるようになっていますツムツムが流行っているけど離れた時にやるの恥ずかしいなぁとか思っていた男性色どんな悩みは今日で解決マーベルツムツムで心ゆくまでツムツムガイコツ鹿児島新作乙女ゲームトップファイターができたでしょが今回紹介したゲームが気になった方は動画の概要欄だらゲームズのレビュー記事をチェックしてみてください今回の動画この辺で終わろうと思いますまた次回のランキング",`

`"ありがとうございました",`

### サンプリングレート別文字起こし比較

冒頭部分抜粋して違いが出るラインと最も低いサンプリングレートで試しました。

- 48000

`アプリストアに行く前にゲームウィズで探そうのゲームウィズの山田です今月もやってまいりました新作アプリランキング最近リリースされたアプリゲームの中で注目度の高いおすすめゲームトップ5小隊新しいゲームを探してる方にピッタリの内容となっております`**（120文字）**

- 16000

`アプリストアに行く前にゲームウィズで探そうゲームウィズの山田です今月もやってまいりました新作アプリランキング最近リリースされたアプリゲームの中で注目度の高いおすすめゲームトップ5小隊新しいゲームを探してる方にピッタリの内容となっております`**（119文字）**

- 8000

`アプリストアに行く前にゲームウィズで探そう注目度の高いおすすめゲームトップ5を紹介新しいゲームを探してる方にピッタリの内容となっております`**（69文字）**

## やってみた結果

動画を視聴しながら文章を見てみると、かなり正確に文字を拾えていて、精度が高いことが分かった。現状だと、句読点はつけてくれないのと、文章の区切りのタイミングも苦手そうなことが分かった。

単一の音声ソースで、2人の方が同時に話している発話を拾うのは厳しかった。（未検証ですが、別々の音声ソースがあればそれぞれで文字起こししてマージすることは可能かもしれない。）

サンプリングレート 48000 と 16000 だと、冒頭部分のみの比較だと1文字欠損で済んでいますが、 8000 になると、50 文字ぐらい欠損していることが分かりました。日本語の場合は、 16000 あたりまでにしておくと支障が無さそうです。（サンプリングの数が少ないので精確ではないかもしれませんので、あくまでも目安にしていただけますと幸いです。）

## 料金について

| 機能 | 0～60 分 | 61～100 万分 |
| --- | --- | --- |
| 音声認識 | 無料 | $0.006 / 15 秒* |

> https://cloud.google.com/speech/pricing?hl=ja 料金表より引用

60 分までは無料で使えます！

## 注意ポイント
- API キーを使用する場合は、 Cloud Storage のファイルの公開設定が「一般公開で共有する」にチェックがされていないといけない
  - 非公開情報を公開しないように気をつける必要がある
- サービスアカウントの場合は、 Cloud Storage のファイルを公開をしなくてもよい（IAM の権限の可能性がありますが、詳細は追っていません）
- モノラルのみ対応している（ステレオ等は失敗する）
- 同期リクエストに1 分以上のものを解析させようとすると失敗する
  - 1 分以上は非同期リクエストの方を使用する必要がある
- Config（request-gcs.json）が存在するディレクトリ内で API を叩く必要がある

## エラーレスポンスまとめ

- モノラルにしてくださいという意味

```
Invalid audio channel count
```

- サンプルレートが間違っている

```
sample_rate_hertz (16000) in RecognitionConfig must either be unspecified or match the value in the FLAC header (44100).
```

- request-gcs.json に指定したサンプリングレートと flac のサンプリングレートが異なっている

```json
{
  "error": {
    "code": 400,
    "message": "sample_rate_hertz (48000) in RecognitionConfig must either be unspecified or match the value in the FLAC header (4
4100).",
    "status": "INVALID_ARGUMENT"
  }
}
```

- アクセスが拒否される（API キーで非公開の Cloud Storage のファイルを参照したりするなど）

```json
{
  "error": {
    "code": 403,
    "message": "The caller does not have permission",
    "status": "PERMISSION_DENIED"
  }
}
```

## まとめ
ある程度サンプリングレートが高く、ニュースの語り口調で、一人の方だけが話している発話であれば、かなり高い精度で文字起こしができることが分かりました。次回はこれを利用して簡単なアプリケーション（script）を作ってみようと思います！