Supabaseでのストリーミングとキャッシュ
Supabaseでのストリーミングとキャッシュ
Supabase Edge Functionsを介して音声を生成・ストリーミングします。音声をSupabase Storageに保存し、組み込みCDNでレスポンスをキャッシュします。
ハウツーガイド · ElevenAPI クイックスタートを完了し、Supabaseアカウントを持っていることを前提としています。
はじめに
このガイドでは、Supabase Edge Functions、Supabase Storage、ElevenLabsを使用して、音声を生成、ストリーミング、保存、キャッシュするエッジAPIを構築する方法を学びます。
必要なもの
- APIキーを持つElevenLabsアカウント。
- Supabaseアカウント(database.newから無料アカウントに登録できます)。
- マシンにインストールされたSupabase CLI。
- マシンにインストールされたDenoランタイム、および任意でお好みのIDEでのセットアップ。
セットアップ
ローカルでSupabaseプロジェクトを作成する
Supabase CLIをインストールしたら、次のコマンドを実行してローカルに新しいSupabaseプロジェクトを作成します。
ストレージバケットを設定する
config.tomlファイルに次の設定を追加すると、Supabase CLIでストレージバケットを自動生成するよう設定できます。
supabase startを実行すると、ローカルのSupabase
プロジェクトに新しいストレージバケットが作成されます。これをホストされているSupabaseプロジェクトにプッシュするには、supabase seed buckets --linkedを実行します。
Supabase Edge Functionsのバックグラウンドタスクを設定する
ローカル開発でSupabase Edge Functionsのバックグラウンドタスクを使用するには、config.tomlファイルに次の設定を追加する必要があります。
per_workerポリシーで実行する場合、Functionは編集時に自動リロードされません。supabase functions serveを実行して、
手動で再起動する必要があります。
音声生成用のSupabase Edge Functionを作成する
次のコマンドを実行して、新しいEdge Functionを作成します。
VS CodeまたはCursorを使用している場合は、CLIで「Generate VS Code settings for Deno? [y/N]」と表示されたらyを選択してください。
環境変数を設定する
supabase/functionsディレクトリ内に新しい.envファイルを作成し、次の変数を追加します。
依存関係
このプロジェクトでは、いくつかの依存関係を使用します。
- Supabaseデータベースを操作するための@supabase/supabase-jsライブラリ。
- テキスト読み上げAPIを操作するためのElevenLabs JavaScript SDK。
- リクエストパラメータからハッシュを生成するためのオープンソースのobject-hash。
Supabase Edge FunctionはDenoランタイムを使用するため、依存関係をインストールする必要はありません。代わりに、npm:プレフィックスを使用してインポートできます。
Supabase Edge Functionを実装する
新しく作成したsupabase/functions/text-to-speech/index.tsファイルに、次のコードを追加します。
コードの詳細
コードには注目すべき点がいくつかあります。順を追って見ていきましょう。
受信リクエストを処理する
受信リクエストを処理するには、Deno.serveハンドラーを使用します。このデモではリクエストのオリジンを検証していませんが、たとえばリクエストのオリジンを検証したり、ユーザーアクセストークンを追加してSupabase Authで検証したりできます。
関数は受信リクエストからtextとvoiceIdパラメータを抽出します。voiceIdパラメータは任意で、デフォルトでは「Allison」音声のElevenLabs IDが使用されます。
object-hashライブラリを使用して、関数はリクエストパラメータからハッシュを生成します。このハッシュは、Supabase Storage内の既存のオーディオファイルを確認するために使用されます。
Supabase Storage内の既存オーディオファイルを確認する
Supabase StorageにはスマートCDNが組み込まれており、ファイルを簡単にキャッシュして配信できます。
ここでは、関数がSupabase Storage内の既存オーディオファイルを確認します。ファイルが存在する場合、関数はSupabase Storageからそのファイルを返します。
音声をストリームとして生成し、2つのブランチに分割する
ElevenLabs APIのストリーミング機能を使用して、関数はストリームを生成します。これにより、大きなテキストでもすぐにユーザーへの音声ストリーミングを開始し、バックグラウンドでストリームをSupabase Storageにアップロードできます。
これにより最高のユーザー体験が実現し、大きなテキストブロックでも驚くほど速く感じられます。ポイントは17行目で、stream.tee()メソッドが読み取り可能なストリームを2つのブランチに分けます。1つはブラウザ用、もう1つはSupabase Storage用です。
バックグラウンドでオーディオストリームをSupabase Storageにアップロードする
前のステップの20行目にあるEdgeRuntime.waitUntilメソッドは、uploadAudioToStorage関数を使用して、バックグラウンドでオーディオストリームをSupabase Storageにアップロードします。これにより、オーディオをSupabase Storageにアップロードしている間も、関数はすぐにストリーミングレスポンスをブラウザに返せます。
ストレージオブジェクトが作成されると、次回ユーザーが同じパラメータでリクエストを行った際、関数はSupabase Storage CDNからオーディオファイルを返します。
ローカルで実行する
ローカルで関数を実行するには、次のコマンドを実行します。
ローカルのSupabaseスタックが起動したら、次のコマンドを実行して関数を起動し、ログを確認します。
試してみる
http://127.0.0.1:54321/functions/v1/text-to-speech?text=hello%20worldにアクセスして、関数の動作を確認します。
その後、http://127.0.0.1:54323/project/default/storage/buckets/audioにアクセスして、ローカルのSupabase Storageバケット内のオーディオファイルを確認します。
Supabaseにデプロイする
まだ作成していない場合は、database.newで新しいSupabaseアカウントを作成し、ローカルプロジェクトをSupabaseアカウントにリンクします。
完了したら、次のコマンドを実行して関数をデプロイします。
関数のシークレットを設定する
ローカルですべてのシークレットを設定したら、次のコマンドを実行してSupabaseプロジェクトにシークレットを設定できます。
関数をテストする
この関数は、<audio>要素のソースとして直接使用できるよう設計されています。