Files
Pre_Seg_Server/工程分析/经验记录.md

259 lines
17 KiB
Markdown
Raw Blame History

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