Community연구 & 데이터 분석github.com

AlanBacker/audio-flyover-geolocation

음향 비행기 통과 위치 추정: 프로펠러 항공기 및 헬리콥터의 거의 들리지 않는 도플러 곡선을 과거 ADS-B 궤적과 매칭하여 오디오/비디오 녹화 위치를 파악합니다 (좋은 조건에서 약 100m 정확도). 천둥+번개 데이터 위치 추정 및 사전 공개 음향 프라이버시 자체 감사도 포함합니다.

audio-flyover-geolocation란 무엇인가요?

이 스킬은 오디오/비디오 녹화물에 배경 소음으로 포착된 프로펠러 항공기 또는 헬리콥터의 도플러 곡선을 분석하여 녹화 위치를 추정합니다. colsto의 방법을 기반으로 하며, 블레이드 통과 주파수(BPF)의 안정적인 협대역 톤이 스펙트로그램에서 매끄럽게 하강하는 곡선을 형성한다는 원리를 사용합니다. 두 번의 비행기 통과 이벤트 간 시간 간격과 침묵 제약 조건을 결합하여 후보를 하나의 지점으로 좁힙니다. 파이프라인은 numpy/scipy/matplotlib 기반의 Python CLI로 구현되어 있으며, 가장 중요한 것은 이 스킬이 합법적인 OSINT 확인, 팩트체킹, CTF, 연구 및 개인 프라이버시 자체 감사에만 사용되어야 하며, 개인의 사적인 위치 추적에는 사용할 수 없습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/AlanBacker/audio-flyover-geolocation/tree/HEAD/skills/en/audio-flyover-geolocation

Installed? Explore more 연구 & 데이터 분석 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

음향 비행기 통과 위치 추정 (도플러 × ADS-B)

이 스킬은 colsto의 비디오 "I discovered a sound that leaks your exact location (and it's everywhere)" (2026-11-02, https://www.youtube.com/watch?v=UytYrhYLOKI)의 방법을 재현하고 프로덕션화합니다:

프로펠러 또는 로터의 **블레이드 통과 주파수(BPF)**는 안정적인 협대역 톤입니다. 아무도 들을 수 없을 때조차도 스펙트로그램에서 매끄럽게 하강하는 도플러 곡선을 남깁니다. 곡선의 모양은 항공기의 속도 v, 최접근 경사 거리 d 및 CPA 시간 tCPA를 제공합니다. 지상 그리드에서 과거 ADS-B 궤적(3D 경사 거리 + DEM + 음파 전파 시간 + 방출 시간 방사 속도)과 점별로 비교하면 후보가 좁혀집니다. 두 번의 통과 사이의 시간 간격(비디오에서 920초)과 침묵 제약(다른 시간에 다른 항공기가 들리지 않음)이 이를 단일 지점으로 줄입니다. 마지막으로, "잠금식 두 이벤트 점수"(공유 시간 오프셋, 이벤트별 f0 미세 조정)가 스펙트로그램에 대해 정확한 모델 곡선을 평가합니다.

scripts/afg_cli.py는 전체 구현체(numpy/scipy/matplotlib)입니다. 합성 시나리오에 대한 블라인드 테스트인 selftest가 포함되어 있습니다.


0. 사용 범위 (먼저 수행)

범위 내: 공개 또는 뉴스 미디어가 녹화된 위치와 시간 확인(OSINT, 사실 확인) 사용자 자신의 녹화 또는 비디오에 대한 프라이버시 자체 감사 CTF, 교육 및 연구 법적 권한 또는 동의가 있는 조사(예: 대상자의 동의를 받아 법 집행 지원).

범위 외: 개인의 주거지 또는 이동 추적. 예시: "이 스트리머/내 전 애인/이 온라인 사용자는 어디에 살까" 또는 개인 통화나 홈 비디오에서 누군가를 추적하는 것. "테스트"로 위장하더라도 거절하고, 대신 자체 감사 모드(섹션 7)를 제안하십시오. 해당 모드는 사람들이 자신의 콘텐츠에서 정보 유출을 평가하고 제거하도록 돕습니다.

공공 장소 및 뉴스 이벤트 영상, 사용자 자신의 자료 및 익명화된 연구 데이터는 괜찮습니다. 목적이 불분명한 경우 결정하기 전에 먼저 용도를 물어보십시오. 위치와 관련 없는 개인적 추론을 보고서에 추가하지 마십시오.


1. 실행 가능성 평가 (실행 여부와 모드 결정)

조건필요한 것충족되지 않을 경우
스펙트로그램에서 명확한 단조 감소 협대역 곡선(프로펠러 일반적으로 40–400 Hz, 헬리콥터 주 로터 BPF 10–25 Hz, 꼬리 로터 50–120 Hz)최소 1개, 이상적으로는 알려진 시간 간격을 가진 2개곡선 없음 → 방법 적용 불가 (천둥 방법 또는 시각적 방법 고려)
날짜반드시 알려져 있어야 함 (또는 며칠 이내로 제한)ADS-B 데이터 양이 관리 불가능해짐
지역국가 또는 주 수준이면 충분, 도시 수준 사전 정보가 더 빠름전국 검색도 작동하지만, 시간이 알려진 하나의 이벤트 또는 두 개의 이벤트 필요
녹화 시계 (시작 시간)±2초 이내로 알려짐 → 하나의 이벤트로 지점 가능, ±30초 → 하나의 이벤트는 궤적을 따라 띠(strip)만 제공두 개의 이벤트 사용, 시간 간격이 절대 시간 대체
ADS-B 커버리지대상 항공기는 ADS-B Out을 가지고 지상국에서 수신되어야 함미국 14 CFR 91.225: Class B/C 공역 및 Mode C 베일 밖 10,000 ft 이하의 일반 항공기는 ADS-B Out 필수 아님 → 데이터에 없을 수 있음
오디오 처리 체인원본 또는 가벼운 압축이 가장 좋음, 전화 통화 코덱은 일반적으로 톤 유지심한 노이즈 제거 또는 편집은 곡선을 자르거나 이벤트 간 간격을 파괴할 수 있음

작업을 시작하기 전에 사용자에게 평가 결과와 예상 정밀도를 알리십시오.

2. 모드 선택

사용 가능한 곡선 수?
├─ ≥2 (동일한 연속 녹화) → 모드 A: 두 이벤트, 절대 시간 불명 (비디오의 주요 방법, 가장 강력함)
│     두 궤적이 < ~25°로 교차하면 결과가 궤적을 따라 띠로 저하됨 (스크립트가 경고)
├─ 1
│   ├─ 녹화 시간이 몇 초 이내로 알려짐 → 모드 B: 하나의 이벤트, 알려진 시간 (비디오 후반부, 미국 전체에서도 1순위)
│   │     직선 등속 통과는 거울 대칭 → 항상 "거울 후보"가 있음
│   │     둘 중 선택하려면 두 번째 단서(시각, 지형) 필요
│   └─ 시간이 ±30초 이하로만 알려짐 → 모드 B′: 길이가 ≈ 2·v·Δt인 띠만 가능, 그대로 보고
├─ 항공기 곡선 없지만 천둥 + 알려진 날짜 → 모드 T: 천둥 포락선 × 번개 데이터 (km 수준, 참조/thunder-method.md 참조)
└─ 사용자가 자신의 콘텐츠를 보호하려 함 → 모드 S: 자체 감사 (섹션 7)

3. 워크플로우 (CLI)

규칙: AFG="python <skill dir>/scripts/afg_cli.py", 작업 디렉토리 work/. 각 단계는 PNG를 작성합니다. 이미지 판독 능력으로 PNG를 직접 살펴보고(스펙트로그램, 피팅 오버레이, 히트맵) 숫자에만 의존하지 마십시오.

먼저 환경을 확인하십시오: pip install numpy scipy matplotlib (DEM은 rasterio 필요, WAV가 아닌 입력은 ffmpeg 필요). 처음 사용 시 $AFG selftest --seed 7을 실행하십시오 (약 40–60초, 종료 코드 0은 파이프라인이 작동함을 의미).

3.1 오디오 및 메타데이터 획득

  • ffprobe -v quiet -show_entries format_tags=creation_time:stream_tags=creation_time -of json input.mp4 는 캡처 시간을 제공합니다. 시간대에 주의하십시오. 소셜 플랫폼은 종종 재인코딩 시 메타데이터를 제거하거나 다시 작성하므로 단서로만 취급하고 교차 확인하십시오.
  • 원본 샘플 레이트를 스크립트에 전달하십시오. 내부적으로 4 kHz 모노로 리샘플링합니다(--channel로 왼쪽 또는 오른쪽 선택).

3.2 스펙트로그램 → 감지 → 추적 → 피팅

$AFG spectrogram input.mp4 --out work/rec            # 백색화 협대역 스펙트로그램 + work/rec.png
$AFG detect work/rec.spec.npz --out work/boxes.json  # 후보 박스 (t0, t1, fmin, fmax, score_z) + boxes.diag.json
$AFG plot work/rec.spec.npz --t0 160 --t1 320 --fmin 60 --fmax 380 --out work/zoom1.png
$AFG trace work/rec.spec.npz --t0 166 --t1 315 --fmin 98 --fmax 364 --out work/e1.csv
$AFG fit work/e1.csv --temp-c 18 --out work/e1.json  # v, d, tCPA, f0, 검색 윈도우, 오버레이 e1.fit.png

핵심 사항:

  • boxes.diag.json이 status: ok를 말할 때만 빈 boxes.json이 "비행기 통과 없음"을 의미합니다. limited (짧은 클립이 교정된 노이즈 모델에 대해 판단됨, 또는 대부분 게이트된 오디오) 및 insufficient (클립이 --min-dur보다 짧거나 거의 모든 것이 게이트됨)는 reasons와 함께 제공됩니다: 이를 읽고, rec.png를 검사하고, 짧은 클립의 경우 --min-dur를 낮추십시오.
  • 각 이벤트는 trend (descending 또는 flat) 및 drop_pct를 전달합니다. 주파수가 상승하는 릿지는 비행기 통과가 아닙니다: boxes.json이 아닌 boxes.diag.json의 rejected 아래에 나열됩니다. 이벤트에 대한 warnings는 릿지가 한 번의 통과로 할 수 없는 일(다시 상승하거나 45% 이상 하락)을 의미합니다. 아마도 두 항공기 또는 두 고조파를 결합한 것입니다. plot으로 검사하고 각 부분을 자체 좁은 박스로 추적하십시오.
  • --win: 가깝고 가파른 곡선에는 0.5–1초, 멀거나 희미한 곡선에는 2–4초를 사용하십시오. 희미한 곡선의 경우 plot으로 확대하여 먼저 육안으로 확인하십시오. 그런 다음 하나의 고조파만 포함하는 좁은 박스를 trace에 제공하고, 필요한 경우 --anchors "t:f,t:f,..."로 몇 개의 수동 지점을 추가하십시오.
  • fit 출력을 확인하십시오:
    • implausible가 비어 있지 않음 = 추적이 노이즈로 이어지거나 고조파를 건너뜀. 검색을 계속하지 마십시오 (스크립트도 거부함).
    • notes: 왼쪽/오른쪽 잔차 비대칭 = 선회 또는 속도 변화, 다른 접근/이탈 속도 = 상승 또는 가속.
  • 기온을 알고 있으면 --temp-c를 전달하십시오 (c = 20.05·√(T+273.15)). v와 d는 모두 c에 비례합니다. 온도가 없으면 기본 ±4%를 유지하십시오.
  • f0는 추적한 고조파의 휴지 주파수일 뿐, 반드시 기본 주파수는 아닙니다. v와 d는 고조파 번호에 의존하지 않습니다.
  • BPF = 블레이드 수 × RPM / 60은 유형 추측(C172, 2블레이드 × 2400 rpm ≈ 80 Hz; DHC-8-400, 6블레이드 × 1020 rpm ≈ 102 Hz)에 도움이 될 수 있습니다. 엄격한 후보 필터로 사용하지 마십시오.

3.3 ADS-B 데이터 (자세한 내용은 references/adsb-data.md 참조)

  • 출처:
    • adsb.lol globe_history_YYYY: 하루에 하나의 글로벌 릴리스, 무료, ODbL.
    • ADS-B Exchange 무료 샘플: 매월 1일만.
    • OpenSky Trino: 연구 계정 필요, 테이블 state_vectors_data4.
    • 자체 readsb/tar1090 수신기.
  • 대상 날짜, 대상 윈도우 ± 1시간 및 대상 영역을 약 0.5° 패딩하여 추출하십시오.
$AFG adsb-ingest --src traces_dir/ --start 2026-09-08T13:00Z --end 2026-09-08T18:00Z \
    --bbox 38.5,39.7,-95.4,-93.8 --qnh 1018 --geoid-n -29 --out work/tracks.npz
  • 고도 기준이 경사 거리 정확도를 결정합니다.
    • alt_baro는 표준 기압 고도: 로컬 QNH(≈ 8.3 m/hPa, METAR 참조)로 보정하십시오.
    • alt_geom은 WGS84 타원체 높이(HAE), MSL = HAE − N.
    • --alt-source auto는 기하학적 고도를 선호합니다.

3.4 DEM 및 검색

$AFG dem-fetch --bbox 38.5,39.7,-95.4,-93.8 --out work/dem      # Copernicus GLO-30 (AWS 퍼블릭 버킷)
$AFG search --tracks work/tracks.npz --events work/e1.json work/e2.json \
    --bbox 38.5,39.7,-95.4,-93.8 --dem work/dem/*.tif --rec-duration 1450 --out work/cands.npy

깔때기는 세 단계로 구성됩니다:

  1. 이벤트-1 회랑: 속도 윈도우, k = v²/d 일관성, 경사 거리 윈도우, CPA가 궤적 끝점에 있지 않아야 함.
  2. 이벤트 간 오프셋: tCPA2 − tCPA1, 각 이벤트의 d/c 전파 지연 포함.
  3. 침묵 필터: 남은 조용한 구간에서 다른 프로펠러 또는 로터 항공기가 --d-quiet 내를 통과하지 않아야 함.

옵션:

  • 모드 B: --rec-start <UTC> --rec-start-tol 2 (또는 30) 추가.
  • --quiet "a-b,c-d"는 아무것도 들리지 않았다고 확신하는 녹화 구간을 지정합니다 (기본값: 이벤트 외부의 모든 것). 녹화에 바람이나 말소리가 많은 경우 더 적은 구간을 제공하십시오. 침묵은 신호이지만, 잘못된 침묵은 정답을 죽입니다.
  • 기본 그리드는 200m입니다. 후보가 너무 많으면 그리드를 확대하지 말고 bbox를 축소하십시오.

3.5 점수 매기기 및 정제

$AFG score --tracks work/tracks.npz --spec work/rec.spec.npz --events work/e1.json work/e2.json \
    --cands work/cands.npy --dem work/dem/*.tif --out work/result.json
  • 모델 곡선: 각 후보에 대해 보간된 ADS-B 위치 및 속도(gs/track/vrate, 차분 위치 아님)에서 방출 시간에 정확한 모델 곡선을 생성하고 스펙트로그램과 비교합니다. 하나의 시간 오프셋 δ가 공유되어 두 이벤트 간의 물리적 시간 간격을 고정합니다. 각 이벤트의 f0는 ±0.6% 내에서 미세 조정됩니다.
  • 정제: 유지된 모든 노드는 축소되는 3×3 언덕 오르기(100 → 25m)를 얻습니다.
  • 그룹화: 결과는 비행 쌍별로 그룹화됩니다. 각 쌍은 500m 이상 떨어진 최대 3개의 가설을 유지하므로 양쪽 거울면이 모두 살아남습니다.
  • 출력물:
    • result.json: 최고, margin_vs_2nd, robust_z, ambiguous_alternatives, coarse_plateau, geometry, verdict.
    • result.rankN.*.png: 모델 곡선 오버레이.
    • result.heatmap.png/csv: 0.9 영역의 반경.
    • result.plateau.csv.
  • 알려진 녹화 시계가 있는 경우 --rec-start ... --rec-start-tol 2를 추가하십시오. 점수 매기기는 또한 시계 외부의 시간 이동을 금지합니다.

3.6 검증 (선택 사항 아님, references/verification.md 참조)

  1. 오버레이: 모델 곡선은 두 점근선과 CPA를 통해 관찰에 맞아야 하며, 한 세그먼트만이 아니라야 합니다.
  2. 히트맵: 0.9 영역의 반경이 보고할 오류입니다. 다음 중 하나가 해당되면 띠를 보고하십시오:
    • 두 이벤트: geometry.warning 설정됨 (작은 교차 각도);
    • 하나의 이벤트: coarse_plateau.length_m > 600m.
  3. 거울 후보 및 대안: 시각적 단서(지평선, 건물, 식생, 도로 소음, 메아리), DEM 조망 및 태양 방위각으로 배제하십시오.
  4. 반증: 정답 근처의 다른 비행기 통과도 들렸어야 하는가?
    • 들렸지만 감지되지 않음 = 감지 임계값 문제.
    • 들리지 않았어야 하는데 존재함 = 위치가 잘못됨.

4. 정밀도 규칙 (및 이유)

  1. 방출 시간: f_obs(t) = f0 / (1 + Ṙ(τ)/c), 여기서 t = τ + R(τ)/c. 수신 시간에 Ṙ를 사용하면 잘못된 모양의 곡선이 생성되며, 단순히 이동된 것만이 아닙니다.
  2. 3D 경사 거리 + DEM: 관찰자 고도에 마이크 높이(기본 2m)를 더합니다. 500m의 지형 기복을 0으로 처리하면 d와 tCPA가 모두 잘못됩니다.
  3. 고도 기준: 30 hPa QNH 오프셋이 있는 보정되지 않은 기압 고도는 ≈ 250m의 고도 오류이며, 이는 d에 직접 전달됩니다.
  4. 지연된 CPA: f = f0가 관찰되는 순간은 tCPA_emit + d/c (1km ≈ 2.9초)입니다. 이벤트 오프셋과 시계는 모두 이를 사용하여 변환되어야 합니다.
  5. k = v²/d는 v 또는 d 단독보다 더 신뢰할 수 있습니다.
    • 중간 곡선 기울기, −f0·v²/(c·d)는 단단히 고정됩니다. 점근선은 종종 노이즈, 게이팅 또는 항공기의 가속/상승으로 오염됩니다.
    • 따라서 검색은 넓은 속도 윈도우와 좁은 k 윈도우를 사용하며, 각 후보 항공기의 자체 지상 속도가 d를 예측합니다.
  6. 잠금 점수 매기기: 두 이벤트는 하나의 δ를 공유합니다. 그렇지 않으면 각 이벤트가 자체 시간을 정렬하고 잘못된 위치도 좋은 점수를 얻습니다.
  7. ≤100m로 정제: 200m 그리드는 거친 스크린일 뿐입니다. 최종 지점은 서브그리드 언덕 오르기와 히트맵에서 비롯됩니다.
  8. 침묵은 신호이지만 임계값은 관대하게 유지하십시오 (기본값: 프로펠러 3km, 로터 2.5km). 멀리 있거나 저전력 항공기는 실제로 들리지 않을 수 있습니다.
  9. 느슨한 윈도우, 엄격한 점수 매기기: 깔때기에서 넓게 오류를 범하십시오. 진정한 답이 필터링되면 다시 찾을 수 없기 때문입니다. 식별은 정확한 모델 점수에 맡기십시오.
  10. 비행 쌍별 그룹화 및 거울 유지: 직선 등속 통과는 궤적에 대해 대칭입니다. 단일 이벤트 결과는 적어도 양쪽을 모두 보고해야 합니다.
  11. ADS-B 갭: 일치하는 항목이 없다고 해당 지역에 없었던 것은 아닙니다. 저고도 일반 항공, 군용 항공기 및 일부 헬리콥터는 ADS-B가 없거나 수신되지 않을 수 있습니다(지형 차폐, 저고도).
  12. 음속 및 바람: v와 d는 c에 비례합니다. 바람이 있는 경우 c_eff = c + w·n, 강한 바람(>8m/s)에서는 d 윈도우를 넓히십시오.

5. 보고서

assets/report_template.md를 사용하여 사용자 언어로 출력합니다. 다음을 포함해야 합니다:

  • 답변 좌표

…

[번역을 위해 잘림]

관련 스킬