Azure AI Foundry で Whisper モデルの API を Node-RED から試したメモ

Azure AI Foundry で Whisper モデルの API を Node-RED から試したメモです。

背景

2025/01/09 時点の情報で進めます。

先日こんな記事で Azure AI Foundry でモデル選んで API も使えることが分かったので Whisper モデルも使ってみます。

モデルを探す

azure-aI-foundry-whisper-model-api-try_05.png

モデル カタログ では whisper が使えることがわかります。

azure-aI-foundry-whisper-model-api-try_11.png

クリックしてみた詳細です。最後のトレーニング「使用できません」となって使えるのか心配になりますが、ちゃんと使えました。

左上のデプロイボタンをクリックします。

azure-aI-foundry-whisper-model-api-try_14.png

デプロイ確認画面です。

Azure AI Foundry から gpt-4o モデルを使ってみるメモ – 1ft-seabass.jp.MEMO で使ったプロジェクトをそのまま使います。

デプロイをクリックします。

azure-aI-foundry-whisper-model-api-try_07.png

すぐにデプロイ完了しました!

Node-RED の仕組み

現時点では OpenAI 社の API の構造と Azure AI Foundry の OpenAI の API は同じようなので、

Speech to text – OpenAI API

を参考にしつつ、

azure-aI-foundry-whisper-model-api-try_03.png

まず Node-RED でこのようなフローを作り、 OpenAI 社の API での Whisper のほうで成功することを確認しました。

azure-aI-foundry-whisper-model-api-try_19.png

API 設定の change ノードでは、

azure-aI-foundry-whisper-model-api-try_15.png

サウンドデータ付与以外の部分で、ヘッダーや URL 、model などを設定しています。

azure-aI-foundry-whisper-model-api-try_01.png

サウンドデータ付与の change ノードでは、

azure-aI-foundry-whisper-model-api-try_02.png

このようにサウンドデータ付与を行っています。

azure-aI-foundry-whisper-model-api-try_00.png

inject ノードをクリックして動かすとこんなかんじです。

azure-aI-foundry-whisper-model-api-try_20.png

Whisper の詳細画面で Azure AI Foundry のほうの API のエンドポイントと API キーの情報を確保しつつ、

azure-aI-foundry-whisper-model-api-try_12.png

さきほどのフローをコピーして、Azure AI Foundry の設定をします。

azure-aI-foundry-whisper-model-api-try_17.png

API 設定の change ノードでは、OpenAI 社の API のヘッダー情報である Authorization ヘッダーを、Azure AI Foundry の OpenAI の API のヘッダー情報である api-key にしつつ Bearer はなくします。

動かしてみると何かがおかしい→翻訳だった

azure-aI-foundry-whisper-model-api-try_16.png

こんな感じで、文字お越しはされるものの、変な文字が混ざるときがあります。

azure-aI-foundry-whisper-model-api-try_04.png

英語が来る?何かがおかしい?

Azure OpenAI client transcribes or translates speech depending on the deployment used, not the library function · Issue #1910 · openai/openai-python

こういった issue をみていて「あ、これは文字起こしじゃなくて翻訳のほうが発動してる!」と気づきました。

azure-aI-foundry-whisper-model-api-try_06.png

ここに示されるエンドポイントのサンプルが translations になっちゃってるんですよね。気づきませんでした。

azure-aI-foundry-whisper-model-api-try_13.png

そのままコピペしてたので、

azure-aI-foundry-whisper-model-api-try_10.png

transcriptions に変更します。

Speech to text – OpenAI API

こちらの API の仕様を参考にしてます。

うまくいった

azure-aI-foundry-whisper-model-api-try_08.png

にあわせて translations を transcriptions に変更したら翻訳っぽい挙動がなくなり、素直な自動言語認識の文字起こしになりました。

azure-aI-foundry-whisper-model-api-try_18.png

やった!

短時間にたたき続けてるとエラーが返ってくる学び

azure-aI-foundry-whisper-model-api-try_09.png

ちなみに、デフォルトでプロジェクトで使われる S0 tier を使ってると、短時間にたたき続けてるとエラーが返ってきます。

Requests to the Audio_Transcriptions Operation under Azure OpenAI API version 2024-06-01 have exceeded call rate limit of your current AIServices S0 pricing tier. Please retry after 5 seconds. Please contact Azure support service if you would like to further increase the default rate limit.

すこし間を置けばアクセスできるので安心してください。5 秒後リトライしてねと書いてありますね。

以下に JSON のフローも置いておきます。

[{"id":"22828b14f4fc87e9","type":"debug","z":"6c85d499b1c334b0","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":760,"wires":[]},{"id":"d826ed327d0b3135","type":"http request","z":"6c85d499b1c334b0","name":"","method":"POST","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":590,"y":760,"wires":[["22828b14f4fc87e9"]]},{"id":"d706cc46f00aeb7b","type":"change","z":"6c85d499b1c334b0","name":"multipart/form-data でのサウンドデータ付与","rules":[{"t":"set","p":"payload.file","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.file.value","pt":"msg","to":"buffer","tot":"msg"},{"t":"set","p":"payload.file.options","pt":"msg","to":"{}","tot":"bin"},{"t":"set","p":"payload.file.options.filename","pt":"msg","to":"voice.wav","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":270,"y":760,"wires":[["d826ed327d0b3135"]]},{"id":"6e0b9c1337c4e0a8","type":"change","z":"6c85d499b1c334b0","name":"API 設定","rules":[{"t":"set","p":"url","pt":"msg","to":"{url}","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"headers.api-key","pt":"msg","to":"{api-key}","tot":"str"},{"t":"set","p":"headers.Content-Type","pt":"msg","to":"multipart/form-data","tot":"str"},{"t":"set","p":"payload.model","pt":"msg","to":"whisper-1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":660,"wires":[["d706cc46f00aeb7b"]]},{"id":"4ee9ea2ea06f9b3c","type":"change","z":"6c85d499b1c334b0","name":"音データ msg.buffer 保管","rules":[{"t":"set","p":"buffer","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":660,"wires":[["6e0b9c1337c4e0a8"]]},{"id":"41d40b4c8f81b66c","type":"file in","z":"6c85d499b1c334b0","name":"音データ読み込み","filename":"{path}","filenameType":"str","format":"","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":350,"y":660,"wires":[["4ee9ea2ea06f9b3c"]]},{"id":"b349cf79921725b7","type":"inject","z":"6c85d499b1c334b0","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":660,"wires":[["41d40b4c8f81b66c"]]}]