From 1db99778ed87387bc4f7a2425deb2bc48f290aa0 Mon Sep 17 00:00:00 2001 From: QiuSW Date: Thu, 23 Jul 2026 22:52:33 +0800 Subject: [PATCH] feat(v2): add CMD release packaging entrypoint --- docs/03-tech-stack.md | 2 +- docs/current-state.md | 4 +- docs/v2-demo-runbook.md | 13 ++++++ progress.md | 9 ++++ v2/scripts/build-v2-release-bat.test.ps1 | 56 ++++++++++++++++++++++++ v2/scripts/build-v2-release.bat | 11 +++++ 6 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 v2/scripts/build-v2-release-bat.test.ps1 create mode 100644 v2/scripts/build-v2-release.bat diff --git a/docs/03-tech-stack.md b/docs/03-tech-stack.md index 71fadb1..c8dd8df 100644 --- a/docs/03-tech-stack.md +++ b/docs/03-tech-stack.md @@ -52,7 +52,7 @@ | V2 录像事件回归 | `Set-Location v2; $env:CGO_ENABLED='1'; go run ./cmd/regression --ffmpeg --video --width --height --fps --onnx assets\best.onnx --ort-dll ` | | V2 Walk UI 编译 Spike | `Set-Location v2; $env:CGO_ENABLED='0'; go build ./cmd/ui-spike` | | V2 正式应用 | `Set-Location v2; $env:CGO_ENABLED='1'; go run ./cmd/silver-pose --config ` | -| V2 发布目录 | `Set-Location v2; ./scripts/build-v2-release.ps1 -OnnxPath -OrtDllPath -FfmpegPath -FfprobePath -OutputDirectory ` | +| V2 发布目录 | PowerShell:`Set-Location v2; ./scripts/build-v2-release.ps1 -OnnxPath -OrtDllPath -FfmpegPath -FfprobePath -OutputDirectory `;CMD 便捷入口:`scripts\build-v2-release.bat`,参数完全相同且退出码透传。 | ## 演进决策 diff --git a/docs/current-state.md b/docs/current-state.md index 1c52159..c44c2cc 100644 --- a/docs/current-state.md +++ b/docs/current-state.md @@ -4,12 +4,12 @@ ## 当前快照 -- 日期:2026-07-22 +- 日期:2026-07-23 - 阶段:V1 客户演示闭环、T-301 模型导出一致性、T-302 Go 技术 Spike 与 T-303 Go 事件引擎均已关闭;T-304 正在实现 Go 实时演示、报警和发布。判定灵敏度默认已放宽(低位俯视:持续水平即可疑,膝踝可缺,水平阈值 45°),确认窗为主防误报闸。 - 已验证环境:Windows PowerShell;Python 3.8.10;Ultralytics 8.3.205;PyQt5 可导入。注意:当前 WSL/Linux 环境未安装 PyQt5,且其 ultralytics/torch 版本与该基线不兼容(模型前向不可用),故 GUI 可视化与真实模型端到端渲染只在 Windows 验证;本环境用 Qt-free 的 `view_model.py` 单元测试与假适配器管线冒烟覆盖视图逻辑。 - 旧生产基线:`demo/main.py`、`demo/fall_detection_gui.py`、`demo/detect_fall.py`、`demo/best.pt`。 - V1 代码:已建立安全配置、显式 Replay/Stream 视频源、Pose、轻量跟踪、质量/几何证据、倒地领域规则、按 ID 四态事件机及 `v1/pipeline.py` 事件管线;运行事件带非敏感 `config_version`,缺帧/低质量/断流会中断证据确认。新增 `v1/view_model.py`(Qt-free 监控视图状态与设置草稿三份隔离)、`v1/gui.py` 薄 PyQt5 双 Tab 外壳与 `v1/app.py` 装配(`FrameWorker` 只发出已判定的 `FrameAnalysis`,窗口只渲染)。新增 `v1/alerts.py`:按 `event_id` 去重,对首次 CONFIRMED 保存带标注截图、追加 JSONL 事件行,并经可注入 `AlertSink`(Windows 侧 `QtAlertSink` 提供声音与一次性弹窗)触发一次声音/弹窗。新增 `v1/camera.py`(RTSP URL 构建 + 有界连接测试抓帧)与 `config.py` 的结构化来源(host/端口/通道/账号/密码,凭证百分号编码)、`write_local_camera_source`;设置页新增摄像头连接分组、测试连接与预览,以及传输协议/连接超时/低延迟三项抓流调优(由 `config` 存值、`app` 开流前写入 `OPENCV_FFMPEG_CAPTURE_OPTIONS`)。真实海康流已用 `VideoSource(STREAM)` 连通(1920×1080)。 -- V2 代码:T-303 已落地 `internal/pose`(Ultralytics 114 letterbox、BGR→RGB/CHW、YOLO Pose NMS、17 点及坐标还原)与 `internal/fall`(中心点跟踪、质量/几何证据、策略、四态状态机和事件 ID);`cmd/regression` 使用 FFmpeg 顺序回放本机录像并将 ONNX Pose 接入事件引擎。用户已手动确认 T-303 完成,但其缺少部署边界内真实正例录像的事实仍保留在诊断记录中。T-304 已新增安全 V2 配置、FFprobe/FFmpeg 有界重连源、后台监控装配、叠加 PNG/JSONL 证据、浅色 Walk 双 Tab 操作窗口和 `cmd/silver-pose` 正式装配命令;窗口只接收完成帧和可靠告警队列。`v2/scripts/build-v2-release.ps1` 已在本机从显式 ONNX/DLL/FFmpeg/FFprobe 输入生成临时发布目录与哈希清单。现场 RTSP、声音、弹窗、截图和安全模拟摔倒的目视验收尚未完成,V2 仍不能作为客户演示版。 +- V2 代码:T-303 已落地 `internal/pose`(Ultralytics 114 letterbox、BGR→RGB/CHW、YOLO Pose NMS、17 点及坐标还原)与 `internal/fall`(中心点跟踪、质量/几何证据、策略、四态状态机和事件 ID);`cmd/regression` 使用 FFmpeg 顺序回放本机录像并将 ONNX Pose 接入事件引擎。用户已手动确认 T-303 完成,但其缺少部署边界内真实正例录像的事实仍保留在诊断记录中。T-304 已新增安全 V2 配置、FFprobe/FFmpeg 有界重连源、后台监控装配、叠加 PNG/JSONL 证据、浅色 Walk 双 Tab 操作窗口和 `cmd/silver-pose` 正式装配命令;窗口只接收完成帧和可靠告警队列。`v2/scripts/build-v2-release.ps1` 已在本机从显式 ONNX/DLL/FFmpeg/FFprobe 输入生成临时发布目录与哈希清单;`v2/scripts/build-v2-release.bat` 是参数/退出码透传的 CMD 便捷入口,不持有凭证或运行时路径。现场 RTSP、声音、弹窗、截图和安全模拟摔倒的目视验收尚未完成,V2 仍不能作为客户演示版。 - 非代码设计工件:docs/ui/silver-pose-ui-ux-spec.md、docs/ui/2026-07-20-html-prototype-plan.md、docs/ui/silver-pose-v1-prototype.html 与 docs/ui/silver-pose-v2-prototype.html 已建立。v2 HTML 是符合正式浅色 Windows 规范的当前视觉参考:浅灰蓝底、白色卡片,红色只表示确认摔倒、其弹窗和事件证据;文件名中的 v2 只表示原型设计修订,不能理解为 Go V2 实现已开始。v1 HTML 保留为历史深色对照。两者均使用顶部双 Tab、设置草稿与状态交互,且画面、事件和时间都是模拟数据,不连接真实摄像头、模型或网络,也不改变 Phase 1 任务顺序。 - 测试:`python -m compileall -q v1 demo` 已通过(含 `gui.py`、`app.py`、`alerts.py`、`camera.py` 语法);`./init.ps1` 当前运行 V1 测试为 88 passed、1 skipped。T-303 的 `CGO_ENABLED=1 go test ./...` 通过。对同一 317 帧本机录像,V1 回放得到 253 个有人帧、263 人次、0 个 CONFIRMED;Go 回放得到 255 个有人帧、265 人次、0 个 CONFIRMED。该录像经用户确认是摔倒正例,二者的 0 事件是漏检,不是“无报警反例”通过:V1 在 2.400–2.467 秒仅有 3 帧横向候选,随后倒地人体的 Pose 置信度降至 0.012,并在 3.000 秒帧以 0.01 推理仍无任何人体姿态。它是室外斜视且有字幕遮挡,超出当前固定俯视大厅/走廊验收边界;降低检测阈值至 0.10 仍为 0 事件。人次差异来自 OpenCV/FFmpeg 解码像素不同,不能据此声称 Go 已完成真实正例一致性。Go 合成正例契约和 V1 状态机均在 1.81 秒时产生一个 `CONFIRMED`。Walk UI Spike 以 `CGO_ENABLED=0 go build ./cmd/ui-spike` 编译通过。这些不表示摔倒识别准确率或完整 Go 客户演示已验收。`init.ps1` 会检查运行时依赖、编译旧基线并运行 V1 测试,但不会安装软件包。 - 模型:`demo/best.pt` 可加载为 YOLO Pose,类别 `person`,`kpt_shape=[17, 3]`;与 `D:\PythonP\fall_detection\best.pt` 哈希一致。 diff --git a/docs/v2-demo-runbook.md b/docs/v2-demo-runbook.md index 86c3167..ea7272f 100644 --- a/docs/v2-demo-runbook.md +++ b/docs/v2-demo-runbook.md @@ -17,6 +17,19 @@ -OutputDirectory ``` +若操作者使用 `cmd.exe`,可使用同一目录的批处理入口;它只转发相同的五个参数给上述 PowerShell 脚本,并返回相同的成功或失败退出码: + +```bat +scripts\build-v2-release.bat ^ + -OnnxPath ^ + -OrtDllPath ^ + -FfmpegPath ^ + -FfprobePath ^ + -OutputDirectory +``` + +不要双击 `.bat` 文件;必须从已打开的 `cmd.exe` 或 PowerShell 调用,以便核对参数错误和生成结果。 + 发布目录包含 `silver-pose.exe`、`runtime/`、公开 `config.example.json`、本手册和运行时哈希清单。不要把真实摄像头地址、密码、客户录像、事件截图或本机 `config.local.json` 放进发布目录。 ## 本机安全配置 diff --git a/progress.md b/progress.md index 2344e1a..e97b879 100644 --- a/progress.md +++ b/progress.md @@ -657,3 +657,12 @@ - 验证:`CGO_ENABLED=1 go build -mod=vendor ./internal/store/...` 退出码 0(WSL gcc 编译 sqlite3.c);`go test ./internal/store/... ./internal/config/...` 全 ok(含无密码列守卫);`GOOS=windows CGO_ENABLED=0 go build -mod=vendor ./internal/ui/... ./cmd/ui-spike/...` 退出码 0。DB 路径 `v2/artifacts/fall-events.db` 已被 gitignore。 - 阻塞:无(T-309 六项代码全部完成)。 - 下一步:用户在 Windows 侧目视核验(窗口不抢前台、2×3 截图墙、Esc 关弹窗、按钮灰化、测试连接弹窗、弹窗 5 秒自动关、SQLite 落库)。 + +## 【2026-07-23】T-304 Windows CMD 发布打包入口 + +- 状态:DOING(补充发布工具;现场演示验收仍待完成)。 +- 变更:新增 `v2/scripts/build-v2-release.bat`,从 `cmd.exe` 定位同目录 `build-v2-release.ps1`,原样转发五个显式发布输入并透传退出码;新增 `build-v2-release-bat.test.ps1`。批处理在自身 `setlocal` 作用域内清除继承的 `PSModulePath`,使 Windows PowerShell 5.1 使用其默认内置模块目录;调用者环境不会被修改。同步 V2 发布手册、技术栈和当前状态。 +- 验证:`./init.ps1` 通过(88 passed、1 skipped);`CGO_ENABLED=1 go test ./...` 通过;批处理契约测试通过。以锁定 ONNX、ONNX Runtime DLL、FFmpeg 与 FFprobe 调用 `.bat` 成功生成新的忽略发布目录,包含 `silver-pose.exe`、4 个运行时文件、公开配置、手册和 `runtime-manifest.json`(共 8 项);清单检查未发现 `rtsp://`、用户名或密码标记。 +- 诊断:首次真实打包在 `.bat` 中报 `Get-FileHash` 不存在。直接运行相同 `.ps1` 成功;CMD 中继承 PowerShell 7 的模块搜索路径时 Windows PowerShell 5.1 找不到该内置命令,清除该变量后命令与真实打包均成功。不是 ONNX、FFmpeg、模型或凭据问题。 +- 阻塞:T-304 仍需使用未跟踪现场 RTSP 与经同意安全动作,目视验收实时画面、确认报警声音/弹窗、PNG/JSONL 和断流恢复;不得将本次构建验证表述为现场摔倒检测验收。 +- 下一步:以 `docs/v2-demo-runbook.md` 在客户现场使用发布目录完成 T-304 最终验收。 diff --git a/v2/scripts/build-v2-release-bat.test.ps1 b/v2/scripts/build-v2-release-bat.test.ps1 new file mode 100644 index 0000000..0d79344 --- /dev/null +++ b/v2/scripts/build-v2-release-bat.test.ps1 @@ -0,0 +1,56 @@ +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest + +$batchEntrypoint = Join-Path $PSScriptRoot 'build-v2-release.bat' +$powerShellEntrypoint = Join-Path $PSScriptRoot 'build-v2-release.ps1' + +if (-not (Test-Path -LiteralPath $batchEntrypoint -PathType Leaf)) { + throw "Batch entrypoint is missing: $batchEntrypoint" +} + +$sandbox = Join-Path ([System.IO.Path]::GetTempPath()) ("silver-pose-v2-bat-test-" + [guid]::NewGuid().ToString('N')) +try { + New-Item -ItemType Directory -Path $sandbox | Out-Null + $inputs = @{ + OnnxPath = Join-Path $sandbox 'best.onnx' + OrtDllPath = Join-Path $sandbox 'onnxruntime.dll' + FfmpegPath = Join-Path $sandbox 'ffmpeg.exe' + FfprobePath = Join-Path $sandbox 'ffprobe.exe' + } + $inputs.Values | ForEach-Object { New-Item -ItemType File -Path $_ | Out-Null } + $output = Join-Path $sandbox 'non-empty-output' + New-Item -ItemType Directory -Path $output | Out-Null + New-Item -ItemType File -Path (Join-Path $output 'sentinel.txt') | Out-Null + + $directArgs = @( + '-NoLogo', + '-NoProfile', + '-ExecutionPolicy', 'Bypass', + '-File', $powerShellEntrypoint, + '-OnnxPath', $inputs.OnnxPath, + '-OrtDllPath', $inputs.OrtDllPath, + '-FfmpegPath', $inputs.FfmpegPath, + '-FfprobePath', $inputs.FfprobePath, + '-OutputDirectory', $output + ) + $directOutput = & powershell.exe @directArgs 2>&1 | Out-String + $directExitCode = $LASTEXITCODE + + $batchCommand = '"{0}" -OnnxPath "{1}" -OrtDllPath "{2}" -FfmpegPath "{3}" -FfprobePath "{4}" -OutputDirectory "{5}"' -f $batchEntrypoint, $inputs.OnnxPath, $inputs.OrtDllPath, $inputs.FfmpegPath, $inputs.FfprobePath, $output + $batchOutput = & cmd.exe /d /c $batchCommand 2>&1 | Out-String + $batchExitCode = $LASTEXITCODE + + if ($directExitCode -eq 0 -or $directOutput -notmatch 'OutputDirectory must be empty') { + throw "The PowerShell release script did not reject the non-empty output directory. Output: $directOutput" + } + if ($batchExitCode -eq 0 -or $batchOutput -notmatch 'OutputDirectory must be empty') { + throw "The batch entrypoint did not forward release arguments and exit status. Output: $batchOutput" + } + + Write-Output 'PASS: batch release entrypoint forwards arguments to the PowerShell release script.' + exit 0 +} finally { + if (Test-Path -LiteralPath $sandbox) { + Remove-Item -LiteralPath $sandbox -Recurse -Force + } +} diff --git a/v2/scripts/build-v2-release.bat b/v2/scripts/build-v2-release.bat new file mode 100644 index 0000000..d77d3ad --- /dev/null +++ b/v2/scripts/build-v2-release.bat @@ -0,0 +1,11 @@ +@echo off +setlocal EnableExtensions + +set "SCRIPT_DIR=%~dp0" +rem Avoid passing a PowerShell 7 module path to Windows PowerShell 5.1. +rem The release script needs the built-in Microsoft.PowerShell.Utility module. +set "PSModulePath=" +powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%build-v2-release.ps1" %* +set "EXIT_CODE=%ERRORLEVEL%" + +endlocal & exit /b %EXIT_CODE%