# CamTalk

多模态实时 AI 视觉对话助手。用户通过摄像头和麦克风与 AI 交互，AI 理解视觉场景和语音输入后，以文字和语音形式给出自然回应。

- **路演视频**：[哔哩哔哩弹幕网——七牛云第四批议题1](https://www.bilibili.com/video/BV1dDJK6cE5S/)
- **线上体验**：http://8.161.227.145:9000

> ⚠️ **注意**：由于线上地址使用 HTTP 协议，浏览器默认禁止在非 HTTPS 环境下调用摄像头和麦克风。需要按以下步骤配置 Chrome 浏览器：
>
> 1. 在浏览器地址栏中输入 `chrome://flags/#unsafely-treat-insecure-origin-as-secure`，回车
> 2. 将 **Insecure origins treated as secure** 选项设置为 **Enabled**（已启用）
> 3. 在输入框中输入 `http://8.161.227.145:9000` 地址
> 4. 点击右下角弹出的 **Relaunch** 按钮，自动重启浏览器
>
> 重启后即可在该 HTTP 地址下正常调用摄像头和麦克风。

![](docs/pictures/1.png)

## 架构

三层系统，前端做轻量预处理，后端做智能编排，云端 AI 服务按需调用：

```mermaid
graph TB
    subgraph client[浏览器客户端]
        A1[媒体采集]
        A2[VAD 语音检测]
        A3[关键帧检测]
        A4[UI 渲染]
    end

    subgraph gateway[Go 网关 :8080]
        B1[WebSocket Handler]
        B2[Session Manager]
        B3[AI Orchestrator]
        B4[REST API]
        B5[Auth 模块]
        B6[Store 层]
    end

    subgraph cloud[云端 AI 服务]
        C1[STT 语音识别]
        C2[LLM 多模态推理]
        C3[TTS 语音合成]
    end

    client <-->|WebSocket| gateway
    gateway <-->|HTTP| cloud
```

**关键模式**：LLM 文本流和 TTS 音频流并行推送，用户先看到文字、紧接着听到语音，感知延迟 < 0.5 秒。

## 技术栈

| 层级 | 技术 |
|------|------|
| 前端 | React 18, TypeScript, Vite, @ricky0123/vad-web |
| 后端 | Go, Gin, gorilla/websocket, Viper, Zap |
| STT | MiMo ASR（默认） / Deepgram |
| LLM | DashScope qwen3-vl-plus（默认，通过 eino-ext OpenAI ChatModel 接入） |
| TTS | MiMo TTS（默认） / OpenAI TTS |

## 项目结构

```
CamTalk/
├── frontend/                   # 浏览器客户端
│   └── src/
│       ├── components/         # UI 组件
│       │   ├── LandingPage/    # 登录着陆页 + LoginModal
│       │   ├── AuthPage/       # 登录/注册表单
│       │   ├── CameraManager/  # 摄像头流采集
│       │   ├── MicManager/     # 麦克风音频采集
│       │   ├── EdgeProcessor/  # VAD + 关键帧检测
│       │   ├── WebSocketManager/ # WS 连接管理
│       │   ├── ChatPanel/      # 消息展示
│       │   ├── VideoPreview/   # 摄像头画面预览
│       │   ├── SessionSidebar/ # 对话历史侧边栏
│       │   ├── ConfigPanel/    # 配置面板
│       │   └── Toast/          # 通知提示
│       ├── hooks/              # 自定义 Hooks
│       │   ├── useVisionSession.ts  # 核心会话 Hook
│       │   ├── useSessionList.ts    # 对话列表管理
│       │   └── useObservationMode.ts # 观察模式
│       ├── lib/                # 工具库
│       │   ├── websocket.ts    # WebSocket 连接管理
│       │   ├── api.ts          # REST API 客户端
│       │   ├── auth.tsx        # 认证上下文（JWT 管理）
│       │   ├── audio.ts        # 音频编码
│       │   ├── ttsPlayer.ts    # TTS 播放器
│       │   ├── i18n/           # 国际化（zh-CN/en-US/ja-JP）
│       │   └── sampling.ts     # 采样策略
│       └── types/              # TypeScript 类型定义
├── backend/                    # Go 网关
│   ├── cmd/server/             # 入口
│   └── internal/
│       ├── ai/                 # AI 服务抽象层
│       │   ├── llm/            # LLM 提示词与场景
│       │   ├── stt/            # STT 服务（MiMo/Deepgram）
│       │   └── tts/            # TTS 服务（MiMo/OpenAI）
│       ├── eino/               # Eino Graph 编排层（7 节点 DAG）
│       ├── orchestrator/       # Orchestrator 接口
│       ├── session/            # 会话管理（三级存储：Memory/Redis/PG）
│       ├── store/              # 持久化层（Repository 接口 + PG/内存实现）
│       ├── auth/               # 认证（JWT、bcrypt、中间件）
│       ├── ws/                 # WebSocket Handler
│       ├── api/                # REST API（Auth/Conversation）
│       ├── config/             # 配置管理
│       ├── models/             # 数据模型
│       ├── errors/             # 错误码
│       └── logger/             # 日志
├── migrations/                 # 数据库迁移（嵌入式 SQL）
├── docs/                       # 设计文档
└── CLAUDE.md                   # Claude Code 指引
```

## 快速开始

### 前置条件

- Node.js >= 18
- Go >= 1.25

### 前端

```bash
cd frontend
npm install
npm run dev          # Vite 开发服务器 http://localhost:5173
```

### 后端

```bash
cd backend
go mod download
go run ./cmd/server  # 启动网关 :8080
```

### 配置

后端配置文件位于 `backend/config/config.yaml`，支持环境变量覆盖（前缀 `CAMTALK_`）。

```bash
# 最小启动（需要至少一个 AI 服务的 API Key）
cd backend
CAMTALK_AI_LLM_API_KEY=sk-xxx \
CAMTALK_AI_STT_API_KEY=xxx \
go run ./cmd/server
```

配置优先级：环境变量 > `config.{env}.yaml` > `config.yaml` > `.env`

## WebSocket 协议

连接地址：`ws://localhost:8080/ws`

所有消息为 JSON 文本帧，统一信封格式 `{type, request_id?, timestamp?}`。

**客户端 → 服务端**：`query`、`config`、`interrupt`、`ping`
**服务端 → 客户端**：`connected`、`stt_result`、`llm_chunk`、`llm_done`、`tts_audio`、`error`、`pong`

完整协议见 [docs/02-接口文档.md](docs/02-接口文档.md)。

## 文档

| 文档 | 内容 |
|------|------|
| [01-架构设计](docs/01-架构设计.md) | 三层架构、技术栈、数据库设计、部署方案 |
| [02-接口文档](docs/02-接口文档.md) | WebSocket 协议、REST API、AI 服务层、编排器、配置管理 |
| [03-技术选型](docs/03-技术选型.md) | AI 服务栈、持久化层、前端边缘处理选型 |
| [04-用户故事](docs/04-用户故事.md) | 用户场景与优先级 |
| [05-语音交互](docs/05-语音交互.md) | VAD → STT → LLM → TTS 全链路 |
| [06-视觉理解](docs/06-视觉理解.md) | 帧采样、关键帧检测、多模态输入 |
| [07-成本控制](docs/07-成本控制.md) | 采样策略、端云协同、模型分级 |
| [08-功能创意](docs/08-功能创意.md) | 功能创意与规划 |
| [对话历史技术设计](docs/conversation-history-technical-design.md) | 对话历史功能的前端技术方案 |

## License

[MIT](LICENSE) © XEngineers
