Files
dronevideoplayer/PLAN.md
minsung 2aae3d1c0d feat: StationOverlay 렌더링 최적화 및 스무딩 적용 close #1
- 텍스트(측점/POI) 전 프레임 사전 계산 Map (requestIdleCallback 백그라운드)
- 드론 데이터 이동 평균 스무딩 (smoothFrame ±N프레임)
- 30fps→60fps 프레임 간 선형 보간 (performance.now() 기반)
- EMA(지수이동평균) 표시 위치 스무딩 (α=0.01 기본값)
- 글씨 2배 크기, bold, strokeText 테두리, 배경 박스 제거
- 카메라 파라미터 패널에 smooth/EMA α 슬라이더 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 15:11:39 +09:00

11 KiB

PLAN.md — abcvideo 구현 계획

이 파일은 전체 구현 계획과 각 단계별 세부 태스크를 정의합니다. 에이전트는 작업 시작 전 반드시 이 파일을 읽고, 자신이 담당할 단계를 확인합니다.


단계 1: 프로젝트 구조 세팅

목표

모노레포 구조 생성, TypeScript/빌드 설정, 개발 환경 구축

세부 태스크

  • 루트 package.json (npm workspaces: client, server, shared)
  • client/ — Vite + React 18 + TypeScript 초기화
  • server/ — TypeScript + ts-node/tsx 설정
  • shared/ — 공유 타입 패키지 설정
  • Tailwind CSS 설치 및 설정 (client)
  • ESLint + Prettier 설정 (루트)
  • tsconfig.json — 루트/client/server/shared 각각 설정 (경로 별칭 포함)
  • storage/ 디렉토리 구조 생성 + .gitignore 설정
  • server/.env.example 작성
  • 개발 서버 동시 실행 스크립트 (concurrently 또는 npm scripts)
  • 빈 앱 기동 확인 (client dev + server dev 동시 실행)

산출물 (완료 기준)

  • npm install 성공
  • npm run dev로 client(5173) + server(3001) 동시 기동
  • TypeScript 컴파일 에러 없음
  • 빈 React 앱이 브라우저에 표시됨

다음 단계 의존성

  • 단계 2, 3 모두 이 단계 완료 후 시작 가능

단계 2: 백엔드 서버

목표

Express 서버 + Range Request 스트리밍 + FFmpeg spawn 래퍼 + tus 업로드 + HLS 변환 + SSE 진행률

세부 태스크

2-1. 서버 기본 골격

  • Express 앱 생성 (server/src/app.ts)
  • CORS 미들웨어 설정 (개발: localhost:5173 허용)
  • 보안 미들웨어: Path traversal 방어 (middleware/security.ts)
  • 에러 핸들링 미들웨어
  • 환경변수 로드 (dotenv + server/.env)
  • storage/ 하위 디렉토리 자동 생성 로직

2-2. Range Request 스트리밍

  • routes/stream.ts — GET /api/stream/:videoId
  • services/streaming.ts — Range 파싱, createReadStream, 206 응답
  • Accept-Ranges 헤더, Content-Range 헤더 정확한 구현
  • highWaterMark 1MB, 청크 크기 10MB 제한
  • 테스트: curl로 Range Request 동작 확인

2-3. FFmpeg spawn 래퍼

  • services/ffmpeg.ts — runFFmpeg(), runFFprobe() 함수
  • FFmpeg 설치 확인 로직 (서버 시작 시)
  • stderr 진행률 파싱 (time=HH:MM:SS.ms 패턴)
  • 코덱 감지: FFprobe로 H.264 여부 확인 → -c copy vs 트랜스코딩 분기
  • 프레임 추출: -accurate_seek -ss {time} -i {file} -frames:v 1

2-4. HLS 변환

  • routes/hls.ts — POST /api/hls/:videoId/convert, GET 플레이리스트/세그먼트
  • 변환 작업 관리 (Map 기반 인메모리 상태: idle/converting/done/error)
  • H.264 → -c copy (빠른 리먹스), 비-H.264 → 트랜스코딩
  • 세그먼트 6초, 키프레임 2초 간격
  • SSE 진행률 엔드포인트: GET /api/hls/:videoId/progress

2-5. tus 업로드

  • @tus/server + @tus/file-store 설정
  • routes/upload.ts — /api/upload 경로에 tus 서버 마운트
  • 업로드 완료 훅: onUploadFinish에서 파일 이동 + FFprobe 메타데이터 추출
  • 업로드 크기 제한: MAX_UPLOAD_SIZE (기본 20GB)
  • MIME 타입 + FFprobe 실제 코덱 검증

2-6. 메타데이터 & 영상 관리

  • routes/meta.ts — GET /api/meta/:videoId (FFprobe 기반)
  • GET /api/videos — 업로드된 영상 목록
  • DELETE /api/videos/:videoId — 원본+HLS+프레임+썸네일+DB 일괄 삭제

2-7. SQLite + 주석 API

  • db/schema.sql — annotations 테이블 스키마
  • better-sqlite3 초기화 (services/storage.ts)
  • routes/annotations.ts — CRUD + 내보내기 (VTT, SRT, JSON, CSV)

2-8. 파일 정리

  • 서버 시작 시 24시간 이상 된 임시 파일 정리
  • 주기적 정리 (setInterval, 1시간마다)
  • 디스크 잔여 공간 체크 (check-disk-space, 10GB 미만 시 로그 경고)

산출물 (완료 기준)

  • 서버 기동 성공 (FFmpeg 감지 로그 출력)
  • curl로 Range Request 스트리밍 동작 확인
  • curl로 영상 업로드 (tus) 성공
  • HLS 변환 시작/진행률/완료 확인
  • 주석 CRUD API 동작 확인

다음 단계 의존성

  • 단계 3 (기본 플레이어)은 최소 2-1, 2-2 완료 시 시작 가능
  • 단계 4 (프레임 추출)은 2-3 완료 필요
  • 단계 6 (텍스트 오버레이)은 2-7 완료 필요

단계 3: 기본 플레이어

목표

Video.js + 이중 경로 재생 (로컬 File API + 서버 Range Request/HLS) + 기본 UI

세부 태스크

3-1. Video.js 통합

  • Video.js 8.23.x + 타입 정의 설치
  • components/player/VideoPlayer.tsx — ref + useEffect 패턴
  • hooks/useVideoPlayer.ts — 초기화/제어/이벤트 추상화
  • Video.js 옵션: fluid, responsive, playbackRates 설정
  • 전체화면: 컨테이너 div 기준 fullscreen (오버레이 유지)

3-2. 서버 파일 재생

  • 서버 영상 목록 조회 UI
  • Range Request URL로 즉시 재생
  • HLS 변환 트리거 + SSE 진행률 표시
  • HLS 준비 완료 시 hls.js로 소스 전환

3-3. 로컬 파일 재생

  • 파일 드래그앤드롭 / 파일 선택 UI
  • URL.createObjectURL() → Video.js src 설정
  • 재생 종료/파일 변경 시 URL.revokeObjectURL() 호출

3-4. hls.js 설정

  • hls.js 1.6.x 설치 및 Video.js VHS와의 역할 분담 결정
  • backBufferLength: 30, maxBufferSize: 60MB 등 필수 설정 적용
  • 에러 복구 로직 (QuotaExceededError 대응)

3-5. 기본 UI 레이아웃

  • 메인 레이아웃: 플레이어 영역 + 사이드 패널 (영상 목록/주석)
  • 반응형 기본 구조 (Tailwind)
  • Zustand 스토어 기본 구조 (현재 영상, 재생 상태, 소스 타입)

산출물 (완료 기준)

  • 로컬 mp4 파일 드래그앤드롭 → 즉시 재생
  • 서버 영상 선택 → Range Request로 재생
  • HLS 변환 완료 후 HLS로 전환 재생
  • 전체화면 동작 확인

다음 단계 의존성

  • 단계 4, 5, 6 모두 이 단계 완료 후 시작 가능

단계 4: 프레임 추출

목표

Canvas 즉시 미리보기 + 서버 FFmpeg API를 통한 정확한 프레임 추출

세부 태스크

  • utils/frameCapture.ts — Canvas 기반 현재 프레임 캡처 (로컬 파일용 즉시 미리보기)
  • 단일 Canvas 재사용 패턴 적용
  • routes/frame.ts 연동 — 서버 FFmpeg 프레임 추출 요청
  • 프레임 추출 결과 표시 UI (모달 또는 패널)
  • 프레임 이미지 다운로드 기능
  • Shift+S 단축키 → 현재 프레임 캡처

산출물 (완료 기준)

  • 일시정지 상태에서 Shift+S → 프레임 이미지 표시 + 다운로드
  • 서버 영상: FFmpeg 정확 추출
  • 로컬 파일: Canvas 즉시 캡처

다음 단계 의존성

  • 단계 5에서 FPS 감지 로직과 연계

단계 5: 단위 이동

목표

프레임/초/장면 단위 seek + requestVideoFrameCallback FPS 감지 + 키보드 단축키

세부 태스크

  • hooks/useFrameStep.ts — requestVideoFrameCallback으로 FPS 동적 감지 (fallback 30fps)
  • 프레임 이동: ,(이전) / .(다음) — 일시정지 상태에서만
  • 초 이동: ←/→(5초), J/L(10초)
  • 장면 이동: [/] — 키프레임 기반 또는 일정 간격(30초) 이동
  • 10% 단위 탐색: 0~9 키
  • 재생 속도: +/- 키 (0.25x ~ 4x)
  • 전체화면 토글: F 키
  • 음소거 토글: M 키
  • 키보드 이벤트: 플레이어 포커스 시에만 활성, 텍스트 입력 시 비활성
  • 현재 프레임 번호 / 타임코드 표시 UI

산출물 (완료 기준)

  • 모든 키보드 단축키 동작 확인
  • 프레임 단위 이동 시 타임코드 정확 갱신
  • FPS 감지 로그 출력

다음 단계 의존성

  • 없음 (단계 6과 병렬 진행 가능)

단계 6: 텍스트 오버레이

목표

자막형(WebVTT track) + 메모형(interact.js DOM 오버레이) + 내보내기(subsrt)

세부 태스크

6-1. 자막형

  • WebVTT <track kind="subtitles"> 연동
  • 자막 추가/편집 UI (시작 시간, 종료 시간, 텍스트)
  • 서버 주석 API 연동 (type: "subtitle")
  • VTT/SRT 내보내기 (subsrt 라이브러리)

6-2. 메모형

  • components/overlay/MemoOverlay.tsx — DOM 오버레이 컨테이너
  • interact.js 드래그/리사이즈 연동
  • 좌표 정규화: px → % 변환/저장
  • 메모 추가 UI: Shift+M → 현재 시점에 메모 생성
  • 메모 편집/삭제 UI
  • 표시 로직: requestAnimationFrame 루프 + 이진 탐색
  • 서버 주석 API 연동 (type: "memo")
  • JSON/CSV 내보내기

6-3. 주석 관리 패널

  • hooks/useAnnotations.ts — 주석 CRUD + 서버 동기화
  • 사이드 패널: 시간순 주석 목록, 클릭 시 해당 시점으로 이동
  • 타임라인 위 주석 마커 표시

산출물 (완료 기준)

  • 자막 추가 → 영상 재생 시 하단에 표시
  • 메모 추가 → 드래그로 위치 조정 가능
  • VTT/SRT/JSON/CSV 내보내기 동작 확인

다음 단계 의존성

  • 없음 (단계 5와 병렬 진행 가능)

단계 7: UI/UX 통합

목표

전체 기능 통합, UI 다듬기, 썸네일 미리보기, 디스크 관리

세부 태스크

  • 전체 레이아웃 정리 (플레이어 + 컨트롤 + 사이드패널 통합)
  • 탐색바 썸네일 미리보기 (서버 FFmpeg 스프라이트 + VTT)
  • HLS 변환 진행률 UI (프로그레스 바 + 상태 텍스트)
  • 영상 목록 UI 개선 (업로드 상태, HLS 변환 상태, 용량)
  • 디스크 사용량 표시 + 경고
  • 로딩/에러 상태 처리 (스켈레톤, 에러 바운더리)
  • 키보드 단축키 도움말 오버레이 (? 키)
  • 전체 기능 통합 테스트
  • README.md 작성 (설치, 실행, 사용법)

산출물 (완료 기준)

  • 전체 기능이 하나의 UI에서 동작
  • 서버 파일 + 로컬 파일 모두 테스트 완료
  • README.md로 프로젝트 세팅/실행 가능

다음 단계 의존성

  • 모든 이전 단계 완료 필요

단계 의존성 다이어그램

단계 1 (프로젝트 구조)
  ├── 단계 2 (백엔드 서버)
  │     ├── 단계 4 (프레임 추출) ──┐
  │     └── 단계 6-자막 (주석 API) │
  └── 단계 3 (기본 플레이어)       │
        ├── 단계 4 (프레임 추출) ──┤
        ├── 단계 5 (단위 이동) ────┤ → 단계 7 (UI/UX 통합)
        └── 단계 6 (텍스트 오버레이)┘

※ 단계 5와 6은 병렬 진행 가능