Disable autofocus on USB webcam config using v4l2-ctl on Linux

After playing around with the camera_usb_options settings in /boot/octopi.txt, I was able to configure most of my preferences, but there's one parameter the mjpg-streamer interface doesn't seem to have options for, so I had to come up with a different way to get what I want.

I hate the constant focus-hunting behavior of the ancient USB camera I'm using, so I wanted to turn that off and set a constant focus distance instead. My solution was to use the Event System to run some shell commands whenever the server starts up. Fortunately, this was pretty easy to set up. There are just three easy steps.

First, you're going to need a command-line utility that lets you change the settings of your camera.
Linux has one called v4l2-ctl that lets you set all kinds of parameters for any attached USB webcams. That does everything I want, so that's what I'm going to use, but if you have a different command-line tool, you can use yours instead by replacing my commands with your own in the YAML section below.

If you want to use the v4l2-ctl utility, begin by making sure it's actually installed. Do this with:
sudo apt install v4l-utils.

Next, we need to edit /home/pi/.octoprint/config.yaml and add the following:

events:
    subscriptions:
    - command:
        - v4l2-ctl --set-ctrl=focus_auto=0
        - v4l2-ctl --set-ctrl=focus_absolute=17
        - v4l2-ctl --set-ctrl=brightness=70
        event: Startup
        type: system

In this example, I've disabled autofocus, set a constant focus distance of 17 and told OctoPrint to run those v4l2-ctl commands as system (shell) commands whenever the server starts up. And just for demonstration purposes, I've also set the brightness to 70, to show that all the normal camera preferences can be set here as well. (You can run: sudo v4l2-ctl -L to get a list of all the different parameters that can be controlled with this method.)

Finally, we need to take care of permissions. The v4l2-ctl command requires sudo rights to execute, but by default, OctoPrint runs as the pi user, who does not have those privileges, so we have to grant them. Fortunately, that's also pretty easy. Just create a new file in the /etc/sudoers.d/ directory. You can call it whatever you like, but I called mine octoprint-v4l2. Inside that file, you need a single line that reads:

pi ALL=NOPASSWD: /usr/bin/v4l2-ctl

This will give the pi user the right to run the v4l2-ctl utility as sudo without having to provide a password to do so. (You should never grant sudo permissions lightly, but that's a conversation for a different thread. I'm assuming you know your situation better than I do, and can judge the slight increase in risk for yourself.)

Anyway, that's all there is to it. Reboot your Pi. When OctoPrint comes back up, it should be with all your sweet, sweet camera prefs set just the way you like them.

2 Likes

Nice solution @Jefficus typically I see people add these commands to crontab, neat idea using OctoPrint events instead.

Hello,

I like Jefficus solution! In the past I try to set my camera settings in "/home/pi/mjpg-streamer/start.sh", but that dont worked.

Now, I setup Jeffikus solution as descripted, but afterwards my octoprint Server don‘t start anymore ?!
Raspberry Pi OS starts, but the Octoprint service (and also Python) won‘t start.

Sadly, I also can't find any needful informations into my octoprint.log. There is nothing suspicious.

I have no idea why the octoprint service get stucked with the supplemented "config.yaml". The same camera settings for my Logitech C920 are proofed and work into the bash...

Thank's for helping me, m0eppi

Here's my additional entry I have made in the "config.yaml":

events:
    subscriptions:
    - command:
        - v4l2-ctl --set-ctrl=exposure_auto=1
        - v4l2-ctl --set-ctrl=exposure_absolute=250
        - v4l2-ctl --set-ctrl=focus_auto=0
        - v4l2-ctl --set-ctrl=focus_absolute=0
        event: Startup
        type: system

My OctoPrint system info:

browser.user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36
connectivity.connection_check: 8.8.8.8:53
connectivity.connection_ok: true
connectivity.enabled: false
connectivity.online: true
connectivity.resolution_check: octoprint.org
connectivity.resolution_ok: true
env.hardware.cores: 4
env.hardware.freq: 1500
env.hardware.ram: 1903988736
env.os.bits: 32
env.os.id: linux
env.os.platform: linux
env.plugins.pi_support.model: Raspberry Pi 4 Model B Rev 1.4
env.plugins.pi_support.octopi_version: 0.18.0
env.plugins.pi_support.throttle_state: 0x0
env.python.pip: 20.3.3
env.python.version: 3.7.3
env.python.virtualenv: true
octoprint.safe_mode: false
octoprint.version: 1.5.3

typically space indentation is an issue when you manually edit your config.yaml. I also think you can only have one command, not a list of commands, but I may be wrong there.

Command lists are definitely supported, but jneiliii could definitely be right about the indentation issue. Especially if you have mixed spaces and tabs.

Have you checked to be sure v4l2-ctl is installed on your Pi?
Have you confirmed that each of your v4l2-ctl commands works on the command line with your camera?

If that's not it, you may have to take the commands out of the config file and put them back in one at a time until you find the problem.

Thank you for your support, I have found a solution.

I study the OctoPrint documentation for "config.yaml" and built my own code snippet to set my camera settings (inspired by Jefficus :wink: )

That's what I pasted into my yaml.conf:

events:
  subscriptions:
    - event: Startup
      command: "v4l2-ctl --set-ctrl=focus_auto=0 && v4l2-ctl --set-ctrl=focus_absolute=0"
      type: system
      debug: true

After an reboot, I tooked a second view into my yaml.conf. I was a little bit surprided, that my settings was changed automagically like this (just for info):

events:
    subscriptions:
    -   command: v4l2-ctl --set-ctrl=focus_auto=0 && v4l2-ctl --set-ctrl=focus_absolute=0
        debug: true
        event: Startup
        type: system

But what shall I say, octoprint comes up again after reboot :slight_smile:

Maybe in my first try there was an error with space indentation or something else...?!

Anyway - no errors anymore and the camera settings still get applied by every reboot. :sunglasses:

Yeah the docs are in 2 space indentation, and recent versions were configured in 4 space indentation, and I believe the next release 1.6.0 will be back to 2 space indentation to get back in line with docs. You'll notice that the list of items with - changed to having 3 spaces after them rather than the single space you had before.