目录

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

模块定位:多模态实时事件提取模块,是大型系统中的中间层组件,专注于感知和事件解析。

部署架构

  • 部署位置:边缘服务器(局域网内的 NUC/工控机 + GPU)
  • 不是:手机 App(手机性能不足,只能达到 5-8 FPS,无法实时处理 30fps 视频)
  • 原因:需要 30-60 FPS 实时处理能力,延迟要求 40-60ms

数据流向

输入:终端设备(摄像头/麦克风)→ [蓝牙/WiFi] → 边缘服务器
处理:三个管道(视觉/音频/飞书)→ AI 推理 → 事件提取
输出:结构化 A 层事件(JSON)→ 下游模块(云端服务/手机 App/其他系统)

核心功能:实时监控摄像头、录音机、飞书等多路输入,将感知信息解析为结构化的 A 层事件(JSON 格式),供下游模块消费。

实现进度

  • Phase 1(视觉管道):已实现(face_detection、person_track、scene_detection)
  • Phase 2(音频管道):已实现(speech_segment,含声纹 embedding)
  • Phase 3(飞书管道):已实现(ui_state_change、notification_event)

性能指标(边缘服务器 GPU 模式):

  • 视觉管道:30-60 FPS(1080p 视频)
  • 音频管道:20x 实时速度
  • 端到端延迟:40-60ms

项目结构

国创赛/
├── src/
│   ├── __init__.py
│   ├── core/                  # 核心模块
│   │   ├── __init__.py
│   │   ├── config.py          # 全局配置(阈值、路径、设备等)
│   │   ├── schemas.py         # 事件数据模型(BaseEvent 及各子类)
│   │   ├── utils.py           # 工具函数(日志、ID 生成、bbox 操作)
│   │   └── event_generator.py # 事件生成(EventGenerator)和输出(EventSink,线程安全)
│   ├── vision/                # 视觉管道模块
│   │   ├── __init__.py
│   │   ├── face_analyzer.py   # 人脸检测 + embedding(insightface)
│   │   ├── scene_classifier.py # 场景描述生成(Florence-2)
│   │   └── vision_pipeline.py # 视觉管道核心(VisionPipeline、TrackStateManager、SceneStateTracker)
│   ├── audio/                 # 音频管道模块
│   │   ├── __init__.py
│   │   ├── audio_vad.py       # 人声检测(Silero-VAD,SpeechSegment 数据类)
│   │   ├── audio_asr.py       # 语音识别(FunASR SenseVoice,支持 ITN 标点与逆文本正则化)
│   │   ├── audio_embedder.py  # 声纹 embedding(WeSpeaker ResNet34 ONNX,256 维)
│   │   └── audio_pipeline.py  # 音频管道核心(AudioPipeline)
│   └── feishu/                # 飞书管道模块
│       ├── __init__.py
│       ├── feishu_client.py   # 飞书 API 客户端(WebSocket/Webhook 连接、事件监听)
│       └── feishu_pipeline.py # 飞书管道核心(FeishuPipeline)
├── run_vision_pipeline.py     # 视觉管道入口脚本
├── run_audio_pipeline.py      # 音频管道入口脚本
├── run_feishu_pipeline.py     # 飞书管道入口脚本
├── run_integration.py         # 串行集成测试(视觉 → 音频,顺序执行)
├── run_parallel.py            # 并行集成测试(视觉 + 音频,时间轴对齐)
├── models/
│   ├── AI-ModelScope/
│   │   └── Florence-2-base/   # Florence-2 模型权重(本地)
│   └── wespeaker/
│       └── wespeaker-cnceleb-resnet34-LM/  # WeSpeaker 声纹模型(ONNX)
├── data/                      # 测试视频目录
├── outputs/                   # 输出目录(自动创建)
│   ├── events.jsonl           # 事件输出(JSONL,每行一个事件)
│   ├── vision_pipeline.log    # 视觉管道日志
│   ├── audio_pipeline.log     # 音频管道日志
│   └── feishu_pipeline.log    # 飞书管道日志
├── botsort_custom.yaml        # BoTSort 追踪器配置
├── yolo12n.pt                 # YOLOv8-Nano 模型权重
├── requirements.txt           # 依赖列表
├── 事件规范格式.md             # A 层事件 schema 规范
└── 技术路线.md                # 项目技术路线

视觉管道架构

每帧按顺序执行三个步骤:

1. 人体检测与追踪(快线路)

  • YOLOv8-Nano 检测人体 → BoTSort 维持跨帧 track_id
  • 同时收集非人物体类别(COCO 80 类),存入 self._scene_objects,供场景事件 payload 使用

2. 人脸分析(全帧检测 + 追踪关联)

  • insightface(buffalo_l)在完整帧上检测所有人脸并计算 embedding
  • 用人脸中心点是否落在追踪框内进行关联(match_faces_to_tracks
  • 每帧合格人脸生成一个 face_detection 事件(含 512 维 L2 归一化 embedding)
  • 追踪结束时生成一个 person_track 事件(含代表性 embedding)

注意:必须在完整帧上做人脸检测,裁剪图像分辨率太低会导致检测失败。

3. 场景描述(两级触发)

  • 第一级(每帧,零成本):HSV 直方图对比,检测到疑似场景变化才触发第二级
  • 第二级(按需,冷却期保护):调用 Florence-2 对完整帧生成自由文本描述
  • 每次触发关闭上一个场景事件(记录起止时间)、开启新场景
  • 场景事件在 scene_label 字段存放 Florence-2 生成的自然语言描述

时间戳:并行模式下使用视频时间 start_time + frame_idx / video_fps,与音频时间戳对齐。

音频管道架构

流程: 提取音轨(ffmpeg)→ VAD(Silero-VAD)→ ASR + 声纹 embedding(并行推理)→ SpeechSegmentEvent

1. 音轨提取

  • ffmpeg subprocess 提取视频音轨为 16kHz 单声道 float32 PCM
  • 不依赖 torchaudio(2.10 移除了旧 backend)

2. VAD 人声检测(Silero-VAD)

  • chunk 大小严格为 512 samples(32ms@16kHz,VAD 硬性要求)
  • onset=0.5 / offset=0.35,最短语音段 300ms,最长 30s
  • 过滤掉背景音乐、环境音等非人声片段

3. ASR(FunASR SenseVoice)

  • 不挂 vad_model(VAD 已由 Silero 独立处理)
  • use_itn=True,输出含标点和逆文本正则化(ITN)
  • 首次运行自动下载到 ~/.cache/modelscope/
  • SenseVoice 输出自带语种/情绪标签(如 <|zh|><|NEUTRAL|><|Speech|>),text 字段为纯汉字

4. 声纹 Embedding(WeSpeaker ResNet34 ONNX)

  • 输入:80 维 Log-Mel Fbank,自实现特征提取(不依赖 wespeaker 包)
  • 输出:256 维 L2 归一化声纹向量,与 face_embedding 结构对齐
  • 模型路径:models/wespeaker/wespeaker-cnceleb-resnet34-LM/cnceleb_resnet34_LM.onnx

飞书管道架构

流程: 飞书事件监听(WebSocket/Webhook)→ 事件解析 → A 层事件转换 → EventSink

连接模式:

  • WebSocket 模式(推荐):长连接,实时接收飞书推送事件,无需公网 IP
  • Webhook 模式:HTTP 回调,需要公网可访问地址,适合生产环境

支持的飞书事件类型:

1. 消息事件(im.message.receive_v1)→ notification_event

  • 监听私聊(p2p)和群聊(group)消息
  • 提取发送者、消息内容、聊天 ID
  • 支持文本、图片、文件、富文本等多种消息类型
  • 输出 notification_event,subtype 为 message_notification

2. Bot 加入群聊(im.chat.member.bot.added_v1)→ ui_state_change

  • Bot 被添加到群聊时触发
  • 输出 ui_state_change,subtype 为 chat_thread_opened

3. 群聊更新(im.chat.updated_v6)→ ui_state_change

  • 群聊信息变更(名称、描述等)时触发
  • 输出 ui_state_change,subtype 为 group_updated

4. 日历事件(calendar.calendar.event.created_v6)→ notification_event

  • 新日程创建时触发
  • 输出 notification_event,subtype 为 calendar_reminder

时间戳:所有飞书事件使用接收时的系统时间 datetime.now()

并行处理与时间轴对齐

run_parallel.py 使用 threading 同时运行两个管道:

shared_start_time = datetime.now()   # 两管道共用时间基准
# 视觉管道:event_ts = shared_start_time + frame_idx / video_fps
# 音频管道:event_ts = shared_start_time + segment.start_sec
  • EventSink 加了 threading.Lock,两个线程安全并发写入同一文件
  • 模型预加载在主线程完成(串行),避免并发下载冲突
  • 音频管道使用外部传入的 EventSink 时不自动关闭(_owns_sink=False

运行方式

source linux_env/bin/activate

# 视觉管道(单独)
python run_vision_pipeline.py --video data/xxx.mp4 --max-frames 750

# 音频管道(单独)
python run_audio_pipeline.py --output outputs/audio_events.jsonl

# 飞书管道(单独,需配置 FEISHU_APP_ID 和 FEISHU_APP_SECRET)
python run_feishu_pipeline.py

# 串行集成测试
python run_integration.py --max-frames 750

# 并行集成测试(推荐,时间轴对齐)
python run_parallel.py --max-frames 750

关键配置(src/config.py)

参数 默认值 说明
DEVICE "cuda" 计算设备,无 GPU 时自动降级为 CPU
YOLO_CONF_THRESHOLD 0.5 人体检测置信度阈值
MIN_FACE_QUALITY 0.3 人脸质量过滤阈值
MIN_TRACK_AGE 5 最少持续帧数,达到才输出 person_track 事件
FACE_REEMBED_INTERVAL 15 每 N 帧重新计算人脸 embedding
ENABLE_SCENE_CLASSIFICATION True 是否启用场景描述
FLORENCE2_MODEL_DIR models/AI-ModelScope/Florence-2-base Florence-2 模型路径
SCENE_CHANGE_THRESHOLD 0.85 直方图相关性阈值
SCENE_CHANGE_COOLDOWN_SEC 3.0 Florence-2 推理最小间隔(秒)
AUDIO_SAMPLE_RATE 16000 音频采样率(VAD/ASR/声纹统一要求)
AUDIO_CHUNK_SAMPLES 512 Silero-VAD chunk 大小(严格要求)
VAD_ONSET_THRESHOLD 0.5 语音段开始阈值
VAD_OFFSET_THRESHOLD 0.35 语音段结束阈值
ASR_MODEL "iic/SenseVoiceSmall" FunASR SenseVoice 模型名称
VOICE_EMBEDDER_MODEL_PATH models/wespeaker/.../cnceleb_resnet34_LM.onnx 声纹模型路径
FEISHU_APP_ID "" 飞书应用 App ID
FEISHU_APP_SECRET "" 飞书应用 App Secret
FEISHU_BOT_MODE "websocket" 连接模式(websocket 或 webhook)
FEISHU_WEBHOOK_PORT 8080 Webhook 模式监听端口
FEISHU_VERIFICATION_TOKEN "" Webhook 模式验证 token
FEISHU_ENCRYPT_KEY "" Webhook 模式加密 key
EVENT_OUTPUT_FILE outputs/events.jsonl 事件输出路径

模型依赖

  • yolo12n.pt - YOLOv8-Nano,位于项目根目录
  • insightface buffalo_l - 人脸检测 + ArcFace embedding,自动下载到 ~/.insightface/
  • Florence-2-base - 场景描述,models/AI-ModelScope/Florence-2-base/
    • 必须用 modelscope.AutoModelForCausalLM 加载,需 trust_remote_code=True
    • 需要 einopstimm 依赖
  • FunASR SenseVoice - ASR,首次运行自动下载到 ~/.cache/modelscope/
  • WeSpeaker ResNet34 - 声纹,models/wespeaker/wespeaker-cnceleb-resnet34-LM/
    • 使用 ONNX 推理,不依赖 wespeaker Python 包(包有依赖冲突)
    • 需手动从 HuggingFace 下载真实模型文件(非 LFS 指针)

安装方法

1. 克隆仓库

git clone <repository-url>
cd 国创赛

2. 安装系统依赖

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y libgl1 ffmpeg

# macOS
brew install ffmpeg

3. 创建虚拟环境并安装 Python 依赖

# 创建虚拟环境(Python 3.10)
python3.10 -m venv linux_env

# 激活虚拟环境
source linux_env/bin/activate  # Linux/macOS
# 或 linux_env\Scripts\activate  # Windows

# 安装依赖
pip install -r requirements.txt

4. 下载模型文件

YOLOv8 模型:

  • 下载 yolo12n.pt 到项目根目录

Florence-2 模型:

  • 下载到 models/AI-ModelScope/Florence-2-base/
  • 或首次运行时自动下载

WeSpeaker 声纹模型:

# 从 HuggingFace 下载(确保下载真实文件,非 LFS 指针)
mkdir -p models/wespeaker/wespeaker-cnceleb-resnet34-LM
# 下载 cnceleb_resnet34_LM.onnx 到上述目录

insightface 模型:

  • 首次运行时自动下载到 ~/.insightface/

FunASR 模型:

  • 首次运行时自动下载到 ~/.cache/modelscope/

环境与依赖

  • Python: 3.10
  • 虚拟环境: ./linux_env/
  • 主要依赖: ultralytics、insightface、onnxruntime、opencv-python、numpy、modelscope、transformers==4.40.0、einops、timm、funasr、silero-vad、soundfile、librosa、lark-oapi
  • 系统依赖: libgl1sudo apt-get install -y libgl1)、ffmpeg(手动安装)

重要:Florence-2 需要 transformers==4.40.0,不能升级到 5.x(会导致 Florence2LanguageConfig 兼容性错误)。

重要AUDIO_CHUNK_SAMPLES 固定为 512,Silero-VAD 硬性要求,不可修改。

性能指标(CPU,1080p 视频)

管道 性能
视觉管道(YOLO + insightface + Florence-2) ~8-10 FPS
音频管道(VAD + ASR + 声纹) ~12x 实时速度(50s 视频 4s 处理完)
并行集成(视觉 + 音频同时) 视觉约 8.7 FPS,音频 4s 内完成

事件输出格式

输出文件 outputs/events.jsonl,每行一个 JSON 事件。

face_detection:每帧每个合格人脸输出,含 bbox、face_quality、512 维 face_embedding

person_track:追踪结束时输出,含 track_id、face_event_ids、representative_embedding

scene_detection:场景切换时输出,含 scene_label(Florence-2 描述)、objects、subtype=”generated_description”

speech_segment:每段语音结束时输出,payload 含:

  • text:ASR 识别文本(纯汉字,含标点,已 ITN 处理)
  • language"zh"
  • turn_index:本次会话第几段话
  • audio_features{volume, speech_rate}
  • voice_embedding{model, vector(256维), vector_dim, norm="l2"}

ui_state_change(飞书管道):UI 状态变化事件,payload 含:

  • subtype"chat_thread_opened""group_updated"
  • app_name"Feishu"
  • page_type"group_chat"
  • thread_id:飞书聊天 ID(格式:feishu_{chat_id}

notification_event(飞书管道):通知事件,payload 含:

  • subtype"message_notification""calendar_reminder"
  • app_name"Feishu"
  • notification_type"dm_message" / "group_message" / "calendar_event"
  • title:发送者或日程标题
  • preview_text:消息预览文本(截断至 200 字符)
  • thread_id:关联的聊天或日历 ID
  • priority_hint:优先级提示("unknown" / "normal"

已知问题与注意事项

  • insightface 模型加载日志(duplicated model: w600k_r50.onnx)属正常现象
  • FunASR 加载时打印 trust_remote_code: False 属正常现象(SenseVoice 默认关闭 remote_code)
  • WeSpeaker 不使用 Python 包(pip install wespeaker 有 s3prl/torchaudio 兼容性问题),直接 ONNX 推理
  • WeSpeaker 模型从 HuggingFace 下载时需确保是真实文件(26MB ONNX,34MB pt),非 Git LFS 指针
  • torchaudio 2.10 移除了旧 audio backend,读取视频音轨改用 ffmpeg subprocess
  • 测试时建议视觉管道用 --max-frames 750 限制帧数,音频管道处理全视频(前段无人声由 VAD 过滤)
关于
167.8 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802032778号