fSpy is an open source, cross platform app for still image camera matching. See fspy.io for more info. The source code is available under the GPL license.
Once upon a time I wrote BLAM, a Blender add-on for still image camera calibration that, despite its clunky UI, has gained some popularity in the Blender community. fSpy is an attempt to bring BLAM's functionality to a wider audience in the form of a stand alone app.
In theory, camera parameters computed by fSpy could be used in any application that has a notion of a 3D camera and provides some way of setting the camera parameters. If you're a Blender user, have a look at the offical fSpy importer add-on. If you're using an application without a dedicated importer, you may still be able to manually copy the camera parameters from fSpy.
Interested in writing an importer for your favorite application? Then the fSpy project file format spec is a good starting point.
The following instructions are for developers. If you just want to run the app, download the latest executable for your platform.
fSpy is written in Typescript using Electron, React and Redux. Visual Studio Code is recommended for a pleasant editing experience.
To install necessary dependencies, run
npm install
The src folder contains three subfolders: main and gui, containing code for the Electron main and renderer processes respectively, and cli, which contains a command-line interface for processing fSpy project files without the GUI. The main process includes a preload script (src/main/preload.ts) that bridges the renderer and main processes via IPC.
To run the app in development mode, run
npm start
This runs electron-vite in dev mode: it builds the main and preload code, serves the GUI (renderer) with Vite's dev server, and launches Electron. Changes to GUI (renderer) code hot-reload with Fast Refresh (component state is preserved); changes to src/main or src/main/preload.ts rebuild and restart Electron automatically.
Executables are produced by Electron builder. Each dist-* script first runs a clean production build (build-dist) and then packages the app.
To build for all platforms at once, run
npm run dist
or build a single platform with npm run dist-mac, npm run dist-win or npm run dist-linux.
nsis target needs Wine, and the Linux AppImage target typically needs Docker/Linux. In practice, the all-platform npm run dist and npm run publish-release are meant to run on matching per-OS CI runners; locally, build only for the platform you are on. npm run dist-mac skips code signing, so it works on any Mac without a signing certificate.
All available scripts and when to use them:
| Script | Description |
|---|---|
npm start |
Runs electron-vite dev: builds main/preload, serves the renderer with HMR, and launches Electron. Renderer changes hot-reload with Fast Refresh; src/main changes rebuild and restart automatically. This is the main development command. |
npm test |
Runs the Jest test suite. |
| Script | Description |
|---|---|
npm run build-dist |
Runs electron-vite build, producing the production bundles in out/ (main/, preload/, renderer/). Called automatically by every dist-* and publish-release script. |
| Script | Description |
|---|---|
npm run dist-preview |
Produces an unpacked build (electron-builder --dir) for a quick local smoke test — faster than a full installer. |
npm run dist |
Packages installers for macOS, Windows and Linux (-mwl). See the cross-compiling caveat above. |
npm run dist-mac |
Packages a macOS build only, skipping code signing (works without a signing certificate). |
npm run dist-win |
Packages a Windows build only. |
npm run dist-linux |
Packages a Linux build only. |
| Script | Description |
|---|---|
npm run publish-release |
Builds and publishes installers for all platforms to GitHub Releases (electron-builder --publish always). Intended to run from CI on per-OS runners. |
