fujimatic is an interactive CLI/TUI for tethered control of Fujifilm mirrorless cameras (initial focus: X-T3) to support film scanning and astrophotography workflows. Written in Go with a small C wrapper for the Fujifilm Camera Control SDK.
- CLI/TUI client to interact with camera
- Full manual control over exposure settings
- Ability to start/pause/stop an imaging session with pre-defined number of frames or integration time
- Session state storage
- Intervalometer with delay feature
- Ability to view camera status, including battery level
- RAF to FITS/TIFF conversion for astrophotography workflows (NINA, PixInsight, Siril)
- Fake HAL implementation for unit tests (integration tests run manually against real hardware)
- Cross-platform: Windows and Linux (incl. Raspberry Pi) support
- Client/Server model for remote control
- sdk-c-wrapper (C) – Minimal API over the Fujifilm SDK.
- pkg/sdk (Go) – cgo bindings that expose
Init,Connect, etc. - pkg/hal – Hardware abstraction layer;
Camerainterface + real/fake implementations. - pkg/session – Session manager (handles intervalometer, file naming, persistence).
- cmd/fujimatic – CLI shell frontend (REPL).
- libs/ – SDK redistributables (not committed).
- scripts/ – build/test utilities.
User → CLI → Session Manager → HAL → SDK Wrapper → Fujifilm SDK → Camera.
default_outdir: "C:\\Users\\cfonseca\\Pictures\\fujimatic"
last_project_name: "orion_m42"
battery_threshold_percent: 10
sdk_path: "C:\\Users\\cfonseca\\Documents\\fujimatic\\sdk\\REDISTRIBUTABLES"
viewer_cmd: "mpv"Project Structure:
fujimatic/
├── cmd/fujimatic/ # Main CLI
├── pkg/ # Go packages (sdk, hal, session)
├── sdk-c-wrapper/ # C wrapper around Fujifilm SDK
├── libs/ # Compiled C wrapper libraries
├── scripts/ # Build utilities
├── README.md # This file
├── BUILD_INSTRUCTIONS.md # Build documentation
├── STORIES.md # Development progress
└── CLAUDE.md # AI assistant guidance
See BUILD_INSTRUCTIONS.md for detailed build documentation.
Basic workflow:
- Install Go 1.24.3+ and MSYS2 with MinGW64
- Obtain Fujifilm Camera Control SDK (not included in repo)
- Build C wrapper:
gcc -shared -o libs/windows/fmwrapper.dll ... - Build Go app:
go build -o bin/fujimatic.exe ./cmd/fujimatic - Copy DLL:
cp libs/windows/fmwrapper.dll bin/
# With real camera
./bin/fujimatic.exe
# With fake camera (for testing)
./bin/fujimatic.exe --fake-camera
# Start REST API server
./bin/fujimatic.exe server --port 8080
# Connect to remote server (client mode)
./bin/fujimatic.exe client --server localhost:8080Fujimatic includes a built-in REST API server for remote camera control, making it ideal for automation and integration with other tools.
# Start server on default port 8080
./bin/fujimatic.exe server
# Start server on custom port
./bin/fujimatic.exe server --port 8080
# Use fake camera for testing
./bin/fujimatic.exe server --fake-camera --port 8080| Method | Endpoint | Description |
|---|---|---|
| POST | /api/camera/connect |
Connect to camera |
| POST | /api/camera/disconnect |
Disconnect from camera |
| GET | /api/camera/status |
Get connection and battery status |
| GET | /api/camera/battery |
Get battery level |
| GET/POST | /api/settings/iso |
Get/set ISO sensitivity |
| GET/POST | /api/settings/shutter |
Get/set shutter speed |
| GET/POST | /api/settings/focus |
Get/set focus mode |
| GET | /api/session |
Get current session info |
| POST | /api/session/start |
Start new capture session |
| POST | /api/session/stop |
Stop current session |
| POST | /api/capture/single |
Capture single image |
| GET | /api/capture/status |
Get capture status |
All successful responses include both numeric status codes and human-readable messages:
{
"status": "ok",
"status_code": 200
}Settings endpoints return both the value and status:
// GET /api/settings/iso
{
"iso": 800,
"status": "ok",
"status_code": 200
}
// POST /api/settings/shutter
{
"shutter_speed": "1/60",
"status": "ok",
"status_code": 200
}curl -X POST http://localhost:8080/api/settings/shutter \
-H "Content-Type: application/json" \
-d '{"shutter": "1/60"}'curl http://localhost:8080/api/settings/shutter
curl http://localhost:8080/api/settings/isocurl -X POST http://localhost:8080/api/capture/singleThe included PowerShell script demonstrates API usage:
. ./scripts/Test-FujimaticApi.ps1
$server = "http://localhost:8080"
Test-FujimaticAPIFujimatic supports both synchronous and asynchronous intervalometer modes:
Traditional sequential operation: capture → download → delay → repeat.
capture 100 10 # 100 frames, 10s delay between framesTiming: Each cycle takes capture_time + download_time + delay
Pipeline architecture: capture frame N+1 while downloading frame N.
capture --async 100 10 # Same capture, ~20-25% fasterTiming: Overlapped operations, time ≈ N × delay + overhead
| Frames | Delay | Sync Time | Async Time | Speedup |
|---|---|---|---|---|
| 5 | 0s | 13s | 13s | 0% |
| 5 | 1s | 17s | 13s | 23% |
| 5 | 2s | 24s | 18s | 25% |
| 100 | 10s | 500s | 402s | 20%* |
*Projected based on measured capture (~1s) and download (~2s) times.
Best for:
- ✅ Astrophotography (long delays between exposures)
- ✅ Time-lapse with delays ≥2 seconds
- ✅ Long capture sessions (100+ frames)
Use sync for:
⚠️ Single captures or very short delays⚠️ When you need simpler, proven behavior
Synchronous Flow:
Frame 1: [Capture 1s] → [Download 2s] → [Delay 10s]
Frame 2: [Capture 1s] → [Download 2s] → [Delay 10s]
Total: 2 × (1 + 2 + 10) = 26 seconds
Async Pipeline Flow:
Frame 1: [Capture 1s] ────────────────┐
Frame 2: [Capture 1s] ───┼──┐
↓ ↓
[Download 2s] [Download 2s]
[Delay 10s] [Delay 10s]
Total: ~20 seconds (captures/downloads overlap during delays)
- Manual exposure control: Full control over ISO, shutter speed, and focus mode
- Focus mode control: Switch between manual and auto focus (for astrophotography workflows)
- Interactive:
get focus,set focus manual|auto - Non-interactive:
--focus-mode manual|auto - Default: Manual mode (prevents unwanted autofocus during long capture sessions)
- Soft error handling for manual-only lenses
- Interactive:
- Focus mode control: Switch between manual and auto focus (for astrophotography workflows)
- RAF to FITS/TIFF Conversion: Automatic conversion for astrophotography software
- Supported formats: FITS (Flexible Image Transport System) and TIFF (with Deflate compression)
- Use case: NINA, PixInsight, Siril, DS9 don't support Fujifilm RAF files natively
- Quality: 16-bit RGB color, preserves full dynamic range from sensor
- Metadata: Includes EXPTIME, ISO, DATE-OBS, camera model in FITS headers
- Performance: Background conversion (doesn't block captures), FITS ~3.5s, TIFF ~12s
- Disk space: TIFF saves 23% space vs FITS (compressed), both larger than RAF
- Interactive mode:
session start nebula ./captures set convert tiff # Enable TIFF conversion set delete-raf true # Delete RAF after successful conversion capture 100 10 # Captures will auto-convert in background
- Non-interactive mode:
./bin/fujimatic.exe --frames 100 --delay 10 --convert-format tiff --delete-raf
- REST API:
GET /api/settings/conversion # Get current settings POST /api/settings/conversion # Set format and delete-raf flag
- Session management: Save/load capture sessions with state persistence
- Battery monitoring: Auto-pause at configurable threshold (default 10%)
- Pause/Resume: Interrupt and continue intervalometer sessions
- File naming: Sequential numbering with collision detection
See STORIES.md for detailed development progress.
MIT License