Generiertes Audio über Twilio senden

Erfahren Sie, wie Sie generierte Sprache mit Twilio in Telefonanrufe integrieren.

Anleitung · Setzt voraus, dass Sie den ElevenAPI- Schnellstart abgeschlossen haben und über ein Twilio-Konto verfügen.

In dieser Anleitung erfahren Sie, wie Sie mit Twilio und ElevenLabs eine KI-generierte Nachricht über einen Telefonanruf senden. So können Sie Ihren Anrufern hochwertige Sprachnachrichten direkt übermitteln.

Konten bei Twilio und ngrok erstellen

Für diese Anleitung verwenden wir Twilio und ngrok. Erstellen Sie daher Konten bei beiden.

Server mit Express erstellen

Projekt initialisieren

Erstellen Sie einen neuen Ordner für Ihr Projekt.

mkdir elevenlabs-twilio
cd elevenlabs-twilio
npm init -y

Abhängigkeiten installieren

npm install @elevenlabs/elevenlabs-js express express-ws twilio

Entwicklungsabhängigkeiten installieren

npm i @types/node @types/express @types/express-ws @types/ws dotenv tsx typescript

Dateien erstellen

// src/app.ts
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import "dotenv/config";
import express, { Response } from "express";
import ExpressWs from "express-ws";
import { Readable } from "stream";
import VoiceResponse from "twilio/lib/twiml/VoiceResponse";
import { type WebSocket } from "ws";
const app = ExpressWs(express()).app;
const PORT: number = parseInt(process.env.PORT || "5000");
const elevenlabs = new ElevenLabsClient();
const voiceId = "aMSt68OGf4xUZAnLpTU8";
const outputFormat = "ulaw_8000";
const text = "This is a test. You can now hang up. Thank you.";
function startApp() {
app.post("/call/incoming", (_, res: Response) => {
const twiml = new VoiceResponse();
twiml.connect().stream({
url: `wss://${process.env.SERVER_DOMAIN}/call/connection`,
});
res.writeHead(200, { "Content-Type": "text/xml" });
res.end(twiml.toString());
});
app.ws("/call/connection", (ws: WebSocket) => {
ws.on("message", async (data: string) => {
const message: {
event: string;
start?: { streamSid: string; callSid: string };
} = JSON.parse(data);
if (message.event === "start" && message.start) {
const streamSid = message.start.streamSid;
const response = await elevenlabs.textToSpeech.convert(voiceId, {
modelId: "eleven_flash_v2_5",
outputFormat: outputFormat,
text,
});
const readableStream = Readable.from(response);
const audioArrayBuffer = await streamToArrayBuffer(readableStream);
ws.send(
JSON.stringify({
streamSid,
event: "media",
media: {
payload: Buffer.from(audioArrayBuffer as any).toString("base64"),
},
})
);
}
});
ws.on("error", console.error);
});
app.listen(PORT, () => {
console.log(`Local: http://localhost:${PORT}`);
console.log(`Remote: https://${process.env.SERVER_DOMAIN}`);
});
}
function streamToArrayBuffer(readableStream: Readable) {
return new Promise((resolve, reject) => {
const chunks: Buffer[] = [];
readableStream.on("data", (chunk) => {
chunks.push(chunk);
});
readableStream.on("end", () => {
resolve(Buffer.concat(chunks).buffer);
});
readableStream.on("error", reject);
});
}
startApp();
# .env
SERVER_DOMAIN=
ELEVENLABS_API_KEY=

Code verstehen

Eingehenden Anruf verarbeiten

Wenn Sie Ihre Nummer anrufen, sendet Twilio eine POST-Anfrage an Ihren Endpunkt unter /call/incoming. Anschließend verwenden wir twiml.connect, um Twilio mitzuteilen, dass wir den Anruf über unseren WebSocket verarbeiten möchten. Dazu setzen wir die URL auf unseren Endpunkt /call/connection.

function startApp() {
app.post('/call/incoming', (_, res: Response) => {
const twiml = new VoiceResponse();
twiml.connect().stream({
url: `wss://${process.env.SERVER_DOMAIN}/call/connection`,
});
res.writeHead(200, { 'Content-Type': 'text/xml' });
res.end(twiml.toString());
});

Text to Speech erstellen

Hier hören wir auf Nachrichten, die Twilio an unseren WebSocket-Endpunkt sendet. Wenn wir ein start-Nachrichtenereignis erhalten, generieren wir Audio mit dem ElevenLabs-TypeScript SDK.

app.ws('/call/connection', (ws: WebSocket) => {
ws.on('message', async (data: string) => {
const message: {
event: string;
start?: { streamSid: string; callSid: string };
} = JSON.parse(data);
if (message.event === 'start' && message.start) {
const streamSid = message.start.streamSid;
const response = await elevenlabs.textToSpeech.convert(voiceId, {
modelId: 'eleven_flash_v2_5',
outputFormat: outputFormat,
text,
});

Nachricht senden

Sobald wir das Audio von ElevenLabs zurückerhalten, wandeln wir es in einen Array-Buffer um und senden es über den WebSocket an Twilio.

const readableStream = Readable.from(response);
const audioArrayBuffer = await streamToArrayBuffer(readableStream);
ws.send(
JSON.stringify({
streamSid,
event: "media",
media: {
payload: Buffer.from(audioArrayBuffer as any).toString("base64"),
},
})
);

ngrok auf Ihre Anwendung verweisen

Twilio benötigt eine öffentlich zugängliche URL. Mit ngrok leiten wir den lokalen Port unserer Anwendung weiter und stellen ihn als öffentliche URL bereit.

Führen Sie folgenden Befehl im Terminal aus:

ngrok http 5000

Kopieren Sie die ngrok-Domain (ohne https://), um sie in Ihren Umgebungsvariablen zu verwenden.

Umgebungsvariablen aktualisieren

Aktualisieren Sie die .env-Datei mit Ihrer ngrok-Domain und dem ElevenLabs-API-Schlüssel.

# .env
SERVER_DOMAIN=*******.ngrok.app
ELEVENLABS_API_KEY=*************************

Anwendung starten

Führen Sie folgenden Befehl aus, um die App zu starten:

npm run dev

Twilio einrichten

Folgen Sie den Anleitungen von Twilio, um eine neue Nummer zu erstellen. Nachdem Sie Ihre Nummer erstellt haben, navigieren Sie zum Tab „Configure“ unter Phone Numbers -> Manage -> Active numbers.

Geben Sie im Abschnitt „A call comes in“ die vollständige URL Ihrer Anwendung ein (achten Sie darauf, den Pfad /call/incoming hinzuzufügen):

Beispiel: https://***ngrok.app/call/incoming

Telefonanruf tätigen

Rufen Sie Ihre Nummer an. Sie sollten eine Nachricht mit der ElevenLabs-Stimme hören.

Tipps für die Bereitstellung in Produktion

Wenn Sie die Anwendung in Produktion ausführen, legen Sie die Umgebungsvariable SERVER_DOMAIN auf die Domain Ihres Servers fest. Aktualisieren Sie auch die URL in Twilio, damit sie auf Ihren Produktionsserver verweist.

Fazit

Sie sollten nun ein grundlegendes Verständnis für die Integration von Twilio mit ElevenLabs-Stimmen haben. Wenn Sie weitere Fragen oder Vorschläge zur Verbesserung dieses Blogbeitrags haben, wählen Sie unten gerne die Schaltfläche „Suggest edits“ oder „Raise issue“ aus.