IBM Watson Speech to Textのカスタマイズをcurlコマンドで試す

# はじめに
こんにちは。今回はIBM Cloudのサービスの1つである、Watson Speech to Text（STT)のカスタマイズを試してみます。基本的な動作の確認と、カスタマイズすることによって、音声を書き起こした結果がどう変わるのかを試してみたいと思います。

尚、筆者はWatson Speech to Textについては、初心者であるため、当記事も初心者目線の記事となっています。

Watson Speech to Textは、APIを呼び出しにより利用します。pythonなどのスクリプトから呼び出すことももちろん可能ですが、今回は手軽に実行出来るcurlコマンドを用いて実施しています。

この記事は2022年1月時点の情報を用いて作成しています。

:::note info
＊ 2023年2月28日追記 この記事は、前世代モデル（Previous-generation model）を用いて作成されています。前世代モデルは非推奨となり、2023年7月31日にサービス終了となります。詳細はリリースノートに記載されています。
:blue_book: [IBM Cloud Docs (Speech to Text リリースノート)](https://cloud.ibm.com/docs/speech-to-text?topic=speech-to-text-release-notes)
:::

# 利用環境
- Macbook Air (M1, 2020)
 - OS: Big Sur 11.6.2

# 準備
- curlコマンドが実行できればok（Macの場合は特に準備はいらないはずです）
- IBM Cloudのアカウント取得
- Watson Speech to Textのサービス作成（カスタマイズを利用する場合、「追加プラン」で作成する必要があります） 

:::note info
＊Watson Speech to Textの「追加プラン」は利用時間に応じて費用が発生する有料プランとなります。
＊ 無料の「ライトプラン」ではカスタマイズ機能が利用できません。
:::

# 参考文書（リンク）
:blue_book: [IBM Cloud Docs (Speech to Text)](https://cloud.ibm.com/docs/speech-to-text/getting-started.html)
いわゆる製品マニュアルなのですが、結構詳しく書かれており、curlでの実行ならマニュアル通り進めていけば簡単に実行することが出来ました。

# Watson Speech to Textのカスタマイズ方法
Watson Speech to Textでは大きく言語モデルカスタマイズと音響モデルカスタマイズの2つがあります。言語モデルは、特有の単語・用語や言い回しに対応するモデルで、音響モデルは周囲の雑音などに対応するモデルとなっています。
- 言語モデルカスタマイズはテキスト文書を登録することにより行います。
- 音響モデルカスタマイズは音声を登録することにより行います。


今回は特有の単語・用語や言い回しに対してカスタマイズを行いたいので、言語モデルを用いてカスタマイズを行うことにします。

参考までに以下に、カスタマイズ目的ごとの言語モデルと音響モデルの対応表を掲載します。
単語登録・文書登録は言語モデルカスタマイズです。

|カスタマイズ目的 |単語登録  |文書登録  |音響モデルカスタマイズ|
|---|:-:|:-:|:-:|
|特有の用語（製品名など）|○|○||
|特有の言い回し（コールセンター電話、放送など）||○||
|同音異義語（お食事券と汚職事件など）||○||
|環境雑音|||○|
|発話スタイル（くだけた会話調の発話など）|||○|
|特定のアクセント|||○|
|特定の録音条件により劣化した音声（Bluetoothマイク、遠隔マイクなど）|||○|
|方言|○|○|○|


:::note info
2023年2月28日追記 上記表は前世代モデルを前提としたものになります。次世代モデルでは音響モデルカスタマイズは利用できません。
:blue_book: [IBM Cloud Docs (Speech to Text 次世代モデルでサポートされる機能)](https://cloud.ibm.com/docs/speech-to-text?topic=speech-to-text-models-ng#models-ng-features)
:::

# 手順

## 0. 音声ファイルの準備

#### 対象音声
まず、私が今回対象としたのが以下の内容の音声です（すみません、音声ファイルはDL出来ません）。この音声をベースに書き起こし、カスタマイズを進めていきます。5つの文章で約1分の音声となります。これは、車のダブルウィッシュボーンというサスペンションについて説明した音声となります。特有の用語が多く含まれているので、このあたりがどう書き起こされるのかを見ていきます。

**（Sample音声ファイル）**
DoubleWishborn.mp3
**（音声内容）**
>上下に配置されたアームの間に、スプリングとショックアブソーバーを備えたサスペンションがダブルウィッシュボーンと呼ばれています。コイルダンパーユニットに複数のリンクを組み合わせたものが主流となっており、5リンクのものもあります。複数のリンクを持つことで、走行状況に応じたきめ細かいキャンバー制御とトーコントロールを行うことが出来ます。ハイマウントアッパーアーム型ダブルウィッシュボーンでは、キングピン角度を立てたまま、ネガティブオフセットに設定できるため、スタビリティが向上し、アンダーステアを軽減する効果があります。リヤ用では、フロント用とは違い ハイマウントアッパーアーム式は普及しておらず、各自動車メーカーは伝統的なダブルウィッシュボーンをベースとした様々なタイプのものを採用しています。

#### Macbookでの音声ファイルの準備
既存の音声ファイルを利用する方は問題無いのですが、私は今回音声ファイルの作成から行いました。なるべくMacの標準機能で作成しようとした際に躓いた点がありましたので、記載しておきます。

##### 録音はQuickTime Playerで出来る
Macには標準で「QuickTime Player」がインストールされていますが、QuickTime Playerを用いて簡単に録音することが出来ます。Macbookの場合はマイクも内蔵されているので、何も準備はいりません。

**＜手順＞**
QuickTime Playerを起動して、メニューから「ファイル＞新規オーディオ収録」を選択するだけです。

ただ、作成されるファイルが **拡張子m4a** なのでここから一手間必要です。
どうやら、Watson Speech to Textでは拡張子m4aは対応していないようで、色々試したのですがそのままではうまく取り込めませんでした。
Watson Speech to Textで対応している音声フォーマットは下記を参照ください。
:blue_book: [IBM Cloud Docs (Watson Speech to Text 「音声フォーマット」)](https://cloud.ibm.com/docs/speech-to-text?topic=speech-to-text-audio-formats)

##### ミュージックアプリで音声ファイル（m4a）をmp3形式に変換する
ファイルのフォーマット変換ソフトは色々なものが出ており、それらを利用してもよいかと思います。今回はMac標準機能を用いて実施したかったので、標準でインストールされている「ミュージック」アプリを利用しました。一般的な音声ファイルの拡張子ということで、mp3を選択しました。

**＜手順＞**
1. 環境設定を開き、「ファイル」タブの「読み込み設定…」をクリック
2. 「読み込み方法：」を”MP3エンコーダ”、「設定：」で任意の音質を選択する（今回は”高音質（192kbps）”を使いました）
3. ミュージックアプリに対象の音声ファイルをドラッグ＆ドロップ
４. メニューから「ファイル＞変換＞MP3バージョンを作成」とするとmp3に変換されたファイルが作成されます（もとのファイルはそのまま残ります）


## 1. 音声ファイルの書き起こし

###### 構文（例）
```sh
curl -X POST -u "apikey:{apikey}" \
--header "Content-Type: audio/mp3" \
--data-binary @{path_to_file}DoubleWishborn.mp3 \
"{url}/v1/recognize?model=ja-JP_BroadbandModel"
```
:::note info
＊日本語の場合、「model」パラメータを指定しないと正しく結果が返って来ないのでパラメータを指定する必要があります。上記は「model」パラメータを指定した例となります。
＊{apikey}と{url}は作成したWatson Speech to Textサービスのものに置き換えてください。
:::


###### 実行結果
こんな感じで返ってきます。

```
     {
   "result_index": 0,
   "results": [
      {
         "final": true,
         "alternatives": [
            {
               "transcript": "上下 に 配置 された もの 間 に スプリング と ショック アブソーバー を 備えた サスペンション が ＷＢＣ 法 と 呼ばれて います ",
               "confidence": 0.82
            }
         ]
      },
      {
         "final": true,
         "alternatives": [
            {
               "transcript": "コイル ダンパー ユニット に 複数 の リンク を 組み合わせ た もの が 主流 と なって おり 五輪 九 の もの も あります ",
               "confidence": 0.83
            }
         ]
      },
      {
         "final": true,
         "alternatives": [
            {
               "transcript": "複数 の リンク を 持つ こと で 走行 状況 に 応じた きめ細かい キャンバー 角 制御 と 投稿 トロール を 行う こと が できます ",
               "confidence": 0.9
            }
         ]
      },
      {
         "final": true,
         "alternatives": [
            {
               "transcript": "はい マウント バーム が ダブル ウィッシュボーン では キング ピン 角度 を 立てた まま ネガティブ を 生徒 に 設定 できる ため スタビリティー が 向上 し アンダー ステア を 軽減 する 効果 が あります ",
               "confidence": 0.8
            }
         ]
      },
      {
         "final": true,
         "alternatives": [
            {
               "transcript": "リアル では フロント 用 とは 違い はい マウント バーム 式 が 普及 して おらず 各 自動車 メーカー は 伝統的 な ダブル ウィッシュボーン を ベース と した さまざまな タイプ の もの を 採用 して います ",
               "confidence": 0.8
            }
         ]
      }
   ]

```

分かりづらいので1箇所に纏めると…

>上下 に 配置 された <font color="Red">も</font>の 間 に スプリング と ショック アブソーバー を 備えた サスペンション が <font color="Red">ＷＢＣ 法</font> と 呼ばれて います
>コイル ダンパー ユニット に 複数 の リンク を 組み合わせ た もの が 主流 と なって おり <font color="Red">五輪 九</font> の もの も あります
>複数 の リンク を 持つ こと で 走行 状況 に 応じた きめ細かい キャンバー 角 制御 と <font color="Red">投稿 トロール</font> を 行う こと が できます
><font color="Red">はい マウント バーム が</font> ダブル ウィッシュボーン では キング ピン 角度 を 立てた まま ネガティブ <font color="Red">を 生徒</font> に 設定 できる ため スタビリティー が 向上 し アンダー ステア を 軽減 する 効果 が あります
><font color="Red">リアル</font> では フロント 用 とは 違い <font color="Red">はい マウント バーム 式 が</font> 普及 して おらず 各 自動車 メーカー は 伝統的 な ダブル ウィッシュボーン を ベース と した さまざまな タイプ の もの を 採用 して います

ある程度書き起こしは出来ていますが、特に専門用語の部分がうまく書き起こせておらず分かりづらい文章となってしまっています。


## 2.カスタム言語モデル

### 2.1 カスタム言語モデルの作成

###### 構文（例）

"DoubleWishborn model"という名前のモデルを作成します。

```sh
curl -X POST -u "apikey:{apikey}" --header "Content-Type: application/json" --data "{\"name\": \"DoubleWishborn model\", \"base_model_name\": \"ja-JP_BroadbandModel\", \"description\": \"Description of Double Wishborn\"}" "{url}/v1/customizations"
```

###### 実行結果

作成されたカスタム言語モデルのIDが返ってきます。XXX部分は固有のIDが設定されます。

```ｓｈ
{"customization_id": "XXXXXXXXX"}
```

### 2.2 カスタム言語モデルの確認

###### 構文（例）

```sh
curl -X GET -u "apikey:{apikey}" "{url}/v1/customizations"
```
###### 実行結果

現在登録されているカスタム言語モデルが表示されます。

```sh
{"customizations": [
   {
      "owner": "XXXXXXXXX",
      "base_model_name": "ja-JP_BroadbandModel",
      "customization_id": "XXXXXXXXX",
      "dialect": "ja-JP",
      "versions": ["ja-JP_BroadbandModel.v2020-09-10"],
      "created": "2022-01-07T02:52:02.483Z",
      "name": "DoubleWishborn model",
      "description": "Description of Double Wishborn",
      "progress": 100,
      "language": "ja-JP",
      "updated": "2022-01-07T03:21:50.918Z",
      "status": "available"
   }
]}
```


### 2.3 カスタム言語モデルへの単語の追加

#### 2.3.1 単語の追加

サスペンション関係の専門用語を追加します。追加する用語は下記形式のjsonでファイル化しておきます。「5リンク」というのは正確には用語ではないのですが、書き起こし出来ていなかったため、試しに登録してみます。

```DoubleWishborn_words.json
{
   "words":[
      {"word":"ダブルウィッシュボーン","sounds_like":["ダブルウィッシュボーン"],"display_as":"ダブルウィッシュボーン"},
      {"word":"トーコントロール","sounds_like":["トーコントロール"],"display_as":"トーコントロール"},
      {"word":"オフセット","sounds_like":["オフセット"],"display_as":"オフセット"},
      {"word":"アッパーアーム式","sounds_like":["アッパーアームシキ"],"display_as":"アッパーアーム式"},
      {"word":"5リンク","sounds_like":["ゴリンク"],"display_as":"5リンク"},
      {"word":"ハイマウント","sounds_like":["ハイマウント"],"display_as":"ハイマウント"}
   ]
}
```

:::note info
jsonファイルの形式は、UTF-8にしておく必要があります。
:::

###### 構文（例）
```sh
curl -X POST -u "apikey:{apikey}" --header "Content-Type: application/json" --data-binary @DoubleWishborn_words.json "{url}/v1/customizations/{customization_id}/words"
```
:::note info
{customization_id}には先程作成したモデルのIDを設定します。
:::

###### 実行結果

上記コマンドは非同期のものになるので、Terminal上ではすぐ応答が返ってきます。実行結果を確認するには以下のコマンドを実行します。

```sh
curl -X GET -u "apikey:{apikey}" "{url}/v1/customizations/{customization_id}"
```

"status"が"ready"となれば、単語の追加は完了しています。"ready"となっていない場合は、処理中であるため上記コマンドを一定間隔で繰り返し実行し、"ready"となることを確認します。

```sh
{
   "owner": "XXXXXXXXX",
   "base_model_name": "ja-JP_BroadbandModel",
   "customization_id": "XXXXXXXXX",
   "dialect": "ja-JP",
   "versions": ["ja-JP_BroadbandModel.v2020-09-10"],
   "created": "2022-01-07T02:52:02.483Z",
   "name": "DoubleWishborn model",
   "description": "Description of Double Wishborn",
   "progress": 0,
   "language": "ja-JP",
   "updated": "2022-01-07T03:03:16.214Z",
   "status": "ready"
}
```

#### 2.3.2 カスタム言語モデルのトレーニング

単語の追加を行った場合、モデルのトレーニングが必要となります。

###### 構文（例）

```sh
curl -X POST -u "apikey:{apikey}" "{url}/v1/customizations/{customization_id}/train"
```
###### 実行結果

トレーニングのコマンドも非同期で実行されるので、Terminal上は応答がすぐ返ってきます。トレーニングの実行結果は単語の追加と同じコマンドで確認します。"status"が"available"となれば、トレーニング完了です。

```sh
{
   "owner": "XXXXXXXXX",
   "base_model_name": "ja-JP_BroadbandModel",
   "customization_id": "XXXXXXXXX",
   "dialect": "ja-JP",
   "versions": ["ja-JP_BroadbandModel.v2020-09-10"],
   "created": "2022-01-07T02:52:02.483Z",
   "name": "DoubleWishborn model",
   "description": "Description of Double Wishborn",
   "progress": 100,
   "language": "ja-JP",
   "updated": "2022-01-07T03:21:50.918Z",
   "status": "available"
}
```

#### 2.3.3 カスタム言語モデルの適用結果

トレーニングが完了したので、カスタム言語モデルを用いて音声を書き起こしてみます。

###### 構文（例）

```sh
curl -X POST -u "apikey:{apikey}" --header "Content-Type: audio/mp3" --data-binary @DoubleWishborn.mp3 "{url}/v1/recognize?language_customization_id=XXXXXXXXX&model=ja-JP_BroadbandModel"
```

###### 実行結果

>上下 に 配置 された <font color="Red">も</font>の 間 に スプリング と ショック アブソーバー を 備えた サスペンション が <font color="Blue">ダブルウィッシュボーン</font> と 呼ばれて います 
>コイル ダンパー ユニット に 複数 の リンク を 組み合わせ た もの が 主流 と なって おり <font color="Blue">5リンク</font> の もの も あります
>複数 の リンク を 持つ こと で 走行 状況 に 応じた きめ細かい キャンバー 角 制御 と <font color="Blue">トーコントロール</font> を 行う こと が できます
><font color="Blue">ハイマウント アッパーアーム式</font> <font color="Red">た</font> ダブルウィッシュボーン では キング ピン 角度 を 立てた まま ネガティブ <font color="Blue">オフセット</font> に 設定 できる ため スタビリティー が 向上 し アンダー ステア を 軽減 する 効果 が あります
><font color="Red">リアル</font> では フロント 用 とは 違い <font color="Blue">ハイマウント アッパーアーム式</font> が 普及 して おらず 各 自動車 メーカー は 伝統的 な ダブルウィッシュボーン を ベース と した さまざまな タイプ の もの を 採用 して います

かなり良くなりました。今回用いた音声は通常の会話ではないのですが、このようななにかを説明する音声だと用語の登録だけでもかなり効果はありそうです。第1パラグラフの「上下に配置されたアーム」や第5パラグラフ先頭の「リヤ用では」の部分などがうまく書き起こされていないので、さらなるカスタマイズを行ってみます。


### 2.4 カスタム言語モデルへのコーパスの追加

#### 2.4.1 コーパスの追加

###### コーパスファイル

コーパスとはその分野で使われる例文をテキスト形式で登録するものとなります。特定の単語がその分野でどのように使われるかを学習させることにより、音声書き起こしの精度を高めるというものです。
今回は以下の内容で登録してみました。今回は試しということでもとの音声に非常に近い内容にしてみました。これで書き起こしの結果がどう変わるのか見ていきます。

:::note info
今回、単語登録のみでどれくらい効果があるかをみるため、単語の登録を先に行いましたが、マニュアルを見る限り、本来はコーパスを登録し、コーパスに出てくる専門用語などの単語を登録するということが正しいカスタマイズのやり方のようです。
:::

```DoubleWishborn_corpus.txt
リアサスペンションはフロントに追従するだけのものと思われがちです 実はリヤサスペンションにも
精緻なアライメントが設定され 車両を安定させる方向に働くような ジオメトリーが設定されています。
フロントが主にストラットとハイマウントアッパーアーム式ダブルウィッシュボーンの2形式なのに対し
リヤサスペンションには様々な形式が採用されています。
ダブルウィッシュボーンでは 上下に配置されたアームの間にスプレングとショックアブソーバを備えています。
小型FF車ではトレーリングビームが主流となり FR車ではマルチリンクが主流となっている。
リヤ用のダブルウィッシュボーンでは ハイマウントアッパーアーム式はリヤ用としては普及していません。
```
:::note info
コーパスファイルの形式は、UTF-8にしておく必要があります。
:::

###### 構文（例）

以下のコマンドでコーパスを追加します。言語の追加と同じく応答はすぐに返ってきます。"DoubleWishborn"という名称のコーパスを追加します。

```sh
curl -X POST -u "apikey:{apikey}" --data-binary @DoubleWishborn_corpus.txt "{url}/v1/customizations/{customization_id}/corpora/DoubleWishborn"
```

#### 2.4.2 コーパスの分析

###### 構文（例）

コーパスを追加するとその内容が分析されます。分析状況を確認するには以下のコマンドを実行します。

```sh
curl -X GET -u "apikey:{apikey}" "{url}/v1/customizations/{customization_id}/corpora/DoubleWishborn"
```

###### 実行結果

"status"が"analyzed"になればOKです。単語の追加と同じく、"analyzed"になっていない場合は、上記コマンドを一定間隔で繰り返し実行し、"analyzed"になるのを待ちます。

```sh
{
   "out_of_vocabulary_words": 0,
   "total_words": 104,
   "name": "carmaintenance",
   "status": "analyzed"
}
```

#### 2.4.3 コーパスのトレーニング

コーパスを追加した場合、単語の追加と同じくモデルのトレーニングが必要となります。
トレーニング方法は 「[2.3.2 カスタム言語モデルのトレーニング](#232-カスタム言語モデルのトレーニング)」と同じです。

#### 2.4.4 カスタム言語モデルの適用結果

コーパス追加の結果を確認します。コマンドは「[2.3.3 カスタム言語モデルの適用結果](#233-カスタム言語モデルの適用結果)」と同じです。

###### 実行結果

>上下 に 配置 された <font color="Blue">アーム</font> の 間 に スプリング と ショック アブソーバー を 備えて サスペンション が ダブルウィッシュボーン と 呼ばれて います
>コイル ダンパー ユニット に 複数 の リンク を 組み合わせ た もの が 主流 と なって おり 5リンク の もの も あります
>複数 の リンク を 持つ こと で 走行 状況 に 応じた きめ細かい キャンバー 角 制御 と トーコントロール を 行う こと が できます
>ハイマウント アッパーアーム式 ダブルウィッシュボーン では キング ピン 角度 を 立てた まま ネガティブ オフセット に 設定 できる ため スタビリティー が 向上 し アンダー ステア を 軽減 する 効果 が あります
><font color="Blue">リヤ 用</font> では フロント 用 とは 違い ハイマウント アッパーアーム式 は 普及 して おらず 各 自動車 メーカー は 伝統的 な ダブルウィッシュボーン を ベース と した さまざまな タイプ の もの を 採用 して います

単語の追加だけではうまく書き起こされていなかった、第１パラグラフの「上下に配置されたアーム」の部分や、第５パラグラフ先頭の「リヤ用では」の部分もうまく書き起こされるようになりました。

# まとめ

今回curlコマンドだけで、音声の書き起こしからカスタマイズまでを試してみましたが、curlコマンドの実行だけなので、簡単に行うことが出来ました。簡単な動作を確認したい場合は、これで十分な印象です。
また、カスタマイズも単語の登録とコーパス（例文）の登録を試してみましたが、カスタマイズを行った場合と行わない場合では、書き起こし結果にかなり差が出る可能性があるということが分かりました（音声の内容によっては期待通りの結果にならない可能性も考えられます）。