cameractrls: V4L2 camera controls on Linux, down to the non standard ones
Camera controls for Linux
At a glance
- What is it?
- cameractrls is a Python project that sets camera controls on Linux through V4L2, including the vendor specific controls that no generic tool exposes, with a CLI, GTK3 and GTK4 interfaces, an SDL camera viewer and PTZ control from a keyboard, game controller, SpaceMouse or MIDI controller. The extensions are the point, and they are tied to specific hardware.
- Who is it for?
- Adopt cameractrls if you have a Linux machine, a camera whose controls expose something beyond the standard V4L2 set, and a habit of wanting a command you can script. Do not expect it to manage cameras on other platforms or to support hardware it has no extension for.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 98 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Standard V4L2 controls, and the ones nobody else exposes
cameractrls is a standalone Python CLI and GUI, built on GTK3 and GTK4, plus a camera viewer built on SDL, whose purpose is to set camera controls in Linux.
The generic part of that is not novel. V4L2 already exposes brightness, contrast and the rest of the standard control set, and the standard Linux tools can move them. The interesting part is the second half of the description: it is extendable with the non standard controls, and the extensions shipped today are named in the README.
There is a Logitech extension covering LED mode, LED frequency, BRIO FoV, relative pan and tilt, and PTZ presets. A Kiyo Pro extension covering HDR, HDR mode, FoV, AF mode and Save. A Dell UltraSharp WB7022 extension. An AnkerWork C310 extension. A preset extension for saving and restoring controls. And a control restore daemon that restores presets when a device is connected.
Those names tell you what the project is for. A Logitech Brio with an LED ring, a Kiyo Pro webcam with a physical HDR mode, a Dell monitor with a built in camera: each of these has controls that the vendor documents but that no standard interface exposes. Without a tool like this, setting the LED brightness on a Brio means sending vendor specific USB control transfers by hand, and nobody does that twice.
So the value is narrow and concrete: a supported camera with hidden controls, and a Linux user who wants those controls from a terminal, a GTK window or a launcher entry.
Three front ends over the same control set
The repository root is a set of Python scripts rather than a package with a single entry point, and the naming tells you what each one is.
cameractrls.py is the CLI. cameractrlsgtk.py is the GTK3 interface and cameractrlsgtk4.py is the GTK4 one, with both shown in the README with screenshots of the crop, image, exposure, advanced, capture and PTZ control screens. cameraview.py is the camera viewer. cameractrlsd.py is the control restore daemon, which the README says to add to systemd or the desktop portal alongside the GUI or CLI.
Three further scripts handle the exotic input paths: cameraptzgame.py, cameraptzmidi.py and cameraptzspnav.py, for game controllers, MIDI controllers and the SpaceMouse respectively. The pkg/ directory holds the packaging files, including the desktop entry and the icon used by the launcher entries, and screenshots/ holds the images used in the README.
The split between the GTK3 and GTK4 scripts is worth a moment. They are maintained side by side, which means the project follows both generations of the desktop toolkit rather than insisting on one, and it means a distribution that ships GTK4 by default and one that still ships GTK3 are both supported without argument. The cost is that a feature has to exist twice, and the README documents them as two separate install steps with two separate desktop file entries.
The daemon is the piece with a real operational role. A camera that resets its controls when it is unplugged and replugged is a common annoyance, and a service that watches for the device and reapplies your saved preset removes it.
Four ways to install, and the one that needs no packages
The README documents installation from Flathub, from the Arch repository, from the Manjaro repository, and from a git clone.
The Flathub route is a single command:
flatpak install flathub hu.irl.cameractrlsThe Arch and Manjaro routes are equally short:
pacman -S cameractrlspamac install cameractrlsThe git route asks for the runtime dependencies first, via apt:
sudo apt install git libsdl2-2.0-0 libturbojpegor via dnf:
sudo dnf install git SDL2 turbojpegand then clones the repository:
git clone https://github.com/soyersoyer/cameractrls.git
cd cameractrlsThe dependency list is small and readable: SDL2 for the viewer and turbojpeg for JPEG handling. There is no video processing framework and no driver library, because the control path goes through V4L2 rather than through GStreamer.
The flatpak is the interesting option, since the app id is hu.irl.cameractrls and it ships a launcher icon. The trade with a sandboxed package is access to the video device nodes, which is exactly what a camera tool needs, and the README does not explain how that is handled. The distribution packages and the git clone have no such question to answer, which is why they are listed first for anyone who wants to control the details.
The CLI surface, and what a control name looks like
The command line interface is the part of this project most likely to end up in a script, and its shape is easy to read:
usage: ./cameractrls.py [--help] [-d DEVICE] [--list] [-c CONTROLS]
optional arguments:
-h, --help show this help message and exit
-d DEVICE use DEVICE, default /dev/video0
-l, --list list the controls and values
-L, --list-devices list capture devices
-c CONTROLS set CONTROLS (eg.: hdr=on,fov=wide)
example:
./cameractrls.py -c brightness=128,kiyo_pro_hdr=on,kiyo_pro_fov=wideFour operations cover most needs. Listing controls and their current values, listing the capture devices on the machine, setting a comma separated set of controls, and selecting the device with -d, which defaults to /dev/video0.
The control naming is the part to internalise. Standard controls keep their plain names, so brightness=128. Vendor specific controls are prefixed with the device extension, so kiyo_pro_hdr=on and kiyo_pro_fov=wide for the Kiyo Pro, and logitech_pantilt_preset for the Logitech preset selection. The prefix is what keeps the namespace consistent once several extensions are enabled at once, and it is why the example mixes a standard control with two vendor ones in a single call.
Values are typed per control. A brightness takes a number, a mode takes a name such as on, off or wide, and the preset extension takes a preset number. The listing command is therefore the reference you need once, since it shows the available controls and their values for the device actually attached.
PTZ from a keyboard, a gamepad, a SpaceMouse or a MIDI controller
The PTZ support is the part of cameractrls that goes beyond setting a value once, and it covers four input methods.
The keyboard is the baseline. You control the camera with the arrow keys, the keypad keys, wasd, Home, End, PageUp, PageDown and plus and minus, while one of the PTZ controls has focus or while the camera viewer window is focused. Alt plus a preset number selects a preset for logitech_pantilt_preset.
The 3Dconnexion SpaceMouse maps its axes onto absolute motion, with the mappings given in the README:
Z => zoom_absolute
X => pan_absolute
Y => tilt_absolute
RY => pan_speed
RX => tilt_speed
BTN1 => PTZ resetAbsolute axes drive the position, and the rotational axes drive the speed of the movement, which is a sensible mapping because a proportional control feels wrong for absolute positioning. This path needs spacenavd and libspnav installed:
sudo apt install spacenavd libspnav0
sudo cp /usr/share/doc/spacenavd/examples/example-spnavrc /etc/spnavrcThe README also suggests setting `led = auto` in /etc/spnavrc.
Game controllers map their sticks and triggers, with the left stick selecting between speed and absolute behaviour for pan and tilt, the right stick and the D-pad driving absolute motion, the triggers driving zoom, and the shoulder and face buttons selecting PTZ presets 1 to 8 with the guide button as reset.
MIDI controllers are the most configurable path, through SysEx controls or the settings of a particular controller. With a joystick, CC78 and CC79 map to pan and tilt speed or absolute movement. With absolute knobs, CC71, CC72 and CC73 map to pan, tilt and zoom absolute. With relative knobs, where the knob sends an increment or a decrement, CC70, CC74 and CC75 through CC77 map to speed and absolute movement. CC121 is the PTZ reset and program changes PGM0 to PGM7 select presets 1 to 8.
For a studio where the camera is on a desk and the operator is on a couch, the MIDI and SpaceMouse paths are the ones that change how the tool is used.
The SDL viewer and the presets
cameraview.py is a separate program with its own interface, and it is not just a preview:
usage: ./cameraview.py [--help] [-d DEVICE] [-s SIZE] [-r ANGLE] [-m FLIP] [-c COLORMAP]
optional arguments:
-h, --help show this help message and exit
-d DEVICE use DEVICE, default /dev/video0
-s SIZE put window inside SIZE rectangle (wxh), default unset
-r ANGLE rotate the image by ANGLE, default 0
-m FLIP mirror the image by FLIP, default no, (no, h, v, hv)
-c COLORMAP set colormap, default none
(none, grayscale, inferno, viridis, ironblack, rainbow)The rotation, mirroring and colormap options are for framing and for inspection rather than for the image itself, and the keyboard shortcuts mirror the options: f toggles fullscreen, r rotates by 90 degrees with shift+r going the other way, m cycles the flip and c cycles the colormap. The colormap list is a practical detail, since an inferno or ironblack map makes a blown out highlight readable in a way that a normal view does not.
The preset extension is the other piece of shared state. It saves and restores control sets, and the restore daemon, cameractrlsd.py, reapplies them when the device is connected. That combination is what turns a set of controls from a one-off setting into a profile: light setup for a daytime shoot, another for a dim room, each restored automatically when the camera is plugged in.
The README also points at a different set of desktop entries for the two GTK versions, installed with desktop-file-install into your applications directory, and shows running the scripts directly with ./cameractrlsgtk.py or ./cameractrlsgtk4.py.
Where cameractrls stops
The limits are structural and easy to state.
First, it is Linux only, and specifically V4L2 only. The tools available to set controls are the V4L2 ones, and the vendor extensions are built on the control mechanisms those devices expose. A camera on macOS or Windows is out of scope, and so is a device that does not present controls through V4L2 at all.
Second, and more important, the extensions are hardware specific. A Logitech Brio user gets the LED mode, LED frequency, BRIO FoV, relative pan and tilt and PTZ presets. A user of a different Logitech camera does not get them automatically, because the extension targets a device. The Kiyo Pro, Dell UltraSharp WB7022 and AnkerWork C310 extensions are separate. If your camera is not on that list, the interesting half of this project does nothing for you, and you are left with the standard brightness and contrast controls that other tools also provide.
Third, there is no release stream. The repository publishes no GitHub releases, the last push was on 2026-07-16, and the update path in the README is a git pull. The CHANGELOG.md at the root is the only version history, and the README warns that upgrading from 0.5.x to 0.6.x requires disabling, stopping and deleting the old systemd user services, which is a sign of how the service files changed between those lines.
The licence is a fourth point to check. GitHub records it as a custom licence it cannot classify, so the terms live in the LICENSE file at the root of the repository, and nobody should assume they are permissive without reading them.
Editorial conclusion
Adopt cameractrls if you have a Linux machine, a camera whose controls expose something beyond the standard V4L2 set, and a habit of wanting a command you can script. Do not expect it to manage cameras on other platforms or to support hardware it has no extension for. Before you install, check the extension list against your device, read the LICENSE file since the terms are a custom one, and note that the repository publishes no GitHub releases with the last push on 2026-07-16, and that a 0.5.x to 0.6.x upgrade moves your systemd user services.
Frequently asked questions
How do I install cameractrls on Linux?
From Flathub with flatpak install flathub hu.irl.cameractrls, from Arch with pacman -S cameractrls, from Manjaro with pamac install cameractrls, or from a git clone after installing git, SDL2 and turbojpeg.
How do I list and set camera controls with cameractrls?
Use the -l flag to list the controls and their values and the -c flag to set them, for example ./cameractrls.py -c brightness=128,kiyo_pro_hdr=on,kiyo_pro_fov=wide. Vendor specific controls are prefixed with the device name.
Which cameras does cameractrls support extensions for?
The README names a Logitech extension, a Kiyo Pro extension, a Dell UltraSharp WB7022 extension, an AnkerWork C310 extension, a preset extension and a control restore daemon. Controls outside those extensions are limited to the standard V4L2 set.
Can I control PTZ cameras with a game controller or a MIDI controller?
Yes. The README documents mappings for game controllers, where the sticks and triggers drive pan, tilt and zoom and the buttons select presets, and for MIDI controllers through SysEx controls or the settings of a particular controller.
What is the cameractrls control restore daemon for?
cameractrlsd.py is the daemon that restores saved presets when a device is connected, and the README says to add it to systemd or the desktop portal alongside the GUI or CLI.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/soyersoyer-cameractrls)