Python 3.10+ Backend: PyAV (FFmpeg) Hardware Sync: Arduino Platform: Windows Version License: GPL v3 FreeMoCap
Caution
Please Note: This project is currently undergoing active development and testing. It is NOT YET in a state where it can be easily replicated as a turnkey / plug-and-play solution. Hardware-level camera synchronization involves specific driver, USB controller bandwidth, and timing considerations. You may encounter issues depending on your hardware environment. Follow the issue tracker or discussions for ongoing updates.
Disclaimer: MoCapSTR is an independent open-source companion tool and is not officially affiliated with the FreeMoCap project.
MoCapSTR is an open-source multi-camera recording tool designed to capture frame-accurate, hardware-synchronized video datasets for FreeMoCap. It synchronizes global-shutter USB cameras (e.g. Innomaker OV9281, tested up to 50 FPS hardware-synced / 120 FPS free-run) via an Arduino trigger signal, and also supports Blackmagic SDI capture cards.
Hardware-level synchronization has fundamentally different USB bandwidth requirements than standard webcam setups:
- Free-Running Cameras (Standard Webcams / Standard FreeMoCap): Cameras run on independent internal clocks. Their frames arrive staggered across time, so the data stream is naturally distributed.
- Hardware-Triggered Mode (MoCapSTR): An Arduino fires a 5V square-wave pulse to all cameras simultaneously. All connected cameras expose and push raw frame packets at the exact same microsecond.
Most standard PC motherboards share only 1 or 2 USB host controllers across all external USB ports:
- Motherboard Limits: In our testing, standard onboard USB controllers reliably handle a maximum of 3 cameras in hardware-trigger mode before bandwidth saturation causes dropped frames.
- Recommended for 4+ Cameras (Verified Hardware): We strongly recommend using a PCIe USB expansion card with dedicated host controllers per port (e.g. 4 separate USB controller chips on a single PCIe card) to ensure unconstrained bandwidth for all cameras.
- Tested & Verified Model: StarTech 4-Port USB 3.0 PCIe Card (Model:
P5Q4A-USB-CARD) — features 4 independent controller channels, reliably streaming 4 InnoMaker OV9281 cameras simultaneously without frame drops.
- Tested & Verified Model: StarTech 4-Port USB 3.0 PCIe Card (Model:
- Smart USB Polling Rate: In the Setup tab,
USB Pollingdefaults toAuto. In Hardware Trigger mode,Autorequests a 120 FPS UVC stream to eliminate beat-frequency host polling jitter, while in Free-Run mode it matches your target FPS.
Extensive empirical benchmark sweeping has characterized the InnoMaker OV9281 USB camera in hardware-trigger mode:
- Free-Run Mode: The camera sensor streams up to 120 FPS (1280x720 / 1280x800 MJPG) via continuous internal pipelining.
-
Hardware-Trigger Mode: The on-board USB bridge ISP firmware operates with a fixed non-overlapping state machine lockout window of
$\approx 18\text{–}20\text{ ms}$ per frame (regardless of resolution). -
Physical Hardware Ceiling: As a result, the physical hardware ceiling in trigger mode is strictly 50 FPS (20 ms frame period). Triggering faster than 50 Hz causes the firmware to reject subsequent pulses, producing exact harmonic sub-rates (60 Hz
$\rightarrow$ 30 FPS, 90 Hz$\rightarrow$ 45 FPS, 120 Hz$\rightarrow$ 40 FPS). -
Optimal Setting for Motion Capture: 1280x720 (720p HD) @ 50 FPS with
AutoUSB Polling and Exposure-9/-10(~1–2 ms shutter). This delivers 200 frame-accurate, global-shutter synchronized images per second across 4 cameras without motion blur or frame drops.
MoCapSTR Hardware Setup
Arduino Trigger Box (with Start/Stop button) connected via XLR cable to the Splitter Box.
- Hardware Camera Synchronization: Synchronous frame capture across all OV9281 cameras via Arduino FSIN pin (with auto-fallback to free-run mode if disconnected).
- Zero-Copy PyAV Backend: Writes raw MJPEG streams directly to disk via FFmpeg/PyAV without CPU decoding, minimizing frame drops.
- Live Preview & Charuco Calibration: Multi-camera live view with per-camera rotation (0°, 90°, 180°, 270°) and live
cv2.arucoCharuco board detection overlay. - FreeMoCap Folder Structure: Direct export into FreeMoCap's expected
synchronized_videos/structure with matching frame counts. - Built-in Offline Converter: Batch-converts raw
.avirecordings into compatible H.264 (.mp4) files. - Hardware Diagnostics: Built-in Camera Test tab to scan connected cameras for supported resolutions, framerates, and pixel formats.
- Wiring:
- Connect Arduino GND -> GND of all cameras.
- Connect Arduino Pin 2 -> FSIN (Frame Sync In) of all cameras.
- (Optional) Connect physical Start/Stop push-button between Arduino Pin 4 and GND.
- Guides & 3D Models:
- 3D printable files, fastener BOM, and step-by-step photo guide: 3Dprint & Assembly Guide.
- Detailed wiring guide and splitter box schematic: HARDWARE_SETUP.md.
- Camera sensor specifications: CAMERA_SPECS.md.
Pre-built Executable: A ready-to-run
.exeis available under Releases.
- Requirements: Python 3.10+ (and Blackmagic Desktop Video Drivers if using SDI).
git clone https://github.com/ZClassified/MoCapSTR.git
cd MoCapSTR
pip install -r requirements.txt
python python/main.py(Flash the Arduino sketch from arduino/trigger_firmware/trigger_firmware.ino using the Arduino IDE).
- Setup Tab: Choose project name and save folder (
~/Videos/MoCap_Projects/). Select resolution, target FPS, and the Arduino COM port. Click Initialize System & Start Preview. - Live Preview Tab: Verify all camera feeds and rotations. Enable Show Calibration (Auto-Detect) when recording a Charuco calibration take.
- Record: Start/Stop recording via the UI button or the physical button on the trigger box.
- Export & Convert Tab: Batch-convert raw takes into FreeMoCap-compatible H.264 (
.mp4) files. - Import into FreeMoCap: In FreeMoCap, select "Process Pre-recorded Data", navigate to your project folder (
calibrationortakes/take_...), and start tracking.
- Symptom: When clicking "Initialize System", one or more camera feeds show an initial frame and immediately freeze at
0.0 FPSwith a red warning overlay. - Root Cause: The camera has switched to Hardware Trigger mode (
AutoFocus=1) and is waiting for electrical pulses on itsFSINpin. If no trigger pulse or ground reaches the camera, the sensor produces zero further frames. - Step-by-Step Diagnostic:
- Quick Software Isolation (Free-Run Test): In the Setup tab, uncheck
Enable UVC Hardware Triggerand click Initialize System. If all cameras stream smoothly at 30/60 FPS in Free-Run mode, your USB card, bandwidth, and software are 100% working — the issue is strictly the physical hardware trigger connection. - Check Splitter Box Wiring: Open the splitter box and ensure all WAGO cage clamp terminals and DC jack solder joints are firm and not disconnected.
- Check
FSIN+/FSIN-Polarity: Ensure the 2-pin plug on the camera PCB is oriented correctly (Red =FSIN+, Black =FSIN-/ Ground). If polarity is reversed, the camera's internal diode blocks the trigger pulses. - Cross-Test Cables: Swap the DC barrel jack of the frozen camera with a working camera at the splitter box to isolate whether the cable or splitter port is faulty.
- Quick Software Isolation (Free-Run Test): In the Setup tab, uncheck
GPL-3.0 License. See LICENSE for details.
Hinweis: MoCapSTR ist ein unabhängiges Open-Source Companion-Tool und steht nicht in offizieller Verbindung mit dem FreeMoCap-Projekt.
MoCapSTR ist eine Multi-Kamera-Aufnahmesoftware zur Erstellung synchroner, frame-genauer Datensätze für FreeMoCap. Sie synchronisiert Global-Shutter USB-Kameras (z. B. Innomaker OV9281, getestet bis 50 FPS Hardware-Sync / 120 FPS Free-Run) über ein Arduino-Triggersignal und unterstützt zusätzlich Blackmagic SDI Capture Cards.
Warning
Projektstatus (Beta / Prototyp): Diese Software ist ein aktives Open-Source-Projekt im Prototypen-Stadium. Es können Fehler, Hardware-Inkompatibilitäten oder unerwartetes Verhalten auftreten. Feedback, Bug-Reports und Mithilfe sind über GitHub Issues ausdrücklich willkommen!
Hardware-Synchronisation stellt völlig andere Anforderungen an den USB-Bus als normale Webcams:
- Free-Run Modus (Normale Webcams / Standard FreeMoCap): Jede Kamera läuft auf ihrem eigenen internen Takt. Die Bildübertragungen treffen zeitlich leicht versetzt ein, wodurch sich die USB-Bandbreite natürlich verteilt.
- Hardware-Trigger Modus (MoCapSTR): Der Arduino sendet einen 5V-Rechteckimpuls zeitgleich an alle Kameras. Alle Kameras belichten und senden ihre JPEG-Datenpakete in der exakt selben Mikrosekunde.
Auf herkömmlichen PC-Mainboards teilen sich fast alle USB-Ports nur 1 bis 2 interne USB-Host-Controller:
- Mainboard-Limit: In Praxistests schaffen normale Onboard-Controller im Hardware-Trigger-Modus maximal 3 Kameras zuverlässig. Bei 4 Kameras kommt es zu Bandbreiten-Staus und Frame-Drops.
- Empfehlung für 4+ Kameras (Verifizierte Hardware): Eine PCIe-USB-Erweiterungskarte mit je einem dedizierten USB-Controller-Chip pro Port (z. B. 4 getrennte Controller auf einer Karte) wird dringend empfohlen.
- Getestetes & verifiziertes Modell: StarTech 4-Port USB 3.0 PCIe-Karte (Modell:
P5Q4A-USB-CARD) — verfügt über 4 getrennte USB-Host-Controller und betreibt 4 InnoMaker OV9281 Kameras absolut reibungslos ohne Frame-Drops.
- Getestetes & verifiziertes Modell: StarTech 4-Port USB 3.0 PCIe-Karte (Modell:
- Intelligentes USB-Polling: Im Setup-Tab steht
USB Pollingstandardmäßig aufAuto. Im Hardware-Trigger-Modus fordertAutoautomatisch einen 120-FPS-UVC-Stream an, um Phasen-Schwebungen (Jitter) zu eliminieren. Im Free-Run-Modus passt es sich der Ziel-FPS an.
Umfassende Benchmark-Messreihen haben das Verhalten der InnoMaker OV9281 USB-Kameras im Trigger-Modus eindeutig charakterisiert:
- Free-Run Modus: Der Sensor streamt via Pipelining problemlos mit bis zu 120 FPS (1280x720 / 1280x800 MJPG).
-
Hardware-Trigger Modus: Der interne Firmware-Zustandsautomat des USB-Bridge-Controllers (ISP) besitzt pro Frame ein festes Auslese- und Freischaltfenster (Lockout) von
$\approx 18\text{–}20\text{ ms}$ (unabhängig von der gewählten Auflösung). -
Physikalisches Hardware-Limit: Im Trigger-Modus liegt die maximale Obergrenze daher stabil bei 50 FPS (20 ms Periodendauer). Bei Triggerraten über 50 Hz werden nachfolgende Pulse vom Sensor verworfen, wodurch sich exakte sub-harmonische Raten ergeben (60 Hz
$\rightarrow$ 30 FPS, 90 Hz$\rightarrow$ 45 FPS, 120 Hz$\rightarrow$ 40 FPS). -
Optimale Einstellung für Motion Capture: 1280x720 (720p HD) @ 50 FPS mit
AutoUSB-Polling und Belichtung-9/-10(~1–2 ms Verschlusszeit). Dies liefert 200 gestochen scharfe, mikrosekundengenau synchrone Bilder pro Sekunde über alle 4 Kameras ohne Motion Blur oder Frame-Drops.
MoCapSTR Hardware Setup
Arduino Trigger-Box (mit Start/Stop-Taster) über XLR-Kabel mit der Splitter-Box verbunden.
- Hardware-Kamera-Synchronisation: Zeitgleiche Auslösung aller OV9281-Kameras über den Arduino FSIN-Pin (automatischer Fallback auf Free-Run bei getrenntem Arduino).
- Zero-Copy PyAV Backend: Schreibt rohe MJPEG-Streams via FFmpeg/PyAV ohne CPU-Decodierung direkt auf die Festplatte, um Frame-Drops zu vermeiden.
- Live Preview mit Charuco-Erkennung: Multi-Kamera-Vorschau mit individueller Bildrotation (0°, 90°, 180°, 270°) und zuschaltbarem
cv2.arucoCharuco-Erkennungs-Overlay. - FreeMoCap-Ordnerstruktur: Speichert direkt in
synchronized_videos/mit identischer Frame-Anzahl über alle Kameras. - Integrierter Offline-Konverter: Stapelverarbeitung zur Umwandlung von
.avi-Aufnahmen in hochkompatible H.264-Videos (.mp4). - Hardware-Diagnose: Kamera-Test-Tab zum automatischen Prüfen aller unterstützten Auflösungen, Frameraten und Formate verbundener Kameras.
- Verkabelung:
- Arduino GND -> GND aller Kameras.
- Arduino Pin 2 -> FSIN aller Kameras.
- (Optional) Physischer Start/Stop-Taster zwischen Arduino Pin 4 und GND.
- Anleitungen & 3D-Druck:
- Druckdateien, Stückliste und Foto-Montageanleitung: 3D-Druck- & Montage-Guide.
- Detaillierte Verkabelung und Splitter-Box: HARDWARE_SETUP.md.
- Kameraspezifikationen: CAMERA_SPECS.md.
Fertige EXE: Eine ausführbare Windows-Datei (
.exe) steht unter Releases zum Download bereit.
- Voraussetzungen: Python 3.10+ (und Blackmagic Desktop Video Treiber für SDI).
git clone https://github.com/ZClassified/MoCapSTR.git
cd MoCapSTR
pip install -r requirements.txt
python python/main.py(Den Arduino-Sketch aus arduino/trigger_firmware/trigger_firmware.ino über die Arduino IDE flashen).
- Setup Tab: Projektname und Speicherordner wählen. Auflösung, Ziel-FPS und Arduino COM-Port einstellen. Auf Initialize System & Start Preview klicken.
- Live Preview Tab: Kamera-Feeds und Rotation prüfen. Bei der Kalibrierungsaufnahme Show Calibration (Auto-Detect) aktivieren.
- Aufnahme: Aufnahme über den Software-Button oder den physischen Taster an der Trigger-Box starten/stoppen.
- Export & Convert Tab: Aufnahmen gesammelt in H.264 (
.mp4) für FreeMoCap umwandeln. - Import in FreeMoCap: In FreeMoCap "Process Pre-recorded Data" wählen, den Projektordner auswählen und das Tracking starten.
- Symptom: Nach dem Klick auf "Initialize System" zeigt eine Kamera nur ein einzelnes Standbild und bleibt mit einem roten Warn-Overlay bei
0.0 FPSstehen (oder alle Kameras bleiben stehen). - Ursache: Die Kamera ist im Hardware-Trigger-Modus (
AutoFocus=1) und wartet auf externe 5V-Taktsignale amFSIN-Pin. Wenn kein Signal oder keine Masse ankommt, liefert der Sensor keine weiteren Frames. - Lösungsschritte zur Fehlersuche:
- Schnelltest im Free-Run-Modus: Deaktiviere im Tab „1. Project & Setup" das Häkchen
[ ] Enable UVC Hardware Triggerund klicke auf Initialisieren. Laufen alle Kameras im Free-Run flüssig mit ~30 FPS, sind USB-Karte, Treiber und Software zu 100 % in Ordnung – der Fehler liegt ausschließlich an der physischen Trigger-Leitung. - Splitter-Box Verkabelung prüfen: Prüfe, ob in der Splitter-Box eine Klemme (WAGO) lose ist oder ein Kabel an einer DC-Buchse abgegangen ist.
- Polarität an der Kamera prüfen (
FSIN+/FSIN-): Prüfe, ob der 2-Pin JST-Stecker richtig herum aufgesteckt ist (Rot =FSIN+, Schwarz =FSIN-). Bei vertauschten Adern sperrt die sensorinterne Schutzdiode das Triggersignal. - Kreuztest durchführen: Stecke den DC-Stecker der betroffenen Kamera an der Splitter-Box in einen funktionierenden Port um, um Kabel- vs. Buchsendefekte zu isolieren.
- Schnelltest im Free-Run-Modus: Deaktiviere im Tab „1. Project & Setup" das Häkchen
GPL-3.0 Lizenz. Siehe LICENSE für Details.