Commit Graph

13 Commits

Author SHA1 Message Date
ericwyuan
203b076783 feat: NAS端FFmpeg预压缩 — 根治360MB视频跨境上传超时
根因诊断(网络问题,非代码逻辑):
- NAS(中国移动) → Oracle(美国Phoenix) 跨境上行带宽实测仅 0.5-0.9MB/s 且波动大
- 下载方向 3.0MB/s(非对称,典型国际出口拥塞)
- Tailscale P2P: ping 可通(224ms)但持续数据流被阻断(0 B/s, 127s超时)
- 360MB 原始视频上传需 10-20min,任何大分块都会超时

NAS dispatcher:
- 新增 _compress_video: 480p/CRF28/veryfast,静态监控场景实测 ~36x 压缩比
  (360MB → ~12MB,上传时间 20min → ~30s)
- ffmpeg 自动探测: CodecPack ffmpeg41(带libx264) > /usr/local/bin > PATH
  (Synology 系统 ffmpeg 被裁剪,无 h264 编解码)
- scale 两级滤镜: force_original_aspect_ratio=decrease + trunc(iw/2)*2
  (h264 要求偶数尺寸,853x480 会报错)
- 压缩缓存 /tmp/fam_compressed/task_{id}/,源文件未变则重试复用,TTL 24h
- 压缩完成后重置 PROCESSING 状态(重置 stale 回收计时基准)
- 压缩失败回退原始文件分块上传
- _query_uploaded_chunks 失败时记录日志(原静默失败导致全量重传无感知)

Edge api_gateway:
- fix: total_chunks 变更清理旧分块后同步重写 meta.json
  (原 bug: meta.json 不更新导致每块上传都触发清理,删除同批新分块死循环)

config:
- stale_timeout 600→1800(覆盖压缩+上传+Edge队列积压总时长)
- 新增 ffmpeg_path / compress_timeout 配置项
2026-08-20 14:59:50 +08:00
ericwyuan
5915cf4be3 fix: 分块大小减至5MB + Edge端chunk_size变更自动清理 + 断点续传防护
NAS dispatcher:
- CHUNK_SIZE 10MB→5MB(~1Mbps上行带宽下可靠传输)
- chunk上传timeout (30,120)→(60,180)(增加连接和读取余量)
- _query_uploaded_chunks 返回 (set, edge_total) 元组
- expected_total != edge_total 时跳过断点续传(防止chunk_size变更导致文件损坏)

Edge api_gateway:
- upload_chunk 检测 total_chunks 变更,自动清理旧分块
- 防止不同chunk_size的旧分块与新分块混合导致assemble后文件损坏
2026-08-20 14:18:29 +08:00
ericwyuan
d6054de060 fix: 分块大小减至10MB + 上传失败确认机制 + 重试前置检查
- CHUNK_SIZE 20MB→10MB,CHUNK_THRESHOLD 50MB→20MB,降低单次超时概率
- 新增 _query_uploaded_chunks 独立方法,connect timeout 10s→30s
- 分块上传失败后查询 Edge 确认是否实际收到,避免响应丢失导致不必要重试
- 补全 uploaded_set.add(idx) 防止重复上传已成功分块
- _poll_once 中前置 retry_count 检查,超限任务直接标记 FAILED
2026-08-20 13:55:59 +08:00
ericwyuan
881ea3f470 fix: dispatcher 串行上传 + 看门狗自动重启 + 线程状态真实检测
- Dispatcher limit=10→1: 一次只传一个视频,传完再传下一个
- 退避缩短: min(30*(n+1),300)s → 失败后更快重试(原 min(60*(n+1)*2,600)s)
- /api/status: 用 thread.is_alive() 替代 _running 布尔标志
- 三组件(scheduler/dispatcher/poller)添加 is_alive()+check_and_restart()
- app.py 新增 watchdog 线程: 每 60s 检测线程死亡并自动重启
2026-08-20 13:37:07 +08:00
ericwyuan
b6c13a9047 feat: 分块断点续传上传 — 20MB/块 + 分块级重试 + 断点查询
Edge 端新增 3 个端点:
- POST /api/edge/video/chunk: 接收单块,保存到 task_{id}/chunk_{index:04d}
- GET /api/edge/video/chunks: 查询已上传分块(断点续传)
- POST /api/edge/video/assemble: 合并全部分块入队

NAS Dispatcher 重写:
- 大文件(>50MB)自动分块上传(20MB/块)
- 每块最多重试 3 次(分块级重试,非整文件级)
- 上传前查询已上传分块,跳过已有的(断点续传)
- 全部上传后调 /assemble 合并入队
- 小文件(<=50MB)走直接上传路径
- max_retries 3→5(文件级重试次数)
- scheduler 切回生产目录

解决: 360MB 视频跨公网单次上传超时/断连问题
2026-08-20 12:27:30 +08:00
ericwyuan
4f0f19bccd fix: dispatcher/poller 超时改为分离模式,stale_timeout 缩短到 10 分钟
- dispatcher 上传 timeout 从 300s 改为 (10s connect, 60s read)
  避免大文件上传无限阻塞 dispatcher 线程
- poller 拉取 timeout 从 30s 改为 (10s connect, 15s read)
- stale_timeout 从 3600s 缩短到 600s(10 分钟)
  更快回收卡死的 PROCESSING 任务
2026-08-20 12:12:19 +08:00
ericwyuan
02da23ef42 feat: 异步任务队列架构 - SQLite队列 + 速率限制 + NAS Poller
Edge端:
- 新增 SQLite 异步任务队列 (queue_manager + consumer)
- 新增 TokenBucket 速率限制器 (Gemini 1000 RPM, NVIDIA 40 RPM, burst 2x)
- 新增 /api/edge/video/enqueue + /api/edge/results 端点
- 消费者线程从队列消费任务,按速率限制调用AI模型
- orchestrator 集成 rate_limiter,Gemini优先→NVIDIA兜底

NAS端:
- Dispatcher 重构为 enqueue 模式(上传后立即返回,不等结果)
- 新增 Poller 线程(定期从Edge拉取结果写 MariaDB)
- app.py 启动 Poller,config.yaml 新增 poller 配置
- db_layer 更新 valid_stages 添加 'process'
2026-08-20 12:07:09 +08:00
ericwyuan
d75c745b95 fix: dispatcher crash on invalid failure_stage + per-task error isolation
Two fixes:
1. db_layer.update_task_status: map invalid failure_stage values (e.g.
   'process' from Edge) to 'callback' before DB write, preventing
   MariaDB ENUM DataError (1265 "Data truncated")
2. dispatcher._poll_once: wrap each task dispatch in try/except so one
   task's failure doesn't skip remaining tasks in the batch

Root cause: Edge returns failure_stage='process' but DB ENUM only allows
  download/extract/vlm_visual/vlm_fusion/callback. The DataError crashed
  _poll_once(), causing all subsequent PENDING tasks to be skipped.
2026-08-20 11:09:10 +08:00
ericwyuan
e7c1641b72 fix(dispatcher): resp.json(silent=) 是 Flask API,requests 不支持会抛 TypeError
Edge 返回结果解析时 TypeError 逃逸到轮询循环,任务卡死 PROCESSING
2026-08-20 01:59:10 +08:00
ericwyuan
3a195d69b9 fix(dispatcher): 僵尸PROCESSING任务回收 + fam-core文件日志
- db_layer 新增 reclaim_stale_processing: PROCESSING 超过 push_timeout+120s 重置 PENDING
- dispatcher 轮询前先回收僵尸任务(进程重启/Edge重启导致 in-flight 请求丢失的场景)
- logger 增加 fam-core/logs/fam-core.log 文件输出(daemon 模式 stdout 不可见)
2026-08-20 01:42:59 +08:00
ericwyuan
40944428d1 feat: video analysis switched to push mode (upload whole video, sync response)
Rationale: Oracle cannot reach NAS (Tailscale userspace mode on NAS, no TUN),
the old pull+webhook design requires Edge to download video from NAS and
callback to NAS - both blocked. New design is one-way NAS -> Oracle:

- FAM-Edge: new POST /api/edge/video/push endpoint accepts multipart video
  upload, reuses existing OpenCV scene-change keyframe selection, analyzes
  synchronously and returns the result payload directly in the HTTP response
  (no webhook callback). Old /api/edge/video/analyze kept for compatibility.
- FAM-Edge: VideoPreprocessor.save_upload() saves the uploaded file
- FAM-Edge: AIOrchestrator.process_push_task() runs the full pipeline
  (health check -> extract -> select -> compress -> VLM -> fusion) and
  returns callback-style payload dict
- FAM-Core: Dispatcher rewritten to push mode - reads local video file,
  uploads with task metadata (camera_name, event_start_time from file mtime,
  known_members_context), applies the result to DB via shared
  event_receiver.apply_success_event()
- FAM-Core: event_receiver success logic extracted into reusable
  apply_success_event() (used by both webhook route and dispatcher)
- config: edge_url -> /api/edge/video/push, push_timeout 1800s, gunicorn
  Edge timeout raised to 1800s for long synchronous analysis
2026-08-20 01:03:48 +08:00
ericwyuan
c45464c3e2 [补全] 各模块 __init__.py 导出 - 确保import链路完整 2026-08-19 22:37:47 +08:00
ericwyuan
da6b1c8d39 [2.1-2.5] FAM-Core 六个子模块 - Scheduler/Dispatcher/Event-Receiver/Chat-Handler/Member-Manager/Video-Server + DB层 + 配置 2026-08-19 22:21:31 +08:00