Speech Engineクイックスタート

ElevenLabs SDKを使ってチャットエージェントに音声を追加します。

このガイドでは、Speech Engineを使って音声対応エージェントを構築します。LLMをElevenLabsに接続するサーバーをセットアップし、ユーザーがエージェントと音声で会話できるようにブラウザークライアントを連携させます。

ElevenLabs Speech Engineスキルを使用して、チャットエージェントに音声機能を追加できます。

npx skills add elevenlabs/skills --skill speech-engine

Speech Engineの仕組み

Speech EngineはLLMをElevenLabsに接続し、ユーザーがエージェントに話しかけ、応答を聞けるようにします。ElevenLabsがスピーチtoテキストとテキスト読み上げを処理し、サーバーがLLMロジックを提供します。

各WebSocket接続は1つの会話を表します。ユーザーが話すと、ElevenLabsはオーディオを書き起こし、トランスクリプトをサーバーに送信します。サーバーはそれをLLMに渡し、応答をストリーミングで返します。ElevenLabsはテキストを音声に変換し、ブラウザーで再生します。SDKが接続管理、ターンテイキング、割り込み検出を処理します。

前提条件

このチュートリアルでは、LLMにOpenAIのAPIを使用します。OPENAI_API_KEY環境変数に設定したOpenAI APIキーが必要です。

サーバーのセットアップ

1

APIキーを作成

ダッシュボードでAPIキーを作成し、安全にAPIへアクセスするために使用します。

キーは管理されたシークレットとして保存し、好みに応じて.envファイルによる環境変数として、またはアプリの設定で直接SDKに渡してください。

.env
ELEVENLABS_API_KEY=<your_api_key_here>
2

依存関係をインストール

pip install elevenlabs openai python-dotenv
3

サーバーを公開

Speech Engineには、パブリックからアクセス可能なURLが必要です。ngrokを使用してローカルサーバーを公開します。サーバーはまだ構築していませんが、次の手順で必要になるURLを取得するため、先にngrokを実行しておく必要があります。

ngrok http 3001

転送URL(例:https://abc123.ngrok.io)をコピーします。

4

Speech Engineインスタンスを作成

SDKを使用してSpeech Engineインスタンスを作成します。WebSocket URLには、ngrok URLの末尾に/wsパスを追加して渡します。

import asyncio
from dotenv import load_dotenv
from elevenlabs import AsyncElevenLabs
load_dotenv()
elevenlabs = AsyncElevenLabs(
api_key=os.getenv("ELEVENLABS_API_KEY"),
)
async def main():
engine = await elevenlabs.speech_engine.create(
name="My Speech Engine",
speech_engine={
# Note we use the wss protocol instead of https
"ws_url": "wss://abc123.ngrok.io/ws",
},
)
print(f"Speech Engine ID: {engine.engine_id}")
if __name__ == "__main__":
asyncio.run(main())

このスクリプトを実行し、次の手順で使用するSpeech Engine ID(例:seng_8k3m9xr4hjnfg983brhmhkd98n6)をコピーします。

5

サーバーを作成

server.pyまたはserver.mtsというファイルを作成し、以下の内容を追加します。これによりサーバーをセットアップし、/wsパスにSpeech Engineを接続して、OpenAIで応答を生成します。

import asyncio
import os
from dotenv import load_dotenv
from openai import AsyncOpenAI
from elevenlabs import AsyncElevenLabs
load_dotenv()
# Replace with your Speech Engine ID from step 4
SPEECH_ENGINE_ID = "seng_8k3m9xr4hjnfg983brhmhkd98n6"
openai = AsyncOpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
)
elevenlabs = AsyncElevenLabs(
api_key=os.getenv("ELEVENLABS_API_KEY"),
)
def on_init(conversation_id, session):
print(f"Session started: {conversation_id}")
async def on_transcript(transcript, session):
stream = await openai.responses.create(
model="gpt-4o",
instructions="You are a helpful voice assistant. Keep responses concise and conversational.",
input=[
{"role": "assistant" if m.role == "agent" else m.role, "content": m.content}
for m in transcript
],
stream=True,
)
await session.send_response(stream)
def on_close(session):
print(f"Session ended: {session.conversation_id}")
def on_error(err, session):
print(f"Error: {err}")
async def main():
engine = await elevenlabs.speech_engine.get(SPEECH_ENGINE_ID)
await engine.serve(
port=3001,
path="/ws",
debug=True,
on_init=on_init,
on_transcript=on_transcript,
on_close=on_close,
on_error=on_error,
)
if __name__ == "__main__":
asyncio.run(main())

onTranscript/on_transcriptコールバックは、会話履歴全体と現在のセッションを受け取ります。TypeScript SDKでは、ユーザーが応答の途中で割り込んだ場合に発火するAbortSignalも提供されます。signalをOpenAI呼び出しに渡すと、割り込み時にLLMリクエストを自動的にキャンセルできます。

sendResponse()/send_response()は、文字列、非同期イテラブル、またはOpenAI、Anthropic、Google Geminiからのストリームを受け取ります。SDKがテキストコンテンツを自動的に抽出します。

上記の例では、ユーザーからの完全なトランスクリプトをLLMに渡しています。本番環境では、プロンプトインジェクションや操作の試みを防ぐためのガードレールを追加してください。

6

サーバーを起動

python server.py

クライアントのセットアップ

1

クライアントSDKをインストール

npm install @elevenlabs/react
2

トークンエンドポイントを作成

会話トークンを生成するサーバー側エンドポイントを追加します。これによりAPIキーをブラウザーに公開せず、最高のオーディオ品質を得るためにWebRTCを使用できます。

import os
from dotenv import load_dotenv
from flask import Flask, jsonify
from elevenlabs import ElevenLabs
load_dotenv()
app = Flask(__name__)
elevenlabs = ElevenLabs(
api_key=os.getenv("ELEVENLABS_API_KEY"),
)
@app.route("/api/token")
def get_token():
# Replace with your Speech Engine ID from step 4 of the server setup
speech_engine_id = "seng_8k3m9xr4hjnfg983brhmhkd98n6"
response = elevenlabs.conversational_ai.conversations.get_webrtc_token(
agent_id=speech_engine_id,
)
return jsonify(token=response.token)
if __name__ == "__main__":
app.run(port=3002)
3

会話UIを構築

サーバーから会話トークンを取得し、それを使ってセッションを開始します。

App.tsx
import { useConversation } from "@elevenlabs/react";
import { useCallback } from "react";
async function getToken(): Promise<string> {
const response = await fetch("/api/token");
if (!response.ok) {
throw Error("Failed to get conversation token");
}
const data = await response.json();
return data.token;
}
export default function App() {
const conversation = useConversation({
onConnect: () => console.log("Connected"),
onDisconnect: () => console.log("Disconnected"),
onError: (error: Error) => console.error("Error:", error),
});
const startConversation = useCallback(async () => {
await navigator.mediaDevices.getUserMedia({ audio: true });
const token = await getToken();
await conversation.startSession({ conversationToken: token });
}, [conversation]);
const stopConversation = useCallback(async () => {
await conversation.endSession();
}, [conversation]);
return (
<div>
<p>Status: {conversation.status}</p>
<button onClick={startConversation} disabled={conversation.status === "connected"}>
Start conversation
</button>
<button onClick={stopConversation} disabled={conversation.status !== "connected"}>
End conversation
</button>
</div>
);
}
4

試してみる

次の3つのプロセスが実行されていることを確認します。

  1. ngrok - ポート3001に転送
  2. Speech Engineサーバー - python server.pyまたはnpx tsx server.mts
  3. トークンサーバー - npx tsx token-server.mtsまたはpython token_server.py

ブラウザーでクライアントアプリケーションを開き、Start conversationをクリックします。求められたらマイクへのアクセスを許可して、話しかけてください。スピーカーからエージェントの応答が聞こえます。

サーバーでdebug: trueを有効にしている場合は、受信したトランスクリプトと送信した応答がコンソールに記録されます。

セッションイベント

イベントTypeScriptコールバックPythonコールバック説明
user_transcriptonTranscripton_transcriptユーザー音声を書き起こし。会話履歴全体と中断シグナルを含みます。
initonIniton_init会話IDとともにセッションを初期化。
closeonCloseon_closeElevenLabsから正常に切断。
disconnectedonDisconnecton_disconnectWebSocketが予期せず切断。
erroronErroron_errorプロトコルまたはWebSocketのエラー。

エージェントの最初のメッセージを設定

デフォルトでは、エージェントはユーザーが先に話すのを待ちます。会話開始時にエージェントからユーザーに挨拶させるには、セッション開始時にクライアントのoverridesオプションで最初のメッセージを設定します。

1

エージェントが先に話せるようにするには、クライアントからこの設定を行えるよう、Speech Engineリソースを更新する必要があります。

engine = await elevenlabs.speech_engine.update(
speech_engine_id="seng_8k3m9xr4hjnfg983brhmhkd98n6",
overrides={
"first_message": True,
},
)
2

次に、クライアントSDKで最初のメッセージを設定します。

conversation.startSession({
conversationToken: token,
overrides: {
agent: {
firstMessage: "Hello! How can I help you today?",
},
},
});

接続が確立されるとすぐに、エージェントが最初のメッセージを読み上げます。これはサーバーのonTranscriptコールバックをトリガーしません。すべてElevenLabs側で処理されます。

次のステップ