とういうことで、Transformers.jsを使ってブラウザでWhisperを動かすOracle APEXアプリケーションを作ってみました。可能であればWebGPUも使用します。
作成したアプリケーションは以下のように動作します。長さが23秒の日本語の音声ファイルの処理に、WebGPUを使って3.6秒かかっています。
作成したAPEXアプリケーションについて紹介します。
空のアプリケーションを作成し、ホーム・ページにすべての機能を実装しています。
ページ・プロパティのJavaScriptのファンクションおよびグローバル変数の宣言に、以下を記述しています。Whisperによる文字起こしを行なうオブジェクトtranscriberを、ページのどこからでも呼び出せるようにしています。
var transcriber;
WhisperをロードするJavaScriptのコードは、ページに静的コンテンツのリージョンを作成し、そのリージョンのソースのHTMLコードに記述します。
最初にP1_USE_GPUのスイッチを確認します。スイッチがオン(つまりP1_USE_GPUの値がY)で、かつ、ブラウザでWebGPUが有効であればWebGPUを使用します。それ以外の場合は、WebGPUは使用しません。
続いてWhisperのモデルを読み込みます。ここではonnx-community/whisper-smallを決め打ちでロードしています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script type="module" defer> | |
import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers/+esm'; | |
/* | |
* WebGPUの使用を決定する。 | |
*/ | |
let config = {}; | |
if ( apex.item("P1_USE_GPU").getValue() !== 'Y' ) { | |
apex.item("P1_GPU").setValue("WebGPU is not used."); | |
} | |
else | |
{ | |
if ( 'gpu' in navigator ) { | |
config.device = "webgpu"; | |
apex.item("P1_GPU").setValue("WebGPU is available."); | |
} | |
else | |
{ | |
apex.item("P1_GPU").setValue("WebGPU is not available"); | |
} | |
} | |
/* | |
* Whisperのモデルをロードする。 | |
* whisper-smallはそこそこ大きいので時間はかかる。 | |
* | |
* モデルはonnx-comminity以下より選択。 | |
* https://huggingface.co/models?pipeline_tag=automatic-speech-recognition&library=transformers.js | |
*/ | |
let model; | |
// whisper-small | |
model= 'onnx-community/whisper-small'; | |
config.dtype='fp32'; | |
// whisper-large-v3-trubo | |
// model='onnx-community/whisper-large-v3-turbo'; | |
// config.dtype='q4'; // fp16,q8,int8,uint8,q4,q4fp16,bnb4 選択できる模様。 | |
apex.item("P1_STATUS").setValue("Loading Transcriber..."); | |
transcriber = await pipeline( | |
'automatic-speech-recognition', | |
model, | |
config | |
); | |
apex.item("P1_STATUS").setValue("Transcriber loaded"); | |
</script> |
画面には表示しないため、外観のテンプレートはなしにしています。
ページ・プロパティP1_GPUにはGPUの使用の有無、P1_STATUSには、Whisperの状態を表示します。その他、P1_ELAPSED_TIMEには、文字起こしに要した時間をミリ秒単位で表示します。
ページ・アイテムP1_AUDIOで文字起こしをする音声ファイルを選択します。P1_OUTOUTに音声ファイルから起こした文字列を出力します。
ボタンTRANSCRIBEをクリックしたときに、ページ・アイテムP1_AUDIOで選択済みの音声ファイルの文字起こしを実行します。これは、以下のJavaScriptを実行する動的アクションで実装しています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* P1_AUDIOで選択した音声ファイルをテキストに起こす。 | |
*/ | |
apex.item("P1_STATUS").setValue("Start transcribe..."); | |
const audioFile = document.getElementById("P1_AUDIO").files[0]; | |
const audioURL = URL.createObjectURL(audioFile); | |
// 文字起こしの開始。日本語は決め打ち。 | |
const startTime = performance.now(); | |
transcriber(audioURL, { language: "ja" } ).then( (output) => { | |
apex.item("P1_STATUS").setValue("Transcribe done."); | |
const endTime = performance.now(); | |
apex.item("P1_OUTPUT").setValue(output.text); | |
apex.item("P1_ELAPSED_TIME").setValue((endTime - startTime)); | |
}); |
以上で実装は完了です。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/transformers-js-whisper-webgpu.zip
Hugging Faceのモデルの説明によると(Long-Form Transcriptionの章)、処理できる音声の長さは30秒が上限のようです。そのため、長い音声の場合は30秒以下のチャンクに分割して、それぞれのチャンクごとに文字起こしをする必要がありそうです。
今回の記事は以上になります。
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完