The camera_recorder project supports Windows and Linux from one codebase.
Camera indexes and OpenCV backends differ by OS; a shared API in
src/camera_utils.py hides that so apps and tests call the same functions
everywhere.
# 1. Detect cameras and write the platform config file
# Windows:
python scripts/detect_windows_cameras.py
# Linux:
python scripts/detect_linux_cameras.py
# 2. Run the GUI (reads config_windows.json or config_linux.json automatically)
python scripts/flask_gui.py
# 3. Run unit tests (no cameras needed — same command on both OSes)
python run_all_tests.py --unit
# 4. Run hardware/camera scripts when cameras are plugged in
python run_all_tests.py --hardware| Concern | Windows | Linux |
|---|---|---|
| Config file | config_windows.json |
config_linux.json |
| OpenCV backend | cv2.CAP_DSHOW |
default (V4L2) |
| Typical dual-cam IDs | 0, 2 (skip built-in) |
0, 1 |
| Detection script | scripts/detect_windows_cameras.py |
scripts/detect_linux_cameras.py |
| Console Unicode | fix_console_encoding() |
no-op |
Use these helpers instead of branching on sys.platform in new code:
from camera_utils import (
get_camera_ids, # (cam1, cam2) from config or defaults
load_camera_config, # dict from config_*.json (any platform)
create_camera_capture, # VideoCapture with correct backend
get_opencv_backend, # CAP_DSHOW or None
fix_console_encoding, # UTF-8 stdout on Windows
describe_platform_setup, # banner-friendly snapshot
){
"platform": "linux",
"camera1_id": 0,
"camera2_id": 1,
"recording_settings": { "general": {...}, "golf_swing": {...} },
"detected_cameras": [ ... ],
"detection_date": "2026-07-15",
"notes": "..."
}python run_all_tests.py --unit
# or a single module:
python -m unittest tests.test_platform_config -vtests/test_platform_config.py mocks sys.platform so Windows and Linux
config paths, defaults, and backends are verified on whichever host you use.
python run_all_tests.py --hardwareStandalone scripts under tests/ now:
- Call
fix_console_encoding()(safe on Linux). - Open cameras with
create_camera_capture()(no hardcodedCAP_DSHOW). - Resolve indexes with
get_camera_ids()(reads the local config file).
# tests/test_utils.py — re-exports camera_utils for existing imports
from test_utils import get_camera_ids, create_camera_capture, print_platform_bannerfrom test_utils import get_camera_ids keeps working; it no longer
Windows-only-loads config.
CameraManager and DualCameraRecorder both call get_camera_ids() and
create_camera_capture(), so the same binary behaves correctly after you
generate the platform config once.
Override anytime:
python scripts/flask_gui.py --camera1 0 --camera2 2python scripts/detect_windows_cameras.py- Device Manager → cameras present
- Close apps that lock the camera (Zoom, OBS, Camera app)
ls -la /dev/video*groupsshould includevideo(sudo usermod -aG video $USER)python scripts/detect_linux_cameras.py- Re-check
config_linux.jsoncamera IDs
Re-run the platform detection script; unit tests stay green because they do not depend on live indexes.
Previously Linux tests skipped Windows config, and several hardware scripts
hardcoded CAP_DSHOW (broken on Linux). The shared helpers + dual config
files + --unit / --hardware split let you develop on Linux, ship on
Windows, and run the same commands on both.