Files
GhiVideo_v4/docs/명세_GhiVideo_데이터폴더_입력명세.md
b23042andClaude Fable 5 d38b842e8d GhiVideo 소스 복제 — v4 작업 시작 기준
기존 GhiVideo 저장소 HEAD의 트래킹 소스 362개 파일을 복제.
(node_modules·storage·빌드 산출물·대용량 미디어는 .gitignore 규칙대로 제외)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 14:32:51 +09:00

11 KiB

데이터 폴더 입력 명세 — 스테이션기반 플레이어

웹플레이어가 동영상이 있는 폴더를 전달받아 재생할 때, 폴더 안에 어떤 파일이 어떤 형식으로 있어야 하는지를 정의한다. 근거: client/src/utils/geoData.ts(폴더 파서) 기준. 실데이터(v3.0, 대전조차장–회덕)로 검증.


1. 동작 개요

  1. 사용자가 브라우저에서 폴더를 선택하면(<input type="file" webkitdirectory>), 폴더 내 전체 파일 목록이 플레이어에 전달된다.
  2. 플레이어는 파일명 규칙으로 각 파일을 자동 식별·파싱한다(별도 설정 불필요).
  3. 기준 이름 base = 영상 파일명에서 확장자를 뺀 것 (예: 상행)대전조차장-회덕.MP4 → base는 상행)대전조차장-회덕). 나머지 파일은 base 일치를 우선 매칭하고, 없으면 폴백 규칙으로 찾는다.

2. 폴더 구성 요약

# 파일 필수 역할
1 <base>.MP4 필수 드론 촬영 항공영상 (mp4/webm)
2 <base>.csv 필수 드론 비행로그 — 프레임별 위치·자세각·초점거리
3 01)측점.csv 또는 측점.csv 필수 측점 목록(이정·좌표·실측 표고) → 중심선·스테이션바·POI 높이 보완의 근간
4 <base>.kmz (또는 .kml) 필수(정책) POI·구조물의 유일한 소스 (지장물·교량·터널·출입문·구교·철도역)
5 <base>.route.json 또는 route.json 선택 노선 기본 정보 + 구조물 위치 보정
6 <base>_poi_overrides.json 선택 POI 드래그 보정 저장값 (역투영 결과)
.srt, .qgz, .qgs 등 그 외 파일 무시 플레이어가 읽지 않음 (작업용 부산물)

예시 폴더 (실데이터 v3.0):

상행)대전조차장-회덕 데이터(v3.0)/
├── 상행)대전조차장-회덕.MP4          ← 영상 (base 기준)
├── 상행)대전조차장-회덕.csv          ← 드론 비행로그
├── 01)측점.csv                       ← 측점 (루트 또는 building/ 하위 모두 허용)
├── 상행)대전조차장-회덕.kmz          ← POI·구조물 원본
├── 상행)대전조차장-회덕.route.json   ← 노선 정보 (선택)
├── 상행)대전조차장-회덕.srt          ← (무시됨)
└── 상행)대전조차장-회덕.qgz          ← (무시됨, QGIS 작업파일)

3. 파일별 상세 명세

3.1 영상 — <base>.MP4

  • 확장자: .mp4 또는 .webm (대소문자 무관). building/ 하위가 아닌 루트의 첫 번째 영상 파일을 사용한다.
  • 코덱: 브라우저 직접 재생이므로 H.264 권장.
  • 용량: 2GB 이상 가능 (URL.createObjectURL() 참조 방식 — 메모리에 통째로 올리지 않음).
  • 이 파일명이 폴더 전체의 base 를 결정한다.

3.2 드론 비행로그 — <base>.csv

드론이 촬영과 동시에 기록한 프레임별 데이터. 헤더 이름으로 컬럼을 찾으며(순서 무관), 헤더가 깨졌을 때만 위치 인덱스로 폴백한다.

컬럼(헤더명) 의미 단위/규약
frame_cnt 프레임 번호 (0부터) 정수
latitude / longitude 드론 위치 위도/경도 도(WGS84)
altitude 드론 고도 m (타원체고)
yaw 기수 방위각 도 — 북=0, 시계방향
pitch 카메라 틸트 도 — 음수=아래
roll
focal_len 초점거리 mm (35mm 환산)
  • 추가 컬럼(rel_alt, 5186x, 5186y, X좌표, Y좌표 등)이 있어도 무시되고 오류 없음.
  • latitude 가 숫자가 아닌 행은 건너뜀.
  • 파일 선택 규칙: 루트의 .csv 중 ① <base>.csv 정확 일치 우선, ② 없으면 파일명에 POI 가 없는 첫 .csv (영상명 비의존 폴백).
  • fps 자동 산출: 최대 frame_cnt ÷ 영상 길이(초) → 표준 fps(24/25/29.97/30/50/60…)에 스냅. 따라서 비행로그의 프레임 수는 영상의 실제 프레임 수와 일치해야 한다.

3.3 측점 — 01)측점.csv (또는 측점.csv)

철도 노선 측량 성과. 시간↔측점 대응표(스테이션바)와 선로 중심선, POI 높이 보완의 근간 데이터.

  • 파일 찾기 규칙 (3단 폴백): ① building/ 하위에서 파일명에 01)측점 포함 → ② 루트 포함 아무 위치에서 01)측점 포함 → ③ 파일명에 측점 포함.
  • 컬럼 (헤더 이름 기준):
컬럼 필수 의미
측점 필수 이정 표기 (예 157K900) — 스테이션 정렬·표시 기준
lat / lon 필수 측점 좌표 (도, WGS84) — 숫자 아니면 해당 행 제외
Z좌표_한국 권장 실측 정표고(EL, m) — 있으면 최우선 사용
Z좌표 폴백 Z좌표_한국 이 없을 때 사용
비고 선택 방향전환점(상행->하행, 02:05) 패턴이 있으면 방향전환점으로 추출
  • 중심선 자동 생성: v2.0 이후 center.csv 가 없으므로, 측점을 이정 순으로 이어 만든 폴리라인이 선로 중심선이 된다. → 측점 정확도가 곧 측점 투영·POI 높이 보완의 정확도.

⚠️ 주의 (실데이터에서 발견): 상행 v3.0의 01)측점.csv 는 실측 표고가 z 컬럼에 있고 Z좌표 컬럼은 0.0 인데, 파서는 Z좌표_한국Z좌표 순서로만 읽으므로 표고가 0으로 로드된다. 하행 파일처럼 표고 컬럼명을 Z좌표_한국 으로 통일하거나, 파서에 z 컬럼 폴백 추가가 필요하다.

3.4 POI·구조물 — <base>.kmz (또는 .kml)

POI·구조물의 유일한 소스다 (building/ 하위 02)~06) CSV는 더 이상 읽지 않음). 루트의 bare .kml 이 있으면 우선, 없으면 .kmz(zip)를 해제해 doc.kml 을 읽는다.

  • KML 폴더 구조 → 분류 매핑:
KML 폴더명 (포함 키워드) 분류 이름 필드 (description 표)
03)교량 구조물 bridge 구분 (+ 연장(m), 시설종별)
04)터널 구조물 tunnel 구분 (+ 연장(m), 시설종별)
06)구교 구조물 bridge(구교) 시설물명 (+ 연장(m))
05)출입문번호 POI (출입문) 출입문번호
02)지장물 등 그 외 POI (지장물 등) 구분title → placemark name
source=KAKAO_RAIL 또는 category_clean=철도역/역사 POI + 역사 구조물 (스테이션바에도 표출) 위와 동일
  • Placemark 좌표: <coordinates>lon,lat[,alt] 우선. 없으면 description 속성 lat/lon. 한국 범위 검증(위도 3339, 경도 124132) 밖이면 버림.
  • 속성(description): HTML <table> 의 (키, 값) 행으로 기재 — 구분, 연장(m), 시설종별(1종/2종/3종/기타), 시설물명, 출입문번호, source, category_clean, title, 표고(z/Z좌표/절대고도) 등. 구글어스 재저장본의 표 변형(<tbody>, 엔티티 등)도 허용.
  • 표고: POI 속성에 z/절대고도 가 있으면 사용, 없으면 0 → 재생 시 최근접 측점 실측 표고로 보완된다.
  • 누락 시: 경고 로그 후 POI·구조물 없이 동작(측점·드론·영상은 정상). CSV 폴백은 없다.

3.5 노선 기본 정보 — <base>.route.json (선택)

루트의 <base>.route.json 우선, 없으면 route.json. UTF-8 JSON.

{
  "routeInfo": {
    "name": "대전조차장-회덕",       // 노선명 (표시용)
    "direction": "상행",             // 방향 라벨
    "lengthKm": 4.25,                // 구간 연장 (km)
    "durationSec": 568,              // 영상 길이 (초)
    "startStationName": "대전",      // 시점역
    "endStationName": "신탄진",      // 종점역
    "stationTolerance": 20,          // 측점 인정 반경(m) — 기본 40
    "endStationGapMeters": 0         // 종점 미도착 거리(m) — 0이면 도착
  },
  "structures": [                    // (선택) 구조물 보정 — name 매칭으로 override
    {
      "name": "회덕천교",            // 괄호 이하 제거 후 부분일치 매칭
      "station": "158k400",          // 최우선: 이 측점값 위치에 배치 (숫자 m 또는 "158k400")
      "offset": -10,                 // 진행방향 ±N m 미세조정
      "startMileage": 158400,        // 매칭 실패 시 폴백 이정
      "endMileage": 158500,
      "lat": 36.4031, "lon": 127.4216   // 좌표 직접 지정도 가능
    }
  ]
}
  • structures 항목은 KMZ 유래 구조물에 명시된 필드만 덮어쓰고, KMZ에 없는 항목은 새 구조물로 추가된다.

3.6 POI 위치 보정 — <base>_poi_overrides.json (선택)

영상에서 POI 라벨을 드래그(역투영) 해 보정한 좌표의 저장/배포 파일. 폴더에 있으면 로드 시 자동 적용된다.

{
  "baseName": "상행)대전조차장-회덕",
  "overrides": {
    "회덕터널": { "lat": 36.40312, "lon": 127.42169, "z": 66.1 }
  }
}
  • overrides 없이 평면 맵({ "회덕터널": {…} })도 허용. z 는 정표고(m). POI title 정확 일치로 매칭.

4. 공통 규칙 (인코딩·파싱)

항목 규칙
CSV 인코딩 자동 감지 — 앞 3바이트가 UTF-8 BOM(EF BB BF)이면 UTF-8, 아니면 EUC-KR. 파일별 하드코딩 없음
CSV 컬럼 헤더 이름으로 탐색 (순서 무관, 여분 컬럼 무시). 헤더 훼손 시 위치 인덱스 폴백
CSV 형식 큰따옴표 필드 지원, 빈 줄 무시, \r\n/\n 모두 허용
KML UTF-8. .kml > .kmz(내부 doc.kml) 우선순위
JSON UTF-8. 파싱 실패 시 조용히 무시(선택 파일이므로)
폴더 구조 building/ 하위는 측점 CSV 탐색 외에는 사용하지 않음. 하위 폴더 깊이는 1단계(building/)만 인식

5. 파일 누락 시 동작

누락 파일 동작
영상 재생 불가 (폴더 인식 실패)
드론 비행로그 측점 투영·POI 오버레이·fps 산출 불가 → 사실상 일반 플레이어로 전락
측점 CSV 중심선·스테이션바·POI 높이 보완 불가 (시간축 재생만 가능)
KMZ/KML 경고 로그 후 POI·구조물 미표시 (측점·드론·영상은 정상 동작)
route.json 기본값으로 동작 (노선명 등 미표시, stationTolerance=40)
poi_overrides.json 보정 없이 원본 좌표 사용

부록 — 구현 근거 (소스 위치)

항목 위치
폴더 통합 로더 client/src/utils/geoData.tsloadFolderGeoData()
영상/base 식별 같은 파일 — findVideoFile(), deriveBaseName()
드론 CSV 파서 같은 파일 — parseDroneFrames()
측점 CSV 파서 (+방향전환점) 같은 파일 — parseStations()
KMZ/KML 파서 같은 파일 — parseKmz()
route.json / 구조물 병합 같은 파일 — parseRouteMeta(), mergeStructures()
POI 보정 로드/적용 같은 파일 — parsePoiOverrides(), applyPoiOverrides()
인코딩 자동 감지 같은 파일 — decodeBytes()
중심선 생성 같은 파일 — buildCenterlineFromStations()
(참고) 서버 검색 API 용 데이터 server/src/routes/geo.ts — 환경변수 GEO_DATA_DIR 폴더에 동일 형상 필요