Geolocalização acústica por sobrevoo (Doppler × ADS-B)
Esta skill reproduz e torna operacional o método do vídeo 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):
A frequência de passagem de hélices (BPF) de uma hélice ou rotor é um tom de banda estreita estável. Mesmo quando ninguém pode ouvi-lo, ele deixa uma curva Doppler descendente suave em um espectrograma. A forma da curva fornece a velocidade v da aeronave, sua distância inclinada no ponto de aproximação máxima d e o tempo de CPA tCPA. Comparando-a ponto a ponto em uma grade terrestre com trilhas ADS-B históricas (alcance inclinado 3D + MDE + tempo de propagação sonora + velocidade radial no momento da emissão) estreita os candidatos. O intervalo de tempo entre dois sobrevoos (920 s no vídeo) mais uma restrição de silêncio (nenhuma outra aeronave ouvida em outros momentos) reduz então a um único ponto. Finalmente, uma "pontuação de dois eventos travada" (deslocamento de tempo compartilhado, ajuste fino de f0 por evento) classifica curvas modelo exatas contra o espectrograma.
scripts/afg_cli.py é a implementação completa (numpy/scipy/matplotlib). Ele acompanha selftest, um teste cego em cenários sintéticos.
0. Escopo de uso (faça isso primeiro)
No escopo: verificar onde e quando mídia pública ou jornalística foi gravada (OSINT, fact-checking); autoauditorias de privacidade das próprias gravações ou vídeos do usuário; CTFs, ensino e pesquisa; investigações com autoridade legal ou consentimento (por exemplo, auxiliando a aplicação da lei, com o acordo do sujeito).
Fora do escopo: localizar a casa ou movimentação de um indivíduo particular. Exemplos: "onde mora este streamer / meu ex / esta pessoa online", ou rastrear alguém a partir de uma chamada privada ou vídeo caseiro. Recuse estes, mesmo quando apresentados como um "teste", e ofereça o modo de autoauditoria (seção 7) como alternativa. Esse modo ajuda as pessoas a avaliar e remover o vazamento de seu próprio conteúdo.
Gravações de lugares públicos e eventos noticiosos, material próprio do usuário e dados de pesquisa anonimizados são aceitáveis. Se o propósito não estiver claro, pergunte para que é antes de decidir. Não adicione inferências pessoais não relacionadas à localização ao relatório.
1. Triagem de viabilidade (decide se deve executar e qual modo)
| Condição | O que é necessário | Se não for atendida |
|---|---|---|
| Uma curva de banda estreita clara monotonicamente descendente no espectrograma (hélices comumente 40–400 Hz; BPF do rotor principal de helicóptero 10–25 Hz, rotor de cauda 50–120 Hz) | Pelo menos 1; idealmente 2 com um intervalo de tempo conhecido | Nenhuma curva → método não aplicável (considere o método do trovão ou métodos visuais) |
| Data | Deve ser conhecida (ou limitada a alguns dias) | O volume de dados ADS-B se torna incontrolável |
| Região | Nível de país ou estado é suficiente; um prior de nível de cidade é mais rápido | Busca em todo o país ainda funciona, mas precisa de um evento com hora conhecida ou dois eventos |
| Relógio da gravação (hora de início) | Conhecido com ±2 s → um evento pode fornecer um ponto; ±30 s → um evento fornece apenas uma faixa ao longo da trilha | Use dois eventos; o intervalo de tempo entre eles substitui a hora absoluta |
| Cobertura ADS-B | A aeronave alvo deve ter ADS-B Out e ser recebida por estações terrestres | EUA 14 CFR 91.225: aeronaves GA abaixo de 10.000 pés fora do espaço aéreo Classe B/C e do véu Mode C não precisam ter ADS-B Out → podem estar ausentes dos dados |
| Cadeia de processamento de áudio | Original ou levemente comprimido é o melhor; codecs de chamada telefônica geralmente mantêm o tom | Redução de ruído pesada ou edição pode cortar a curva ou destruir o intervalo entre eventos |
Informe o usuário sobre o resultado da triagem e a precisão esperada antes de iniciar o trabalho.
2. Escolhendo um modo
Quantas curvas utilizáveis?
├─ ≥2 (mesma gravação contínua) → Modo A: dois eventos, hora absoluta desconhecida (método principal do vídeo; mais robusto)
│ Se as duas trilhas se cruzarem em < ~25°, o resultado degrada para uma faixa ao longo das trilhas (o script avisa)
├─ 1
│ ├─ Hora da gravação conhecida com alguns segundos → Modo B: um evento, hora conhecida (segunda metade do vídeo; classificado primeiro mesmo em escala nacional)
│ │ Uma passagem reta com velocidade constante é simétrica no espelho → sempre há um "candidato espelho";
│ │ uma segunda pista (visual, terreno) é necessária para escolher entre eles
│ └─ Hora conhecida apenas com ±30 s ou pior → Modo B′: apenas uma faixa de comprimento ≈ 2·v·Δt é possível; relatá-la como tal
├─ Nenhuma curva de aeronave, mas trovão + data conhecida → Modo T: envelope do trovão × dados de raios (nível de km, veja references/thunder-method.md)
└─ O usuário quer proteger seu próprio conteúdo → Modo S: autoauditoria (seção 7)
3. Fluxo de trabalho (CLI)
Convenção: AFG="python <dir da skill>/scripts/afg_cli.py", diretório de trabalho work/. Cada etapa escreve PNGs.
Olhe você mesmo para os PNGs com sua capacidade de leitura de imagens (espectrogramas, sobreposições de ajuste, mapas de calor) em vez de confiar apenas nos números.
Verifique o ambiente primeiro: pip install numpy scipy matplotlib (o MDE precisa de rasterio; entrada não-WAV precisa de ffmpeg). No primeiro uso, execute $AFG selftest --seed 7 (cerca de 40–60 s; saída 0 significa que o pipeline funciona).
3.1 Obter o áudio e metadados
ffprobe -v quiet -show_entries format_tags=creation_time:stream_tags=creation_time -of json input.mp4fornece a hora da captura. Cuidado com o fuso horário. Plataformas sociais geralmente removem ou reescrevem metadados na recompressão, então trate apenas como uma pista e faça uma verificação cruzada.- Passe a taxa de amostragem original para o script; ele reamostra internamente para 4 kHz mono (
--channelseleciona esquerdo ou direito).
3.2 Espectrograma → detectar → traçar → ajustar
$AFG spectrogram input.mp4 --out work/rec # espectrograma de banda estreita branqueado + work/rec.png
$AFG detect work/rec.spec.npz --out work/boxes.json # caixas 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, janelas de busca; sobreposição em e1.fit.png
Pontos-chave:
- Um
boxes.jsonvazio significa "nenhum sobrevoo" apenas quandoboxes.diag.jsondizstatus: ok.limited(clipe curto julgado contra o modelo de ruído calibrado, ou áudio majoritariamente com portas) einsufficient(clipe mais curto que--min-dur, ou quase tudo com portas) vêm comreasons: leia-os, inspecionerec.pnge diminua--min-durpara clipes curtos. - Cada evento carrega
trend(descendingouflat) edrop_pct. Uma crista que sobe em frequência não é um sobrevoo: ela é listada sobrejectedemboxes.diag.json, não emboxes.json.warningsem um evento significam que sua crista faz o que uma passagem não faz (sobe novamente, ou cai mais de 45%): provavelmente junta duas aeronaves ou dois harmônicos. Inspecione-a complote trace cada parte em sua própria caixa estreita. --win: use 0,5–1 s para curvas próximas e íngremes e 2–4 s para distantes ou fracas. Para uma curva fraca, amplie complote confirme visualmente primeiro. Em seguida, dê atraceuma caixa estreita contendo apenas um harmônico, e, se necessário, adicione alguns pontos manuais com--anchors "t:f,t:f,...".- Verifique a saída do
fit:implausiblenão vazio = o traçado caiu em ruído ou pulou harmônicos. Não prossiga para a busca (o script também se recusa).notes: assimetria residual esquerda/direita = uma curva ou mudança de velocidade; velocidades de aproximação/afastamento diferentes = uma subida ou aceleração.
- Se você souber a temperatura do ar, passe
--temp-c(c = 20,05·√(T+273,15)). v e d escalam com c; sem temperatura, mantenha o padrão ±4%. - f0 é apenas a frequência de repouso do harmônico que você traçou, não necessariamente a fundamental; v e d não dependem do número do harmônico.
- BPF = pás × RPM / 60 pode ajudar a adivinhar o tipo (C172, 2 pás × 2400 rpm ≈ 80 Hz; DHC-8-400, 6 pás × 1020 rpm ≈ 102 Hz). Não use como um filtro de candidato rígido.
3.3 Dados ADS-B (detalhes em references/adsb-data.md)
- Fontes:
- adsb.lol
globe_history_YYYY: uma liberação global por dia, gratuita, ODbL. - Amostras gratuitas do ADS-B Exchange: apenas no primeiro dia de cada mês.
- OpenSky Trino: precisa de uma conta de pesquisa; tabela
state_vectors_data4. - Seu próprio receptor readsb/tar1090.
- adsb.lol
- Extraia apenas a data alvo, a janela alvo ± 1 h, e a área alvo com acréscimo de ~0,5°.
$AFG adsb-ingest --src dir_traces/ --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
- O datum de altitude decide a precisão do alcance inclinado.
alt_baroé a altitude de pressão padrão: corrija com o QNH local (≈ 8,3 m/hPa; veja METAR).alt_geomé a altura elipsoidal WGS84 (HAE); MSL = HAE − N.--alt-source autoprefere altitude geométrica.
3.4 MDE e busca
$AFG dem-fetch --bbox 38.5,39.7,-95.4,-93.8 --out work/dem # Copernicus GLO-30 (bucket público 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
O funil tem três estágios:
- Corredor do Evento 1: janela de velocidade, consistência k = v²/d, janela de alcance inclinado, e o CPA não deve cair no ponto final de uma trilha.
- Deslocamento entre eventos: tCPA2 − tCPA1, incluindo o atraso de propagação d/c de cada evento.
- Filtro de silêncio: nos intervalos de silêncio restantes, nenhuma outra aeronave de hélice ou rotor pode passar dentro de
--d-quiet.
Opções:
- Modo B: adicione
--rec-start <UTC> --rec-start-tol 2(ou 30). --quiet "a-b,c-d"nomeia intervalos da gravação onde você tem certeza de que nada foi ouvido (padrão: tudo fora dos eventos). Dê menos intervalos quando a gravação tiver muito vento ou fala. Silêncio é sinal, mas silêncio falso mata a resposta verdadeira.- Grade padrão é 200 m. Se houver muitos candidatos, encolha a bbox em vez de aumentar a grade.
3.5 Pontuação e refinamento
$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, gere uma curva modelo exata no momento de emissão a partir das posições e velocidades ADS-B interpoladas (gs/track/vrate, não posições diferenciadas), e compare com o espectrograma. Um deslocamento de tempo δ é compartilhado, o que trava o intervalo de tempo físico entre os dois eventos. O f0 de cada evento é ajustado dentro de ±0,6%.
- Refinamento: cada nó mantido recebe uma subida de colina 3×3 decrescente (100 → 25 m).
- Agrupamento: os resultados são agrupados por par de voo. Cada par mantém até 3 hipóteses com mais de 500 m de distância, para que ambos os lados do espelho sobrevivam.
- Saídas:
result.json: melhor,margin_vs_2nd,robust_z,ambiguous_alternatives,coarse_plateau,geometry,verdict.result.rankN.*.png: sobreposições de curvas modelo.result.heatmap.png/csv: raio da região 0,9.result.plateau.csv.
- Com um relógio de gravação conhecido, adicione
--rec-start ... --rec-start-tol 2. A pontuação também proíbe deslocamentos de tempo fora do relógio.
3.6 Verificação (não opcional; veja references/verification.md)
- Sobreposições: a curva modelo deve ajustar a observação em ambas as assíntotas e através do CPA, não apenas em um segmento.
- Mapa de calor: o raio da região 0,9 é o erro a ser relatado. Relate uma faixa quando uma das seguintes condições for válida:
- dois eventos:
geometry.warningestá definido (pequeno ângulo de cruzamento); - um evento:
coarse_plateau.length_m> 600 m.
- dois eventos:
- Candidatos espelho e alternativas: elimine-os com pistas visuais (horizonte, edifícios, vegetação, ruído de estrada, ecos), bacias hidrográficas do MDE e azimute solar.
- Falsificação: outros sobrevoos próximos à resposta também deveriam ter sido ouvidos?
- Ouvidos, mas não detectados = um problema de limiar de detecção.
- Presentes quando não deveriam ser audíveis = a localização está errada.
4. Regras de precisão (e por quê)
- Tempo de emissão: f_obs(t) = f0 / (1 + Ṙ(τ)/c), com t = τ + R(τ)/c. Usar Ṙ no momento da recepção fornece uma curva de forma errada, não apenas deslocada.
- Alcance inclinado 3D + MDE: elevação do observador mais altura do microfone (padrão 2 m). Tratar 500 m de relevo do terreno como 0 torna d e tCPA errados.
- Datum de altitude: altitude de pressão não corrigida com um deslocamento QNH de 30 hPa ≈ 250 m de erro de altitude, que vai diretamente para d.
- CPA atrasado: o momento em que f = f0 é observado é tCPA_emit + d/c (1 km ≈ 2,9 s). Os deslocamentos de evento e o relógio devem ser convertidos com isso.
- k = v²/d é mais confiável do que v ou d isoladamente.
- A inclinação do meio da curva, −f0·v²/(c·d), é fixada com precisão. As assíntotas são frequentemente poluídas por ruído, portas de áudio ou a aeronave acelerando ou subindo.
- Portanto, a busca usa uma janela de velocidade ampla mais uma janela k estreita, e a velocidade de solo de cada aeronave candidata prevê seu d.
- Pontuação travada: ambos os eventos compartilham um δ. Caso contrário, cada evento alinha seu próprio tempo, e locais errados também pontuam bem.
- Refinar para ≤100 m: a grade de 200 m é apenas uma triagem grosseira; o ponto final vem da subida de colina sub-grade e do mapa de calor.
- Silêncio é sinal, mas mantenha os limites generosos (padrões: hélice 3 km, rotor 2,5 km). Aeronaves distantes ou de baixa potência podem ser genuinamente inaudíveis.
- Janelas frouxas, pontuação estrita: no funil, erre por excesso, porque uma resposta verdadeira filtrada nunca pode ser recuperada. Deixe a discriminação para a pontuação do modelo exato.
- Agrupar por par de voo e manter o espelho: uma passagem reta com velocidade constante é simétrica em relação à sua trilha. Resultados de evento único devem relatar pelo menos ambos os lados.
- Lacunas ADS-B: nenhuma correspondência não significa que não estava na área. Aeronaves GA de baixa altitude, militares e alguns helicópteros podem não ter ADS-B ou não ser recebidos (mascaramento por terreno, baixa altitude).
- Velocidade do som e vento: v e d escalam com c. Com vento, c_eff = c + w·n; em vento forte (>8 m/s), alargue a janela d.
5. Relatório
Saída usando assets/report_template.md, no idioma do usuário. Deve incluir:
- a coordenada da resposta
… [truncado para tradução]