2025年01月14日
Astroを用いた文字起こし機能の構築
※この投稿は、Agoraの日本代理店であるブイキューブが、Agoraブログを翻訳した記事です。
この記事は、高速なWebサイトを構築するためのWebフレームワークであるAstroを用いたバックエンド構築に関するシリーズのパート3です。
目次
[非表示]前提条件
- NodeJSとAstroがインストールされていること
- Agoraの開発者アカウント
- Astroで構築されたトークンジェネレータ (パート1記事参照)
プロジェクトのセットアップ
このガイドでは、トークン生成ガイドをベースに説明します。
トークン生成ガイドでは、api/tokens.json エンドポイントを構築する手順を説明します。 このエンドポイントは、トークン生成ロジックを処理する handleGenerateToken 関数を使用します。同じバックエンドサーバー上にあるので、Speech-To-Textエンドポイント内でこの関数を直接使用します。
前のガイドで利用した環境変数のAPP_IDとAPP_CERTIFICATEを使って、書き起こしを開始したり停止したりできます。
文字起こし(Speech-To-Text) 概要
Real-Time Speech-To-Text は Agora が提供する RESTful API で、ビデオ通話をリアルタイムで書き起こしたり、選択したストレージプロバイダ内に保存することができます。
あなたのビジネスバックエンドは、機密データがアプリケーションとの間で直接受け渡しされないように、このトランスクリプションサービスをトリガーする必要があります。
Speech-To-Textセッションを成功させるためのフローは以下の通りです。
- Agora Speech-To-Text リソースを取得します。
- Speech-To-Text サービスを開始します。
- Speech-To-Text サービスを停止します。
Agora RESTful API の有効化
このガイドでは、Agora RESTful API への接続が不可欠です。
接続するには、Customer ID と Customer Secret が必要です。
これらは、Agora コンソールに入り、Developer Toolkit の下の RESTful API タブを選択し、"Add a Secret" ボタンをクリックすることで見つけることができます。そして、これらの値をコピーし、CUSTOMER_ID と CUSTOMER_SECRET 環境変数に格納します。
エンドポイントの定義
api/transcription/start.json と api/transcription/stop.json の2つのエンドポイントを用意します。
エンドポイントは入力情報を必要とするので、POST リクエストを使ってリクエストボディとして入力を渡します。これらの入力が空でないことをチェックします。
もし空であれば、utils/sendResponse.tsのヘルパー関数を使ってBad Requestレスポンスを返します。
エンドポイントはボディに以下の情報を必要とします。
- api/transcription/start.json は channel を必要とします
- api/transcription/stop.json は taskId と builderToken を必要とします
すべてが正しく実行されれば、ヘルパー関数を使って成功したレスポンスを送信します。
import type { APIContext } from "astro";
export async function POST({ request }: APIContext) {
const { channel } = await request.json()
if (!channel) {
return sendBadRequest("channel is required")
}
return sendSuccessfulResponse("<return data>")
}
リクエストヘルパー関数の作成
このガイドの残りの部分は、Agora API の呼び出しを含む、Speech-To-Text の実装に焦点を当てます。
コードを単純化し、統一されたリクエスト構造を持つために、utils/makeRequest.ts でヘルパー関数をセットアップします。 makeRequest 関数は、すべてのヘッダを定義し、リクエストを実行し、レスポンスを返します。 入力には、メソッド(GET と POST を使用します)、url、body、そしてクレデンシャルが必要です。
export const makeRequest = async (method: string, url: string, credential: string, body?: string) => {
const headers = new Headers({
"Authorization": "basic " + credential,
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": `${method}, OPTIONS`,
});
const res = await fetch(url, {
method: method,
headers: headers,
body: body
})
if (!res.ok) {
console.log(await res.text())
throw new Error("Failed to make request")
}
return res
}
utils/generateCredential.ts の別のヘルパー関数がこのクレデンシャルを生成します。 これは、Customer IDとCustomer Secretを使用してBase-64エンコードされた認証情報です。
export const generateCredential = () => {
const credential = import.meta.env.CUSTOMER_ID + ":" + import.meta.env.CUSTOMER_SECRET
const base64_credential = btoa(credential)
return base64_credential
}
文字起こしリソースの生成
ビデオ通話を書き起こす最初のステップは、Speech-To-Textリソースを生成することです。
このリソースを生成するために、Agora サービスに最初のリクエストを行います。 これは https://api.agora.io/v1/projects/${appId}/rtsc/speech-to-text/builderTokens というエンドポイントを使用してリソースを作成し、そのリソースの builderToken を返します。 チャンネル名をこのリソースの instanceId として使用します。
これは、書き起こしセッションを開始するときの 2 つのステップのうちの 1 つです。このステップは、Speech-To-Text ボットを開始するためにバックエンドシステムによってのみ使用されるため、ユーザーに公開する必要はありません。
このため、コードを整理しておくために、utils/generateResource.tsファイルでこの関数を定義します。
import { makeRequest } from "./makeRequest"
export const generateSpeechToTextResource = async (channel: string, credential: string, appId: string) => {
const body = {
"instanceId": channel
}
const url = `https://api.agora.io/v1/projects/${appId}/rtsc/speech-to-text/builderTokens`
const res = await makeRequest("POST", url, credential, JSON.stringify(body))
const data = await res.json()
const builderToken = data["tokenName"]
return builderToken
}
文字起こしの開始
上記のセクションをすべて組み合わせると、api/transcription/start.json.ts ファイルのPOSTリクエスト内で転記を開始することができます。
まずクレデンシャルを生成し、そのクレデンシャルを使用してリソースを生成し、2つのUID用に2つのトークンを作成します。
Speech-To-Textは、チャネルに参加してテキストを書き起こすために1つのUIDを必要とし、書き起こされたテキストを呼び戻すためにもう1つのUIDを必要とします。
それから、Agoraエンドポイント https://api.agora.io/v1/projects/${APP_ID}/rtsc/speech-to-text/tasks?builderToken=${builderToken} でリクエストを行い、リクエストボディに書き起こしの設定を渡します。 リクエストボディのプロパティの完全なリストは、Agora Postmanコレクションで見つけることができます。
const botUid = "2"
const outputUid = "3"
const credential = generateCredential()
const builderToken = await generateSpeechToTextResource(channel, credential, APP_ID)
const botToken = await handleGenerateToken({ channel: channel, role: agoraToken.RtcRole.PUBLISHER, uid: botUid, expireTime: 3600 })
const outputToken = await handleGenerateToken({ channel: channel, role: agoraToken.RtcRole.PUBLISHER, uid: outputUid, expireTime: 3600 })
const url = `https://api.agora.io/v1/projects/${APP_ID}/rtsc/speech-to-text/tasks?builderToken=${builderToken}`
const body = {
"languages": [
"en-US"
],
"maxIdleTime": 60,
"rtcConfig": {
"channelName": channel,
"subBotUid": botUid,
"subBotToken": botToken,
"pubBotUid": outputUid,
"pubBotToken": outputToken
}
}
const res = await makeRequest("POST", url, credential, JSON.stringify(body))
const data = await res.json()
const taskId = data.taskId
return sendSuccessfulResponse({
taskId: taskId,
builderToken: builderToken,
})
成功すると、taskId を受け取ります。 taskIdとbuilderTokenの両方は転写を停止するために使用する必要があるので、呼び出し元に返す必要があります。
これをテストするには、npm run dev を使ってバックエンドを実行します。ターミナルで cURL を使って、channel をボディに含む POST リクエストを送ることができます。
curl -X POST http://localhost:4321/api/transcription/start.json \
-H "Content-Type: application/json" \
-d '{
"channel": "test"
}'
POSTリクエストに情報が欠けている場合、何が欠けているかを伝えるBad Requestレスポンスが返されます。 適切なリクエストであれば、次のような正常なレスポンスが返ってきます。
{"taskId":"<long string>","builderToken":"<another long string>"}
文字起こしの停止
転記を停止するには、appID、taskID、および builderToken を含む URL に DELETE リクエストを送信する必要があります。
const credential = generateCredential()
const url = `https://api.agora.io/v1/projects/${APP_ID}/rtsc/speech-to-text/tasks/${taskId}?builderToken=${builderToken}`
const res = await makeRequest("DELETE", url, credential)
const data = await res.json()
return sendSuccessfulResponse(data)
開始と同じ要領で、ターミナルで cURL を使って channel をボディに含む POST リクエストを送ることができます。
curl -X POST "http://localhost:4321/api/transcription/stop.json" \
-H "Content-Type: application/json" \
-d '{
"taskId": "<from start command return>",
"builderToken": "<from start command return>"
}'
POSTリクエストに情報が欠けている場合、何が欠けているかを伝えるBad Requestレスポンスが返されます。 適切なリクエストであれば、空のボディで正常なレスポンスが返されます。
トークンジェネレーターと文字起こし機能バックエンドがAstroに組み込まれたので、以下の記事も参考にフロントエンドを追加して、1つのコードベースですべて録画できる安全なビデオ通話を実現することが可能です。
話題の最新フロントエンドフレームワーク「Astro」とReactJSを使用してビデオ通話アプリを構築する。
Agoraの開発者アカウントを作る(無料トライアル)
Agoraの無料トライアルは利用時間10,000分/月で、開発期間中はずっと無料となっています。(リリース後から料金が発生)Agoraは株式会社ブイキューブが日本代理店となっており、料金など不明点は日本語での対応が可能です。
Agoraの導入について、お気軽にお問い合わせ下さい。
執筆者ブイキューブ