Vite (JavaScript)

Aprenda a criar uma aplicação web que permite conversas por voz com agentes de IA da ElevenLabs

Este tutorial vai orientar você na criação de um cliente web que pode interagir com um agente da ElevenLabs. Você aprenderá a implementar conversas por voz em tempo real, permitindo que os usuários falem com um agente de IA capaz de ouvir, entender e responder naturalmente usando síntese de voz.

Quer criar com React/Next.js? Confira nosso guia do Next.js

O que você vai precisar

  1. Um agente da ElevenLabs criado seguindo este guia
  2. npm instalado no seu sistema local
  3. Conhecimentos básicos de JavaScript

Configuração do projeto

1

Criar um diretório para o projeto

Abra um terminal e crie um novo diretório para seu projeto:

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

Inicializar o npm e instalar dependências

Inicialize um novo projeto npm e instale os pacotes necessários:

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

Configurar a estrutura básica do projeto

Adicione isto ao seu package.json:

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

Crie a seguinte estrutura de arquivos:

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

Implementar a interface de chat por voz

1

Criar a interface HTML

Em index.html, configure uma interface de usuário simples:

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

Implementar a lógica da conversa

Em script.js, implemente a funcionalidade:

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

Iniciar o servidor do frontend

npm run dev:frontend
Substitua 'YOUR_AGENT_ID' pelo ID real do seu agente na ElevenLabs.

Esta etapa de autenticação é necessária apenas para agentes privados. Se você estiver usando um agente público, pode pular esta seção e usar diretamente o agentId na chamada startSession.

1

Criar variáveis de ambiente

Crie um arquivo .env na raiz do seu projeto:

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

Adicione .env ao seu arquivo .gitignore para evitar o commit acidental de credenciais sensíveis.

2

Configurar o backend

  1. Instale dependências adicionais:
npm install express cors dotenv
  1. Crie uma nova pasta chamada backend:
elevenlabs-conversational-ai/
├── backend
...
3

Criar o servidor

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

Atualizar o código do cliente

Modifique seu script.js para buscar e usar a URL assinada:

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 ...

As URLs assinadas expiram após um curto período. No entanto, todas as conversas iniciadas antes da expiração continuarão sem interrupções. Em um ambiente de produção, implemente o tratamento adequado de erros e a lógica de atualização de URL para iniciar novas conversas.

5

Atualizar o package.json

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

Executar a aplicação

Inicie a aplicação com:

npm run dev

Próximas etapas

Agora que você tem uma implementação básica, pode:

  1. Adicionar feedback visual para a atividade de voz
  2. Implementar tratamento de erros e lógica de repetição
  3. Adicionar uma exibição do histórico de chat
  4. Personalizar a interface para combinar com sua marca

Para recursos mais avançados e opções de personalização, confira o pacote @elevenlabs/client.