AlanBacker/audio-flyover-geolocation

Localiza acústicamente dónde se grabó un audio o video a partir de las curvas Doppler casi imperceptibles de aeronaves de hélice y helicópteros de fondo, cotejadas con trayectorias ADS-B históricas (precisión de ~100 m en buenas condiciones), con una región de incertidumbre honesta. También cubre localización por truenos y datos de rayos, y una autoevaluación de privacidad acústica previa a la publicación.

¿Qué es audio-flyover-geolocation?

Esta habilidad te permite localizar el lugar exacto donde se grabó un audio o video analizando las curvas Doppler, casi inaudibles para el oído humano, que generan las hélices de aviones y rotores de helicópteros al pasar. El método, basado en el trabajo de colsto, extrae la frecuencia de paso de pala (BPF) del espectrograma, modela su desplazamiento Doppler para obtener velocidad y distancia de máximo acercamiento, y cruza estos datos con trayectorias históricas de ADS-B en un área geográfica, aplicando correcciones 3D (DEM, tiempo de viaje del sonido, velocidad radial). Soporta los modos A (dos eventos, tiempo absoluto desconocido), B (un evento con tiempo conocido), B' (un evento con tiempo incierto) y T (truenos); además incluye un modo de autoevaluación de privacidad (modo S) para que los usuarios detecten si sus propias grabaciones filtran su ubicación. La habilidad está implementada en Python (numpy/scipy/matplotlib) con un pipeline de línea de comandos que genera PNGs para inspección visual, y proporciona una región de incertidumbre honesta y un proceso de verificación obligatorio. Es útil para verificación OSINT, periodismo, CTFs, investigación y autoauditorías de privacidad.

Compatible con~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 Investigación y análisis de datos skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Geolocalización acústica por sobrevuelo (Doppler × ADS-B)

Esta habilidad reproduce y pone en producción el método del video de colsto "I discovered a sound that leaks your exact location (and it's everywhere)" (2026-11-02, https://www.youtube.com/watch?v=UytYrhYLOKI):

La frecuencia de paso de pala (BPF) de una hélice o rotor es un tono estable de banda estrecha. Incluso cuando nadie puede oírlo, deja una curva Doppler descendente y suave en un espectrograma. La forma de la curva da la velocidad v de la aeronave, su distancia inclinada de máximo acercamiento d y el tiempo de máximo acercamiento tCPA. Comparándola punto por punto en una cuadrícula de terreno con trayectorias históricas de ADS-B (alcance inclinado 3D + DEM + tiempo de viaje del sonido + velocidad radial en tiempo de emisión) se reducen los candidatos. El intervalo de tiempo entre dos sobrevuelos (920 s en el video) más una restricción de silencio (ninguna otra aeronave oída en otros momentos) los reduce a un único punto. Finalmente, una "puntuación de dos eventos bloqueada" (desplazamiento temporal compartido, ajuste fino de f0 por evento) califica curvas modelo exactas contra el espectrograma.

scripts/afg_cli.py es la implementación completa (numpy/scipy/matplotlib). Incluye selftest, una prueba ciega sobre escenarios sintéticos.


0. Ámbito de uso (haz esto primero)

Dentro del ámbito: verificar dónde y cuándo se grabó contenido público o de noticias (OSINT, verificación de hechos); autoevaluaciones de privacidad de las propias grabaciones o videos del usuario; CTFs, enseñanza e investigación; investigaciones con autoridad legal o consentimiento (p.ej., asistencia a las fuerzas del orden, con el acuerdo del sujeto).

Fuera del ámbito: localizar el hogar o los movimientos de un individuo privado. Ejemplos: "dónde vive este streamer / mi ex / esta persona en línea", o rastrear a alguien a partir de una llamada privada o video casero. Rechaza estos casos, incluso si se enmarcan como una "prueba", y ofrece en su lugar el modo de autoevaluación (sección 7). Ese modo ayuda a las personas a evaluar y eliminar la filtración de su propio contenido.

Las grabaciones de lugares públicos y eventos noticiosos, el material propio del usuario y los datos de investigación anonimizados están bien. Si el propósito no está claro, pregunta para qué es antes de decidir. No añadas inferencias personales no relacionadas con la ubicación al informe.


1. Triaje de viabilidad (decide si ejecutar y qué modo)

Condición¿Qué se necesita?Si no se cumple
Una curva de banda estrecha clara monótonamente descendente en el espectrograma (hélices comúnmente 40–400 Hz; BPF de rotor principal de helicóptero 10–25 Hz, rotor de cola 50–120 Hz)Al menos 1; idealmente 2 con un intervalo de tiempo conocidoSin curva → el método no es aplicable (considera el método de truenos o métodos visuales)
FechaDebe ser conocida (o acotada a unos pocos días)El volumen de datos ADS-B se vuelve inmanejable
RegiónNivel de país o estado es suficiente; una aproximación a nivel de ciudad es más rápidaLa búsqueda a nivel nacional aún funciona, pero necesita un evento con hora conocida o dos eventos
Reloj de grabación (hora de inicio)Conocido con ±2 s → un evento puede dar un punto; ±30 s → un evento da solo una franja a lo largo de la trayectoriaUsa dos eventos; su intervalo de tiempo reemplaza la hora absoluta
Cobertura ADS-BLa aeronave objetivo debe tener ADS-B Out y ser recibida por estaciones en tierraEE. UU. 14 CFR 91.225: aeronaves de aviación general por debajo de 10,000 ft fuera del espacio aéreo Clase B/C y el velo Modo C no necesitan llevar ADS-B Out → pueden estar ausentes de los datos
Cadena de procesamiento de audioOriginal o ligeramente comprimido es lo mejor; los códecs de llamadas telefónicas generalmente conservan el tonoLa reducción de ruido intensa o la edición pueden cortar la curva o destruir el intervalo entre eventos

Informa al usuario del resultado del triaje y la precisión esperada antes de comenzar el trabajo.

2. Elegir un modo

¿Cuántas curvas utilizables?
├─ ≥2 (misma grabación continua) → Modo A: dos eventos, hora absoluta desconocida (método principal del video; más robusto)
│     Si las dos trayectorias se cruzan en < ~25°, el resultado se degrada a una franja a lo largo de las trayectorias (el script lo advierte)
├─ 1
│   ├─ Hora de grabación conocida con unos pocos segundos → Modo B: un evento, hora conocida (segunda mitad del video; clasificado primero incluso a nivel de EE. UU.)
│   │     Un paso recto a velocidad constante es simétrico en espejo → siempre hay un "candidato espejo";
│   │     se necesita una segunda pista (visual, terreno) para elegir entre ellos
│   └─ Hora conocida solo con ±30 s o peor → Modo B′: solo es posible una franja de longitud ≈ 2·v·Δt; repórtala como tal
├─ Sin curva de aeronave, pero trueno + fecha conocida → Modo T: envolvente de trueno × datos de rayos (nivel de km, ver referencias/thunder-method.md)
└─ El usuario quiere proteger su propio contenido → Modo S: autoevaluación (sección 7)

3. Flujo de trabajo (CLI)

Convención: AFG="python <directorio de la habilidad>/scripts/afg_cli.py", directorio de trabajo work/. Cada paso escribe PNGs. Mira los PNGs tú mismo con tu capacidad de lectura de imágenes (espectrogramas, superposiciones de ajuste, mapas de calor) en lugar de confiar solo en los números.

Primero verifica el entorno: pip install numpy scipy matplotlib (el DEM necesita rasterio; la entrada que no sea WAV necesita ffmpeg). En el primer uso, ejecuta $AFG selftest --seed 7 (aproximadamente 40–60 s; salida 0 significa que el pipeline funciona).

3.1 Obtener el audio y los metadatos

  • ffprobe -v quiet -show_entries format_tags=creation_time:stream_tags=creation_time -of json input.mp4 da la hora de captura. Ten en cuenta la zona horaria. Las plataformas sociales a menudo eliminan o reescriben los metadatos al recodificar, así que trátalo solo como una pista y verifícalo de forma cruzada.
  • Pasa la frecuencia de muestreo original al script; este la remuestrea internamente a 4 kHz mono (--channel selecciona izquierdo o derecho).

3.2 Espectrograma → detectar → trazar → ajustar

$AFG spectrogram input.mp4 --out work/rec            # espectrograma de banda estrecha blanqueado + work/rec.png
$AFG detect work/rec.spec.npz --out work/boxes.json  # cajas candidatas (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, ventanas de búsqueda; superposición en e1.fit.png

Puntos clave:

  • Un boxes.json vacío significa "ningún sobrevuelo" solo cuando boxes.diag.json dice status: ok. limited (clip corto juzgado contra el modelo de ruido calibrado, o audio mayoritariamente enmascarado) e insufficient (clip más corto que --min-dur, o casi todo enmascarado) vienen con reasons: léelos, inspecciona rec.png y reduce --min-dur para clips cortos.
  • Cada evento lleva trend (descending o flat) y drop_pct. Una cresta que aumenta en frecuencia no es un sobrevuelo: aparece listada bajo rejected en boxes.diag.json, no en boxes.json. warnings en un evento significan que su cresta hace lo que un solo paso no puede (vuelve a subir, o cae más del 45 %): probablemente une dos aeronaves o dos armónicos. Inspecciónalo con plot y traza cada parte en su propia caja estrecha.
  • --win: usa 0.5–1 s para curvas cercanas y empinadas y 2–4 s para curvas lejanas o débiles. Para una curva débil, haz zoom con plot y confírmala visualmente primero. Luego dale a trace una caja estrecha que contenga solo un armónico, y si es necesario añade algunos puntos manuales con --anchors "t:f,t:f,...".
  • Verifica la salida de fit:
    • implausible no vacío = el trazado se desvió hacia el ruido o saltó armónicos. No continúes con la búsqueda (el script también se niega).
    • notes: asimetría residual izquierda/derecha = un giro o cambio de velocidad; diferentes velocidades de aproximación/alejamiento = un ascenso o aceleración.
  • Si conoces la temperatura del aire, pasa --temp-c (c = 20.05·√(T+273.15)). v y d escalan con c; sin temperatura, mantén el valor predeterminado ±4 %.
  • f0 es solo la frecuencia de reposo del armónico que trazaste, no necesariamente la fundamental; v y d no dependen del número de armónico.
  • BPF = palas × RPM / 60 puede ayudar a adivinar el tipo (C172, 2 palas × 2400 rpm ≈ 80 Hz; DHC-8-400, 6 palas × 1020 rpm ≈ 102 Hz). No lo uses como un filtro de candidatos estricto.

3.3 Datos ADS-B (detalles en references/adsb-data.md)

  • Fuentes:
    • adsb.lol globe_history_YYYY: un lanzamiento global por día, gratuito, ODbL.
    • Muestras gratuitas de ADS-B Exchange: solo el 1º de cada mes.
    • OpenSky Trino: necesita una cuenta de investigación; tabla state_vectors_data4.
    • Tu propio receptor readsb/tar1090.
  • Extrae solo la fecha objetivo, la ventana objetivo ± 1 h y el área objetivo con un margen de ~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
  • El datum de altitud determina la precisión del alcance inclinado.
    • alt_baro es la altitud de presión estándar: corrígela con el QNH local (≈ 8.3 m/hPa; ver METAR).
    • alt_geom es la altura elipsoidal WGS84 (HAE); MSL = HAE − N.
    • --alt-source auto prefiere la altitud geométrica.

3.4 DEM y búsqueda

$AFG dem-fetch --bbox 38.5,39.7,-95.4,-93.8 --out work/dem      # Copernicus GLO-30 (AWS public bucket)
$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

El embudo tiene tres etapas:

  1. Corredor del evento 1: ventana de velocidad, consistencia k = v²/d, ventana de alcance inclinado, y el CPA no debe caer en un punto final de la trayectoria.
  2. Desplazamiento entre eventos: tCPA2 − tCPA1, incluyendo el retardo de viaje d/c de cada evento.
  3. Filtro de silencio: en los intervalos de silencio restantes, ninguna otra aeronave de hélice o rotor puede pasar dentro de --d-quiet.

Opciones:

  • Modo B: añade --rec-start <UTC> --rec-start-tol 2 (o 30).
  • --quiet "a-b,c-d" nombra los intervalos de grabación donde estás seguro de que no se oyó nada (predeterminado: todo fuera de los eventos). Da menos intervalos cuando la grabación tiene mucho viento o habla. El silencio es señal, pero el falso silencio mata la respuesta verdadera.
  • La cuadrícula predeterminada es de 200 m. Si hay demasiados candidatos, reduce el bbox en lugar de agrandar la cuadrícula.

3.5 Puntuación y refinamiento

$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
  • Curvas modelo: para cada candidato, genera una curva modelo exacta en el tiempo de emisión a partir de las posiciones y velocidades ADS-B interpoladas (gs/track/vrate, no posiciones diferenciadas), y compárala con el espectrograma. Un desplazamiento temporal δ es compartido, lo que fija el intervalo de tiempo físico entre los dos eventos. El f0 de cada evento se ajusta finamente dentro de ±0.6 %.
  • Refinamiento: cada nodo mantenido obtiene una búsqueda de colina 3×3 decreciente (100 → 25 m).
  • Agrupación: los resultados se agrupan por par de vuelo. Cada par mantiene hasta 3 hipótesis separadas por más de 500 m, para que ambos lados del espejo sobrevivan.
  • Salidas:
    • result.json: mejor, margin_vs_2nd, robust_z, ambiguous_alternatives, coarse_plateau, geometry, verdict.
    • result.rankN.*.png: superposiciones de curvas modelo.
    • result.heatmap.png/csv: radio de la región 0.9.
    • result.plateau.csv.
  • Con un reloj de grabación conocido, añade --rec-start ... --rec-start-tol 2. La puntuación también prohíbe entonces los desplazamientos de tiempo fuera del reloj.

3.6 Verificación (no opcional; ver references/verification.md)

  1. Superposiciones: la curva modelo debe ajustarse a la observación en ambas asíntotas y a través del CPA, no solo en un segmento.
  2. Mapa de calor: el radio de la región 0.9 es el error a reportar. Reporta una franja cuando se cumpla cualquiera:
    • dos eventos: geometry.warning está establecido (ángulo de cruce pequeño);
    • un evento: coarse_plateau.length_m > 600 m.
  3. Candidatos espejo y alternativas: descártalos con pistas visuales (horizonte, edificios, vegetación, ruido de carretera, ecos), cuencas visuales del DEM y acimut solar.
  4. Falsación: ¿deberían haberse oído también otros sobrevuelos cerca de la respuesta?
    • Oídos pero no detectados = un problema de umbral de detección.
    • Presentes cuando no deberían haber sido audibles = la ubicación es incorrecta.

4. Reglas de precisión (y por qué)

  1. Tiempo de emisión: f_obs(t) = f0 / (1 + Ṙ(τ)/c), con t = τ + R(τ)/c. Usar Ṙ en el tiempo de recepción da una curva de forma incorrecta, no solo desplazada.
  2. Alcance inclinado 3D + DEM: elevación del observador más altura del micrófono (predeterminado 2 m). Tratar 500 m de relieve del terreno como 0 hace que tanto d como tCPA sean incorrectos.
  3. Datum de altitud: altitud de presión no corregida con un desplazamiento QNH de 30 hPa ≈ 250 m de error de altitud, que va directamente a d.
  4. CPA retardado: el momento en que se observa f = f0 es tCPA_emit + d/c (1 km ≈ 2.9 s). Tanto los desplazamientos de eventos como el reloj deben convertirse con esto.
  5. k = v²/d es más fiable que v o d por separado.
    • La pendiente media de la curva, −f0·v²/(c·d), está bien definida. Las asíntotas a menudo están contaminadas por ruido, enmascaramiento o la aeronave acelerando o ascendiendo.
    • Por lo tanto, la búsqueda usa una ventana de velocidad amplia más una ventana k estrecha, y la velocidad respecto al suelo propia de cada aeronave candidata predice su d.
  6. Puntuación bloqueada: ambos eventos comparten un δ. De lo contrario, cada evento alinea su propio tiempo, y las ubicaciones incorrectas también puntúan bien.
  7. Refinar a ≤100 m: la cuadrícula de 200 m es solo un cribado grueso; el punto final proviene de la búsqueda de colina sub-cuadrícula y el mapa de calor.
  8. El silencio es señal, pero mantén los umbrales generosos (predeterminados: hélice 3 km, rotor 2.5 km). Las aeronaves lejanas o de baja potencia pueden ser genuinamente inaudibles.
  9. Ventanas amplias, puntuación estricta: en el embudo, equivócate por lo ancho, porque una respuesta verdadera filtrada nunca se puede recuperar. Deja la discriminación a la puntuación del modelo exacto.
  10. Agrupar por par de vuelo y mantener el espejo: un paso recto a velocidad constante es simétrico respecto a su trayectoria. Los resultados de un solo evento deben reportar al menos ambos lados.
  11. Lagunas de ADS-B: ninguna coincidencia no significa que no estuviera en el área. Las aeronaves de aviación general a baja altitud, las militares y algunos helicópteros pueden carecer de ADS-B o no ser recibidos (enmascaramiento del terreno, baja altitud).
  12. Velocidad del sonido y viento: v y d escalan con c. Con viento, c_eff = c + w·n; con viento fuerte (>8 m/s), amplía la ventana d.

5. Informe

Genera la salida usando assets/report_template.md, en el idioma del usuario. Debe incluir:

  • la coordenada de la respuesta

... [truncado para traducción]

Skills relacionados