😊

ブラウザ完結でOpenAIのwhisperを試したい

2023/03/08に公開

サーバー立てたくないし、wav/mp3などの音声ファイルも作りたくない、whisper動かしたいんだ!っというときのために、ブラウザだけで動かせるサンプル作りました。
HTMLファイル1個だけです。

https://github.com/uemegu/OpenAISample

音声の取得

無音になったら録音止めたいけど、どうしたら・・・と悩んでましたが以下を参考にできました。
VAD(Voice Activity Detection)という技術で良い感じにしてくれるそうで、そのブラウザ版のricky0123/VADというのがありました。

https://knowledge.sakura.ad.jp/34497/

    <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.13.1/dist/ort.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@ricky0123/vad/dist/index.browser.js"></script>
    <script>
      let myvad;
      const startAudio = async (onRecorded) => {
        try {
          if (!myvad) {
            myvad = await vad.MicVAD.new({
              onSpeechEnd: async (arr) => {
                const wavBuffer = vad.utils.encodeWAV(arr);
                var file = new File([wavBuffer], `audio.wav`);
                document.getElementById("testAudio").src =
                  URL.createObjectURL(file);
                try {
                  onRecorded(file);
                } catch (err) {
                  console.log(err);
                }
              },
            });
          }

          myvad.start();
        } catch (e) {
          console.error("Failed:", e);
        }
      };

文字起こし

音声データをフォームデータとしてOpenAIのAPIに送ります。
最初、サーバーエラーが起きて困ったのですが、Content-TypeをsetRequestHeaderで指定しているのが原因でした。

      const callTranscriptions = (file, callback) => {
        const XHR = new XMLHttpRequest();
        XHR.addEventListener("load", (event) => {
          callback(JSON.parse(event.target.responseText).text);
        });
        XHR.addEventListener("error", (event) => {
          alert("error");
        });
        XHR.open("POST", "https://api.openai.com/v1/audio/transcriptions");
        //XHR.setRequestHeader("Content-Type", "multipart/form-data"); これを書いたらサーバーエラーになる
        XHR.setRequestHeader("Authorization", "Bearer ここにAPIキーを書く");

        var formData = new FormData();
        formData.append("model", "whisper-1");
        formData.append("language", "ja");
        formData.append("file", file);
        XHR.send(formData);
      };

実行結果

正常に動くと、ボタンの下に文字起こしの結果が表示されます。
オーディオコントロールは直近の文字起こしした音声を再生できます。

オーディオコントロール周りは以下の記事を参考にしました。

https://zenn.dev/tatsuyasusukida/articles/097321c14ec6f5

Discussion