一个实时检测有害语言并提供反馈的家庭情绪交互系统。系统通过 ESP32-S3 设备或 Web 上传采集音频,使用腾讯云 ASR 进行语音识别,结合 LLM 智能分析有害语句,并通过振动提醒家长注意沟通方式。
- 实时音频处理: 通过 WebSocket 接收设备音频流
- 腾讯云实时 ASR: 使用腾讯云实时语音识别服务,准确识别语音内容
- 双层有害语检测:
- 关键词快速检测(14个常见有害词汇)
- LLM 智能分析(使用 OpenRouter + Gemma 2 27B 模型深度理解语义和上下文)
- 智能反馈: 根据有害程度(1-5级)发送不同强度的振动指令
- 离线 ASR 分析: 会话结束后使用腾讯云录音文件识别 + 说话人分离
- 音频文件上传: 支持通过 Web 界面上传音频文件进行离线分析
- 说话人分离: 自动区分不同说话人(家长/孩子),最多支持 9 个说话人
- 用户认证: JWT 令牌认证,支持用户注册、登录和权限管理
- Web 管理界面: 查看会话列表和详情,高亮显示有害语句
- 腾讯云对象存储: 音频文件自动上传到 COS,支持预签名 URL 私有访问
- ✨ 实时 + 离线双重处理:实时提醒 + 事后精确分析
- 🧠 AI 驱动:LLM 深度理解语义,避免误判
- 🔒 安全认证:JWT 身份验证 + BCrypt 密码加密
- 📊 说话人分离:自动区分家长和孩子的对话(Speaker A/B/C...)
- ☁️ 云端存储:音频文件存储在腾讯云 COS,支持私有读写
- 🎯 有害等级评估:1-5 级有害程度分析
- FastAPI: 高性能 Web 框架
- WebSocket: 实时双向通信
- SQLite: 轻量级数据库
- SQLModel: ORM 框架
- 腾讯云 ASR: 实时语音识别 + 录音文件识别
- 腾讯云 COS: 对象存储服务
- OpenRouter: LLM API 网关(Gemma 2 27B)
- Python 3.10+: 编程语言
- React 18: UI 框架
- Vite: 构建工具
- React Router: 路由管理
- Tailwind CSS: 样式框架
info-tech/
├── backend/ # 后端代码
│ ├── main.py # FastAPI 应用入口
│ ├── config/ # 配置文件
│ │ └── settings.py # 应用设置(腾讯云密钥、COS 配置等)
│ ├── models/ # 数据模型
│ │ ├── db.py # 数据库连接
│ │ ├── user.py # User 模型
│ │ ├── session_model.py # Session 模型
│ │ └── utterance_model.py # Utterance 模型
│ ├── api/ # REST API
│ │ ├── routes.py # 会话 API 路由
│ │ ├── auth_routes.py # 认证 API 路由
│ │ ├── auth.py # JWT 认证逻辑
│ │ └── upload_routes.py # 文件上传 API
│ ├── ingest/ # 数据接入
│ │ ├── websocket_server.py # WebSocket 处理
│ │ ├── session_manager.py # 会话管理
│ │ └── audio_writer.py # 音频写入
│ ├── realtime/ # 实时处理
│ │ ├── tencent_asr.py # 腾讯云实时 ASR
│ │ ├── llm_harmful_detector.py # LLM 有害语检测
│ │ └── harmful_rules.py # 关键词检测规则
│ ├── offline/ # 离线处理
│ │ ├── offline_worker.py # 离线 ASR + 说话人分离
│ │ ├── tencent_offline_asr.py # 腾讯云录音文件识别
│ │ └── cos_uploader.py # 腾讯云 COS 上传
│ ├── data/ # 数据目录
│ │ └── audio/ # 音频文件存储
│ ├── requirements.txt # Python 依赖
│ └── test_upload.py # 上传测试脚本
├── frontend/ # 前端代码
│ ├── src/
│ │ ├── pages/ # 页面组件
│ │ │ ├── Login.jsx # 登录页
│ │ │ ├── SessionsList.jsx # 会话列表页
│ │ │ └── SessionDetail.jsx # 会话详情页
│ │ └── api/ # API 调用
│ │ └── fetch.js # 数据获取函数
│ ├── index.html # HTML 入口
│ ├── vite.config.js # Vite 配置
│ └── package.json # 前端依赖
├── start.bat # 一键启动脚本(Windows)
├── stop.bat # 一键停止脚本(Windows)
├── .gitignore # Git 忽略文件
└── README.md # 项目文档
-
配置腾讯云密钥(必需)
编辑
backend/config/settings.py,填入您的腾讯云密钥:tencent_secret_id: str = "您的 SecretId" tencent_secret_key: str = "您的 SecretKey" tencent_cos_bucket: str = "您的存储桶名称"
-
双击运行
start.bat将自动启动:
- 后端服务(绿色窗口,端口 8000)
- 前端服务(黄色窗口,端口 3000)
-
访问应用
浏览器打开 http://localhost:3000
-
停止服务
双击运行
stop.bat
后端依赖:
cd backend
pip install -r requirements.txt前端依赖:
cd frontend
npm install编辑 backend/config/settings.py:
# 腾讯云 ASR
tencent_secret_id: str = "AKIDxxxxxxxxxxxx"
tencent_secret_key: str = "xxxxxxxxxxxxxxxx"
tencent_asr_region: str = "ap-guangzhou"
# 腾讯云 COS(对象存储)
tencent_cos_region: str = "ap-guangzhou"
tencent_cos_bucket: str = "your-bucket-name-xxxx"
tencent_cos_use_presigned_url: bool = True # True=私有读写,False=公有读cd backend
python -m uvicorn main:app --host 0.0.0.0 --port 8000 --reload后端服务将在 http://localhost:8000 启动
- API 文档: http://localhost:8000/docs
- WebSocket 端点: ws://localhost:8000/ws
打开新的终端窗口:
cd frontend
npm run dev前端服务将在 http://localhost:3000 启动
首次使用需要创建管理员账号:
cd backend
python create_admin_user.py按提示输入用户名、邮箱、密码等信息。
该功能用于硬件 PCM 分片直传后端,并复用离线识别链路入库。接口说明:
POST /api/ingest/pcm(headers 见协议文档)
GET /api/ingest/status/{session_id}
本地运行步骤:
- 启动后端服务:
python -m backend.main
- 运行测试脚本(生成 2 秒 440Hz PCM 分片并发送):
python tools/test_pcm_ingest.py --base http://localhost:8000
- 查看会话详情:
curl http://localhost:8000/api/sessions/<session_id>
- 访问
audio_url进行播放验证。
- 进入 对象存储 COS 控制台
- 创建存储桶:
- 名称:例如
info-tech-1234567890 - 地域:选择与 ASR 相同的地域(如 ap-guangzhou)
- 访问权限:选择"私有读写"
- 名称:例如
- 记录存储桶名称和地域代码
详细配置说明请参考:backend/COS_SETUP_GUIDE.md
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int | 主键 |
| username | string | 用户名(唯一) |
| string | 邮箱(唯一) | |
| hashed_password | string | 密码哈希(BCrypt) |
| full_name | string | 姓名 |
| is_active | bool | 是否激活 |
| is_admin | bool | 是否管理员 |
| created_at | datetime | 创建时间 |
| 字段 | 类型 | 说明 |
|---|---|---|
| session_id | string | 主键(UUID) |
| device_id | string | 设备 ID |
| user_id | int | 用户 ID(外键) |
| start_time | datetime | 会话开始时间 |
| end_time | datetime | 会话结束时间 |
| audio_path | string | 音频文件路径/COS URL |
| harmful_count | int | 有害句子数量 |
| 字段 | 类型 | 说明 |
|---|---|---|
| id | string | 主键(UUID) |
| session_id | string | 外键 |
| start | float | 句子开始时间(秒) |
| end | float | 句子结束时间(秒) |
| speaker | string | 说话人标签(A/B/C...) |
| text | string | 识别文本 |
| harmful_flag | bool | 是否有害 |
POST /api/auth/register
Content-Type: application/json
{
"username": "testuser",
"email": "test@example.com",
"password": "password123",
"full_name": "测试用户"
}POST /api/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "admin123"
}响应示例:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}GET /api/auth/me
Authorization: Bearer <access_token>GET /api/sessions?page=1&page_size=10
Authorization: Bearer <access_token>GET /api/sessions/{session_id}
Authorization: Bearer <access_token>POST /api/upload
Content-Type: multipart/form-data
Authorization: Bearer <access_token>
file: <audio file> (支持 .wav, .mp3, .m4a, .flac, .ogg, .aac, .wma)响应示例:
{
"session_id": "uuid",
"device_id": "web_upload",
"audio_path": "https://bucket.cos.region.myqcloud.com/audio/file.m4a"
}开始会话:
{
"type": "start_session",
"device_id": "band001"
}音频数据:
- 发送二进制音频帧(PCM 格式,16kHz,16-bit,单声道)
结束会话:
{
"type": "end_session"
}会话已开始:
{
"type": "session_started",
"session_id": "uuid"
}振动指令(检测到有害语):
{
"type": "vibrate",
"pattern": 1,
"severity": 3,
"reason": "威胁性语言"
}会话已结束:
{
"type": "session_ended",
"session_id": "uuid"
}系统检测以下关键词为有害语句:
- 没用
- 废物
- 滚出去
- 闭嘴
- 讨厌你
- 后悔生你
- 打死你
- 蠢
- 笨蛋
- 白痴
- 傻子
- 去死
- 滚
- 混蛋
可在 backend/realtime/harmful_rules.py 中修改规则。
使用 OpenRouter + Gemma 2 27B 模型进行深度语义分析,评估:
- 有害等级(1-5 级)
- 有害类型(侮辱、威胁、情感伤害等)
- 是否需要振动提醒
配置文件:backend/realtime/llm_harmful_detector.py
cd backend
python test_upload.py此脚本会:
- 上传测试音频到 COS
- 触发离线 ASR 处理
- 显示识别结果和说话人分离结果
使用 Python 客户端:
import asyncio
import websockets
import json
async def test_websocket():
uri = "ws://localhost:8000/ws"
async with websockets.connect(uri) as websocket:
# 开始会话
await websocket.send(json.dumps({
"type": "start_session",
"device_id": "test_device_001"
}))
response = await websocket.recv()
print(f"Received: {response}")
# 结束会话
await websocket.send(json.dumps({
"type": "end_session"
}))
response = await websocket.recv()
print(f"Received: {response}")
asyncio.run(test_websocket())- 检查端口 8000 是否被占用:
netstat -ano | findstr :8000 - 检查 Python 依赖是否完整:
pip list - 查看错误日志
- 确认后端是否运行: 访问 http://localhost:8000/docs
- 检查 Vite 代理配置:
frontend/vite.config.js - 查看浏览器控制台错误
- 检查腾讯云密钥是否正确
- 确认已开通语音识别服务
- 检查 COS 存储桶配置
- 查看后端日志中的错误信息
- 确保音频质量良好(清晰、低噪音)
- 说话人声音特征需要有明显差异
- 使用单声道音频(系统会自动处理)
- 当前配置
SpeakerNumber=0自动检测,最多支持 9 个说话人
- 检查文件格式是否支持(.wav, .mp3, .m4a, .flac, .ogg, .aac, .wma)
- 检查 COS 存储桶权限设置
- 确认腾讯云账号余额充足
编辑 backend/realtime/harmful_rules.py:
HARMFUL_KEYWORDS = [
"没用",
"废物",
# 添加新的关键词
"新关键词",
]编辑 backend/realtime/llm_harmful_detector.py:
# 修改有害等级阈值
HARMFUL_THRESHOLD = 3 # 1-5 级
# 修改模型
MODEL = "google/gemma-2-27b-it"编辑 backend/ingest/websocket_server.py:
# 根据有害等级发送不同振动模式
vibration_patterns = {
1: "short", # 轻微有害
2: "medium", # 中度有害
3: "long", # 严重有害
4: "double", # 非常严重
5: "continuous" # 极度有害
}- 后端部署:
# 使用 gunicorn + uvicorn worker
pip install gunicorn
gunicorn backend.main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000- 前端部署:
cd frontend
npm run build
# 将 dist/ 目录部署到 Nginx 或其他静态文件服务器- 数据库迁移到 PostgreSQL(可选):
编辑 backend/config/settings.py:
database_url: str = "postgresql://user:password@localhost/dbname"┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
│ ESP32-S3 │ │ Web Browser │ │ FastAPI │
│ Device │◄───────►│ (Frontend) │◄───────►│ Backend │
└─────────────┘ └──────────────────┘ └──────┬──────┘
│ │
│ WebSocket │
│ (Real-time Audio) │
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ Backend Processing │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ Tencent ASR │ │ LLM Detector │ │ Speaker Diarization │ │
│ │ (Real-time) │ │ (Gemma 2) │ │ (Offline ASR) │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────┐
│ Tencent Cloud │
│ COS Storage │
└───────────────────┘
- ✨ 修复说话人分离功能:使用
ResTextFormat=0获得稳定的说话人 ID - ✨ 完善 ASR 结果解析:支持
Result和ResultDetail两种格式 - ✨ 增强音频上传:支持多种音频格式验证
- ✨ 集成腾讯云 COS:音频文件自动上传到对象存储
- ✨ 实现真实 ASR 处理:替换占位数据为实际识别结果
- ✨ 添加一键启动脚本:Windows 环境一键启动/停止
- 🐛 修复导入错误:统一模块导入路径
- ✨ 添加用户认证系统:JWT + BCrypt
- ✨ 集成 LLM 有害语检测:OpenRouter + Gemma 2 27B
- ✨ 音频文件上传功能:Web 界面上传测试
- 📝 完善文档:添加 COS 配置指南
- 🎉 初始版本发布
- ✨ 实时音频处理 WebSocket
- ✨ 离线 ASR + 说话人分离
- ✨ Web 管理界面
MIT License
如有问题,请通过 GitHub Issues 提交。
当前状态: ✅ 生产就绪
系统已集成真实的腾讯云 ASR 服务和 LLM 智能分析,可用于实际场景。