# @anam-ai/js-sdk 中文文档

规范地址：https://npmcn.com/package/%40anam-ai/js-sdk/

版本：4\.29\.1
npm 元数据更新时间：2026-10-19T02:19:57.373Z
中文译文更新时间：2026-11-06T01:54:57.517Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40anam-ai/js-sdk
原文对照：https://npmcn.com/package/%40anam-ai/js-sdk/?lang=original
项目主页：https://github.com/anam-org/javascript-sdk#readme
源码仓库：https://github.com/anam-org/javascript-sdk

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：1.2 MB，668 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：1 个
- 首次发布：2024-06-11T17:43:57.795Z
- 最新版本发布：2026-10-19T02:19:57.206Z
- 近 30 天下载量：307615（2026-10-06 至 2026-11-04，npm 官方下载统计）
- 已发布版本数：216（近 12 个月 74 个）

## 中文简介

Anam AI 客户端 JavaScript SDK

## 安装

```sh
npm install @anam-ai/js-sdk
```

也可以使用：`pnpm add @anam-ai/js-sdk`、`yarn add @anam-ai/js-sdk`、`bun add @anam-ai/js-sdk`

## README

# Anam AI JavaScript SDK 软件

这是JavaScript SDK的官方版本,用于将Anam AI实时数字人物集成到你的产品中. 它提供了一个简单而直观的API,与Anam AI的服务交互.

## 导言

Anam AI JavaScript SDK旨在帮助开发者将Anam AI的数字人格集成到他们的JavaScript应用中. SDK提供一套API和公用设施,以方便在实时环境中创建,管理和与数字人物互动.

## 文档

完整的文件可在 [翻译:](https://docs.anam.ai/)。 。 。 .

## 实例

看看我们 [实例项目](https://github.com/anam-org/anam-examples) 用于执行样本.

## 先决条件

### Anam AI 账户

创建自由账户头到 [阿南实验室](https://lab.anam.ai/) 并注册.

### Anam API 密钥

要使用 SDK 您首先需要 API 密钥 。 遵守指示 [这里](https://docs.anam.ai/guides/get-started/api-key) 来创造一个.

# 开始

首先,在您的工程中安装 SDK

```zsh
npm install @anam-ai/js-sdk
```

## 折旧通知

**重要**编号: `brainType` 输入 `PersonaConfig` 已贬值,并将在未来版本被删除。 请使用 `llmId` 换句话说 如果您正在使用 `brainType`在控制台上你会看到堕落警告 在过渡时期,这两个领域都得到了支持.

## 地方发展

最快速的开始测试 SDK 是直接使用您的 API 密钥与我们的 SDK 和下面显示的示例人物配置 . 要使用 SDK 您首先需要创建实例 `AnamClient`为本地开发,您可以使用 `unsafe_createClientWithApiKey` 方法.

```typescript
import { unsafe_createClientWithApiKey } from '@anam-ai/js-sdk';

const anamClient = unsafe_createClientWithApiKey('your-api-key', {
  personaId: '<PERSONA ID HERE>',
  name: 'Cara',
  avatarId: '30fa96d0-26c4-4e55-94a0-517025942e18',
  voiceId: '6bfbe25a-979d-40f3-a92b-5394170af54b',
  brainType: 'ANAM_GPT_4O_MINI_V1',
  systemPrompt:
    "[STYLE] Reply in natural speech without formatting. Add pauses using '...' and very occasionally a disfluency. [PERSONALITY] You are Cara, a helpful assistant.",
});
```

**页:1**: 方法 `unsafe_createClientWithApiKey` 对生产使用来说是不安全的,因为它需要将您的 api 密钥暴露给客户端。 部署到生产时见 [生产用途](https://npmcn.com/package/%40anam-ai/js-sdk/#readme-usage-in-production) 先说.

一旦您有 Anam 客户端实例 已关闭, 您可以通过流到 DOM 中的音频和视频元素开始会话 .

```typescript
await anamClient.streamToVideoElement('video-element-id');
```

这将使用预配置的人物a id开始一个新的会话,并在 DOM 中以匹配的元素 id 开始流视频元素.

要停止会话使用 `stopStreaming` 方法.

```typescript
anamClient.stopStreaming();
```

## 生产用途

当部署到生产时,重要的是不要公开曝光您的API密钥. 为避免这个问题, 您应该先将您的 API 密钥交换为服务器侧的短长会话符 。 然后会话符号可以传递给客户端, 并用于 Evolution Anam SDK .

**从服务器**

```typescript
const response = await fetch(`https://api.anam.ai/v1/auth/session-token`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${apiKey}`,
  },
  body: JSON.stringify({
    personaConfig: {
      name: 'Cara',
      avatarId: '30fa96d0-26c4-4e55-94a0-517025942e18',
      voiceId: '6bfbe25a-979d-40f3-a92b-5394170af54b',
      llmId: '<LLM ID HERE>',
      systemPrompt:
        "[STYLE] Reply in natural speech without formatting. Add pauses using '...' and very occasionally a disfluency. [PERSONALITY] You are Cara, a helpful assistant.",
    },
  }),
});
const data = await response.json();
const sessionToken = data.sessionToken;
```

一旦您有会话符号,您就可以使用 `createClient` 将 Anam SDK 程序用于初始化 Anam 客户端实例.

```typescript
import { createClient } from '@anam-ai/js-sdk';

const anamClient = createClient('your-session-token');
```

不论您是否使用 API 密钥或会话符号将客户端曝光同一套可用的流化方法 .

[看这里](https://npmcn.com/package/%40anam-ai/js-sdk/#readme-starting-a-session-in-production-environments) 例如,在生产环境中开始会话的序列图.

## 聊天流

`createTalkMessageStream` 直接发送文字给 TTS 供人发言,一次一个块。 溪流中的所有块都有一个相通的ID,这是中断相关联的.

```typescript
const stream = anamClient.createTalkMessageStream();
for (const chunk of llmChunks) {
  await stream.streamMessageChunk(chunk.text, chunk.isLast);
}
```

你可以马上开始谈话 `streamToVideoElement()` 决定。 在信号连接首次打开前发送的块被排出队列,并在完成时发送.

### 交付失败

对话流块通过会话的信号连接。 在回答心跳的引擎上(见 [旧引擎](https://npmcn.com/package/%40anam-ai/js-sdk/#readme-older-engines) 在下面,SDK检查与心跳的关联, 以及一个块确认块到达后发出的心跳的答案。 SDK 不重新发送块 。 如果一个块不能被发送,因为连接已经下降或停止回答,或者它在大约3秒内没有得到确认,流停止接受块, `stream.getState()` 返回时 `TalkMessageStreamState.DELIVERY_FAILED`,客户端会发出 `MESSAGE_DELIVERY_FAILED` 与流的关联 ID。 SDK自己重新连接;决定如何处理答案由你决定. 一个选择是回到 `talk()` 全文为:

```typescript
import { AnamEvent } from '@anam-ai/js-sdk';

interface Answer {
  correlationId: string;
  text: string;
  complete: boolean;
  failed: boolean;
}

// Only the latest answer falls back: once a new one starts, the old one is stale.
let latest: Answer | null = null;

// Register once per client, not once per stream.
anamClient.addListener(AnamEvent.MESSAGE_DELIVERY_FAILED, (failure) => {
  const answer = latest;
  if (!answer || failure.correlationId !== answer.correlationId) return;
  answer.failed = true;
  // If the failure arrives after the answer is complete, speak it now.
  if (answer.complete) anamClient.talk(answer.text).catch(console.error);
});

async function speak(llmChunks: AsyncIterable<{ text: string; isLast: boolean }>) {
  const stream = anamClient.createTalkMessageStream();
  const answer: Answer = {
    correlationId: stream.getCorrelationId(),
    text: '',
    complete: false,
    failed: false,
  };
  latest = answer;
  for await (const chunk of llmChunks) {
    answer.text += chunk.text;
    // A failed or interrupted stream rejects further chunks, so keep collecting the
    // answer instead. This also covers a stale answer, whose failure the listener ignores.
    if (stream.isActive()) await stream.streamMessageChunk(chunk.text, chunk.isLast);
  }
  answer.complete = true;
  if (answer.failed && latest === answer) await anamClient.talk(answer.text);
}
```

故障意味着发动机没有确认块,而不是它从来没有收到过块. 有些答案可能已经说过了 `talk()` 复说. 一旦客户收到 `TALK_STREAM_INTERRUPTED` 对于一溪,它不会发射 `MESSAGE_DELIVERY_FAILED` 对于它。 连接被关闭时发送的中断可以被错过,不过,因此倒计时仍然可以重复用户中断的答案. 反向也可能发生:引擎可以在客户端重新连接后交付中断,所以 `TALK_STREAM_INTERRUPTED` 可以在你开始倒计时后到达已经失败的溪流.

结束会话不是执行失败。 之后 `stopStreaming()`,或者当客户端发出 `CONNECTION_CLOSED` 因为服务器结束会话或媒体连接失败, 未确认块会丢失 `MESSAGE_DELIVERY_FAILED`,之后发送的块被丢弃。 处理 `CONNECTION_CLOSED` 作为每个开口的溪流的尽头。 唯一的例外是信号连接本身就永远关闭:未经证实的块在之前失败了 `CONNECTION_CLOSED`。 。 。 .

只确认谈话流 。 音频发送通过 `createAgentAudioInputStream()` 而不是,所以一个停止工作而不关闭的连接 可能会失去它不发生任何事件.

#### 旧引擎

确认块需要一个能回答心跳的引擎. 当会话准备就绪时会这样说的引擎 `sendsHeartbeatAcks: true` 输入 `sessionready` 留言。 在更古老的引擎上,SDK在会话准备好后会停止跟踪块并像以前一样发送,在连接重新连接时排队. 还发作 `MESSAGE_DELIVERY_FAILED` 在三种情况下:

-   连接关闭后发送块 .
-   一个块在连接首次打开前被排入队列,它永远不会打开.
-   在会话准备好之前发送一个块,会话需要3秒多的时间才能准备好. 在此之前,SDK无法从已经停止响应的引擎中分辨出一个更老的引擎,因此它会使流失效并重新连接. 等待时间 `AnamEvent.SESSION_READY` 在第一个块避免这一点之前.

### 跨工具呼叫的演讲

当您的应用程序运行工具时, 谈话流可以保持开放 。 在工具之前和之后给出演讲,呼叫单独的发音ids,第二个等待第一个完成播放.

> \[注\] Utterance ids需要一个Cara 4相机. Cara 3相机运行一个更古老的引擎, 静悄悄地丢出字段: 文字仍然被说出 `utteranceId`。没有错误或警告,所以请检查身份证明是否回来了而不是等待失败.

> \[大 `utteranceId` 表示语音的开始,而不是单个文本块。 把它放在第一个块上,然后从该词中的剩余块中省去。 仅在下一个语句开始时设置新的 id .

```typescript
const stream = anamClient.createTalkMessageStream();

// Utterance A can begin playing while the tool runs.
await stream.streamMessageChunk('Let me check ', false, crypto.randomUUID());
await stream.streamMessageChunk('that for you.', false); // Continues utterance A.

const toolResultText = await runToolCall();

// Utterance B waits for A to finish, then continues with the result.
await stream.streamMessageChunk(toolResultText, true, crypto.randomUUID());
```

工具必须迅速完成. 服务器关闭一个15秒的谈话流, 却没有收到一个带文字的块, 结束转弯, 并拒绝随后发送到这个关联ID上的任何信息 。 空块不重设计时器 。 对于一个可能跑得更长的工具,让第一句话结束流出,并在结果到来时开始一个新的流出.

同样的命令适用于立即准备好的两种言论。 寄出不同的代号,第二个则等待第一个完成游戏:

```typescript
const stream = anamClient.createTalkMessageStream();
await stream.streamMessageChunk('First utterance.', false, crypto.randomUUID());
await stream.streamMessageChunk('Second utterance.', true, crypto.randomUUID());
```

Ids必须是小写 Canonical UUID v4 字符串,这就是什么 `crypto.randomUUID()` 返回; 其它任何投掷。 他们回来的人 一个消息事件作为 `utteranceId`,所以你可以匹配自己的身份 与人说话.

## 司长说明(第4节)

在Cara 4相机上您可以添加 **司长** 指导阿凡达的表演. 提供内置 `presetStyle` **或者说** 自由形式 `customStylePrompt` ——两者是相互排斥的(由《联合国宪章》和《联合国宪章》所强化) `DirectorNotes` ——加可选 `expressivity` 值,从 `0` 改为 `1`,控制样式的表达性(较低值比较稳定;较高值增加样式并一起进行语音驱动运动;省略后使用引擎默认值)。 Director Notes没有被转发到会话脚本创建中,并且只被应用到Cara 4 avatars上;对于更古老的模型,服务器忽略它们,会话在没有它们的情况下进行.

```typescript
import { unsafe_createClientWithApiKey } from '@anam-ai/js-sdk';

const anamClient = unsafe_createClientWithApiKey('your-api-key', {
  personaId: '<PERSONA ID HERE>',
  name: 'Cara',
  // Use a Cara 4 avatar — Director Notes are ignored on older models.
  avatarId: '30fa96d0-26c4-4e55-94a0-517025942e18',
  voiceId: '6bfbe25a-979d-40f3-a92b-5394170af54b',
  llmId: '<LLM ID HERE>',
  systemPrompt:
    '[STYLE] Reply in natural speech without formatting. [PERSONALITY] You are Cara, a helpful assistant.',
  directorNotes: {
    presetStyle: 'warm',
    expressivity: 0.5,
  },
});
```

要使用自由形式样式而不是预设,请提供 `customStylePrompt`数字 :

```typescript
directorNotes: {
  customStylePrompt:
    'Warm smile, composed, slightly amused, looking directly at camera',
  expressivity: 0.5,
}
```

您也可以设置 `expressivity` 曲调如何表达阿凡达的默认风格:

```typescript
directorNotes: {
  expressivity: 0.2,
}
```

### 发送主任 Note 提示会中段

在卡拉4号,你可以使用 `sendDirectorNoteCue` 以在对话中改变表演。 Cues使用引擎的专用提示路径,因此不会清洗缓冲音频或视频. 数据通道提示主要用于音频通过会话;对于Twitchey会话,偏好在人物语音文本中内置提示标记.

```typescript
import { AnamEvent, type DirectorNoteCueTag } from '@anam-ai/js-sdk';

let cueChannelOpen = false;
anamClient.addListener(AnamEvent.DATA_CHANNEL_OPEN, () => {
  cueChannelOpen = true;
});
anamClient.addListener(AnamEvent.CONNECTION_CLOSED, () => {
  cueChannelOpen = false;
});

// Call this later from your TTS timing callback for an active persona turn.
function onTtsCue(tag: DirectorNoteCueTag, atSeconds: number) {
  if (!cueChannelOpen) {
    throw new Error('Director Note cue channel is not open');
  }

  anamClient.sendDirectorNoteCue(tag, { atSeconds });
}

// Wire onTtsCue to your TTS provider's cue/word-timing callback. For example,
// report `warm` at 0 seconds and `surprised` at 1.25 seconds for that turn.
```

在启动流前注册听众, 使其不能错过事件 。 发送前 `DATA_CHANNEL_OPEN` 而不是悄悄地放弃提示。 发信号时间立即应用提示. `inSeconds` 是一个从现在开始的延迟,在积极反应,同时 `atSeconds` 是一个绝对的相抵,从个人的语音开始,在对齐给生成的音频提示时首选;最多提供一个。 运行时提示标记还包括只显示提示的样式,例如 `laughter`, (中文(简体) ), `curious`, (中文(简体) ), `concerned`,以及 `surprised` 无法作为会话启动的 `presetStyle` 数值.

## 常见问题

### @anam-ai/js-sdk 是什么？

Anam AI 客户端 JavaScript SDK

### 如何安装 @anam-ai/js-sdk？

在项目目录运行 npm install @anam-ai/js-sdk，或使用 pnpm add / yarn add / bun add。

### @anam-ai/js-sdk 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @anam-ai/js-sdk 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @anam-ai/js-sdk 可以商用吗？

@anam-ai/js-sdk 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @anam-ai/js-sdk 的下载量有多少？

根据 npm 官方下载统计，@anam-ai/js-sdk 在 2026/10/06 – 2026/11/04 这 30 天内被下载 307,615 次，日均约 10,254 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @anam-ai/js-sdk 还在维护吗？

最新版本 4\.29\.1 发布于 2026/10/19（19 天前）；至今共发布 216 个版本，其中过去 12 个月发布了 74 个；首次发布于 2024/06/12。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

