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

# JavaScript SDK 参考文档

本页介绍 Speech Engine JavaScript SDK（`@elevenlabs/elevenlabs-js`）的公共 API。

## 获取 Speech Engine 资源

通过引擎 ID 获取 `SpeechEngineResource`。返回的对象提供了挂载到现有 HTTP 服务器、启动独立服务器或创建单个会话的方法。

```typescript
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient();
const engine = await elevenlabs.speechEngine.get("seng_8k3m9xr4hjnfg983brhmhkd98n6");
```

## SpeechEngineResource

### 属性

| 属性         | 类型       | 说明        |
| ---------- | -------- | --------- |
| `engineId` | `string` | 语音引擎的 ID。 |

### attach

挂载到现有 Node.js HTTP 服务器，并开始在指定路径接受 Speech Engine 连接。如果你已有 HTTP 服务器（例如 Express、Fastify 或普通的 `http.createServer()`），并想在现有路由之外添加 Speech Engine，请使用此方法。

自动处理 WebSocket 升级、路径路由和请求验证。返回 `SpeechEngineAttachment`，其 `close()` 方法会停止接受连接，不会影响 HTTP 服务器。

```typescript
const attachment = engine.attach(httpServer, "/ws", {
  debug: true,
  onTranscript(transcript, signal, session) {
    session.sendResponse(stream);
  },
});
```

| 参数           | 类型                      | 说明                         |
| ------------ | ----------------------- | -------------------------- |
| `httpServer` | `http.Server`           | 要挂载的 Node.js HTTP 服务器。     |
| `path`       | `string`                | 用于处理 WebSocket 升级的 URL 路径。 |
| `handler`    | `SpeechEngineCallbacks` | 回调对象（参见 [回调](#callbacks)）。 |

客户端也提供快捷方法，可将 `get()` 和 `attach()` 合并为一次调用：

```typescript
await elevenlabs.speechEngine.attach("seng_8k3m9xr4hjnfg983brhmhkd98n6", httpServer, "/ws", {
  onTranscript(transcript, signal, session) {
    session.sendResponse(stream);
  },
});
```

### verifyRequest

验证传入请求是否来自 ElevenLabs Speech Engine API。检查 `X-Elevenlabs-Speech-Engine-Authorization` 标头中是否包含使用 API 密钥 SHA-256 哈希签名的有效 JWT。

仅在自行管理 WebSocket 升级时需要使用。使用 `attach()` 或 `SpeechEngineServer` 时，会自动完成验证。

```typescript
const isValid = await engine.verifyRequest(req);
```

| 参数    | 类型                                                             | 说明             |
| ----- | -------------------------------------------------------------- | -------------- |
| `req` | `{ headers: Record<string, string \| string[] \| undefined> }` | 传入的 HTTP 请求对象。 |

**返回值：** `Promise<boolean>` — 请求有效时为 `true`。

### createSession

将已接受的 WebSocket 包装为 `SpeechEngineSession`。适用于自定义服务器集成或手动处理 WebSocket。

```typescript
const session = engine.createSession(ws, { debug: true });
session.on("user_transcript", (transcript, signal) => {
  /* ... */
});
```

| 参数              | 类型        | 默认值     | 说明                 |
| --------------- | --------- | ------- | ------------------ |
| `ws`            | WebSocket |         | 已接受的 WebSocket 连接。 |
| `options.debug` | `boolean` | `false` | 启用调试日志。            |

**返回值：** `SpeechEngineSession`

## SpeechEngineServer

独立的 WebSocket 服务器，无需现有 HTTP 服务器即可接受 Speech Engine 连接。如果服务器仅用于处理 Speech Engine 连接，请使用此服务器。

如需与现有 HTTP 服务器（例如 Express、Fastify）集成，请改用 [`engine.attach()`](#attach)。

```typescript
import { SpeechEngine } from "@elevenlabs/elevenlabs-js";

const server = new SpeechEngine.Server({
  port: 3001,
  debug: true,
  onTranscript(transcript, signal, session) {
    session.sendResponse(stream);
  },
});

server.start();
```

### 构造函数选项

| 参数         | 类型                      | 默认值    | 说明                                                                                                            |
| ---------- | ----------------------- | ------ | ------------------------------------------------------------------------------------------------------------- |
| `port`     | `number`                | `3001` | 监听端口。                                                                                                         |
| `apiKey`   | `string`                |        | 用于验证连接的 ElevenLabs API 密钥。会回退到 `ELEVENLABS_API_KEY` 环境变量。`disableAuth` 为 `true` 时无需提供。                        |
| `engineId` | `string`                |        | 语音引擎 ID。通过资源创建时会自动填充。                                                                                         |
| ...        | `SpeechEngineCallbacks` |        | 所有回调选项（`onInit`、`onTranscript`、`onClose`、`onDisconnect`、`onError`、`debug`、`disableAuth`）。参见 [回调](#callbacks)。 |

### start

在配置的端口启动独立 WebSocket 服务器。除非设置了 `disableAuth: true`，否则会使用配置的 API 密钥通过 ElevenLabs API 验证每个传入连接。

```typescript
server.start();
```

### stop

停止 WebSocket 服务器并关闭所有活跃连接。

```typescript
await server.stop();
```

### handleConnection

使用服务器已连接的回调，将现有 WebSocket 包装为 `SpeechEngineSession`。如果你自行管理 WebSocket 服务器并希望包装单个连接，请使用此方法。

```typescript
const session = server.handleConnection(ws);
```

| 参数   | 类型          | 说明                 |
| ---- | ----------- | ------------------ |
| `ws` | `WebSocket` | 已接受的 WebSocket 连接。 |

**返回值：** `SpeechEngineSession`

## SpeechEngineSession

包装单个 WebSocket 连接。每个连接代表一段对话。会话会针对转录和生命周期变更触发事件，并提供将 LLM 响应发回的方法。

收到新的转录时，之前转录处理程序的中止信号会触发，从而中断正在进行的 LLM 调用。

### 属性

| 属性               | 类型        | 说明                       |
| ---------------- | --------- | ------------------------ |
| `conversationId` | `string`  | API 分配的对话 ID。`init` 后可用。 |
| `isOpen`         | `boolean` | 会话是否仍处于打开状态。             |

### on

为事件注册处理程序。返回会话以便链式调用。

```typescript
session.on("user_transcript", (transcript, signal) => {
  /* ... */
});
```

### off

移除之前注册的处理程序。

```typescript
session.off("user_transcript", listener);
```

### once

注册仅触发一次后自动移除的处理程序。

```typescript
session.once("init", (conversationId) => {
  /* ... */
});
```

### sendResponse

将 LLM 响应发回 Speech Engine API 进行文本转语音合成。必须在 `onTranscript` 处理程序内调用。在处理程序外调用会发出警告并直接返回，不会发送响应。

```typescript
// String response
session.sendResponse("Hello, how can I help?");

// Streamed response (OpenAI, Anthropic, or Gemini)
const stream = await openai.responses.create(
  { model: "gpt-4o", input: messages, stream: true },
  { signal }
);
session.sendResponse(stream);
```

| 参数         | 类型                                   | 说明                               |
| ---------- | ------------------------------------ | -------------------------------- |
| `response` | `string` \| `AsyncIterable<unknown>` | 完整字符串，或由文本块 / LLM 流事件组成的异步可迭代对象。 |

SDK 会自动检测并从以下 LLM 流格式中提取文本：

| 提供商                     | 事件格式                                                                           |
| ----------------------- | ------------------------------------------------------------------------------ |
| OpenAI Responses API    | `{ type: "response.output_text.delta", delta: "text" }`                        |
| OpenAI Chat Completions | `{ choices: [{ delta: { content: "text" } }] }`                                |
| Anthropic Messages API  | `{ type: "content_block_delta", delta: { type: "text_delta", text: "text" } }` |
| Google Gemini API       | `{ candidates: [{ content: { parts: [{ text: "text" }] } }] }`                 |

### close

关闭会话及底层 WebSocket 连接。

```typescript
session.close();
```

## SpeechEngineAttachment

由 `engine.attach()` 返回。用于控制 WebSocket 服务器的生命周期，不会影响其挂载的 HTTP 服务器。

### close

停止接受新连接，从 HTTP 服务器移除升级监听器，并关闭底层 WebSocket 服务器。

```typescript
await attachment.close();
```

## 回调

传递给 `attach()` 或 `SpeechEngineServer` 的回调对象。所有回调均为可选。

| 回调             | 签名                                                                                 | 说明                                                     |
| -------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------ |
| `onInit`       | `(conversationId: string, session: Session) => void`                               | 使用对话 ID 初始化会话。                                         |
| `onTranscript` | `(transcript: TranscriptMessage[], signal: AbortSignal, session: Session) => void` | 已转录用户语音。                                               |
| `onClose`      | `(session: Session) => void`                                                       | 与 ElevenLabs 正常断开连接。                                   |
| `onDisconnect` | `(session: Session) => void`                                                       | WebSocket 意外断开。                                        |
| `onError`      | `(error: Error, session: Session) => void`                                         | 协议或 WebSocket 错误。                                      |
| `debug`        | `boolean`                                                                          | 启用调试日志。                                                |
| `disableAuth`  | `boolean`                                                                          | 跳过传入连接的 JWT 验证。参见 [禁用身份验证](#disabling-authentication)。 |

当用户在响应过程中中断时，`onTranscript` 处理程序接收的 `AbortSignal` 会触发。

### 禁用身份验证

默认情况下，`attach()` 和 `SpeechEngineServer` 都会验证每个传入连接的 `X-Elevenlabs-Speech-Engine-Authorization` 标头。如果服务器位于基础设施层之后，且该层已将传入流量限制为仅来自 ElevenLabs（通常是限定为 [ElevenLabs 出站 IP 范围](/docs/zh/eleven-api/resources/ip-allowlisting) 的 IP 允许列表），可通过传入 `disableAuth: true` 跳过 JWT 验证：

```typescript
// Standalone — no apiKey required when disableAuth is true
new SpeechEngine.Server({ port: 3001, disableAuth: true, onTranscript }).start();

// Or on attach
elevenlabs.speechEngine.attach("seng_8k3m9xr4hjnfg983brhmhkd98n6", httpServer, "/ws", {
  disableAuth: true,
  onTranscript,
});
```

禁用身份验证后，服务器会接受所有能够访问它的客户端，并在启动时输出 `console.warn`。

> **Warning**
>
> 仅当服务器前方配置了 IP 允许列表、自定义标头值或等效的
> 网络级限制时，才可使用 `disableAuth: true`。否则，互联网上的任何人都可以打开
> 会话并消耗计算资源及下游 LLM 配额。

## 事件

如果直接使用 `session.on()` 而非回调，以下是事件名称及其处理程序签名。

| 事件                | 处理程序签名                                                   |
| ----------------- | -------------------------------------------------------- |
| `user_transcript` | `(transcript: TranscriptMessage[], signal: AbortSignal)` |
| `init`            | `(conversationId: string)`                               |
| `close`           | `()`                                                     |
| `disconnected`    | `()`                                                     |
| `error`           | `(error: Error)`                                         |

提供事件名称常量以支持类型安全的使用方式：

```typescript
import { SpeechEngine } from "@elevenlabs/elevenlabs-js";

session.on(SpeechEngine.USER_TRANSCRIPT, (transcript, signal) => {
  /* ... */
});
```

## TranscriptMessage

对话历史中的一条消息。每轮对话都会将完整转录传递给 `onTranscript`。

| 属性        | 类型                    | 说明       |
| --------- | --------------------- | -------- |
| `role`    | `"user"` \| `"agent"` | 消息发送者。   |
| `content` | `string`              | 消息的文本内容。 |

## 线协议

以下是通过 WebSocket 连接交换的 JSON 消息，供参考。SDK 会自动处理序列化和反序列化。

### 传入消息（ElevenLabs API 到开发者服务器）

| 消息类型              | 字段                                                         | 说明                 |
| ----------------- | ---------------------------------------------------------- | ------------------ |
| `init`            | `conversation_id: string`                                  | 会话已初始化。            |
| `user_transcript` | `user_transcript: TranscriptMessage[]`, `event_id: number` | 已转录用户语音。           |
| `ping`            |                                                            | 保活。SDK 会以 pong 响应。 |
| `close`           |                                                            | 正常断开连接。            |
| `error`           | `message: string`                                          | 来自 API 的错误。        |

### 传出消息（开发者服务器到 ElevenLabs API）

| 消息类型             | 字段                                                         | 说明                   |
| ---------------- | ---------------------------------------------------------- | -------------------- |
| `agent_response` | `content: string`, `event_id: number`, `is_final: boolean` | 用于 TTS 合成的 LLM 响应片段。 |
| `pong`           |                                                            | 对 ping 的响应。          |