WhisperとNext.js(Edge Runtime)で文字起こし

公開日:2023/7/13更新日:2023/7/13

OpenAIのサービスの1つであるWhisperのAPIを使い、Next.jsのアプリケーションで文字起こしをする実践的な手順をご紹介します。

前提

Whisperを実用的に使うとなると、ユーザーがアップロードした音声データを受け取り、それを(加工して)APIに投げる、流れになります。

しかし、執筆時点、Next.jsのEdge Runtimeでは、ファイルの読み書きなどができないため、OpenAI公式のサンプルコードにあるようなfsモジュールを使ったファイルの読み込みができません

そのため、ライブラリを使わず、FormDataに音声データやその他のパラメーターをセットしてAPIに投げる必要があります。

サーバサイド(API)のコード

/app/api/generate/route.tsのファイルを作成し、クライアントサイドから<あなたのサイト>/api/generateにPOST送信された場合の処理を記述します。

import { NextRequest, NextResponse } from "next/server";

export const runtime = "edge";

export async function POST(request: NextRequest) {
  // クライアントサイドから送られてきたフォームデータを取得
  const formData = await request.formData();

  // フォームデータから音声データを取得
  const resource = formData.get("resource") as File;

  // Whisper-1モデルで日本語の文字起こしを行うためのフォームデータを作成
  const transcriptionFormData = new FormData();
  transcriptionFormData.set("file", resource); // 音声データをセット
  transcriptionFormData.set("model", "whisper-1"); // モデルをwhisper-1にする
  transcriptionFormData.set("language", "ja"); // 言語を日本語にする

  // 文字起こしを実行
  const res = await fetch("https://api.openai.com/v1/audio/transcriptions", {
    headers: {
      Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
    },
    method: "POST",
    body: transcriptionFormData,
  });

  // 文字起こしに失敗した場合はエラーメッセージを返す
  if (!res.ok) {
    return NextResponse.json({
      success: false,
      message: "文字起こしに失敗しました",
    });
  }

  const json = await res.json();
  const result = json.text; // 文字起こしの結果を取得

  // ここでresultの値をバックエンドに保存したり、別のAPIに渡したり、何かしらの処理を行う

  // 成功した場合は成功メッセージを返す
  return NextResponse.json({
    success: true,
    message: "文字起こしに成功しました",
  });
}

クライアントサイドのコード

/app/generate/components/Form.tsxにフォームコンポーネントを作成します。

今回は便宜上、音声データの加工処理を省いていますが、例えば、mp4からmp3へ変換してからアップロードするなどの処理も可能です。

"use client";

export const Form = () => {
  return (
    <form
      onSubmit={async (e) => {
        e.preventDefault();

        const formData = new FormData(e.currentTarget);
        const res = await fetch(`${origin}/api/generate`, {
          method: "POST",
          body: formData,
        });

        alert(res.ok ? "Success" : "Something went wrong");
      }}
      className="flex flex-col gap-8"
    >
      <div className="flex flex-col">
        <label>音声ファイル</label>
        <input type="file" name="resource" accept="audio/*" required />
      </div>
      <div className="flex justify-center">
        <button type="submit">
          送信
        </button>
      </div>
    </form>
  );
};

/app/generate/page.tsxを用意してフォームコンポーネントをインポートします。

import { Form } from "./components/Form";

export const runtime = "edge";

export default async function GeneratePostPage() {
  return (
    <div>
      <Form />
    </div>
  );
}

Whisperの精度を高めるテクニック

特段何もしなくても、精度の高い文字起こしが低価格でできるのがWhisperのすごいところですが、ChatGPTと同じくプロンプトを使うこともできるので、一歩進んだ使い方が可能です。

例として、表記ゆれをなくすテクニックを別記事に紹介しているので、興味があれば参考にしてみてください。