Recording-Pipeline
Die vier Schritte einer Aufzeichnung — MQTT-Befehl aus der StudyControlApp, OBS-Aufnahme über den OBSController, das Flag cockpit_recording im Telemetrie-Log und der FFmpeg-Schritt von Hand.
Diese Seite beschreibt die Recording-Pipeline als Ablauf in vier Schritten. Jeder Abschnitt nennt das Repo, was dort passiert und was man selbst tut. Kein Repo kennt die ganze Kette, deshalb steht sie hier.
Alle Aussagen stammen aus dem Code, geprüft am 2026-09-18 in den Repos
study-control-app, beamngpy (Paket EcoSimlabPy) und obscontroller. Der
OBSController ist nicht öffentlich. Schritt 4 liegt in keinem Repo.
Voraussetzungen
- OBS Studio mit aktiviertem WebSocket-Server. Der OBSController verbindet
sich damit. Die Passwort-Authentifizierung muss aus sein
(
obscontroller/README.md). - Ein MQTT-Broker. Alle drei Schritte laufen über denselben Broker.
- Das OBSController-Binary und seine
.env-Datei. Die.envsetztRECORDING_CONTROL_TOPIC,MQTT_BROKERundOBS_WS. Das Status-Topic heißt ohne Eintragfrom_obs_controller/recording_status. - Ein laufender Trip in der StudyControlApp. Der Aufnahme-Knopf hängt an einem Trip und an dessen Proband*in und Treatment.
- FFmpeg für Schritt 4.
Schritt 1 — Aufnahme aus der StudyControlApp starten und stoppen
Repo: study-control-app
(packages/frontend/src/features/execution/composables/useCockpitRecording.ts).
Das Frontend schickt eine MQTT-Nachricht auf das Topic
from_sca_frontend/recording_control. Der Payload trägt das Pflichtfeld
recording und einen optionalen Dateinamen:
{
"recording": true,
"options": {
"fileName": "tripID:7-subjectId:3-treatmentId:1-driverProfile:NONE"
}
}
Den Dateinamen baut die App aus Trip, Proband*in, Treatment und Fahrprofil.
Ohne Profil steht dort NONE.
Selbst tun: Den Trip öffnen und den Aufnahme-Knopf wählen. Der Knopf
schaltet um: Er sendet recording: true, solange keine Aufnahme läuft, und
recording: false, solange eine läuft.
Die App fragt den Zustand nicht bei OBS ab. Sie pollt den Backend-Endpunkt
getCockpitRecordingStatus, der das Flag der letzten Telemetrie-Zeile des
Trips liefert (packages/backend/src/domains/execution/data.repository.ts).
Der Knopf meldet Erfolg also erst, wenn Schritt 3 das Flag geliefert hat.
Schritt 2 — Der OBSController nimmt in OBS Studio auf
Repo: obscontroller (Go, internes GitLab, nicht öffentlich).
Der Controller hört auf dem Steuer-Topic und bedient OBS über die
WebSocket-API (main.go, Funktion handleRecordingControl):
- Er prüft den Payload. Ist das JSON ungültig oder fehlt das Feld
recording, schreibt er eine Logzeile und lässt die Aufnahme unverändert. - Er liest den aktuellen OBS-Zustand. Er handelt nur bei einem echten Zustandswechsel.
- Vor dem Start schreibt er
options.fileNamein die OBS-ProfileinstellungOutput/FilenameFormatting. Ein Fehler dabei warnt nur, denn die Aufnahme zählt mehr als ihr Name. - Er startet oder stoppt die Aufnahme und meldet den neuen Zustand auf
from_obs_controller/recording_status.
Selbst tun: Den Controller vor dem Trip neben OBS Studio starten. Bei einer ausbleibenden Aufnahme in sein Log sehen.
Der Controller ist nicht öffentlich. Für Binary oder Quellcode beim Team nachfragen.
Schritt 3 — Das Flag cockpit_recording im Telemetrie-Log
Repo: beamngpy, Paket EcoSimlabPy.
EcoSimLabPy hört auf from_obs_controller/recording_status
(EcoSimlabPy/api/v2_topics.py). Es speichert das Feld recording als
cockpit_recording (EcoSimlabPy/vehicle/vehicle_controller.py) und legt es
in den Control-State jedes Ticks. Das Flag gehört zum State-Vertrag
(EcoSimlabPy/contract/beamng_state_v2.py) und steht deshalb in jeder
Nachricht der Fahrdaten.
Die StudyControlApp übernimmt das Flag als cockpitRecording in die
Telemetrie-Zeile
(packages/backend/src/domains/execution/beamngState.v2Reader.ts) und
speichert es zum Trip.
Selbst tun: Während der Fahrt nichts. Nach der Fahrt die Fahrdaten mit dem
Flag auf den aufgezeichneten Teil zuschneiden. Außerhalb der Aufnahme steht das
Flag auf false.
Schritt 4 — Nachbearbeitung mit FFmpeg auf Full HD
Kein Repo. Handarbeit.
OBS Studio schreibt die Datei in der Auflösung der aufgenommenen Szene. Die Video-Studien brauchen Full HD. Die Umwandlung läuft mit FFmpeg außerhalb aller drei Repos.
Selbst tun: Die Datei nach der Studie selbst umwandeln. Für diesen Schritt
gibt es in study-control-app, beamngpy und obscontroller weder ein Skript
noch eine dokumentierte Befehlszeile.
Ergebnisdaten
| Artefakt | Wo | Name |
|---|---|---|
| Videodatei | Der Aufnahmeordner von OBS | Aus options.fileName, sofern OBS-Platzhalter ihn nicht ändern |
| Fahrdaten | Die Datenbank der StudyControlApp, pro Trip | Spalte cockpitRecording pro Zeile |
Video und Fahrdaten sind zwei Dateien. Das Flag ist die einzige Verbindung zwischen ihnen.
Offene Punkte
- Der FFmpeg-Schritt hat kein Skript und keine dokumentierte Befehlszeile. Die Zielauflösung ist Full HD; der genaue Aufruf steht nirgends.
- Der OBSController ist nicht öffentlich und hat keine Lizenz. Ein kurzes Repo-Dokument folgt, sobald das Repo öffentlich ist.
- OBS ersetzt Zeichen, die das Dateisystem verbietet. Welche Dateinamen die StudyControlApp in so einem Fall erzeugt, ist ungeprüft.