Whisper を Azure OpenAI と Azure AI Speech の両方から日本語データで利用する

この記事は[Advent Calendar 2023](https://japan.zdnet.com/extra/ms_202311/35211313/)に参加させていただいております。
ありがとうございます！

Azure では GPT-4 Turbo with Vision のプレビュー開始など、 OpenAI のモデルが次々と使えるようになっておりますね。

今回は音声テキスト変換モデルである Whisper について紹介していきたいと思います。文字起こしの精度が向上している点や、処理の高速性などが注目されています。 Azure OpenAI から利用する方法と、Azure AI Speech から利用する方法の2通りあるのですが、今回は両方試していきたいと思います。

### 音声データ
バッチ文字起こしの際の日本語の音声データセットはMozillaを利用させていただきました。
https://commonvoice.mozilla.org/ja/datasets

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/eeb20f7d-65cb-888f-113c-0a3746795a9f.png)

## Azure の Whisper モデルについて
冒頭にも記載しましたが、Whisper は Azure OpenAI 経由で使う方法と、Azure AI Speech を介して使う場合の2通りあります。どちらを使えばよいのかについては、ドキュメントの[Whisper モデルは、Azure AI Speech または Azure OpenAI Service を介していますか?](https://learn.microsoft.com/ja-jp/azure/ai-services/speech-service/whisper-overview#whisper-model-via-azure-ai-speech-or-via-azure-openai-service) に記載があります。ファイルサイズが25MB以上かどうか、バッチ処理をするかどうか、ファイル形式などがポイントになります。

## 単一音声ファイルの文字起こし (Azure OpenAI)

#### 準備 :  Azure OpenAI リソースを作成し、Whisper をデプロイ
2023年12月時点で [ Azure OpenAI の whisper モデルが利用可能となっているリージョン](https://learn.microsoft.com/ja-jp/azure/ai-services/openai/concepts/models#whisper-models-preview) は米国中北部、西ヨーロッパの2つです。今回は西ヨーロッパを選択しました。ちなみに、Azure AI Speech から Whisper を利用する場合は、米国東部、東南アジア、西ヨーロッパに Speech リソースを作成する必要があるとのことです。

#### プレイグランウドで利用する
デプロイが完了したら、まずは手軽に[Azure OpenAI Studio](https://oai.azure.com/portal) から使ってみます。Whisper 音声テキスト変換より試すことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/8e304f2d-2979-8e83-7506-2c2b9c710989.png)

Azure OpenAI のリソースを選択し、デプロイしたモデル名を選択します。
言語の識別というトグルボタンをオンにしておくと、自動的に音声ファイルの言語を認識してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/6cdffff1-9c08-58e4-20c2-20258193a9eb.png)

無事に文字起こしができていますね。


#### REST APIから利用する
次にAPIを使って試してみましょう。Whisper に限らず、他の Azure OpenAI のモデルもそうですが、API で利用できるというのは便利ですよね。

- **Curl コマンドの場合**

```
curl {AZURE_OPENAI_ENDPOINT}/openai/deployments/{DEPLOYMENT_NAME}/audio/transcriptions?api-version=2023-09-01-preview \
 -H "api-key: {AZURE_OPENAI_KEY}" \
 -H "Content-Type: multipart/form-data" \
 -F file="{PATH_TO_YOUR_AUDIO}"
```

- **python の場合**
```python:whisper.py
import requests
import os
from os.path import join, dirname
from dotenv import load_dotenv

dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)

AZURE_OPENAI_KEY = os.environ.get("AZURE_OPENAI_KEY") 
AZURE_OPENAI_ENDPOINT = os.environ.get("AZURE_OPENAI_ENDPOINT")
DEPLOYMENT_NAME = os.environ.get("DEPLOYMENT_NAME")

url = f"{AZURE_OPENAI_ENDPOINT}/openai/deployments/{DEPLOYMENT_NAME}/audio/transcriptions?api-version=2023-09-01-preview"

headers = {
  'api-key': f'{AZURE_OPENAI_KEY}'
}

files=[
  ('file',('{AUDIO_FILE_NAME.wav}', open('.{PATH_TO_YOUR_AUDIO}/{AUDIO_FILE_NAME.wav}','rb'), 'multipart/form-data'))
]

response = requests.request("POST", url, headers=headers, files=files)
print(response.text)
```

この python ファイルを使う場合は同じディレクトリに .env ファイルを作成し、
下記のように記述してAPI キーやエンドポイントの情報を取得させてください。
``` .env
AZURE_OPENAI_KEY = "{your-openai-key}"
AZURE_OPENAI_ENDPOINT = "https://{resource-group-name}.openai.azure.com"
DEPLOYMENT_NAME = "{your-deployment-name}"
```
#### 実行結果
python ファイルを実行すると下記のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/f7da7ea8-3371-cef1-65ba-f8b95a9c4cad.png)



## バッチ処理で利用する ( Azure AI Speech )
先述の通り、 Whisper は Azure OpenAI 経由で使う方法と、Azure AI Speech 経由で使う場合の2種類あります。バッチ処理の場合は Azure AI Speech より、Whisper モデルを選択して使うことになります。ここでは Azure AI Speech 経由でバッチ処理を行う方法を紹介します。

#### 準備: バッチ処理用の音声ファイルをBlob Storageにあげる
プレイグラウンドで複数の音声ファイルを手動アップロードをし、バッチ処理を行うことも可能ですが、今回60個ほどの音声ファイルを読み込ませたかったため、Blob Storage にアップロードして使っていきたいと思います。先ほどAzure OpenAIリソースを作成したリソースグループ内に、追加で二つのリソースを作成します。

**① Azure AI Speech**:
これは Whisper モデルをAzure AI Speech を介して使うためです。

**② Micorosoft Storage** :
Blob Storage 内にコンテナを作成し、そこに文字起こししたい音声ファイルをアップロードします。REST API を利用する際に、Blob Storage へ URL を指定する必要があるのですが、その URL は SAS URL (共有アクセストークン) というものを作成して指定します。

\<SAS URL> = \<Blob Storage Container URL> + \<SAS トークン>

という形になっています。
下記画像のように、音声ファイルが入っているコンテナの、「共有アクセストークン」より、読み取りとリストのアクセス許可にチェックを入れた上で、「SASトークンおよびURLを作成」ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/611b1825-93b1-9998-5f4e-3d232f511f1b.png)

#### プレイグラウンドからバッチ処理を行う
リソースの作成が完了したら、バッチ処理の場合もプレイグラウンドから簡単に試すことが可能です。[Speech Studio](https://speech.microsoft.com/portal)に移動し、Batch 音声テキスト変換を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/dda29275-0083-ac7c-2914-74e55ba2e3f4.png)

ここで、オーディオの言語として日本語を選択、モデルは "20231026 Whisper Preview" を選択します。よくみるとこちらに書いてある 5e075808-d616-4e6b-bd44-2d965db08b99 というのがモデルIDのようですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/998b402e-7a61-b2de-8895-70a1d446f95b.png)

その他のパラメータもお好みで設定してください。 
- 話者のダイアライゼーション
- 話者の最大数 (話者のダイアライゼーションが True のときに有効になります)
- 不適切表現フィルターモード
- 句読点モード
- 表示形式ワードレベルのタイムスタンプ
- 語彙形式ワードレベルのタイムスタンプ

オーディオファイルのアップロードの欄では、先ほど作成した Blob Storage コンテナーの SAS URL を入力します。Azure AI Speech のリソースが使用されることへの同意にチェックを入れ、実行してみましょう。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/5a4aabf4-37a8-d28f-835d-21def97ce6b9.png)



#### バッチ処理の結果

下記画像のように、バッチジョブが作成され、文字起こしができていることを確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/5623d033-707f-eda0-e40a-bacd71074e3b.png)


#### REST API からバッチ文字起こしをする
次は、サンプルコードを使って REST API から文字起こしを行っていきます。プレイグランドの下部に REST API を使用したサンプルコードが表示されるので、それを使用します。**が、少し注意すべき点があります…。**
執筆時点では、サブスクリプションキーやコンテナへの SAS URL が埋め込まれた下記のようなコードが表示されるかと思いますが、
``` 
curl -v -X POST -H "Ocp-Apim-Subscription-Key: {your-Subscription-Key}" -H "Content-Type: application/json" -d '{
  "displayName": "20231217_204430",
  "description": "Speech Studio Batch speech to text",
  "locale": "ja-jp",
  "contentContainerUrl": "{SAS-URL-to-your-container}",
  "model": {
    "self": "https://{your-resource-region}.api.cognitive.microsoft.com/speechtotext/v3.2-preview.1/models/base/5e075808-d616-4e6b-bd44-2d965db08b99"
  },
  "properties": {
    "wordLevelTimestampsEnabled": true,
    "displayFormWordLevelTimestampsEnabled": true,
    "diarizationEnabled": false,
    "punctuationMode": "DictatedAndAutomatic",
    "profanityFilterMode": "Masked"
  },
  "customProperties": {}
}' "https://{your-resource-region}.api.cognitive.microsoft.com/speechtotext/v3.1/transcriptions"
```
最終行をみると、Speech to text API のバージョンが v3.1 のものになっています。
Whisperは[こちらのドキュメント](https://learn.microsoft.com/ja-jp/azure/ai-services/speech-service/batch-transcription-create?pivots=rest-api#using-whisper-models) の通り バージョン v3.2 を使用する必要があるため最終行の API URL を
```
"https://{your-resource-region}.api.cognitive.microsoft.com/speechtotext/v3.2-preview.1/transcriptions"
```
にしておきましょう。（私はなかなか気づかずに時間を使ってしまいました…。）
[Speech to Text API v3.2 preview1](https://eastus.dev.cognitive.microsoft.com/docs/services/speech-to-text-api-v3-2-preview1/operations/Transcriptions_Create) のAPIリファレンスはこちらにあります。 
それではターミナルで実行します。これ以降の操作は[バッチ文字起こしの結果を取得する](https://learn.microsoft.com/ja-jp/azure/ai-services/speech-service/batch-transcription-get?pivots=rest-api) を参考にしております。応答の中に

```
  "links": {
    "files": "https://{your-resource-region}.api.cognitive.microsoft.com/speechtotext/v3.1/transcriptions/{transcription-id}/files"
  },
```
という URL があると思いますので、その URL に対して GET 要求を行います。

``` 
curl -v -X GET -H "Ocp-Apim-Subscription-Key: {your-Subscription-Key}" -H "Content-Type: application/json" 
https://{your-resource-region}.api.cognitive.microsoft.com/speechtotext/v3.2-preview.1/transcriptions/{transcription-id}/files
```
応答として下記の形で得られました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/6c9713ea-22ab-1731-b307-fefffdb9d764.png)

一つ目の値で"kind"の値が"Transcription Report" の contentUrl を見に行くとバッチ処理結果の一覧を確認できました。すべて"Succeeded"で成功していますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/a87e66de-bfcb-a4de-61b1-da0c0e17c9f1.png)

さらに、各ファイルに対応しているcontentUrl を見に行くと、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620813/7698cc54-8cdd-6f93-559e-e0ff4363fe1a.png)

バッチ処理の結果が確認できました。

### 最後に
今回は、日本語のデータセットで、音声文字起こしのモデルである Whisper を Azure OpenAI 経由で使う方法、Azure AI Speech 経由で使う方法の２通りで紹介いたしました。バッチ処理を行う際は Azure AI Speech が推奨されていますので、その方法をご紹介しました。Azure AI Speech は参考となるドキュメントなども限られているため、ご参考となれば幸いです。Whisper の日本語での精度検証や、処理時間計測などについては別の記事でご紹介できればと思います。


### 余談 
ちなみに、有名なラッパーでエミネムというアーティストがおり、彼の Rap God という曲は、1曲あたりのワード数で世界ギネスをとったことがあるほど、高速のラップとなっています。特に15秒間で97ワード（1秒当たり約6.5ワード）となる箇所が曲の中にあり、圧巻です。

この Rap God を文字起こしサービス達に聞かせてみようと Whisper と従来の Azure AI Speech の文字起こしにいれたところ、音源が英語だということもあったせいか、Whisper はかなりの精度を出してくれました。また文字起こし結果の可読性という点も、体感ですが上がっていると感じました。

歌詞が正直汚いことや、やはり日本語で検証したいという思いもあり、詳しく紹介することはありませんが、もしよければ皆さんも Whisper 試してみてください！