Unter der Haube

Wie ein Kill gefunden wird

Kein neuronales Netz, kein Training, keine Wolke. Die Erkennung sucht eine ganz bestimmte geometrische Figur an einer ganz bestimmten Stelle - und das ist genau der Grund, warum sie zuverlässig ist.

Der Killdot

Bei einem Kill blitzen in FiveM vier kleine Punkte um dein Fadenkreuz auf. Sie sind gleich weit von der Mitte entfernt und liegen sich paarweise gegenüber. Diese Figur ist eindeutig - sie entsteht im normalen Spielgeschehen praktisch nie zufällig.

Andere Auto-Cutter raten über Lautstärke, Bewegung im Bild oder Treffermarkierungen. Alles drei geht schief, sobald jemand danebenhält, eine Granate hochgeht oder die Musik laut wird. Der Killdot ist ein Signal des Spiels selbst: er ist da oder er ist nicht da.

Schritt 1 — nur die Bildmitte

Durchsucht wird nicht das ganze Bild, sondern ein Quadrat von etwa 68 × 68 Pixeln um die Mitte. Das ist der einzige Ort, an dem der Killdot je auftaucht. Der Rest des Bildes wird nicht einmal angeschaut - deshalb kostet ein Frame fast nichts, egal ob 1080p oder 4K.

Größe Wert bei 1080p Wofür
half 34 px halbe Kantenlänge des Suchfensters
min_area / max_area 6 – 260 px² wie groß ein Punkt sein darf
r_min / r_max 3 – 30 px Abstand des Punkts zur Mitte

Alle Werte skalieren mit der Bildhöhe. Bei 1440p oder 4K wird derselbe Faktor angewendet — du musst nichts umstellen.

Schritt 2 — Farbe statt Helligkeit

Der Ausschnitt wird von RGB nach HSV umgerechnet. In HSV steht der Farbton getrennt von Sättigung und Helligkeit — deshalb bleibt "rot" dort auch rot, wenn die Szene dunkel ist oder das Spiel gerade eine Explosion zeigt. In RGB wäre derselbe Punkt bei Nacht ein völlig anderer Zahlenwert.

Die beiden Masken
// Rot liegt in HSV am Rand des Farbkreises -
// deshalb zwei Bereiche statt einem.
if ((h < 12 || h > 168) && s > 90 && v > 70) red[i] = 255;

// Weiße Marker: hell, aber ohne Farbe.
if (v > 200 && s < 60) white[i] = 255;

Danach läuft ein morphologisches Öffnen mit einem 2 × 2-Kernel darüber: erst erodieren, dann dilatieren. Einzelne verrauschte Pixel verschwinden dabei, echte Punkte bleiben stehen.

Schritt 3 — die Ringprüfung

Aus der Maske werden zusammenhängende Flächen gebildet. Flächen mit passender Größe und passendem Abstand zur Mitte gelten als Kandidaten. Dann kommen zwei Bedingungen, die zusammen die eigentliche Erkennung ausmachen:

  1. Gemeinsamer Ring

    Alle Punkte müssen ungefähr gleich weit von der Mitte entfernt sein — 40 % Abweichung sind erlaubt. Ein einzelner roter Fleck irgendwo im Fenster fällt damit raus.

  2. Paarweise gegenüber

    Zwei Punkte gelten als Paar, wenn sich ihre Vektoren zur Mitte aufheben: liegt einer bei (0, −8), muss der andere bei (0, +8) liegen. Es braucht mindestens zwei solcher Paare. Genau das unterscheidet einen Killdot von vier zufälligen roten Pixeln.

Schritt 4 — aus Treffern werden Clips

Abgetastet wird mit 10 Bildern pro Sekunde. Das reicht, weil der Killdot über mehrere Frames sichtbar bleibt, und spart gegenüber jedem einzelnen Frame das Neunfache an Rechenzeit.

so oft muss der Killdot gesehen werden, bevor er zählt
1 Aussetzer wird verziehen — ein Frame Rauch beendet keinen Kill
2,5 s Mindestabstand, damit eine Animation nicht drei Clips ergibt

Schritt 5 — schneiden

Geschnitten wird mit ffmpeg, das hier als WebAssembly direkt im Browser läuft. Der Sprung an die Startzeit passiert vor dem Einlesen (-ss vor -i), damit ffmpeg nicht das halbe Video durchrechnen muss, um an Minute 12 zu kommen.

Im Standardfall wird dabei nichts neu berechnet. -c copy übernimmt die Bilddaten unverändert aus dem Original in die neue Datei. Der Clip ist damit bitgenau dasselbe Bild wie deine Aufnahme, und der ganze Vorgang dauert Millisekunden statt Minuten.

Warum das so wichtig ist: ffmpeg als WebAssembly ist rund zehnmal langsamer als ein installiertes ffmpeg. Gemessen an demselben Clip: 1481 ms mit Neuberechnung, 5 ms ohne. Neu berechnet wird deshalb nur, wenn es einen echten Grund gibt — einen exakten Schnittpunkt oder das 10-MB-Limit von Discord.

Der Preis des Kopierens: ein Video lässt sich nur an Keyframes aufteilen. Der Anfang rutscht deshalb auf das Keyframe davor, der Clip wird etwas länger. Gemessen an einer Aufnahme mit einem Keyframe pro Sekunde: Schnitt bei 6,5 s ergab 2,5 s statt 2,0 s — er begann eine halbe Sekunde früher, das Ende stimmte.

Schritt 6 — mehrere Decoder gleichzeitig

Der Flaschenhals ist nicht das Rechnen. Gemessen an einem 24-Sekunden-Video gingen 75 % der Zeit allein dafür drauf, das Bild aus dem Video in den Arbeitsspeicher zu holen — und nur 2,5 % für die eigentliche Killdot-Erkennung.

Zwei Dinge greifen deshalb ineinander. Erstens wird der Ausschnitt schon beim Übertragen zugeschnitten, und zwar asynchron statt blockierend. Zweitens wird das Video in bis zu vier Abschnitte zerlegt, die gleichzeitig durchsucht werden.

24-s-Video Zeit Faktor Echtzeit
vorher, ein Abschnitt 2083 ms 11,5×
vorher, vier Abschnitte 1759 ms 13,6×
jetzt, ein Abschnitt 1474 ms 16,3×
jetzt, vier Abschnitte 1017 ms 23,6×

Interessant daran: Die Aufteilung allein brachte fast nichts (1,18×). Erst als das Übertragen den Hauptthread nicht mehr blockierte, konnten sich die Abschnitte überhaupt überlappen.

Die Abschnitte überlappen sich um 2,5 Sekunden, damit ein Kill genau auf einer Grenze nicht in beiden Hälften nur halb gesehen und dadurch verworfen wird. Doppelfunde räumt dieselbe Mindestabstands-Regel auf, die auch sonst greift.

Was hier bewusst fehlt

Motion Blur. Die Desktop-Version kann es, hier fehlt es absichtlich. Echtes Motion Blur mittelt mehrere Originalbilder — dafür muss das Video vollständig dekodiert werden, statt nur an den Schnittstellen. Im Browser ist das unbrauchbar langsam, und die schnelle Variante erzeugt Doppelbilder statt Blur.
Regler für die Erkennung. Die Werte sind an echtem FiveM-Material vermessen. Ein Regler daran wäre nur eine Einladung, es kaputtzustellen.
Hochskalieren. 1080p auf 4K zu strecken erfindet keine Details, sondern nur größere Dateien. Was hier passiert: beim Schneiden gehen keine Details verloren.