# camera24 관절 0.10 반영 및 실시간/오프라인 비교

작업일: 2026-11-01 KST. profile `ltb1021`, server `test`.

## 결론

1. camera24의 configured/effective 모두 FIGHT `r5`, 사람 0.25, 관절 0.10으로 일치한다. `restart_pending=false`, RUNNING이며 45초 관측 전후 설정과 run이 유지됐다. 사용자의 설정 변경은 반영된 상태다.
2. 실시간 metadata는 약10FPS로 이어지고 FIGHT 빨강 표시도 발생했다. 관절 score 기준을 통과하는 비율은 기존 오프라인과 비슷한 수준이다.
3. 그러나 같은 장면의 동일 Frame/PTS를 맞춘 시험은 아니다. 표시 비율과 미추적 비율에 차이가 있어 오프라인과 동등한 판정 성능이라고 확정할 수 없다. 엔진의 즉각적인 튜닝 근거도 아니다.
4. 이번에는 새 Event가 없었다. 같은 run의 앞선 Event 전송 성공은 확인했으나, 45초 내부 episode/rearm trace는 외부 metadata에 없어 이번 비발급 사유를 확정하지 않는다.

## 설정 확인

| 항목 | 실제 값 |
| --- | --- |
| FIGHT engine/enabled | r5 / true |
| 사람/관절 기준 | 0.25 / 0.10 |
| ROI | 전체 화면 |
| R5 설정 | schema 1, window 1초, min_samples 2, contact_min_samples 3 |
| 표시 유지 | 고정 구현 1초 |
| Tracker | activation 0.25, matching 0.8, lost_buffer 30, frame_rate 30 |
| 적용 대기 | false |
| runGeneration | 4, 이번 관측 중 유지 |

직전 관절 0.30 관측 당시 runGeneration 2에서 사용자의 설정 변경 이후 run이 바뀌어 있었다. 이번 작업에서 Start/Stop을 호출하지 않았다. `runtime.py`, `core.py`, `web.py`, `scenario_parameters.py`의 실제 서버 SHA256은 직전 관측 및 현재 로컬 구현과 일치했다. 새로운 규칙/설정 변경이 있었던 것으로 해석할 근거는 없다.

이번에는 Web DB/HTTP body를 다시 수집하지 않고 AI configured/effective의 반영만 교차 확인했다. 구형 Web 처리 원리는 [직전 관측 기록](../../2026-11-01_icerti-camera24-fight-observe_r01/shared/00_REPORT_ko.md)을 참조한다.

## 관측과 비교 수치

- 실시간: **2026-11-01 14:13:28.650 ~ 14:14:13.680 KST**, 45.030초, 452관측.
- 오프라인: 고정 R5 camera24 검토본의 **Source Frame 242~722**, 원본 PTS 10.031~29.998초, 201관측. 원래 선택 범위의 끝 723 중 실제 선택 관측 마지막은722다.
- 동일 기준 비교를 위해 객체 통계는 양쪽 모두 사람 score 0.25 이상만 사용하고 좌표를 normalized로 통일했다. 관절 유효성은 원시 score 0.10 이상과 유한한 화면 내 좌표로 다시 계산했다. 과거 `valid_joints`의 0.30 집계를 사용하지 않았다.
- Pose cache와 R5 trace의 SHA256을 기존 spec/replay validation과 대조했다. 저장 결과만 읽었으며 모델/Pose/Tracking/R5를 재실행하지 않았다.

| 항목 | 기존 오프라인 R5 | 현재 실시간 |
| --- | ---: | ---: |
| 관측 수 | 201 | 452 |
| 현재 최종 조건 충족 | 7 (3.48%) | metadata에서 유지와 분리 불가 |
| 현재 충족 또는 유지의 활성 공간/객체 표시 | 31 (15.42%) | 50 (11.06%) |
| 표시 구간 새 Event | 0 | 0 |
| 평균 표시 대상 객체 수 | 4.21 | 4.66 |
| 객체 score 평균 | 0.610 | 0.560 |
| 미추적 객체 관측 비율 | 61/846 (7.21%) | 395/2105 (18.76%) |
| 중점8관절 유효 비율 | 6715/6768 (99.22%) | 16664/16840 (98.95%) |
| 손목2관절 유효 비율 | 1665/1692 (98.40%) | 4115/4210 (97.74%) |

위 분모는 실제 사람 수나 사람이 있는 모든 위치가 아니라, 이미 게시/저장된 객체-관측과 관절 칸이다. 따라서 사람 미탐률, 관절 정확도, Tracking 정확도는 아니다. 미추적 비율을 ID-switch 비율로 읽어서는 안 된다.

오프라인은 현재 충족의 빨강 7관측과 유지의 노랑 그룹 24관측을 합친31관측을 비교용으로 사용했다. 화면 전체 episode 테두리 유지65관측은 대응 그룹이 사라져도 남을 수 있어 비교에서 제외했다. 실시간은 현재 대응되는 기여 객체의 빨강만 게시하므로 공간 그룹과 bbox라는 표시 단위도 완전히 같지는 않다. **15.42%와11.06%의 차이를 정탐률 4.36%p 감소라고 부르면 안 된다.**

직전 관절0.30 실시간 관측은28/452 (6.19%), 이번0.10은50/452 (11.06%)였다. 빨강 관측이 더 많았지만 같은 Frame에 대해 threshold만 바꾼 통제 비교가 아니므로 증가 전체를0.10 변경 효과로 귀속하지 않는다. 이번 cache의 손목 중0.10~0.30 구간은540/4210칸이며, 낮아진 기준으로 참고 가능한 관절이 늘어난 것은 수치상 확인 가능하다. 이것이 모두 최종 싸움 근거가 된다는 뜻은 아니다.

## 처리 상태와 Event

- metadata 10.038건/초, PTS 간격 중앙값0.099초, P95 0.137초. 0.15초 초과 간격3건.
- 동일 run/configVersion 유지, source Frame/PTS 엄격 증가, Redis 읽기 오류0, FIGHT state/빨강 색상 불일치0.
- 수집 상태 조회는 계속 RUNNING이었다. 컨테이너 identity와 설정은 전후 동일했다.
- 이번 구간의 새 Event는 metadata와 관측 종료 DB 조회 모두0건이었다.
- 동일 run의 앞선 Event: **14:09:15.533 KST**, frameSeq17, `bb075d3f-d1a7-4521-8976-c8b9b8451714`. 아티팩트READY, 전송SENT, HTTP200이다. 이번45초에 새로 발생한 건으로 집계하지 않았다.
- 오프라인도 표시 구간 이전의 준비 구간 Source Frame211에서 Event가 발생했고, 이후 표시201관측에는 새 Event가 없었다. 빨강 발생과 매번 새로운 알람 발급은 서로 다른 정책이다.

R5는 유효한 조용한 관측이2초 누적되거나, 마지막 유효 근거 뒤5초 이상 만료돼야 episode를 다시 준비할 수 있다. 이후 내부2초/외부 cooldown 등의 조건도 적용된다. 단순히10초가 지났다고 새 알람이 반드시 발생하는 구조가 아니다. 이번 실시간 내부 latch/quiet/cooldown 상세가 노출되지 않았으므로 원인을 특정하지 않는다. 반복 영상에서 알람 재발급 주기가 기대와 다른지는 사용자 피드백과 내부 상태 진단을 별도로 확인할 사안이다.

최근 Event 전체 범위를 정렬하는 첫 읽기 쿼리는2.5초 statement timeout으로 중단됐다. 기존 evidence를 보존하고 최근10분으로 범위를 제한한 읽기 전용 쿼리는 성공했다. 관측45초 Redis 수집 자체의 오류는 아니다. DB/실행 설정을 변경하거나 timeout을 늘리지 않았다.

## 일치하는 점과 남은 차이

| 영역 | 확인 / 한계 |
| --- | --- |
| 엔진 | 배포 R5 소스 지문 유지. 과거 통합 시험에서 동일 cache32입력/18,045표시관측 및 상세12입력의 재현을 확인한 기록이 있음. 이번에 재실행한 결과는 아님 |
| 주요 기준 | 사람0.25, 관절0.10, R5 기본 window/관측 수가 오프라인과 맞음 |
| Pose 입력 | 둘 다 RFDETRKeypointPreview, 1920x1080 좌표, 명목10FPS, NMS0.85 |
| 원본/시간 | 오프라인 녹화 파일과 현재RTSP 사이의 공통 원본 Frame/PTS 대응 없음. run의 frameSeq를 과거 검토Frame으로 읽지 않음 |
| 전처리 | 오프라인CPU OpenCV resize/정규화, 라이브 native GPU 경로. 기존 보고서도 수치 bit-equivalence를 보장하지 않음 |
| Tracking | offline frame_rate10, live30. 초기 상태/관측 이력도 다름. 미추적 증가의 단일 원인으로 확정하지 않음 |
| Event/표시 | 오프라인 공간 빨강/노랑과 실시간 기여 bbox 빨강, 외부 cooldown/실행 이력의 차이 |

## 판단과 권장 순서

- **현재0.10 반영과 짧은 구간 실행 흐름은 의도대로다.** 눈에 띄는 처리 정체나 전체 판정 중단은 이번 구간에서 확인되지 않았다.
- **오프라인과 성능이 같다는 결론은 보류한다.** 관절 관측 가용성은 비슷하지만 객체 score/미추적/표시 비율이 같지는 않다. 입력 구간이 달라 성능 하락이나 개선으로 환산하지 않는다.
- 이번 수치만으로 싸움 규칙, score 또는 Tracker 설정을 자동 조정하지 않는다. 특히 frame_rate30이 실제 추론30FPS를 뜻하지 않으며 무조건10으로 바꾸는 것도 별도 검토가 필요하다.
- 다음 비교가 필요하면 동일 장면의 짧은 구간에 대해 입력 Frame/PTS를 먼저 맞추고, 현재 조건/유지/episode를 나눠 확인하는 것이 우선이다. 정확한 비교를 위해 추가 RGB/진단 수집 또는 CPU 재생이 필요하면 별도 요청 범위로 둔다.

## 보존 자료

- [비교 수치 및 전후 확인](comparison.json)
- [관절0.10 실시간 게시 metadata cache](camera24_metadata_45s_j010.json)
- [지문/수집 및 검증 manifest](manifest.json)
- 기존 오프라인 입력: `/data/codex-artifacts/contextra/action-model-eval/2026/2026-10-26_contextra-camera24-eval_r01/reports/pose_cache_copy.json`.
- 기존 R5 판정: `/data/codex-artifacts/contextra/action-model-eval/2026/2026-10-30_contextra-r5-review-12clips_r01/Contextra_Fight_R5_Review_20261030/01_camera24_fight/data/R5_diagnostics.jsonl`.
- 원본 조회 응답은 `../private/`, 실행 helper는 `../helpers/`에 보존했다. 비밀값/인증 URI를 공유 보고서에 넣지 않았다.

이번 cache는 게시 metadata이며 모델 직출력 전체나 RGB 녹화본이 아니다. 새 영상/이미지 생성, RTSP 재녹화, 브라우저 픽셀 캡처, 모델/Pose/Tracking/엔진 재실행, Start/Stop, 설정/서비스 변경은 하지 않았다. 비저장소 근거만 추가했고 소스 저장소는 변경하지 않았다.
