초기 커밋: DefVideo 소스 등록

abcVideo 플레이어 소스 (client / server / shared / pythonsource / docs / .claude).
.gitignore 적용으로 node_modules·storage·samplevideo·미디어 등 대용량 일괄 제외.
103 files, ~964K.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 03:20:27 +00:00
commit 82662d417d
103 changed files with 17213 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
# RoutePanel 미니맵 추가 및 개선
**소요 시간**: 약 3시간
**Context 사용량**: input ~60k / output ~20k tokens
**이슈**: 없음
---
## 작업 내용
### RoutePanel 컴포넌트 생성 및 VideoPlayer 통합
- `client/src/components/overlay/RoutePanel.tsx` 신규 생성
- `VideoPlayer.tsx`에 통합 (`showStations` 토글 연동)
- props: `currentTime`, `visible`, `onSeek`
### 기능
- 세로 미니맵 패널 (화면 좌측)
- 교량/터널 POI만 필터링하여 표시 (터널: 보라, 교량: 하늘색)
- 초록 박스: 현재 카메라에 보이는 km 범위
- 오렌지 마커: 현재 위치, 드래그하면 해당 측점으로 seek
- 시점/종점 역명 표시 (역사 카테고리 POI 중 km 최소/최대)
### 수정 이력
- `StationOverlay.tsx` `alt``altitude` 타입 오류 수정
- `cleanTitle()`: (상)/(하) 접미어 제거
- km 방향 여러 차례 수정 끝에 확정: 높은 km = 위, 낮은 km = 아래
- 패널 높이 80%, 겹침 간격 9%
- 글씨 크기 +30%, 배경 투명도 밝게
## 산출물
- `client/src/components/overlay/RoutePanel.tsx` (신규)
- `client/src/components/player/VideoPlayer.tsx`
- `client/src/components/overlay/StationOverlay.tsx`

View File

@@ -0,0 +1,32 @@
# StationOverlay 렌더링 끊김 분석 + history 자동화 규칙 추가
**소요 시간**: 약 15분
**Context 사용량**: input ~8k / output ~3k tokens
**이슈**: 없음
---
## 작업 내용
### 1. StationOverlay 렌더링 파이프라인 분석
- `client/src/components/overlay/StationOverlay.tsx` 코드 분석
- 렌더링 구조: RAF 루프(60fps) + renderCache useEffect(드론 프레임 변경 시)
- 끊김 원인 파악:
- `panelDroneFrame` 상태 변경 시 `useEffect`에서 수백~수천 개 좌표 변환(`toCameraCoords` + `pixelFromCamera`)이 메인 스레드에서 동기 실행
- 계산이 16ms 초과 시 RAF 프레임 드롭 → 뚝뚝 끊김
- 측정 방법 제안: `performance.now()` 로깅으로 캐시 빌드 시간 측정
| 항목 | 실제 |
|------|------|
| RAF draw 횟수 | ~60fps (항상) |
| 캐시 재빌드 횟수 | ~30fps (드론 프레임 변경 시) |
| 끊김 원인 | 캐시 빌드 시 메인 스레드 블로킹 |
### 2. history 자동화 규칙 CLAUDE.md 추가
- 사용자 기대: 작업 완료 시 날짜+주제별 history 파일 자동 작성
- 현재 훅은 "리마인더/가드"만 담당, 파일 생성은 Claude 몫
- CLAUDE.md 상단에 "작업 완료 시 필수 — 히스토리 기록" 섹션 추가
## 산출물
- `CLAUDE.md` — 히스토리 기록 규칙 섹션 추가
- `docs/history/2026-04-01_StationOverlay-렌더링분석.md` (이 파일)

View File

@@ -0,0 +1,52 @@
# StationOverlay 렌더링 최적화 — 텍스트 스무딩
**소요 시간**: 약 90분
**Context 사용량**: input ~40k / output ~12k tokens
**이슈**: 없음
---
## 작업 내용
### 문제
- 측점/지장물 텍스트 라벨이 영상 재생 중 뚝뚝 끊겨 표시됨
- 드론 pitch/GPS 노이즈 + 30fps 데이터 → 60fps RAF 스텝 차이
### 해결 과정
1. **원인 분석**
- `renderCacheRef` useEffect에서 CL 500개 × toCameraCoords = 매 33ms 메인 스레드 블로킹
- 텍스트는 31개로 작은 부분이었음, CL이 실제 병목
- 디버그 패널 추가로 firstY 값이 5-7px 불규칙 점프 확인
2. **텍스트 사전 계산 Map 도입**
- `labelMapRef: Map<frameNum, {stationLabels, poiMarkers}>` 전 프레임 precompute
- `requestIdleCallback` 백그라운드 계산 (메인 스레드 비블로킹)
- RAF: `Map.get(frameNum)` O(1) 조회만
3. **데이터 스무딩 (smoothFrame)**
- ±N 프레임 이동 평균 (yaw는 sin/cos 평균 후 atan2)
- UI 슬라이더로 조절 가능 (0~60fr)
- 기본값: smooth=10
4. **30fps→60fps 보간 (frac interpolation)**
- `performance.now()`로 prop 업데이트 이후 경과 시간 추정
- 현재/다음 프레임 사이 선형 보간 → 스텝 제거
5. **EMA (지수 이동 평균) 표시 위치 스무딩**
- `displayedStRef`, `displayedPoiRef`: 각 라벨별 현재 표시 위치 유지
- RAF마다: `pos = prev + (target - prev) × α`
- UI 슬라이더로 α 조절 (0.01~1.0), 기본값: α=0.01
- α=0.01: 매우 부드럽지만 약간 뒤처짐
6. **시각 개선**
- 글씨 크기 2배 (9px→18px, 10px→20px)
- bold + strokeText 4px 검정 테두리 (배경 박스 제거)
- CL 중심선 재활성화
### 최종 기본값
- smoothHalf: 10 (±333ms 이동 평균)
- emaAlpha: 0.01 (~1600ms lag, 매우 부드러움)
## 산출물
- `client/src/components/overlay/StationOverlay.tsx` 전면 개편

View File

@@ -0,0 +1,40 @@
# history-hooks 적용 및 토큰 사용량 집계
**소요 시간**: 약 40분
**Context 사용량**: input ~13k / output ~142k tokens (cache 포함)
**이슈**: #0
---
## 작업 내용
### 1. history_hooks 리뷰 및 프로젝트 적용
- `history_hooks/` 디렉토리의 5개 파일 분석
- `.claude/hooks/`에 복사: `guard-history-fields.py`, `guard-history-fields.sh`, `guard-history-reminder.sh`, `session-context.sh`, `path.json`
- `session-context.sh`, `guard-history-reminder.sh``$CLAUDE_PROJECT_DIR` 기반 절대경로로 수정
- `.claude/settings.json`에 3개 훅 이벤트 등록:
- `PostToolUse(Edit|Write)``guard-history-fields.sh`
- `Stop``guard-history-reminder.sh`
- `UserPromptSubmit``session-context.sh`
- `docs/history/` 디렉토리 생성
### 2. 일자별 토큰 사용량 집계
- `~/.claude/projects/d--MYCLAUDE-PROJECT-abcvideo/*.jsonl` 파싱
- `requestId` 중복 제거 후 날짜별 집계
- 결과: 총 974 요청, input 12,556 / output 135,445 / cache_create 3,655,924 / cache_read 91,618,473
### 3. Gitea 이슈 코멘트 등록
- `kimminsung/dronevideoplayer#1`에 일자별 토큰 사용량 테이블 코멘트 추가
### 4. guard-history-reminder.sh 수정
- 기존: `exit 0` → stderr 메시지만 출력, Claude 그냥 종료
- 변경: 오늘 날짜 히스토리 파일 없으면 `exit 2`로 Claude 종료 차단 → 히스토리 작성 강제
## 산출물
- `.claude/hooks/guard-history-fields.py`
- `.claude/hooks/guard-history-fields.sh`
- `.claude/hooks/guard-history-reminder.sh` (수정)
- `.claude/hooks/session-context.sh`
- `.claude/hooks/path.json`
- `.claude/settings.json` (Stop, UserPromptSubmit 훅 추가)
- `docs/history/` 디렉토리

View File

@@ -0,0 +1,53 @@
# 2026-04-02 프레임 동기화, 렌더링 최적화, 터널링
## 작업 개요
- 프레임 번호 불일치(Python vs abcvideo) 원인 분석 및 수정
- StationOverlay 렌더링 끊김 개선
- 외부 접속 터널링(cloudflared) 설정
- 빨간선 하단 클리핑 수정
- 좌표계/카메라 파라미터 시스템 설명
## 완료 항목
### 프레임 동기화 수정
- **원인**: VFC 측정에서 첫 프레임 카운트 포함 → 29.97fps 영상이 31fps로 오감지
- 29.97fps → 1초에 30프레임, elapsed≈1.001s, frameCount=31 → round(31/1.001)=**31fps**
- `useFrameStep.ts`: VFC 첫 호출은 startTime만 기록, 카운트 제외
- `VideoPlayer.tsx`: 프레임 표시를 `VIDEO_FPS=30000/1001(29.97)`로 계산 → Python SRT FrameCnt와 일치
- `StationOverlay.tsx`: 드론 프레임 매칭을 `currentTime`(초) 기반으로 변경 (fps 오감지 무관)
### 빨간선 하단 클리핑 수정
- 기존: 한쪽 끝점만 화면 밖이어도 세그먼트 전체 스킵
- 수정: Cohen-Sutherland trivial reject (양쪽 다 같은 방향 밖일 때만 스킵)
- SCREEN_M: 30 → 200으로 증가
### StationOverlay 렌더링 최적화
- 드론 경로(흰색 선) 완전 제거
- 좌표 변환(224점 proj4)을 useEffect로 이동 → 드론 프레임 변경 시만 실행
- RAF 루프: 캐시된 픽셀 좌표만 읽어 draw (계산 없음 → 60fps 유지)
- ResizeObserver로 캔버스 크기 별도 관리
### 기본값 ON
- `showStations` 초기값 `false``true`
### 터널링
- `vite.config.ts`: `allowedHosts: true` 추가
- cloudflared 명령: `cloudflared tunnel --url http://localhost:5173`
- PowerShell 환경변수 설정: `$env:VIDEOS_DIR="..."; npm run dev:server`
### 좌표 시스템 설명
- 타원체고(h) = 표고(H) + 지오이드고(N=25.449m) 설명
- EPSG:5186 TM 투영 원리
- center.csv vs 측점_XY값.csv 역할 차이
- 드론 카메라 회전 행렬(Rz×Rx×Ry) → 핀홀 투영 전체 흐름 설명
## 기술 부채 / 남은 이슈
- 재생 중 끊김이 완전히 제거되지 않음 (데이터 자체가 29.97fps 이산 → 근본적 한계)
- server-side geoMatch.ts는 여전히 구형 ENU 근사 사용 (클라이언트 렌더링에는 미사용)
## Git
- 커밋: `30bec66` (frontend 브랜치)
- push 완료
**소요 시간**: 180분
**Context 사용량**: input 180k / output 18k tokens

View File

@@ -0,0 +1,27 @@
# 동영상 로드 실패 (서버 중지) 복구
**이슈**: #0
**소요 시간**: 10분
**Context 사용량**: input 45k / output 3k tokens
## 증상
좌측 동영상 목록에서 항목 클릭 시 "로드할 수 없음" 에러.
## 원인
- 백엔드 서버(pm2 프로세스 `abcVideo`, 포트 55173)가 **stopped 상태**였음.
- 프론트엔드와 API가 동일 포트(노드 정적 서빙)에서 동작하므로, 서버가 죽으면 `/api/stream/:videoId` 요청이 전부 실패 → 영상 로드 불가.
- pm2 error 로그상 과거 `EADDRINUSE`(포트 3030 충돌)로 재시작 실패 이력이 있었고 stopped로 남아 있었음.
- 코드(URL 인코딩, Range Request, 한글·괄호 포함 파일명 처리)는 정상.
## 조치
1. `pm2 restart abcVideo --update-env` → online 복구
2. 검증
- `GET /api/videos``하행)회덕-대전조차장.MP4` 반환
- `GET /api/stream/...` (Range 01MB) → HTTP 206, 1MB 수신
- `GET /api/meta/...` → HTTP 200
3. `pm2 save`로 프로세스 목록 저장
## 후속 참고
- `FFmpeg not found in PATH` 경고 → HLS 변환/프레임 추출은 FFmpeg 설치 후 동작 (즉시 재생은 영향 없음).
- `client/vite.config.ts` 프록시 타깃이 `localhost:3030`인데 실제 서버 포트는 55173.
프로덕션 정적 서빙에는 무관하나, Vite 개발 서버(`npm run dev`) 사용 시 API 프록시 불일치로 동작 안 함 → 개발 모드 사용 시 포트 정정 필요.