17 KiB
经验记录(Knowledge Base)
本文件按代码编纂工作流规范,以四段式记录项目修改过程中遇到的关键问题及解决方案。
格式: A. 具体问题 / B. 产生原因 / C. 解决方案 / D. 后续如何避免
2026-04-29-23-28-13 — 视频帧显示链路全修复
A. 具体问题
- 项目库中没有默认视频
Data_MyVideo_1.mp4 - 分割工作区点击视频后画面一片黑(无影像)
- 导入新视频后进入工作区同样看不到视频帧
B. 产生原因
- 后端 lifespan 没有任何自动扫描/注册本地视频的逻辑;
server.ts的硬编码项目对前端不可见 CanvasArea.tsx硬编码了一张 Unsplash 外链,没有从 Zustand store 读取帧数据;进入工作区时不调用帧列表 API- 上传流程不完整:未先创建项目再带 project_id 上传,上传后未触发
/api/media/parse帧提取;后端/frames返回的是 MinIO 对象名而非可访问的 presigned URL;MinIO presigned URL 的 host 为localhost:9000,浏览器端无法访问 - 系统磁盘空间(24GB)紧张,MinIO 在提取大量高清 PNG 帧时触发
XMinioStorageFull,导致帧上传失败
C. 解决方案
- 后端默认视频种子:
main.pylifespan 中启动后台线程,自动检测Data_MyVideo_1.mp4,创建 Project → 上传 MinIO → 调用 FFmpeg 解析帧 → 注册 Frame 记录 - 后端帧 URL 修复:
projects.py的list_frames在返回前为每个frame.image_url调用get_presigned_url()生成带签名的可访问 URL - 后端 presigned URL host 修复:
.env中MINIO_ENDPOINT从localhost:9000改为192.168.3.11:9000,确保浏览器端可访问 - 后端 ProjectOut 增强:
schemas.py添加frame_count,projects.py在查询时计算len(p.frames),供前端显示帧数 - 后端 upload 自动创建项目:
media.py的upload_media在不传project_id时自动以文件名创建 Project 并关联视频 - 前端帧加载中枢:
VideoWorkspace.tsx在currentProject变化时调用getProjectFrames,若帧数为 0 则自动触发parseMedia,获取后映射写入 Zustand store - 前端 Canvas 真实渲染:
CanvasArea.tsx接收frameUrlprop,使用useImage(frameUrl)加载真实帧,AI 推理也使用当前帧 URL - 前端时间轴真实帧:
FrameTimeline.tsx从 store 读取frames和currentFrameIndex,渲染真实帧缩略图<img>,点击切换当前帧 - 前端上传链路完善:
ProjectLibrary.tsx上传流程改为:创建项目 →uploadMedia(file, projectId)→parseMedia(projectId)→ 刷新列表 - 磁盘空间优化:将
frame_parser.py的 FFmpeg 输出从 PNG (1920px, ~3MB/张) 改为 JPEG (640px, ~30KB/张),并限制默认视频只提取 100 帧,避免 MinIO 存储溢出
D. 后续如何避免问题
- MinIO endpoint 必须使用服务器 IP:任何生成外部可访问 URL 的服务(MinIO presigned、后端 baseURL、WebSocket)都必须使用服务器 LAN IP,禁止 localhost
- 大文件/视频处理必须考虑磁盘预算:提取帧前估算总大小(帧数 × 单帧大小),必要时降低分辨率、改格式为 JPEG、限制 max_frames
- 前后端数据字段必须显式映射:后端 snake_case 与前端 camelCase 不一致时,API 层必须做转换,不能依赖隐式兼容
- 上传-解析-显示链路必须闭环测试:任何涉及文件上传的功能,测试用例必须覆盖:上传 → 后端存储 → 解析 → 前端获取 → 前端渲染 的全流程
2026-04-29-23-15-26 — 上传/WS/项目库三 Bug 联修
A. 具体问题
- 上传成功后控制台打印
undefined,前端显示 url 为undefined - React StrictMode 下 Dashboard 页面切换时报
InvalidStateError: WebSocket is closed before the connection is established - 上传完成后项目库为空,不显示新上传的项目
B. 产生原因
- 后端
media.py上传接口返回字段为{object_name, file_url, size, message},而前端api.ts的uploadMedia直接return response.data,调用方解构const { url, id }时url为undefined - React 18 StrictMode 在开发环境下会 double-mount/unmount,
Dashboard.tsx的useEffectcleanup 调用progressWS.disconnect(),后者无条件执行this.ws.close();若此时 WebSocket 仍处于CONNECTING(状态 0),调用.close()会抛出 InvalidStateError uploadMedia只将文件存入 MinIO,未调用createProject创建数据库记录,也未在成功后主动刷新项目列表
C. 解决方案
api.ts: 解构file_url和object_name,返回{ url: file_url, id: object_name }websocket.ts:disconnect()中增加readyState === WebSocket.OPEN判断,仅对已连接套接字调用.close()ProjectLibrary.tsx:uploadMediaresolve 后调用getProjects()并setProjects()刷新列表Dashboard.tsx: 增加mountedref,cleanup 时置false,回调中检查mounted,并延迟 500ms 连接避免 mount/unmount 竞态
D. 后续如何避免问题
- 前后端接口契约必须显式文档化:新建/修改 API 时同步更新接口文档,字段名变更需两端对齐
- WebSocket 生命周期防御编程:所有
.close()调用前必须检查readyState,connect/disconnect 需幂等 - 副作用清理必须防竞态:useEffect 中任何异步回调(setInterval、setTimeout、event listener)都需配合
mounted或 AbortController - 上传后必须刷新列表:任何创建资源的操作成功后,应主动重新拉取列表或返回完整资源对象写入本地状态
2026-04-28-22-55-15 — 建立代码编纂工作流
A. 具体问题
项目缺少标准化的代码修改流程,导致需求管理、方案设计、测试验证、知识沉淀等环节可能遗漏,影响项目质量和可维护性。
B. 产生原因
项目初期以快速原型为主,未建立正式的工程化管理流程;随着功能增加,需要更严谨的变更管理机制。
C. 解决方案
建立完整的代码编纂工作流,包含 10 个阶段:时间戳记录、工程分析、需求分析、实现方案(人工审核)、测试方案(人工审核)、执行前准备(阅读经验记录)、方案执行、经验沉淀、Gitea 备份、重新部署。
D. 后续如何避免问题
- 后续所有项目修改严格按工作流执行
- 每次修改前检查工作流检查表
- 定期回顾经验记录,提取共性预防措施
2026-04-28-22-55-15 — 执行环境 Node.js 缺失
A. 具体问题
执行 npm run lint 和 npm run build 时提示 npm: command not found,当前 Shell 环境未安装 Node.js 运行时。
B. 产生原因
AI 助手运行的容器/环境与项目实际开发环境分离,后者才装有 Node.js 和 npm。
C. 解决方案
- 文档创建和 git 操作可在 AI 环境中完成
- 构建验证(
npm run lint、npm run build、npm start)需由用户在本地开发环境执行,或 AI 提供精确命令由用户自行运行 - 实际解决: 用户提供了 sudo 权限和密码后,AI 通过 NodeSource 安装了 Node.js 22.x(
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash+sudo apt install -y nodejs),随后成功执行了完整部署流程 - 在经验记录中标注此限制和解决方案,提醒后续流程
D. 后续如何避免问题
- 每次执行阶段 6 和阶段 9 前,先检查
which npm - 如 npm 不可用,向用户申请 sudo 权限安装 Node.js,或使用项目预设的容器/CI 环境
- 如用户无法提供 sudo,则提供精确的手动执行命令清单
- 考虑在 CI/CD 流程中统一构建环境
2026-04-29-21-27-10 — 组件目录扁平化重构
A. 具体问题
将 src/components/ 下 7 个子目录共 11 个组件文件扁平化到根目录时,需要同步更新多处 import 相对路径,存在遗漏风险。
B. 产生原因
组件文件在子目录中时,引用 lib/utils.ts 的路径为 ../../lib/utils,引用其他组件的路径为 ../workspace/XXX;扁平化到根目录后,这些路径需分别变更为 ../lib/utils 和 ./XXX。涉及文件多、路径变体多,手工逐一修改容易遗漏。
C. 解决方案
- 重构前先通过
grep全局扫描所有 import 语句,建立完整的"文件-旧路径-新路径"映射表 - 移动文件和修改路径分两步执行,每步完成后都用 grep 验证旧路径模式是否完全消失
- 最后运行
npm run lint和npm run build作为最终校验,TypeScript 编译器会捕获任何遗漏的路径错误
D. 后续如何避免问题
- 任何涉及文件移动的 refactoring,都必须先全局 grep 所有相对路径引用,形成清单后再执行
- 执行后立即用 grep 反向验证旧路径模式残留
- 始终将
npm run lint作为路径重构后的强制检查步骤
2026-04-29-21-51-19 — 全栈系统改造(FastAPI + SAM2 + PostgreSQL + Redis + MinIO)
A. 具体问题
- 将纯前端 React 应用改造为全栈系统时,工程涉及后端框架替换、数据库设计、对象存储、AI 推理引擎、前端状态管理重构等多个复杂模块,单次执行工程量大。
- 系统磁盘空间(24G)不足,PyTorch CUDA 版本(>2GB)和 sam2 pip 包编译(需下载 CUDA 工具链 + 编译 C++ 扩展)均因
OSError: No space left on device失败。 - MinIO 对象存储在磁盘紧张时报
XMinioStorageFull,导致文件上传失败。 - 前端 Agent 执行时因目录扁平化后子目录不存在,产生多次
File not found错误。
B. 产生原因
- 项目改造范围超出单次会议合理容量,涉及 15+ 后端文件、10+ 前端文件、4 个基础设施服务、1 个 AI 模型栈。
- 系统盘仅有 24GB,conda 环境(2GB)、node_modules(222MB)、模型权重(1.5GB)、MinIO 帧文件(1.4GB)叠加后迅速耗尽空间。
- sam2 的 pip 包依赖 torch>=2.5.1,pip 会尝试重新下载完整 torch wheel(530MB)作为 build dependency,即使 torch 已安装。
- 前端 Agent 的 prompt 中未明确说明组件目录已扁平化,Agent 仍尝试读取旧的子目录路径。
C. 解决方案
- 任务拆分 + 并行 Agent: 将后端和前端代码编写拆分为两个独立 Agent 并行执行,基础设施安装与代码编写并行推进,显著缩短总耗时。
- 磁盘管理策略:
- 安装 PyTorch CPU 版本替代 CUDA 版本(占用更小)
- 只保留 sam2_hiera_tiny.pt(149MB),删除其他大模型
- 清理 conda pkgs 缓存(释放 600MB+)
- 删除 MinIO 中解析生成的临时帧文件(释放 1.4GB)
- sam2 安装降级: 当前环境以 stub 模式运行,提供
install_sam2.sh脚本供用户在扩展磁盘后执行真实安装。 - API 路径修复: 后端添加
/api/auth/login路由,修复前端 api.ts 中/api/predict→/api/ai/predict的路径不匹配。 - MinIO API 适配: minio 7.2.x 中
presigned_url()已改为get_presigned_url(),需从datetime.timedelta传入 expires。
D. 后续如何避免问题
- 大型改造前先做磁盘评估: 执行
df -h确认可用空间 > 5GB 再开始安装大型依赖。 - AI 模型依赖延迟加载: 所有 AI 推理引擎必须实现 graceful fallback,模型缺失时不阻塞系统启动。
- Agent prompt 需同步最新目录结构: 给 Agent 的上下文必须包含当前真实的文件路径,避免
File not found。 - 构建依赖隔离: 使用
--no-build-isolation或--no-deps安装源码包,避免 pip 重复下载已安装的依赖。 - MinIO 空间监控: 定期清理解析产生的临时帧文件,或配置 MinIO 使用独立大容量数据盘。
2026-04-29-22-29-26 — README.md 完善
A. 具体问题
项目全栈改造完成后,README.md 仍为旧版 AI Studio 模板,未反映真实系统架构和部署流程,新用户无法按文档独立完成部署。
B. 产生原因
前期聚焦功能开发,文档滞后;改造涉及后端/前端/基础设施/AI 模型多个层级,文档编写工作量大。
C. 解决方案
按代码编纂工作流,编写需求分析→实现方案→测试方案,然后一次性重写 README.md,涵盖系统架构、技术栈、目录结构、分步部署命令、环境变量、访问凭证、常见问题。
D. 后续如何避免问题
- 任何架构级变更后,同步更新 README.md
- 将 README 纳入代码审查清单
- 新成员入职时按 README 走通部署流程作为验收标准
2026-04-29-22-37-36 — 登录报错 ERR_CONNECTION_REFUSED
A. 具体问题
用户通过浏览器访问前端并点击登录时,控制台报错 POST http://localhost:8000/api/auth/login net::ERR_CONNECTION_REFUSED,登录失败。
B. 产生原因
- 前端
api.ts中baseURL硬编码为http://localhost:8000 - 用户通过局域网 IP(如
http://192.168.3.11:3000)访问前端,而非http://localhost:3000 - 浏览器运行前端代码时,将
localhost解析为用户本地机器(而非服务器),向用户本地 8000 端口发请求 - 用户本地 8000 端口无服务,TCP 连接被拒绝
- 同时后端 CORS 配置仅允许
http://localhost:3000,未允许 IP 地址访问
C. 解决方案
- 将
src/lib/api.ts的baseURL从http://localhost:8000改为服务器实际 IPhttp://192.168.3.11:8000 - 将
backend/config.py的cors_origins从["http://localhost:3000"]扩展为["http://localhost:3000", "http://192.168.3.11:3000"] - 重启后端服务使 CORS 生效,重新构建前端使 baseURL 生效
D. 后续如何避免问题
- 部署时统一使用服务器实际 IP 替代 localhost,避免浏览器端解析歧义
- 前端 baseURL 应支持环境变量配置(如
VITE_API_BASE_URL),不同环境注入不同值 - 后端 CORS origins 应使用配置化列表,支持开发/测试/生产多环境
- 在 README 中明确说明访问地址,提醒用户必须使用服务器 IP 而非 localhost
2026-04-29-22-49-38 — WebSocket 404 + 项目状态异常 + 导入按钮无响应
A. 具体问题
- 控制台报错
WebSocket connection to 'ws://localhost:8000/ws/progress' failed - 项目库中"测试视频项目"状态显示为"异常"(红色)
- "导入多媒体资源"按钮点击无反应
B. 产生原因
websocket.ts仍为ws://localhost:8000/ws/progress,未随前端 baseURL 一起改为服务器 IP- FastAPI 后端未实现
/ws/progressWebSocket 路由 - Uvicorn 缺少 WebSocket 支持库(
websockets或wsproto未安装) - 后端
Project模型默认状态为"pending",前端只识别"Ready"/"Parsing",其他状态均显示"异常" ProjectLibrary.tsx中"导入多媒体资源"按钮为纯静态<button>,无onClick事件和隐藏的<input type="file">
C. 解决方案
websocket.tsURL 改为ws://192.168.3.11:8000/ws/progressbackend/main.py添加@app.websocket("/ws/progress")路由 +ConnectionManager连接管理pip install websockets为 Uvicorn 提供 WebSocket 协议支持- 后端
Project.status默认值从"pending"改为"Ready" - 前端增加
'pending'/'Pending'状态分支显示"待处理" - 为导入按钮添加
onClick+useRef<HTMLInputElement>+ 隐藏文件输入框,调用uploadMediaAPI
D. 后续如何避免问题
- 任何涉及网络地址的配置(HTTP / WebSocket)必须同步修改,不能遗漏
- 新增 WebSocket 功能时,同步检查 Uvicorn 是否安装了协议支持库
- 前后端状态枚举值必须对齐,或后端返回时做映射转换
- 所有按钮类 UI 元素必须绑定事件处理器,禁止纯装饰性按钮
2026-04-29-23-02-56 — Logo 部署 + Favicon 404
A. 具体问题
Sidebar.tsx引用/Logo.png但文件不存在,logo 无法显示- 浏览器控制台报
favicon.ico 404
B. 产生原因
logo_square.png位于项目根目录,但 Vite 不会自动将根目录文件暴露为静态资源- 前端代码引用路径为
/Logo.png(首字母大写),与实际文件名logo_square.png不匹配 index.html无 favicon 声明,浏览器默认请求/favicon.ico
C. 解决方案
- 创建
public/目录(Vite 原生支持,自动暴露到根 URL) - 将
logo_square.png复制为public/logo.png Sidebar.tsx引用路径改为/logo.pngindex.html添加<link rel="icon" type="image/png" href="/logo.png" />
D. 后续如何避免问题
- 静态资源(图片、字体、favicon)统一放入
public/目录 - 资源文件名与代码引用严格保持大小写一致
- 每个项目初始化时都配置好 favicon,避免浏览器自动请求不存在的 .ico
新增经验请追加到文件末尾,保持时间倒序或正序均可,但需确保每条经验包含完整的 A/B/C/D 四段。