API Reference#
MOSAIC#
- page MOSAIC
Multi-camera Observatory for Social & Activity Interaction Capture
A synchronized multi-camera + audio recording suite for research labs, built around Basler GigE cameras, with live pose/gaze preview, post-recording analysis, and parallel-port/serial trigger integration for syncing with external systems (e.g. EEG amplifiers).
Capabilities#
Synchronized capture from multiple Basler GigE cameras (per-camera settings: exposure, gain, ROI, pixel format, hardware trigger input)
Multi-microphone audio recording alongside video
Post-hoc frame-accurate cross-camera sync (
sync_manifest.json), with per-camera and per-frame timestamp logsKeyboard, serial, and parallel-port trigger sources, with a session-wide trigger event log — parallel ports can also send a recording start/stop marker back out to an external device (e.g. an EEG amplifier’s trigger channel)
Post-hoc EEG-trigger-to-camera-frame lookup (Analysis tab’s “EEG/Trigger ↔ Frame Sync” plugin)
Live in-app pose & gaze preview (MediaPipe, CPU) during acquisition
Post-recording batch pose/motion analysis (
analysis/: YOLOv8-pose, centroid tracking, heatmaps)Checkerboard camera calibration
Per-user/lab-group login profiles, each with fully isolated settings
Session browser + synchronized multi-camera playback
Requirements#
The base build (UI, settings, profiles, tests) only needs Qt + CMake. Everything else is an opt-in
MOSAIC_ENABLE_*flag — see Feature flags below.Tool
Version
Needed for
CMake
≥ 3.25
always
C++ compiler
MSVC 2022 / GCC 13 / Clang 17 (C++23)
always
Qt
6.4+ (Core, Gui, Widgets, Network, Multimedia, Quick, QuickWidgets)
always
vcpkg
—
GTest, OpenCV, FFmpeg
Basler Pylon SDK
7.x
-EnableCamerasFFmpeg
via vcpkg (
x264feature)-EnableFfmpegOpenCV
4.x via vcpkg
-EnableOpenCV(calibration)CUDA + NVIDIA driver
—
-EnableNvencAll optional features compile with stub fallbacks when disabled — you can develop and test the full UI without any lab hardware attached.
Building#
# 1. Clone git clone https://github.com/fcbg-platforms/mosaic.git cd mosaic # 2. Install vcpkg packages vcpkg install # 3. Configure & build — base build, no hardware .\scripts\configure.ps1 -BuildType Release -BuildTests cmake --build build\Release --parallel # Full build with cameras + FFmpeg + calibration .\scripts\configure.ps1 -BuildType Release -EnableCameras -EnableFfmpeg -EnableOpenCV cmake --build build\Release --parallel # Deploy Qt DLLs so the .exe runs on other machines windeployqt --qmldir src\qml build\Release\bin\mosaic.exe
macOS/Linux:
./scripts/configure.sh(seedocs/quickstart.rstfor the full flag reference).Run tests:
cd build\Release ctest --output-on-failure
Feature flags#
Flag
Default
Requires
MOSAIC_ENABLE_CAMERASOFF
Basler Pylon SDK at
PYLON_ROOT%MOSAIC_ENABLE_FFMPEGOFF
FFmpeg (vcpkg,
x264feature)MOSAIC_ENABLE_NVENCOFF
FFmpeg + CUDA + NVIDIA driver
MOSAIC_ENABLE_OPENCVOFF
OpenCV 4.x (vcpkg)
MOSAIC_ENABLE_PARALLEL_PORTOFF
Windows +
InpOut32.dllnext to the exeMOSAIC_ENABLE_SERIALON
Qt SerialPort (auto-detected)
MOSAIC_BUILD_TESTSOFF
GTest (vcpkg)
MOSAIC_BUILD_DOCSOFF
Doxygen + Sphinx (see Python environments)
CI (
.github/workflows/ci.yml) builds and tests the hardware-free configuration only — Pylon is a licensed vendor SDK not fetchable via vcpkg, and no camera hardware exists on hosted runners. Camera/FFmpeg-touching changes need manual verification against real hardware; note how you tested in the PR description.Python environments#
python/,analysis/, anddocs/are three independent uv projects (ownpyproject.toml/uv.lock/.venveach) — not a shared workspace, since they have genuinely conflicting dependencies (e.g.python/needs a light, headless OpenCV for the real-time capture path;analysis/needs the full OpenCV build plus torch/ultralytics for batch pose analysis). Install only what you need:cd python && uv sync # real-time pose/gaze worker (spawned automatically by the app) cd analysis && uv sync # post-recording batch pose/motion analysis (YOLOv8-pose) cd docs && uv sync # Sphinx documentation build
Lint/format with
ruff(config shared at repo-rootruff.toml; ruff isn’t a dependency of any of the three projects, so useuvx— an isolated, ad-hoc tool run — notuv run) from the repo root:uvx ruff check --config ruff.toml . uvx ruff format --config ruff.toml .
or install the
.pre-commit-config.yamlhooks (pre-commit install) to run it automatically.Project structure#
mosaic/ ├── src/ │ ├── core/ # Application bootstrap, settings persistence │ ├── auth/ # Login profiles, per-profile settings isolation │ ├── video/ # Camera grabber (Pylon), encoder (FFmpeg), ring buffer feed │ ├── audio/ # Microphone recorder, WAV writer │ ├── trigger/ # Keyboard / serial / parallel-port triggers │ ├── record/ # Session recording orchestration │ ├── session/ # Session metadata │ ├── analysis/ # Sync manifest, real-time pose/gaze worker, post-recording analysis launcher │ ├── calibration/ # Checkerboard camera calibration │ ├── ui/ # Qt widgets (video/audio/trigger settings, session browser/player, auth) │ ├── qml/ # Live monitor view (Qt Quick) │ └── utils/ # Logger, lock-free ring buffer, timestamps ├── python/ # uv-managed real-time pose/gaze worker (MediaPipe), spawned by src/analysis ├── analysis/ # Post-recording batch pose/motion analysis scripts (YOLOv8-pose, tracking) ├── tests/ # Google Test unit tests ├── docs/ # Sphinx + Doxygen documentation source ├── scripts/ # Build/setup helper scripts (configure, NIC/camera provisioning) └── cmake/ # Find modules and compiler options
Documentation#
Full docs (architecture, quickstart, calibration, recording layout, profiles) live under
docs/— build them withMOSAIC_BUILD_DOCS=ON(see the table above), or start withdocs/quickstart.rstdirectly.Contributing#
See CONTRIBUTING.md — every PR needs a test, and CI must pass.
License#
[MIT](LICENSE)

Developed by
File Hierarchy#
-
- Directory src
- Directory analysis
- File analysis_manager.hpp
- File expression_result.hpp
- File gaze_fusion_result.hpp
- File nearest_by_key.hpp
- File pose_analysis_result.hpp
- File pose_kinematics.hpp
- File pose_models.hpp
- File pose_worker.hpp
- File realtime_metrics.hpp
- File rppg_result.hpp
- File skeleton3d_result.hpp
- File sync_manifest.hpp
- File transcript_result.hpp
- File transcript_worker.hpp
- File trigger_frame_map.hpp
- Directory audio
- File audio_envelope.hpp
- File audio_manager.hpp
- File audio_recorder.hpp
- File wav_writer.hpp
- Directory auth
- File profile.hpp
- File profile_manager.hpp
- Directory calibration
- Directory core
- File application.hpp
- File recording_access_control.hpp
- File settings.hpp
- Directory record
- File record_manager.hpp
- Directory session
- File session_info.hpp
- Directory trigger
- File keyboard_trigger.hpp
- File parallel_port_trigger.hpp
- File serial_trigger.hpp
- File trigger_manager.hpp
- File trigger_recorder.hpp
- File trigger_types.hpp
- Directory utils
- File logger.hpp
- File ring_buffer.hpp
- File timestamp.hpp
- Directory video
- File frame_timestamp_writer.hpp
- File gige_action_command.hpp
- File param_mapping.hpp
- File video_encoder.hpp
- File video_feed_provider.hpp
- File video_frame.hpp
- File video_grabber.hpp
- File video_manager.hpp
- Directory analysis
- File README.md
- Directory src
Full API#
Namespaces#
Classes and Structs#
- Struct CameraParameters
- Struct Documentation
mosaic::CameraParametersto_json()serialNumberfriendlyNamewidthheightoffsetXoffsetYreverseXreverseYpixelFormatspecifyFpsfpsexposureAutoexposureTimeUsexposureAutoLowerUsexposureAutoUpperUsgainAutogainDbgainAutoLowerDbgainAutoUpperDbgammablackLevelbalanceWhiteAutobalanceRatioRedbalanceRatioBluesaturationcontrastbrightnessautoTargetBrightnessdigitalShifthwTriggerEnabledhwTriggerSourcehwTriggerDelayUsliveAnalysisEnabledtestPatterncalibrationfrom_json()
- Struct Documentation
- Struct SessionInfo
- Struct Documentation
mosaic::SessionInfoload_annotations()save_annotations()format_duration()pathnamerecordedBystartUtcdurationMscameraCountmicCountmosaicVersionvideoCodecaudioCodechasPoseAnalysishasMotionAnalysishasTranscripthasExpressionhasGazeFusionhasSkeleton3DhasRppgvideoFilesaudioFilesanalysisFilesannotationsload()list_all()ms_to_hms()
- Struct Documentation
- Class AnalysisManager
- Inheritance Relationships
- Class Documentation
mosaic::AnalysisManagerAnalysisManager()~AnalysisManager()set_auto_analyze()auto_analyze()set_python_path()set_model()set_frame_skip()is_running()analyze_session()run_face_mask()run_diarization()run_expression_analysis()run_gaze_fusion()run_pose3d_reconstruction()run_rppg_analysis()stop()output_receivedanalysis_startedanalysis_finishedsetup_error
- Class ProfileManager
- Inheritance Relationships
- Class Documentation
mosaic::ProfileManagerRegisterResultProfileManager()~ProfileManager()load()profiles()has_profile()find()register_profile()has_admin()verify()touch()delete_profile()rename_display()change_password()set_role()set_institution()profiles_changedroot_dir()profile_dir()settings_path()log_path()next_accent_colour()
- Class RoomCalibrationManager
- Nested Relationships
- Class Documentation
mosaic::RoomCalibrationManagerRoomCalibrationManager()~RoomCalibrationManager()set_board()set_camera_intrinsics()feed_shot()shot_count()clear_shots()solve()is_resolved()extrinsic_for()reprojection_rms_for()use_shot_as_plane()is_available()mosaic::RoomCalibrationManager::BoardSpecmosaic::RoomCalibrationManager::CameraShotResultmosaic::RoomCalibrationManager::SolveResult
- Class VideoGrabber
- Inheritance Relationships
- Class Documentation
mosaic::VideoGrabberVideoGrabber()~VideoGrabber()open()close()apply_live_params()start_grabbing()stop_grabbing()request_calibration_frame()is_actually_grabbing()is_open()frames_grabbed()frames_dropped()current_fps()last_frame_elapsed_ns()action_command_ready()action_device_key()action_broadcast_address()configured_fps()achievable_fps()openedclosedframe_droppedgrab_errorpreview_framecalibration_frame_readyaction_command_capabilityenumerate_devices()run()
- Class VideoManager
- Nested Relationships
- Inheritance Relationships
- Class Documentation
mosaic::VideoManagerVideoManager()~VideoManager()open()close()start_preview()start()stop()apply_live_params()request_calibration_frame()is_recording()is_previewing()camera_count()total_frames_encoded()total_frames_dropped()camera_stats()camera_openedcamera_closedframe_droppedcamera_errorrecording_stoppedframe_previewcalibration_frame_readyaction_command_capabilitymosaic::VideoManager::CameraStats