跳转至

课狐 ClassFox 开发指南

v1.2.0 优化点

  • 品牌升级:产品名统一为“课狐 ClassFox”,Slogan 为 “ClassFox — Hears what you miss.”。
  • 单 exe 启动:release 根目录只保留 课狐ClassFox.exe,应用内负责静默拉起 backend/class-assistant-backend.exe。
  • 启动遮罩:前端首屏新增 logo 启动动画,主窗口与 splash 分离,避免首次启动卡在透明空壳。
  • 紧凑窗口继续打磨:救场 / 进度面板底部返回区整体上移,适配 320 宽主窗口衍生出的各类小尺寸布局。
  • 告警逻辑修正:关键词检测改为只识别当前增量落盘的那一行,避免多行历史文本拼接误报。
  • Local ASR 修正:本地模式增加短时片段拼接与更保守的停顿判定,减少一句话被拆成多个残片。
  • 配置随包下发:build.ps1 会把 api-service/.env.example 同步复制为 release/backend/.env,健康检查结束后再恢复正式配置。

项目概述

课狐 ClassFox 是一个 Windows 桌面悬浮窗应用,目标是把课堂监听、点名预警、AI 救场和课后总结串成一条完整链路。

当前版本已经把最近几轮迭代里最容易出问题的几部分补齐了:

  • 流式 ASR 重复写盘治理
  • 课堂长转录的滚动摘要压缩
  • 开发态与打包态的后端残留进程清理
  • 启动监控前的课程名与资料选择
  • 前端内置 .env 设置编辑面板

技术栈

层级 技术
桌面壳 Tauri 2 + Rust
前端 React 19 + TypeScript + Vite
后端 FastAPI + Uvicorn + Python 3.11
ASR Local / Seed-ASR / DashScope / Mock
LLM OpenAI Compatible API
音频 PyAudio
资料解析 python-pptx / pypdf / python-docx
打包 PyInstaller + Tauri build + build.ps1

目录结构

ClassAssistant/
├── api-service/
│   ├── main.py
│   ├── config.py
│   ├── backend.spec
│   ├── routers/
│   │   ├── monitor_router.py
│   │   ├── ppt_router.py
│   │   ├── rescue_router.py
│   │   ├── settings_router.py
│   │   └── summary_router.py
│   └── services/
│       ├── asr_service.py
│       ├── llm_service.py
│       ├── monitor_service.py
│       ├── ppt_service.py
│       └── transcript_service.py
├── app-ui/
│   ├── src/
│   │   ├── App.tsx
│   │   ├── components/
│   │   │   ├── StartMonitorPanel.tsx
│   │   │   ├── SettingsPanel.tsx
│   │   │   ├── ToolBar.tsx
│   │   │   ├── RescuePanel.tsx
│   │   │   └── CatchupPanel.tsx
│   │   └── services/api.ts
│   └── src-tauri/
│       └── src/lib.rs
├── data/
│   ├── class_transcript.txt
│   ├── current_class_material.txt
│   ├── keywords.txt
│   ├── cite/
│   └── summaries/
├── docs/
├── dev.bat
└── build.ps1

环境准备

Python

项目固定使用 api-service/.venv,后端调试、导入验证和打包都应从这个环境出发。

cd api-service
python -m venv .venv
.venv\Scripts\pip install -r requirements.txt
.venv\Scripts\pip install pyinstaller

Node / Rust

cd app-ui
npm install

需要本机安装 Rust 与 Visual Studio Build Tools,并启用“C++ 桌面开发”工作负载。

环境变量

后端读取 api-service/.env;打包后读取 release/backend/.env。

关键字段:

ASR_MODE=local
SEED_ASR_APP_KEY=
SEED_ASR_ACCESS_KEY=
SEED_ASR_RESOURCE_ID=volc.bigasr.sauc.duration
DASHSCOPE_API_KEY=
LLM_BASE_URL=https://api.deepseek.com
LLM_API_KEY=
LLM_MODEL=deepseek-chat
AUDIO_SAMPLE_RATE=16000
AUDIO_CHANNELS=1
AUDIO_CHUNK_SIZE=3200

前端设置面板通过 GET /api/settings 和 POST /api/settings 直接读写这个文件。

运行方式

一键开发启动

运行根目录 dev.bat。

当前脚本会先做清理,再启动:

  • taskkill class-assistant-backend.exe
  • taskkill 标题为 ClassAssistant-Backend 的后端终端
  • 杀掉占用 8765 端口的监听进程

这样可以避免前端误连到旧的解压版后端或上一次残留的开发后端。

手动启动

后端:

cd api-service
.venv\Scripts\python.exe -m uvicorn main:app --host 127.0.0.1 --port 8765 --reload

前端:

cd app-ui
npm run tauri dev

当前监控链路

1. 开始监控

前端点击“开始摸鱼”后不再直接调用 start_monitor,而是先打开 StartMonitorPanel:

  • course_name:课程名称,可为空
  • cite_filename:从 data/cite 中选一份资料,可为空

后端 monitor_router 会在启动前调用 TranscriptService.activate_cite_file,把选中的 cite 文本复制为 data/current_class_material.txt。

2. 转录写盘策略

MonitorService 现在区分本地 ASR 与在线流式 ASR:

  • Local ASR:保持按句回调,识别到一句就追加一行。
  • Seed-ASR / 其他流式:只落盘最终稳定句,partial 文本仅保存在内存。

核心处理点:

  • _is_meaningful_text:过滤短碎片和纯标点
  • _is_near_duplicate_locked:过滤重复句和相似修正句
  • _append_entry_locked:统一收口写入前的清洗逻辑

3. 滚动摘要

当 _summary_source_entries 累积到 50 条后:

  1. 调用 LLMService.compress_monitoring_progress
  2. 把旧内容压缩进“历史摘要”
  3. 在 class_transcript.txt 中保留:
=== 历史摘要 开始 ===
...
=== 历史摘要 结束 ===

TranscriptService.get_recent_transcript 会自动跳过这段摘要块,只返回近期真实课堂记录供救场与进度总结使用。

ASR 说明

Local ASR

LocalASR 已调整以下参数以提升按句返回速度:

  • energy_threshold = 220
  • pause_threshold = 0.9
  • phrase_threshold = 0.35
  • non_speaking_duration = 0.45
  • phrase_time_limit = 15

另外,MonitorService 针对 Local ASR 新增了短时片段合并逻辑:

  • 如果后一段是前一段的扩展识别结果,则直接覆盖上一条
  • 如果前一段很短,或上一句尚未自然收尾,且两段时间间隔不超过 3 秒,则拼接为同一条
  • 这部分只作用于 Local ASR,不影响 Seed-ASR 的 definite 分句写盘策略

Seed-ASR

Seed 的 bigmodel_async 会持续回传修正中的文本,因此不能直接把 result.text 当成最终记录。

当前实现采用:

  • show_utterances = true
  • result_type = single
  • end_window_size = 800
  • force_to_speech_time = 1000

只处理 utterances 中 definite = true 的稳定分句,并通过 start_time、end_time、text 组合键去重。

另外,_parse_server_response 会忽略空 payload 和非 JSON payload,避免再出现 JSONDecodeError 把线程打崩。

资料上传与引用

上传接口仍然是 POST /api/upload_ppt,但行为已调整:

  • 解析后的文本不再直接覆盖 current_class_material.txt
  • 会写入 data/cite/_.txt
  • 前端收到 cite_filename 后刷新可选资料列表

这使得一个项目目录可以同时保留多份课程资料,真正开始监听时再决定用哪一份做 LLM 辅助上下文。

设置面板

新增 SettingsPanel.tsx,功能很直接:

  • 打开时请求 /api/settings 读取当前 .env
  • 主要字段表单化编辑,额外原始配置保留在高级文本域
  • 提交时调用 /api/settings 保存
  • 面板打开时把窗口放大到 480x520,关闭时恢复到 320x80
  • 底部保存 / 取消操作栏采用悬浮布局,并继续上移以避开小窗底边遮挡

这部分没有做字段级表单化,目的是先把运维动作缩短为最少路径。

打包与发布

打包命令:

./build.ps1 v1.2.0

build.ps1 目前包含以下关键步骤:

  1. 更新 package.json、Cargo.toml、tauri.conf.json 版本号
  2. 使用 .venv 中的 PyInstaller 执行 backend.spec
  3. 执行 npx tauri build --no-bundle
  4. 组装只含单一 launcher exe 的 release 目录
  5. 把 api-service/.env.example 同步复制为 release/backend/.env 与 .env.example
  6. 用独立端口 18765 启动打包后端做健康检查,完成后恢复正式配置
  7. 输出 zip 包

当前发布目录根部不再生成 启动.bat,release/backend/.env 会在打包阶段直接准备好,默认可用试用配置随包下发。

最近已经验证过完整流程能成功产出 zip 包,之前的“无法连接后端”问题当前代码下未复现。

启动与退出清理

为避免端口 8765 被旧实例占住,当前有三层清理:

  • dev.bat 启动前清理
  • 打包版主程序启动前清理
  • app-ui/src-tauri/src/lib.rs 在窗口退出时清理

Rust 侧清理范围包括:

  • class-assistant-backend.exe
  • 标题为 ClassAssistant-Backend 的终端
  • 占用 8765 端口的监听进程

调试建议

后端健康检查

  • GET /api/health
  • GET /api/check_mic
  • GET /docs

常见排查顺序

  1. 先确认是否用了 api-service/.venv。
  2. 再确认 8765 端口没有被旧后端占用。
  3. 如果是打包问题,查看 release/data/_startup.log。
  4. 如果是 Seed-ASR 问题,优先看 definite utterance 是否正常产生。
  5. 如果是救场或进度总结异常,检查 class_transcript.txt 与 current_class_material.txt 是否按预期更新。

维护建议

  • data/cite 属于运行时数据,不应提交到仓库。
  • docs/img 下的 GIF 属于产品演示资源,应随 README 一起维护。
  • 修改监控链路时,优先保证 Local ASR 与 Seed-ASR 逻辑分离,不要把流式修正文处理强行套给本地按句模式。
  • 修改 build.ps1 或 backend.spec 后,最好完整跑一次 ./build.ps1 验证健康检查步骤。
  • 新增 dev.bat 一键启动前后端

2026-03-05:打包发布 + Bug 修复

  • PyInstaller 打包后端 (onedir 模式) → class-assistant-backend.exe
  • Tauri 打包前端 → 上课摸鱼搭子.exe
  • 发布包 ClassAssistant-v0.1.0-win-x64.zip,含 启动.bat 一键启动
  • 修复 PyInstaller 误打包 tesseract 的损坏 libfribidi-0.dll(在 backend.spec 中过滤)
  • Seed-ASR 连接前添加 resource_id 日志,便于排查配置错误

2026-03-06:稳定版收敛与体验优化

  • 关键词外部文件:从内置硬编码改为从 data/keywords.txt 加载,用户可自由编辑
  • 新增 POST /api/reload_keywords 热重载接口
  • 启动监控时自动重载关键词文件
  • 本地 ASR:新增 local 模式,默认可用,无需外部 ASR 密钥
  • 在线 ASR 修复:Seed-ASR 改为收发分离线程,恢复稳定出字
  • 实时转录策略升级:在线 ASR 保持活动行覆盖;本地 ASR 改为逐句追加新行
  • 关键词检测优化:从增量检测调整为检查最近两行,减少重复警报
  • 新增课堂进度接口POST /api/catchup,前端新增“老师讲到哪了”面板
  • 路径配置收敛:新增 config.py,统一处理开发模式与打包模式下的 DATA_DIR
  • 一键打包脚本build.ps1 / build.bat 支持版本同步、后端健康检查、zip 发布
  • 启动脚本优化:发布包启动前自动清理 8765 端口占用进程,避免误连开发后端
  • 发布包数据定位修复:打包版统一写入解压目录下的 data/,并写入 _startup.log 便于排查
  • 开发体验修复dev.bat 退出时自动清理后端窗口,不再残留命令行进程