명세_GhiVideo_데이터폴더_입력명세

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

웹플레이어가 동영상이 있는 폴더를 전달받아 재생할 때, 폴더 안에 어떤 파일이 어떤 형식으로 있어야 하는지를 정의한다. 근거: 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

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

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

컬럼(헤더명) 의미 단위/규약
frame_cnt 프레임 번호 (0부터) 정수
latitude / longitude 드론 위치 위도/경도 도(WGS84)
altitude 드론 고도 m (타원체고)
yaw 기수 방위각 도 — 북=0, 시계방향
pitch 카메라 틸트 도 — 음수=아래
roll
focal_len 초점거리 mm (35mm 환산)

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

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

컬럼 필수 의미
측점 필수 이정 표기 (예 157K900) — 스테이션 정렬·표시 기준
lat / lon 필수 측점 좌표 (도, WGS84) — 숫자 아니면 해당 행 제외
Z좌표_한국 권장 실측 정표고(EL, m) — 있으면 최우선 사용
Z좌표 폴백 Z좌표_한국 이 없을 때 사용
비고 선택 방향전환점(상행->하행, 02:05) 패턴이 있으면 방향전환점으로 추출

⚠️ 주의 (실데이터에서 발견): 상행 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 폴더명 (포함 키워드) 분류 이름 필드 (description 표)
03)교량 구조물 bridge 구분 (+ 연장(m), 시설종별)
04)터널 구조물 tunnel 구분 (+ 연장(m), 시설종별)
06)구교 구조물 bridge(구교) 시설물명 (+ 연장(m))
05)출입문번호 POI (출입문) 출입문번호
02)지장물 등 그 외 POI (지장물 등) 구분title → placemark name
source=KAKAO_RAIL 또는 category_clean=철도역/역사 POI + 역사 구조물 (스테이션바에도 표출) 위와 동일

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   // 좌표 직접 지정도 가능
    }
  ]
}

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

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

{
  "baseName": "상행)대전조차장-회덕",
  "overrides": {
    "회덕터널": { "lat": 36.40312, "lon": 127.42169, "z": 66.1 }
  }
}

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 폴더에 동일 형상 필요