This app records Basler, FLIR, or USB camera video with synchronized Arduino TTL outputs (gate, barcode, 1 Hz sync), and logs metadata.
- Basler, FLIR, and USB camera support
- Basler via Pylon, FLIR machine-vision cameras via Spinnaker /
PySpin, FLIR thermal cameras viaflirpy, USB via OpenCV - Live view with optional ROI cropping
- Collapsible bottom control strip so acquisition and recording panels can be hidden while the record button stays visible
- Recording with FFmpeg (GPU or CPU encoders)
- Per-frame metadata logging (timestamp, exposure, thermal statistics, GPIO line status when available)
- Arduino TTL I/O via pyFirmata with live TTL plot
- Metadata templates saved to JSON plus TTL history saved to CSV
- Windows 10/11
- Python 3.10+ (recommended: Anaconda or Miniconda)
- FFmpeg in PATH
- Arduino with a Firmata sketch flashed (recommended:
StandardFirmata)
Optional:
- Basler Pylon SDK +
pypylon(camera drivers) - FLIR Spinnaker SDK +
PySpinfor FLIR machine-vision cameras flirpyfor FLIR Boson, Lepton, and TeAx/Tau integrations
Compatibility note:
PySpin3.2.x is not compatible with NumPy 2.x in this project. Usenumpy<2in the CamApp environment when you need FLIR Spinnaker support.
Create a fresh environment and install dependencies:
conda env create -f environment.yml
If you are using a system Python:
python -m venv .venv
.\.venv\Scripts\activate
pip install -r requirements.txtCamApp now supports two different FLIR paths:
- FLIR machine-vision cameras through Teledyne FLIR Spinnaker +
PySpin - FLIR thermal cameras through
flirpy
For FLIR machine-vision cameras such as Blackfly / Chameleon / Grasshopper:
- Install the Spinnaker SDK for your Windows/Python build from Teledyne FLIR.
- Install the matching
PySpinwheel provided with Spinnaker. - Confirm
import PySpinworks in the same environment used to launch CamApp. - Restart CamApp and scan cameras again.
Notes:
PySpinis not installed fromrequirements.txt; the wheel must come from the Spinnaker SDK package and must match your Python version and architecture.- The repository's top-level
PySpin/folder is only a local cache for vendor wheels and docs; it is not the installed Spinnaker Python package. - If
PySpinimports fail with_ARRAY_API not foundornumpy.core.multiarray failed to import, the environment is using NumPy 2.x; downgrade tonumpy<2. simple_pyspinandEasyPySpinare useful for standalone diagnostics, but CamApp uses rawPySpindirectly so the app can manage acquisition and GenICam nodes itself.
FFmpeg is used for encoding and saving video. The app uses raw frames piped to FFmpeg, so FFmpeg must be on PATH.
Option A (static build):
- Download a static build from https://www.gyan.dev/ffmpeg/builds/ (full or essentials).
- Extract to a folder like
C:\ffmpeg. - Add
C:\ffmpeg\binto your PATH.
Option B (BtbN build):
- Download a release from https://github.com/BtbN/FFmpeg-Builds/releases
- Extract and add
binto PATH.
ffmpeg -versionThe app supports these encoders:
h264_nvenc(NVIDIA GPU)h264_qsv(Intel QuickSync)libx264(CPU)
Notes:
h264_nvencrequires a compatible NVIDIA GPU and recent drivers.- If GPU encoding fails, switch to
libx264in the UI.
python main.py- Open Arduino IDE.
- Load
File > Examples > Firmata > StandardFirmata. - Flash it to the Arduino.
- Use the CamApp UI to scan and connect to the correct COM port.
Pin mapping is configured directly in the app (Gate, Sync, Barcode, Lever, Cue, Reward, ITI) and uses Firmata digital pin read/write.
Barcode timing notes:
Gap After Codeis the silent interval after one barcode word finishes.- Full barcode cycle time =
start pulse + start low + (bits * bit duration) + gap. - The app no longer depends on legacy custom Arduino sketches in this repo; use
StandardFirmata.
CamApp ships with a checked-in PyInstaller spec at camApp.spec plus a reusable build script at scripts/build_release.ps1.
Local build from the CamApp Python environment:
python -m pip install -r requirements.txt pyinstaller
.\scripts\build_release.ps1 -Version dev -PythonExe python -CleanIf FLIR Spinnaker support matters in the compiled EXE, build with the same interpreter that already passes import PySpin and can see the camera, for example:
.\scripts\build_release.ps1 -Version dev -PythonExe C:\Users\bellone\.conda\envs\CamApp\python.exe -CleanThe build script prints the exact interpreter path plus a PySpin preflight result before packaging.
That produces:
dist/CamApp.exerelease/CamApp-dev-windows-x64.ziprelease/CamApp-dev-windows-x64.sha256release/CamApp-dev-windows-x64-warn.txt
Note: the compiled EXE still requires FFmpeg available on PATH at runtime. Local builds bundle PySpin only when the selected build interpreter already has the real vendor package installed. The GitHub build still does not bundle the Spinnaker SDK because the CI environment does not install the vendor wheel.
There is a manual GitHub Actions workflow at .github/workflows/release-windows.yml.
Use Actions > Build And Release CamApp > Run workflow and provide:
tag: release tag such asv1.0.0release_name: optional display titleprerelease: mark the GitHub release as prereleasedraft: publish as draft instead of a public release
The workflow builds the Windows EXE on windows-latest, zips it, generates a SHA-256 checksum, uploads the build artifacts, and then publishes a GitHub release with those assets attached.
- "FFmpeg not found": add FFmpeg to PATH and restart the terminal.
- "Failed to start Arduino TTLs": make sure no other app is holding the COM port, then reconnect.
- "No Basler camera found": verify Pylon is installed and the camera is detected by Pylon Viewer.
- FLIR Spinnaker camera missing from the list: verify Spinnaker is installed,
import PySpinworks, and the camera is visible in SpinView. - FLIR thermal camera missing from the list: verify
flirpyis installed and Windows still sees the device as a USB video device. - "No USB camera found": verify the device is connected and not in use by another app.