# 使用 Amazon Nova 构建实时音视频 AI

> 结合 Amazon Nova、Transcribe、Polly 与开源 TEN 框架，构建低延迟的多模态 AI 助手。

- 作者: zhuermu
- 发布: 2025-06-15
- 网页版: https://zhuermu.com/blog/amazon-nova-ten-realtime-av/
- 首发于: https://aws.amazon.com/cn/blogs/china/real-time-audio-video-interaction-solution-based-on-amazon-nova-and-ten/

---
## 背景

随着人工智能的飞速发展，实时音视频交互应用正成为市场关注的焦点。通过结合 Amazon Nova 基础模型、Amazon Transcribe、Amazon Polly 等 AWS 服务，你可以构建一套具备多模态理解能力的强大实时音视频交互系统。

本文将完整介绍如何使用开源的 TEN（Transformative Extensions Network）框架来编排各个组件，从而搭建这样一套系统。我们会覆盖逻辑架构、在 AWS 上的物理部署、涉及的核心服务、面向延迟与成本的关键优化策略，以及基于 Amazon EKS 的分步部署指南。

## 技术选型

我们设计了一套**基于 Amazon Nova 与 TEN 框架的实时音视频交互解决方案**。这一方案的核心优势在于：利用 Amazon Nova 的多模态能力支持实时视频理解，同时借助 TEN 框架的插件化架构，让每个组件都保持模块化、可替换。

方案中用到的关键技术：

- **Amazon Nova** —— 原生支持多模态（文本、图像、视频）的基础模型
- **Amazon Transcribe** —— 实时语音转文本
- **Amazon Polly** —— 高质量文本转语音合成
- **TEN Framework** —— 开源 agent 框架，采用基于有向图的插件编排引擎
- **Agora RTC** —— 实时音视频通信网络
- **Amazon EKS** —— 用于生产环境部署的容器编排

## 逻辑架构

该方案采用模块化的逻辑架构，由 TEN 框架通过插件系统对所有功能模块进行编排。下面介绍各组件如何协同工作。

### 前端用户交互模块

- **用户终端**：同时支持 Web 浏览器和移动应用
- **Web 服务器**：作为前端请求的入口，负责频道创建与鉴权

### TEN Agent（核心编排）

TEN Agent 是负责编排和管理所有插件的中枢模块。它使用**有向有环图（Directed Cyclic Graph，DCG）**来实现模块间灵活的数据流处理。关键插件包括：

- **RTC 插件**：通过 Agora RTC 网络收发实时音视频数据
- **Amazon Transcribe 插件**：进行实时语音识别，将用户的语音转换为文本
- **中断（Interrupt）插件**：监测语音中断状态，以便在用户开始讲话时让 agent 停止发声
- **Amazon Bedrock 插件**：将文本与视频帧发送给 Amazon Nova 模型，进行多模态推理并生成响应
- **Amazon Polly 插件**：将 agent 的文本响应转换回自然的语音

### RTC 网络

实时通信由 Agora 的 SD-RTN（软件定义实时网络）承载，在全球范围内提供低延迟的音视频传输。

### 通信频道建立流程

建立实时会话的过程包含以下步骤：

1. 用户客户端调用 HTTP 端点 `/v1/api/generate`，请求频道名与鉴权令牌
2. Web 服务器处理该请求，返回频道名与令牌
3. 用户客户端使用该令牌与 RTC 网络建立通信频道
4. 用户客户端调用 `/v1/api/start`，请求开始会话
5. Web 服务器获取频道信息，并将其传递给 TEN Agent
6. TEN Agent 加入频道，并建立自己到 RTC 网络的连接

当所有连接建立完成后，音视频数据便在用户与 agent 之间实时双向流动。

## 物理架构

整套方案部署在 AWS 云服务之上：

- **终端用户**通过 Web 浏览器或移动应用访问系统
- **Amazon CloudFront** 作为 CDN，加速静态资源分发并降低前端延迟
- **应用负载均衡器（ALB）**将进入的 API 请求路由到后端服务
- **Amazon EKS** 承载所有核心服务，包括 Web 服务器和 TEN Agent 容器
- **Agora SD-RTN** 负责用户与 agent 之间实际的低延迟音视频传输
- **Docker 镜像**构建后存储在 **Amazon ECR**（Elastic Container Registry）中，用于部署到 EKS

运行在 EKS 上的后端服务通过 AWS SDK 调用连接到各类 AWS AI 服务（Bedrock、Transcribe、Polly），从而保持架构清晰、服务边界明确。

## 核心 AWS 服务

### Amazon Nova —— 多模态 AI 引擎

Amazon Nova 是一系列基础模型，为本方案提供智能内核。模型选型取决于你对延迟、成本和能力的要求：

| 模型 | 优势 | 适用场景 |
|-------|-----------|----------|
| **Nova Micro** | 成本低、推理快 | 对速度要求最高的纯文本任务 |
| **Nova Lite** | 成本低，可处理图像和视频 | 视觉输入的快速处理 |
| **Nova Pro** | 性能、速度与成本的最佳平衡 | 需要多模态推理的生产负载 |
| **Nova Premier** | 面向复杂推理的最强能力 | 需要深度分析与多步推理的任务 |

对于本实时交互方案，推荐默认使用 **Nova Pro**。它在响应质量与推理延迟之间提供了最佳平衡，而当用户在实时对话中等待回复时，这一点至关重要。如果成本是首要考量、且视觉理解需求较为简单，那么 Nova Lite 是不错的替代方案。

### Amazon Transcribe —— 语音识别

Amazon Transcribe 提供实时语音转文本能力，支持 100 多种语言。在本架构中，Transcribe 插件从 RTC 流中接收音频帧并实时转换为文本，随后传递给 Amazon Bedrock 插件进行推理。

本方案中用到的关键特性：

- **流式转写**，实现实时、低延迟处理
- **部分结果检测**，用于支持中断处理（下文详述）
- **自动语言检测**，适配多语言场景

### Amazon Polly —— 文本转语音

Amazon Polly 将 agent 的文本响应转换为自然的语音。它支持 40 多种语言，通过流式方式返回音频，可在 150 毫秒内完成语音生成。这样的低延迟对于保持自然的对话节奏至关重要——用户不应感觉自己在等待 agent “开口说话”。

流式能力意味着 Polly 在文本尚未完全处理完之前就开始返回音频，从而让 agent 在响应生成的同时几乎立即开始发声。

## 关键技术挑战与优化策略

### 降低延迟

延迟是实时对话式 AI 中最重要的单一因素。用户期望在几百毫秒内得到响应——超过这个时间就会打破自然对话的错觉。我们从多个层面来应对：

- **模型选型**：Amazon Nova Pro 提供低延迟的多模态推理。对于纯文本场景，Nova Micro 的推理速度更快。
- **异步处理**：TEN 框架支持完全异步的插件执行，因此多个操作可以并行推进，而非顺序执行。
- **全链路流式**：Amazon Transcribe 在用户讲话时流式输出部分转写结果；Amazon Polly 在文本生成时流式输出音频；Bedrock API 也支持流式响应。这意味着流水线的每个阶段都能在上一阶段完成之前就开始产出。

### 成本优化

实时视频理解本身开销很大，因为它需要持续地向模型发送图像帧。有两个关键策略有助于控制成本：

**按时间间隔采样帧**：与其把每一帧视频都发送给模型，不如按可配置的时间间隔对帧进行采样。这在为模型提供足够视觉上下文的同时，大幅减少了需要处理的数据量。

**图像压缩与历史合并**：帧在发送给模型前会先压缩，同时历史帧会被合并，以减少上下文窗口中的图像总数。

以下是 TEN Agent 的 Bedrock 插件中处理视频帧的核心逻辑：

```python
async def _on_video(self, ten_env: AsyncTenEnv):
    while True:
        [image_data, image_width, image_height] = await self.image_queue.get()
        frame_buffer = rgb2base64jpeg(image_data, image_width, image_height)
        self.image_buffers.append(frame_buffer)
        while len(self.image_buffers) > MAX_IMAGE_COUNT:
            self.image_buffers.pop(0)
        while not self.image_queue.empty():
            await self.image_queue.get()
        await asyncio.sleep(VIDEO_FRAME_INTERVAL)
```

该函数在一个持续循环中运行，从队列中拉取视频帧，将其转换为 Base64 编码的 JPEG，并维护一个由最近若干帧组成的滑动窗口（`MAX_IMAGE_COUNT`）。随着新帧到来，较旧的帧会被丢弃。`VIDEO_FRAME_INTERVAL` 参数控制帧的采样频率——增大该值会以牺牲时间分辨率为代价降低成本。内层 `while` 循环会清空队列中积累的所有帧，确保 agent 始终处理最新的视觉数据，而不是过时的旧帧。

### 中断与结束信号检测

在自然对话中，人们经常互相打断。agent 需要检测到用户开始讲话，并立即停止自己的音频输出。这通过 Amazon Transcribe 插件的转写事件处理来实现：

```python
async def handle_transcript_event(self, transcript_event):
    results = transcript_event.transcript.results
    for result in results:
        if result.is_partial:
            is_final = False
        for alt in result.alternatives:
            text_result += alt.transcript
    create_and_send_data(ten=self.ten, text_result=text_result, is_final=is_final, stream_id=self.stream_id)
```

这里的关键在于区分**部分（partial）**与**最终（final）**转写结果。部分结果表示用户正在讲话——这会触发中断插件通知 Polly 插件停止播放音频。最终结果表示用户已完成一段完整的话语，从而触发完整的处理流水线：文本被发送给 Nova 进行推理，响应再被转换回语音。

正是这种 partial/final 检测机制，让对话显得自然，而不是生硬的轮流问答。如果没有它，agent 要么会与用户抢话，要么会在漫长的停顿后才尴尬地回应。

### 支持热插拔插件的模块化架构

TEN 框架的插件化架构意味着流水线中的每个组件都可以独立替换。想把 Amazon Transcribe 换成另一种语音识别服务？只需替换 Transcribe 插件，无需改动任何其他代码。想在转写与推理之间加入一个翻译步骤？往有向图中插入一个新插件即可。

这种模块化在开发与实验阶段尤其有价值。你可以测试不同的模型配置、在 Nova Pro 与 Nova Lite 之间切换做 A/B 测试，或者添加自定义预处理插件，而无需重新设计整体架构。

## 部署指南

### 前置条件

在部署之前，你需要：

1. 一个 **AWS 账户**，具备针对 EKS、ECR、Bedrock、Transcribe、Polly 和 CloudFront 的相应 IAM 权限
2. 一个已启用 RTC 服务的 **Agora 账户**（用于实时音视频网络）
3. 在本地机器上安装并配置好 **AWS CLI 与 eksctl**
4. 安装 **Docker** 以构建容器镜像
5. 安装 **kubectl** 以管理 EKS 集群

### 构建并推送 Docker 镜像

首先，让 Docker 通过 Amazon ECR 注册表进行认证，并构建 TEN Agent 镜像：

```bash
# Authenticate Docker with ECR
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS \
  --password-stdin <your_account_id>.dkr.ecr.us-east-1.amazonaws.com

# Clone the TEN Agent repository
git clone https://github.com/zhuermu/TEN-Agent.git
cd TEN-Agent

# Build the Docker image
docker build -t dev/ten_agent_build .

# Tag and push to ECR
docker tag dev/ten_agent_build:latest \
  <your_account_id>.dkr.ecr.us-east-1.amazonaws.com/dev/ten_agent_build:latest
docker push <your_account_id>.dkr.ecr.us-east-1.amazonaws.com/dev/ten_agent_build:latest
```

### 创建 EKS 集群

使用配置文件创建 EKS 集群：

```yaml
# cluster-config.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: ten-framework-cluster
  region: us-east-1
  version: "1.31"

managedNodeGroups:
  - name: ten-workers
    instanceType: c5.2xlarge
    desiredCapacity: 2
    minSize: 1
    maxSize: 4
    volumeSize: 100
    iam:
      withAddonPolicies:
        ebs: true
        efs: true
```

应用集群配置：

```bash
eksctl create cluster -f cluster-config.yaml
```

### 部署 TEN Agent 服务

创建 Kubernetes 命名空间并部署服务：

```bash
# Create the namespace
kubectl create namespace ten-framework --save-config
```

应用部署清单：

```yaml
# deployment.k8s.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ten-agent
  namespace: ten-framework
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ten-agent
  template:
    metadata:
      labels:
        app: ten-agent
    spec:
      containers:
        - name: ten-agent
          image: <your_account_id>.dkr.ecr.us-east-1.amazonaws.com/dev/ten_agent_build:latest
          ports:
            - containerPort: 8080
          env:
            - name: AWS_REGION
              value: "us-east-1"
            - name: BEDROCK_MODEL_ID
              value: "us.amazon.nova-pro-v1:0"
            - name: AGORA_APP_ID
              valueFrom:
                secretKeyRef:
                  name: ten-agent-secrets
                  key: agora-app-id
            - name: AGORA_APP_CERTIFICATE
              valueFrom:
                secretKeyRef:
                  name: ten-agent-secrets
                  key: agora-app-certificate
          resources:
            requests:
              cpu: "1"
              memory: "2Gi"
            limits:
              cpu: "2"
              memory: "4Gi"
```

```bash
# Apply the deployment and service manifests
kubectl apply -n ten-framework -f deployment.k8s.yaml
kubectl apply -n ten-framework -f service.k8s.yaml
```

### 验证部署

当 Pod 运行起来后，验证部署：

```bash
# Check pod status
kubectl get pods -n ten-framework

# Check service endpoints
kubectl get svc -n ten-framework

# View logs for troubleshooting
kubectl logs -n ten-framework -l app=ten-agent --tail=100
```

## 总结

构建一套实时音视频 AI 交互系统，需要协调众多环节：语音识别、多模态推理、文本转语音、实时通信以及中断处理。将 Amazon Nova 的多模态能力与 TEN 框架的插件编排相结合，比从零开始搭建一切要容易得多。

这套架构的关键要点：

- **Amazon Nova Pro** 在实时多模态对话中提供了质量与延迟的最佳平衡
- 在处理连续视频流时，**帧采样与压缩**对于控制成本至关重要
- **全链路流式**（Transcribe、Bedrock、Polly）是让延迟满足实时交互要求的关键
- **TEN 框架基于 DCG 的插件化架构**让系统保持模块化，每个组件都可独立替换
- **Amazon EKS** 为生产部署提供了具备自动伸缩能力的坚实基础

集成了 Amazon Nova 的 TEN Agent 完整源代码已在 GitHub 上开放。如果你正在 AWS 上构建实时对话式 AI 应用，这套架构为你提供了一个可用于生产的起点，并预留了清晰的扩展点以便定制。

---

## 常见问题

### 实时音视频 AI 交互应该选择哪个 Amazon Nova 模型？

推荐默认使用 Nova Pro，它在响应质量与推理延迟之间提供了最佳平衡，这对用户等待实时对话回复的场景至关重要。如果成本是首要考量、视觉理解需求较简单，Nova Lite 是不错的替代方案；纯文本且对速度要求最高的任务可以选择 Nova Micro。

### 如何降低 AI 实时视频理解的成本？

有两个关键策略：一是按时间间隔采样视频帧，不把每一帧都发送给模型，而是按可配置的间隔采样，大幅减少数据量；二是图像压缩与历史合并，帧在发送前先压缩，并通过滑动窗口（MAX_IMAGE_COUNT）丢弃较旧的帧。增大采样间隔可以进一步降低成本，但会牺牲时间分辨率。

### TEN 框架如何处理用户在 AI 说话时的打断？

依靠 Amazon Transcribe 的部分（partial）与最终（final）转写结果区分：部分结果表示用户正在讲话，会触发中断插件通知 Polly 插件停止播放音频；最终结果表示用户完成了一段完整话语，触发完整流水线——文本发送给 Nova 推理，响应再转换回语音。正是这种机制让对话显得自然，而不是生硬的轮流问答。


---

## 参考资料

- [TEN Framework](https://github.com/TEN-framework/ten-framework) — GitHub
- [TEN documentation](https://theten.ai/docs) — TEN
- [Amazon Nova User Guide](https://docs.aws.amazon.com/nova/latest/userguide/what-is-nova.html) — AWS Documentation
