CommunityRecherche & Datenanalysegithub.com

AlanBacker/audio-flyover-geolocation

Akustische Überflug-Geolokalisierung: Bestimmen Sie den Ort einer Audio- oder Videoaufnahme anhand der nahezu unhörbaren Doppler-Kurven von Propellerflugzeugen und Hubschraubern im Hintergrund, abgeglichen mit historischen ADS-B-Tracks (ca. 100 m unter guten Bedingungen), inklusive ehrlicher Unsicherheitsregion. Behandelt auch Donner- plus Blitzdaten-Lokalisierung und ein Pre-Publication-Acoustic-Privacy-Self-Audit. Verwenden Sie dieses Skill, wenn der Benutzer ein Video, eine Aufnahme, einen Livestream oder einen Anruf anhand seines Tons, Hintergrundgeräuschs, Flugzeuglärms, Doppler-Verschiebung, Spektrogramms, ADS-B-Daten oder Donners lokalisieren, verifizieren oder zeitlich einordnen möchte; Erwähnungen von akustischer Geolokalisierung, Audio-OSINT, „Wo wurde das aufgenommen?“, Verifizierung des Aufnahmeorts eines Videos anhand des Tons oder der colsto-Methode; oder überprüfen möchte, ob das eigene Video seinen Standort durch Ton preisgibt, selbst wenn Doppler oder ADS-B nie erwähnt werden. Für OSINT-Verifikation, Journalismus, CTFs, Forschung und Selbst-Audits; wird mit einer getesteten Python-Pipeline ausgeliefert.

Was ist audio-flyover-geolocation?

Dieses Skill implementiert und produktiviert die in colstos Video vorgestellte Methode zur akustischen Geolokalisierung anhand von Überflügen. Es analysiert die nahezu unhörbare Doppler-Kurve von Propellerflugzeugen oder Hubschraubern in einem Spektrogramm einer Audio- oder Videoaufnahme. Durch den Vergleich dieser Kurve mit historischen ADS-B-Flugdaten, unter Einbeziehung von 3D-Schrägdistanz, Geländemodell (DEM) und Schalllaufzeit, kann der Aufnahmeort auf etwa 100 Meter genau bestimmt werden – mit einer ehrlichen Angabe der Unsicherheit. Das Skill unterstützt mehrere Modi: Zwei Ereignisse (unklare absolute Zeit), ein Ereignis (bekannte oder unbekannte Zeit) sowie einen Donner-Modus. Es enthält außerdem einen Selbsttest und einen Self-Audit-Modus, mit dem Benutzer ihre eigenen Aufnahmen auf akustische Standortlecks überprüfen können. Die vollständige Python-Pipeline (numpy/scipy/matplotlib) ist in `scripts/afg_cli.py` enthalten und wird über die Kommandozeile gesteuert. Die Dokumentation beschreibt detailliert den gesamten Workflow von der Spektrogramm-Erstellung über die Erkennung und Anpassung der Doppler-Kurven bis hin zum ADS-B-Abgleich und der finalen Bewertung und Verifikation der Ergebnisse. Es ist für OSINT, Journalismus, CTFs, Forschung und Datenschutz-Selbstaudits konzipiert.

Funktioniert mit~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 Recherche & Datenanalyse skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Akustische Überflug-Geolokalisierung (Doppler × ADS-B)

Dieses Skill reproduziert und produktiviert die Methode aus colstos Video "I discovered a sound that leaks your exact location (and it's everywhere)" (2026-11-02, https://www.youtube.com/watch?v=UytYrhYLOKI):

Die Blattfolgefrequenz (BPF) eines Propellers oder Rotors ist ein stabiler schmalbandiger Ton. Selbst wenn ihn niemand hören kann, hinterlässt er eine glatte absteigende Doppler-Kurve in einem Spektrogramm. Die Form der Kurve ergibt die Geschwindigkeit v des Flugzeugs, seine Schrägdistanz d beim nächsten Punkt (CPA) und die CPA-Zeit tCPA. Vergleicht man sie Punkt für Punkt auf einem Bodenraster mit historischen ADS-B-Tracks (3D-Schrägdistanz + DEM + Schalllaufzeit + Radialgeschwindigkeit zum Emissionszeitpunkt), werden die Kandidaten eingegrenzt. Die Zeitlücke zwischen zwei Überflügen (920 s im Video) plus eine Stille-Bedingung (zu anderen Zeiten kein anderes Flugzeug hörbar) reduzieren sie dann auf einen einzigen Punkt. Schließlich bewertet ein „gesperrter Zwei-Ereignis-Score" (gemeinsamer Zeitversatz, f0-Feinabstimmung pro Ereignis) exakte Modellkurven gegen das Spektrogramm.

scripts/afg_cli.py ist die vollständige Implementierung (numpy/scipy/matplotlib). Es wird mit selftest, einem Blindtest an synthetischen Szenarien, ausgeliefert.


0. Anwendungsbereich (zuerst durchführen)

Im Rahmen: Verifizierung, wo und wann öffentliche oder Nachrichtenmedien aufgenommen wurden (OSINT, Faktencheck); Datenschutz-Selbstaudits der eigenen Aufnahmen oder Videos des Benutzers; CTFs, Lehre und Forschung; Untersuchungen mit rechtlicher Befugnis oder Einwilligung (z. B. Unterstützung von Strafverfolgungsbehörden, mit Zustimmung der betroffenen Person).

Außerhalb des Rahmens: Lokalisierung des Wohnorts oder der Bewegungen einer Privatperson. Beispiele: „Wo wohnt dieser Streamer / mein Ex / diese Person online", oder das Zurückverfolgen einer Person anhand eines privaten Anrufs oder Heimvideos. Lehnen Sie diese ab, selbst wenn sie als „Test" getarnt sind, und bieten Sie stattdessen den Self-Audit-Modus (Abschnitt 7) an. Dieser Modus hilft Personen, das Leck in ihren eigenen Inhalten zu bewerten und zu entfernen.

Aufnahmen von öffentlichen Orten und Nachrichtenereignissen, eigenes Material des Benutzers und anonymisierte Forschungsdaten sind in Ordnung. Wenn der Zweck unklar ist, fragen Sie nach, bevor Sie entscheiden. Fügen Sie dem Bericht keine persönlichen Schlussfolgerungen hinzu, die nichts mit dem Standort zu tun haben.


1. Machbarkeitstriage (entscheidet, ob ausgeführt wird und welcher Modus)

BedingungWas wird benötigtWenn nicht erfüllt
Eine klare monoton fallende schmalbandige Kurve im Spektrogramm (Propeller üblich 40–400 Hz; Hauptrotor-BPF von Hubschraubern 10–25 Hz, Heckrotor 50–120 Hz)Mindestens 1; idealerweise 2 mit bekannter ZeitlückeKeine Kurve → Methode nicht anwendbar (Donner-Methode oder visuelle Methoden in Betracht ziehen)
DatumMuss bekannt sein (oder auf ein paar Tage eingegrenzt)ADS-B-Datenmenge wird unüberschaubar
RegionLand oder Bundesland reicht; eine Prior auf Stadtebene ist schnellerLandesweite Suche funktioniert trotzdem, benötigt aber ein Ereignis mit bekannter Zeit oder zwei Ereignisse
Aufnahmeuhr (Startzeit)Auf ±2 s bekannt → ein Ereignis kann einen Punkt liefern; ±30 s → ein Ereignis liefert nur einen Streifen entlang der SpurZwei Ereignisse verwenden; ihre Zeitlücke ersetzt die absolute Zeit
ADS-B-AbdeckungDas Zielflugzeug muss ADS-B Out besitzen und von Bodenstationen empfangen werdenUS 14 CFR 91.225: GA-Flugzeuge unter 10.000 ft außerhalb der Klasse B/C Lufträume und des Mode C Schleiers müssen kein ADS-B Out haben → können in den Daten fehlen
Audio-VerarbeitungsketteOriginal oder leicht komprimiert ist am besten; Telefon-Codecs behalten den Ton normalerweiseStarke Rauschunterdrückung oder Bearbeitung kann die Kurve abschneiden oder die Lücke zwischen Ereignissen zerstören

Teilen Sie dem Benutzer das Triage-Ergebnis und die erwartete Genauigkeit mit, bevor Sie mit der Arbeit beginnen.

2. Auswahl eines Modus

Wie viele nutzbare Kurven?
├─ ≥2 (gleiche kontinuierliche Aufnahme) → Modus A: zwei Ereignisse, unbekannte absolute Zeit (Hauptmethode des Videos; robusteste)
│     Wenn sich die beiden Spuren mit < ~25° kreuzen, verschlechtert sich das Ergebnis zu einem Streifen entlang der Spuren (das Skript warnt)
├─ 1
│   ├─ Aufnahmezeit auf wenige Sekunden bekannt → Modus B: ein Ereignis, bekannte Zeit (zweite Hälfte des Videos; selbst bei US-weiter Suche zuerst eingestuft)
│   │     Ein gerader Vorbeiflug mit konstanter Geschwindigkeit ist spiegelsymmetrisch → es gibt immer einen „Spiegelkandidaten";
│   │     ein zweiter Hinweis (visuell, Gelände) wird benötigt, um zwischen ihnen zu wählen
│   └─ Zeit nur auf ±30 s oder schlechter bekannt → Modus B′: nur ein Streifen der Länge ≈ 2·v·Δt möglich; als solcher melden
├─ Keine Flugzeugkurve, aber Donner + bekanntes Datum → Modus T: Donnerhüllkurve × Blitzdaten (km-Genauigkeit, siehe references/thunder-method.md)
└─ Der Benutzer möchte seine eigenen Inhalte schützen → Modus S: Self-Audit (Abschnitt 7)

3. Workflow (CLI)

Konvention: AFG="python <skill dir>/scripts/afg_cli.py", Arbeitsverzeichnis work/. Jeder Schritt schreibt PNGs. Betrachten Sie die PNGs selbst mit Ihrer Bildlesefähigkeit (Spektrogramme, Fit-Overlays, Heatmaps), anstatt sich nur auf die Zahlen zu verlassen.

Überprüfen Sie zuerst die Umgebung: pip install numpy scipy matplotlib (DEM benötigt rasterio; Nicht-WAV-Eingabe benötigt ffmpeg). Bei der ersten Verwendung führen Sie $AFG selftest --seed 7 aus (ca. 40–60 s; Exit 0 bedeutet, dass die Pipeline funktioniert).

3.1 Audio und Metadaten abrufen

  • ffprobe -v quiet -show_entries format_tags=creation_time:stream_tags=creation_time -of json input.mp4 gibt die Aufnahmezeit. Achten Sie auf die Zeitzone. Soziale Plattformen entfernen oder überschreiben Metadaten beim Re-Encode oft, daher nur als Hinweis behandeln und gegenprüfen.
  • Übergeben Sie die ursprüngliche Abtastrate an das Skript; es resampelt intern auf 4 kHz Mono (--channel wählt links oder rechts).

3.2 Spektrogramm → Erkennen → Verfolgen → Anpassen

$AFG spectrogram input.mp4 --out work/rec            # gebleichtes schmalbandiges Spektrogramm + work/rec.png
$AFG detect work/rec.spec.npz --out work/boxes.json  # Kandidatenboxen (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, Suchfenster; Überlagerung in e1.fit.png

Wichtige Punkte:

  • Ein leeres boxes.json bedeutet „kein Überflug" nur, wenn boxes.diag.json status: ok sagt. limited (kurzer Clip, bewertet gegen das kalibrierte Rauschmodell, oder meist getaktetes Audio) und insufficient (Clip kürzer als --min-dur, oder fast alles getaktet) werden mit reasons geliefert: lesen Sie sie, inspizieren Sie rec.png, und senken Sie --min-dur für kurze Clips.
  • Jedes Ereignis hat trend (descending oder flat) und drop_pct. Ein Grat, der in der Frequenz ansteigt, ist kein Überflug: er wird unter rejected in boxes.diag.json aufgeführt, nicht in boxes.json. warnings bei einem Ereignis bedeuten, dass sein Grat das tut, was ein einzelner Vorbeiflug nicht kann (wieder ansteigt oder um mehr als 45 % fällt): es verbindet wahrscheinlich zwei Flugzeuge oder zwei Harmonische. Inspizieren Sie es mit plot und verfolgen Sie jeden Teil in seiner eigenen schmalen Box.
  • --win: 0.5–1 s für nahe, steile Kurven und 2–4 s für entfernte oder schwache. Zoomen Sie für eine schwache Kurve mit plot hinein und bestätigen Sie sie zuerst mit dem Auge. Geben Sie dann trace eine schmale Box, die nur eine Harmonische enthält, und fügen Sie bei Bedarf ein paar manuelle Punkte mit --anchors "t:f,t:f,..." hinzu.
  • Überprüfen Sie die fit-Ausgabe:
    • implausible nicht leer = die Spur lief auf Rauschen oder sprang Harmonische. Fahren Sie nicht mit der Suche fort (das Skript weigert sich ebenfalls).
    • notes: links/rechts Restasymmetrie = eine Kurve oder Geschwindigkeitsänderung; unterschiedliche Annäherungs-/Entfernungsgeschwindigkeiten = ein Steig-/Beschleunigungsflug.
  • Wenn Sie die Lufttemperatur kennen, übergeben Sie --temp-c (c = 20.05·√(T+273.15)). v und d skalieren beide mit c; ohne Temperatur behalten Sie die Standardabweichung von ±4 % bei.
  • f0 ist nur die Ruhefrequenz der Harmonischen, die Sie verfolgt haben, nicht unbedingt die Grundfrequenz; v und d hängen nicht von der Harmonischennummer ab.
  • BPF = Blätter × RPM / 60 kann helfen, den Typ zu erraten (C172, 2 Blätter × 2400 rpm ≈ 80 Hz; DHC-8-400, 6 Blätter × 1020 rpm ≈ 102 Hz). Verwenden Sie es nicht als harten Kandidatenfilter.

3.3 ADS-B-Daten (Details in references/adsb-data.md)

  • Quellen:
    • adsb.lol globe_history_YYYY: eine globale Veröffentlichung pro Tag, kostenlos, ODbL.
    • ADS-B Exchange kostenlose Samples: nur am 1. jedes Monats.
    • OpenSky Trino: benötigt ein Forschungskonto; Tabelle state_vectors_data4.
    • Eigener readsb/tar1090-Empfänger.
  • Extrahieren Sie nur das Zieldatum, das Zielfenster ± 1 h und das Zielgebiet, gepolstert um ~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
  • Das Höhendatum bestimmt die Schrägdistanzgenauigkeit.
    • alt_baro ist die Standarddruckhöhe: korrigieren Sie sie mit lokalem QNH (≈ 8.3 m/hPa; siehe METAR).
    • alt_geom ist die WGS84-Ellipsoidhöhe (HAE); MSL = HAE − N.
    • --alt-source auto bevorzugt geometrische Höhe.

3.4 DEM und Suche

$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

Der Trichter hat drei Stufen:

  1. Ereignis-1-Korridor: Geschwindigkeitsfenster, k = v²/d Konsistenz, Schrägdistanzfenster und der CPA darf nicht an einem Spur-Endpunkt liegen.
  2. Inter-Ereignis-Versatz: tCPA2 − tCPA1, einschließlich der d/c Laufzeitverzögerung jedes Ereignisses.
  3. Stille-Filter: In den verbleibenden ruhigen Abschnitten darf kein anderes Propeller- oder Rotorflugzeug innerhalb von --d-quiet passieren.

Optionen:

  • Modus B: --rec-start <UTC> --rec-start-tol 2 (oder 30) hinzufügen.
  • --quiet "a-b,c-d" benennt Aufnahmeabschnitte, in denen Sie sicher sind, dass nichts gehört wurde (Standard: alles außerhalb der Ereignisse). Geben Sie weniger Abschnitte an, wenn die Aufnahme viel Wind oder Sprache enthält. Stille ist Signal, aber falsche Stille tötet die wahre Antwort.
  • Standardraster ist 200 m. Wenn es zu viele Kandidaten gibt, verkleinern Sie die Bbox, anstatt das Raster zu vergrößern.

3.5 Bewertung und Verfeinerung

$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
  • Modellkurven: Generieren Sie für jeden Kandidaten eine exakte Modellkurve zum Emissionszeitpunkt aus den interpolierten ADS-B-Positionen und -Geschwindigkeiten (gs/track/vrate, nicht differenzierte Positionen) und vergleichen Sie sie mit dem Spektrogramm. Ein Zeitversatz δ wird gemeinsam genutzt, was die physikalische Zeitlücke zwischen den beiden Ereignissen festlegt. Das f0 jedes Ereignisses wird innerhalb von ±0,6 % feinabgestimmt.
  • Verfeinerung: Jeder behaltene Knoten erhält eine schrumpfende 3×3-Hügelkletter-Suche (100 → 25 m).
  • Gruppierung: Ergebnisse werden nach Flugpaar gruppiert. Jedes Paar behält bis zu 3 Hypothesen, die mehr als 500 m voneinander entfernt sind, sodass beide Spiegelseiten überleben.
  • Ausgaben:
    • result.json: bestes, margin_vs_2nd, robust_z, ambiguous_alternatives, coarse_plateau, geometry, verdict.
    • result.rankN.*.png: Modellkurven-Overlays.
    • result.heatmap.png/csv: Radius der 0.9-Region.
    • result.plateau.csv.
  • Mit bekannter Aufnahmeuhr --rec-start ... --rec-start-tol 2 hinzufügen. Die Bewertung verbietet dann auch Zeitverschiebungen außerhalb der Uhr.

3.6 Verifikation (nicht optional; siehe references/verification.md)

  1. Overlays: Die Modellkurve muss die Beobachtung auf beiden Asymptoten und durch den CPA anpassen, nicht nur auf einem Segment.
  2. Heatmap: Der Radius der 0.9-Region ist der zu meldende Fehler. Melden Sie einen Streifen, wenn eines von beidem zutrifft:
    • zwei Ereignisse: geometry.warning ist gesetzt (kleiner Kreuzungswinkel);
    • ein Ereignis: coarse_plateau.length_m > 600 m.
  3. Spiegelkandidaten und Alternativen: Schließen Sie sie durch visuelle Hinweise (Horizont, Gebäude, Vegetation, Straßenlärm, Echos), DEM-Sichtbarkeitsanalysen und Sonnenazimut aus.
  4. Falsifikation: Sollten andere Überflüge in der Nähe der Antwort ebenfalls gehört worden sein?
    • Gehört, aber nicht erkannt = ein Problem der Erkennungsschwelle.
    • Vorhanden, wenn sie nicht hörbar gewesen sein sollten = der Ort ist falsch.

4. Genauigkeitsregeln (und warum)

  1. Emissionszeit: f_obs(t) = f0 / (1 + Ṙ(τ)/c), mit t = τ + R(τ)/c. Die Verwendung von Ṙ zum Empfangszeitpunkt ergibt eine Kurve mit der falschen Form, nicht nur einer verschobenen.
  2. 3D-Schrägdistanz + DEM: Beobachterhöhe plus Mikrofonhöhe (Standard 2 m). Die Behandlung von 500 m Geländehöhenunterschied als 0 macht sowohl d als auch tCPA falsch.
  3. Höhendatum: Unkorrigierte Druckhöhe mit einem QNH-Versatz von 30 hPa ≈ 250 m Höhenfehler, der direkt in d eingeht.
  4. Verzögerter CPA: Der Moment, in dem f = f0 beobachtet wird, ist tCPA_emit + d/c (1 km ≈ 2,9 s). Ereignisversätze und die Uhr müssen beide damit umgerechnet werden.
  5. k = v²/d ist zuverlässiger als v oder d allein.
    • Die mittlere Kurvensteigung, −f0·v²/(c·d), ist genau bestimmt. Die Asymptoten sind oft durch Rauschen, Taktung oder Beschleunigen/Steigen des Flugzeugs verunreinigt.
    • Daher verwendet die Suche ein weites Geschwindigkeitsfenster plus ein schmales k-Fenster, und die eigene Geschwindigkeit über Grund jedes Kandidatenflugzeugs sagt sein d voraus.
  6. Gesperrte Bewertung: Beide Ereignisse teilen sich ein δ. Andernfalls richtet jedes Ereignis seine eigene Zeit aus, und auch falsche Standorte erzielen gute Bewertungen.
  7. Verfeinerung auf ≤100 m: Das 200-m-Raster ist nur ein grobes Sieb; der endgültige Punkt stammt aus der sub-Raster-Hügelkletter-Suche und der Heatmap.
  8. Stille ist Signal, aber halten Sie die Schwellen großzügig (Standards: Propeller 3 km, Rotor 2,5 km). Entfernte oder leistungsschwache Flugzeuge können tatsächlich unhörbar sein.
  9. Lockere Fenster, strenge Bewertung: Im Trichter irren Sie sich weit, denn eine herausgefilterte wahre Antwort kann nie wiedergewonnen werden. Überlassen Sie die Diskriminierung der exakten Modellbewertung.
  10. Nach Flugpaar gruppieren und den Spiegel behalten: Ein gerader Vorbeiflug mit konstanter Geschwindigkeit ist symmetrisch zu seiner Spur. Ergebnisse mit einem Ereignis sollten mindestens beide Seiten melden.
  11. ADS-B-Lücken: Keine Übereinstimmung ≠ nicht im Gebiet. Tief fliegende GA, Militärflugzeuge und einige Hubschrauber haben möglicherweise kein ADS-B oder werden nicht empfangen (Geländeverdeckung, niedrige Höhe).
  12. Schallgeschwindigkeit und Wind: v und d skalieren mit c. Bei Wind ist c_eff = c + w·n; bei starkem Wind (>8 m/s) das d-Fenster erweitern.

5. Bericht

Ausgabe unter Verwendung von assets/report_template.md, in der Sprache des Benutzers. Er muss enthalten:

  • die Antwortkoordinaten
  • ...

[gekürzt für Übersetzung]

Verwandte Skills