> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# Next.JS

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

## 必要なもの

1. [このガイド](/docs/ja/eleven-agents/quickstart)に従って作成したElevenLabsエージェント
2. ローカルシステムにインストールされた`npm`
3. このチュートリアルではTypescriptを使用しますが、必要に応じてJavascriptも使用できます。

> **Note**
>
> 完全な例をお探しですか？GitHubの[Next.jsデモ ](https://github.com/elevenlabs/examples/tree/main/agents/nextjs/quickstart)をご覧ください。

![](/docs/_fern-img/c1bc26a84d079cebcdfe6b4eb602bd27476d5afc92419e9ddfb92b755ca8058e.webp)

## セットアップ

#### 新しいNext.jsプロジェクトを作成

ターミナルウィンドウを開き、次のコマンドを実行します。

```bash
npm create next-app my-conversational-agent
```

プロジェクトの構築方法についていくつか質問されます。このチュートリアルでは、デフォルトの推奨設定に従います。

#### プロジェクトディレクトリに移動

```shell
cd my-conversational-agent
```

#### ElevenLabs依存関係をインストール

```shell
npm install @elevenlabs/react
```

#### セットアップをテスト

次のコマンドを実行して開発サーバーを起動し、表示されたURLをブラウザで開きます。

```shell
npm run dev
```

![](/docs/_fern-img/537e2c5609df75b2fd15bf3a37c86da75410de053dfb0c76267a72d7b8d9914a.webp)

## ElevenLabs Agentsを実装

#### 会話コンポーネントを作成

新しいファイル`app/components/conversation.tsx`を作成します。

**`app/components/conversation.tsx`**

```tsx app/components/conversation.tsx
'use client';

import { useConversation } from '@elevenlabs/react';
import { useCallback } from 'react';

export function Conversation() {
  const conversation = useConversation({
    onConnect: () => console.log('Connected'),
    onDisconnect: () => console.log('Disconnected'),
    onMessage: (message) => console.log('Message:', message),
    onError: (error) => console.error('Error:', error),
  });


  const startConversation = useCallback(async () => {
    try {
      // Request microphone permission
      await navigator.mediaDevices.getUserMedia({ audio: true });

      // Start the conversation with your agent
      await conversation.startSession({
        agentId: 'YOUR_AGENT_ID', // Replace with your agent ID
        userId: 'YOUR_CUSTOMER_USER_ID', // Optional field for tracking your end user IDs
      });

    } catch (error) {
      console.error('Failed to start conversation:', error);
    }
  }, [conversation]);

  const stopConversation = useCallback(async () => {
    await conversation.endSession();
  }, [conversation]);

  return (
    <div className="flex flex-col items-center gap-4">
      <div className="flex gap-2">
        <button
          onClick={startConversation}
          disabled={conversation.status === 'connected'}
          className="px-4 py-2 bg-blue-500 text-white rounded disabled:bg-gray-300"
        >
          Start Conversation
        </button>
        <button
          onClick={stopConversation}
          disabled={conversation.status !== 'connected'}
          className="px-4 py-2 bg-red-500 text-white rounded disabled:bg-gray-300"
        >
          Stop Conversation
        </button>
      </div>

      <div className="flex flex-col items-center">
        <p>Status: {conversation.status}</p>
        <p>Agent is {conversation.isSpeaking ? 'speaking' : 'listening'}</p>
      </div>
    </div>
  );
}
```

#### メインページを更新

`app/page.tsx`の内容を次のように置き換えます。

**`app/page.tsx`**

```tsx app/page.tsx
'use client';

import { ConversationProvider } from '@elevenlabs/react';
import { Conversation } from './components/conversation';

export default function Home() {
  return (
    <ConversationProvider>
      <main className="flex min-h-screen flex-col items-center justify-between p-24">
        <div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm">
          <h1 className="text-4xl font-bold mb-8 text-center">
            ElevenLabs Agents
          </h1>
          <Conversation />
        </div>
      </main>
    </ConversationProvider>
  );
}
```

#### （任意）署名付きURLでエージェントを認証

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

認証が必要なプライベートエージェントを使用する場合は、サーバーで署名付きURLを生成する必要があります。このセクションでは、その設定方法を説明します。

### 必要なもの

1. ElevenLabsアカウントとAPIキー。[こちら](https://elevenlabs.io/app/sign-up)から登録してください。

#### 環境変数を作成

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

**`.env.local`**

```yaml .env.local
ELEVENLABS_API_KEY=your-api-key-here
NEXT_PUBLIC_AGENT_ID=your-agent-id-here
```

> **Warning**
>
> 1. 機密性の高い認証情報を誤ってバージョン管理にコミットしないよう、`.env.local`を`.gitignore`ファイルに追加してください。
> 2. クライアントサイドのコードでAPIキーを公開しないでください。必ずサーバー上で安全に保管してください。

#### APIルートを作成

新しいファイル`app/api/get-signed-url/route.ts`を作成します。

**`app/api/get-signed-url/route.ts`**

```tsx app/api/get-signed-url/route.ts
import { NextResponse } from 'next/server';

export async function GET() {
  try {
    const response = await fetch(
      `https://api.elevenlabs.io/v1/convai/conversation/get-signed-url?agent_id=${process.env.NEXT_PUBLIC_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();
    return NextResponse.json({ signedUrl: data.signed_url });
  } catch (error) {
    return NextResponse.json(
      { error: 'Failed to generate signed URL' },
      { status: 500 }
    );
  }
}
```

#### Conversationコンポーネントを更新

`conversation.tsx`を変更して、署名付きURLを取得・使用します。

**`app/components/conversation.tsx`**

```tsx app/components/conversation.tsx {5-12,19,23}
// ... existing imports ...

export function Conversation() {
  // ... existing conversation setup ...
  const getSignedUrl = async (): Promise<string> => {
    const response = await fetch("/api/get-signed-url");
    if (!response.ok) {
      throw new Error(`Failed to get signed url: ${response.statusText}`);
    }
    const { signedUrl } = await response.json();
    return signedUrl;
  };

  const startConversation = useCallback(async () => {
    try {
      // Request microphone permission
      await navigator.mediaDevices.getUserMedia({ audio: true });

      const signedUrl = await getSignedUrl();

      // Start the conversation with your signed url
      await conversation.startSession({
        signedUrl,
      });

    } catch (error) {
      console.error('Failed to start conversation:', error);
    }
  }, [conversation]);

  // ... rest of the component ...
}
```

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

## 次のステップ

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

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

> **Info**
>
> より高度な機能とカスタマイズオプションについては、
> [@elevenlabs/react](https://www.npmjs.com/package/@elevenlabs/react)パッケージをご覧ください。