Vite(JavaScript)

ElevenLabs AIエージェントと音声会話できるWebアプリケーションの作成方法

このチュートリアルでは、ElevenLabsエージェントとやり取りできるWebクライアントを作成します。リアルタイムの音声会話を実装し、ユーザーが音声合成を使って聞き取り、理解し、自然に応答できるAIエージェントと会話する方法を学びます。

React/Next.jsで構築したい場合は、Next.js ガイドをご覧ください。

必要なもの

  1. このガイドに従って作成したElevenLabsエージェント
  2. ローカルシステムにインストールされたnpm
  3. JavaScriptの基本知識

プロジェクトのセットアップ

1

プロジェクトディレクトリを作成

ターミナルを開き、プロジェクト用の新しいディレクトリを作成します:

mkdir elevenlabs-conversational-ai
cd elevenlabs-conversational-ai
2

npmを初期化して依存関係をインストール

新しいnpmプロジェクトを初期化し、必要なパッケージをインストールします:

npm init -y
npm install vite @elevenlabs/client
3

基本的なプロジェクト構成を設定

package.jsonに以下を追加します:

package.json
{
"scripts": {
...
"dev:frontend": "vite"
}
}

次のファイル構成を作成します:

elevenlabs-conversational-ai/
├── index.html
├── script.js
├── package-lock.json
├── package.json
└── node_modules

音声チャットインターフェースの実装

1

HTMLインターフェースを作成

index.htmlで、シンプルなユーザーインターフェースを設定します:

index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ElevenLabs Agents</title>
</head>
<body style="font-family: Arial, sans-serif; text-align: center; padding: 50px;">
<h1>ElevenLabs Agents</h1>
<div style="margin-bottom: 20px;">
<button id="startButton" style="padding: 10px 20px; margin: 5px;">Start Conversation</button>
<button id="stopButton" style="padding: 10px 20px; margin: 5px;" disabled>Stop Conversation</button>
</div>
<div style="font-size: 18px;">
<p>Status: <span id="connectionStatus">Disconnected</span></p>
<p>Agent is <span id="agentStatus">listening</span></p>
</div>
<script type="module" src="../images/script.js"></script>
</body>
</html>
2

会話ロジックを実装

script.jsに機能を実装します:

script.js
import { Conversation } from '@elevenlabs/client';
const startButton = document.getElementById('startButton');
const stopButton = document.getElementById('stopButton');
const connectionStatus = document.getElementById('connectionStatus');
const agentStatus = document.getElementById('agentStatus');
let conversation;
async function startConversation() {
try {
// Request microphone permission
await navigator.mediaDevices.getUserMedia({ audio: true });
// Start the conversation
conversation = await Conversation.startSession({
agentId: 'YOUR_AGENT_ID', // Replace with your agent ID
onConnect: () => {
connectionStatus.textContent = 'Connected';
startButton.disabled = true;
stopButton.disabled = false;
},
onDisconnect: () => {
connectionStatus.textContent = 'Disconnected';
startButton.disabled = false;
stopButton.disabled = true;
},
onError: (error) => {
console.error('Error:', error);
},
onModeChange: (mode) => {
agentStatus.textContent = mode.mode === 'speaking' ? 'speaking' : 'listening';
},
});
} catch (error) {
console.error('Failed to start conversation:', error);
}
}
async function stopConversation() {
if (conversation) {
await conversation.endSession();
conversation = null;
}
}
startButton.addEventListener('click', startConversation);
stopButton.addEventListener('click', stopConversation);
3

フロントエンドサーバーを起動

npm run dev:frontend
'YOUR_AGENT_ID'をElevenLabsの実際のエージェントIDに置き換えてください。

この認証手順は、プライベートエージェントにのみ必要です。パブリックエージェントを使用している場合は、このセクションをスキップして、startSession呼び出しで直接agentIdを使用できます。

1

環境変数を作成

プロジェクトルートに.envファイルを作成します:

.env
ELEVENLABS_API_KEY=your-api-key-here
AGENT_ID=your-agent-id-here

機密性の高い認証情報を誤ってコミットしないよう、.envを.gitignoreファイルに必ず追加してください。

2

バックエンドをセットアップ

  1. 追加の依存関係をインストールします:
npm install express cors dotenv
  1. backendという新しいフォルダを作成します:
elevenlabs-conversational-ai/
├── backend
...
3

サーバーを作成

backend/server.js
require("dotenv").config();
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
app.use(express.json());
const PORT = process.env.PORT || 3001;
app.get("/api/get-signed-url", async (req, res) => {
try {
const response = await fetch(
`https://api.elevenlabs.io/v1/convai/conversation/get-signed-url?agent_id=${process.env.AGENT_ID}`,
{
headers: {
"xi-api-key": process.env.ELEVENLABS_API_KEY,
},
}
);
if (!response.ok) {
throw new Error("Failed to get signed URL");
}
const data = await response.json();
res.json({ signedUrl: data.signed_url });
} catch (error) {
console.error("Error:", error);
res.status(500).json({ error: "Failed to generate signed URL" });
}
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
4

クライアントコードを更新

署名付きURLを取得して使用するよう、script.jsを変更します:

script.js
// ... existing imports and variables ...
async function getSignedUrl() {
const response = await fetch('http://localhost:3001/api/get-signed-url');
if (!response.ok) {
throw new Error(`Failed to get signed url: ${response.statusText}`);
}
const { signedUrl } = await response.json();
return signedUrl;
}
async function startConversation() {
try {
await navigator.mediaDevices.getUserMedia({ audio: true });
const signedUrl = await getSignedUrl();
conversation = await Conversation.startSession({
signedUrl,
// agentId has been removed...
onConnect: () => {
connectionStatus.textContent = 'Connected';
startButton.disabled = true;
stopButton.disabled = false;
},
onDisconnect: () => {
connectionStatus.textContent = 'Disconnected';
startButton.disabled = false;
stopButton.disabled = true;
},
onError: (error) => {
console.error('Error:', error);
},
onModeChange: (mode) => {
agentStatus.textContent = mode.mode === 'speaking' ? 'speaking' : 'listening';
},
});
} catch (error) {
console.error('Failed to start conversation:', error);
}
}
// ... rest of the code ...

署名付きURLは短時間で有効期限が切れます。ただし、有効期限前に開始された会話は中断されずに続行されます。本番環境では、新しい会話を開始するための適切なエラー処理とURL更新ロジックを実装してください。

5

package.jsonを更新

package.json
{
"scripts": {
...
"dev:backend": "node backend/server.js",
"dev": "npm run dev:frontend & npm run dev:backend"
}
}
6

アプリケーションを実行

次のコマンドでアプリケーションを起動します:

npm run dev

次のステップ

基本的な実装ができたので、次のことができます:

  1. 音声アクティビティの視覚的フィードバックを追加する
  2. エラー処理と再試行ロジックを実装する
  3. チャット履歴の表示を追加する
  4. ブランドに合わせてUIをカスタマイズする

より高度な機能やカスタマイズオプションについては、 @elevenlabs/clientパッケージをご覧ください。