Building from source
This page is for developers. To use FPVFlow, download a ready build from the releases page instead.
- Languages and technologies
- Code structure
- Dev environment
- Building on Windows
- Building on macOS
- Building on Linux
- Android and iOS
- The MDK SDK is pinned
- Profiling
- Contributing
- Translations
Languages and technologies
FPVFlow, like Gyroflow, is written in Rust, with the UI in QML. The application depends on Qt, FFmpeg, OpenCV and mdk-sdk; the core library is pure Rust with no external dependencies.
- OpenCV is kept to a minimum: only lens calibration and parts of the synchronization use it (
src/core/calibration/mod.rsand, insrc/core/synchronization/, the optical-flow backendsoptical_flow/opencv_dis.rsandoptical_flow/opencv_pyrlk.rs, the pose estimators inestimate_pose/andfind_offset/visual_features.rs). The core algorithms and the undistortion do not. - GPU: DirectX, OpenGL, Metal and Vulkan through Qt RHI and wgpu. Processing runs on OpenCL or wgpu, with a multi-threaded CPU implementation as the fallback.
- Qt 6.7.3 is used on every platform (upstream still defaults x86_64 desktop to 6.4.3). The compiled Qt RHI shaders in
src/qt_gpu/compiledare one set of.qsbfiles shared by all platforms, and the.qsbformat is versioned, so every platform has to use the same Qt.
The FPVFlow binary links against mdk-sdk, which is closed-source and not licensed under the GNU GPL. FPVFlow, like Gyroflow, is licensed under GPLv3 with an additional permission allowing linking with mdk-sdk. mdk-sdk is distributed under its own license.
Code structure
src/uiholds the entire GUI (QML). The side panels are insrc/ui/menu.src/controller.rsis the bridge between UI and core: it takes every command from QML and calls into the core.src/coreis the stabilization engine. It does not depend on Qt or FFmpeg; OpenCV is optional. The Gyrogate repair lives insrc/core/gyrogate.src/renderingholds all the FFmpeg code, for rendering the final video and for processing used by synchronization.src/core/gpuholds the GPU implementations of the undistortion.src/qt_gpuis the zero-copy GPU undistortion path, using Qt RHI and a GLSL compute shader.src/fpvflow.rsis the main entry point.mod.rsorlib.rsin each directory is the entry of that module (the directory name is the module name).
The crates are renamed to fpvflow. Code and docs inherited from upstream may still say gyroflow_core or gyroflow.rs; in this repository they are the fpvflow equivalents.
Dev environment
- Visual Studio Code with the
rust-analyzerextension. - Qt Creator for QML: load the QML files there for auto-complete and syntax highlighting.
- UI live reload: set
ui_live_reloadtotrueinsrc/fpvflow.rs. From then on, every change to a QML file is reloaded in the running app immediately.
Building on Windows
- Install the prerequisites:
git,7zand a workingpowershell. If you have never run PowerShell scripts, runset-executionpolicy remotesignedin PowerShell as administrator. - Install the latest stable Rust from rustup.rs. When the Visual Studio Installer adds the C++ build tools, check the “English language pack” option.
- Install Just:
cargo install --force just - Clone the repository:
git clone https://github.com/rodrigosclosa/fpvflow.git - In the project directory, install the dependencies:
just install-deps - Compile and run:
just run
Building on macOS
- Install the prerequisites:
gitandbrew. - Install the latest stable Rust from rustup.rs.
- Install Just:
cargo install --force just - Clone the repository:
git clone https://github.com/rodrigosclosa/fpvflow.git - In the project directory, install the dependencies:
just install-deps - Run
just deployonce. The firstjust rundoes not work without it. - Compile and run:
just run
Building on Linux
- Install the prerequisites:
git,7z,pythonand theaptpackage manager. On another distribution, adjust the commands inside the scripts in_scripts/. - Install the latest stable Rust from rustup.rs.
- Install Just:
cargo install --force just - Clone the repository:
git clone https://github.com/rodrigosclosa/fpvflow.git - In the project directory, install the dependencies:
just install-deps - Compile and run:
just run
Android and iOS
The just android ... and just ios ... recipes (_scripts/android.just, _scripts/ios.just) are inherited from Gyroflow, but FPVFlow does not build or test them. Use Gyroflow on mobile.
The MDK SDK is pinned
The video player in the preview is mdk-sdk, pulled in through a fork of qml-video-rs (rodrigosclosa/qml-video-rs), referenced by commit in Cargo.toml. The SDK version is fixed in that fork’s build.rs, always to a tagged GitHub release of wang-bin/mdk-sdk: today v0.38.0 (git 6c92f5a).
Never point it at the “latest” build on SourceForge. That is a rolling build: the rolling 0.38.0 of 2 September 2026 (git 744fc5b) broke the external audio track with no visible error. The video played, the audio did not, and the log showed read packet error and seekTo jumping backwards. The tagged v0.38.0 release plays the same files normally.
The Windows package is mdk-sdk-windows-clang.7z. The mdk-sdk-windows-desktop-clang.7z still published with the releases is a legacy package that contains 0.35.1.
Validating an MDK update
Any MDK SDK update requires re-validating the external audio track in the preview before it is accepted.
- Change the release in the
qml-video-rsfork’sbuild.rs, update the commit inCargo.tomland build locally. - Load a video and a WAV file as its external audio track.
- Run the audio auto-sync.
- Press play and confirm the audio plays.
- Drag the playhead to another point and press play again.
- In the log, confirm the line
[MDK] <version> (git <hash>)shows the version you expect, and that the audio kept playing after the seek.MDKPlayer.cpplogs every seek with the result MDK returned, and every play and pause.
If the audio breaks, compare first with a C++ harness built directly on the SDK, running the same sequence (setMedia → setMedia(wav, Audio) → setActiveTracks → prepare → seek → play), before blaming the app.
Profiling
On Windows
- Install and run Visual Studio Community Edition.
- Compile and run with the
profileprofile:just profile - In Visual Studio, open
Debug -> Performance Profiler.... - Under
Target, openChange Target, chooseRunning Process...and select the runningfpvflow.exeprocess.
QML
- Uncomment
config.define("QT_QML_DEBUG", None);inbuild.rs. - Comment out the
cli::run(...)check insrc/fpvflow.rs. - Run in debug mode with the QML debugger arguments:
cargo run -- "-qmljsdebugger=port:1234,block,services:CanvasFrameRate,EngineControl,DebugMessages" - In Qt Creator, open
Analyze->QML Profiler (Attach to Waiting Application)and enter port 1234.
Contributing
- Bugs and feature ideas for FPVFlow go to the FPVFlow issue tracker. A sample clip makes a bug report far more useful. Please do not take FPVFlow problems to the Gyroflow project.
- Code: fork the repository, work on a branch from
fpvflowand open a pull request.
New to the stack? The Rust book, quickref.me/rust, cheats.rs and the Qt QML book are good starting points.
Translations
The UI translations are the .ts files in resources/translations, compiled to .qm files that are embedded in the binary.
- Gyroflow’s own strings are translated upstream on Crowdin and arrive in FPVFlow when upstream is merged.
- Strings added by FPVFlow (the colour panel, the external audio panel and the Gyrogate section of the motion data panel) are not in that Crowdin project, so translating them there does not reach FPVFlow. Open an issue if you want to translate them.