Irrelevant backstory: As I started with Timescale as a Developer Advocate, I got a new Ubuntu laptop for work which I chose myself. Just when I was done installing most of the programs I use for work I realized that my webcam looks very flickery during calls. It is due to “an interaction between lights and the shutter speed of the webcam” as Google taught me. Now the thing is, I had this problem previously with an older Ubuntu laptop as well, but I didn’t quite remember how I had solved it before so I thought I’d document this process here now.
The process to make permanent changes to your webcam (or other video device) settings:
- Come up with the proper command (I’m using
- Create a bash script with that command
- Create a service to run the bash script during start-up
To adjust webcam settings in the command line, you can use the
uvcdynctrl package. This package should already be available in your Ubuntu but if not, this is how to install it:
sudo apt update sudo apt install uvcdynctrl
After installing it you, you can set a lot of things with it.
In my case, I need to change the power line frequency:
uvcdynctrl -d video4 "--set=Power Line Frequency" 1
-d parameter is
--device which is the name of the device you want do adjust. In my case it is
video4. If you don’t know the name of your device you can just guess the number (video1, video2, etc), or skip to the end of the article and I show you how to find it.
Unfortunately if you run the command above that will only apply the modification until you reboot. After reboot, all changes are lost. In order to make this change permanent you need to set up a service which runs this command everytime the computer starts.
#!/bin/bash uvcdynctrl -d video4 "--set=Power Line Frequency" 1
Nothing new here, just using the same command I used before.
Save it wherever you want (you’ll need to reference it later in your service file), I saved it to
This is the general idea for a service file like this:
set_webcam.service: (save it to
[Unit] Description=Set Logitech webcam frequency to 50Hz [Service] ExecStart=/usr/local/bin/set_webcam_freq.sh [Install] WantedBy=multi-user.target
This service will run everytime I boot up. But I found that in my case there’s a minor problem which you might encounter as well: the script appearently runs just before my webcam becomes availabe as a device, which means the service fails. If you encounter this problem you need to add a condition to only run the script after the device actually becomes available.
To achieve this, you need to edit one of
udev rule files to add a symlink to your device which then you can use inside your service file.
More on udev rules here.
So let’s edit, for example,
/lib/udev/rules.d/99-systemd.rules, add this line to add a symlink to your device: (use the device name you have, in my case
KERNEL=="video4", SYMLINK="video4", TAG+="systemd"
After saving this file, add
After parameters to the service file to reference your device:
[Unit] Description=Set Logitech webcam frequency to 50Hz BindsTo=dev-video4.device After=dev-video4.device [Service] ExecStart=/usr/local/bin/set_webcam_freq.sh [Install] WantedBy=multi-user.target
Make sure to enable the service so it runs during start-up:
systemctl enable set_webcam.service
That’s it. This service will run during each start-up after the
video4 device (which is my Logitech webcam in my case) becomes available and modifies the webcam’s settings.
If you don’t know the device name of your webcam (video0, video1, etc), keep reading…
You can list all of your video devices with this command:
ls -ltrh /dev/video*
crw-rw----+ 1 root video 81, 0 máj 14 10:17 /dev/video0
If the output is something similar to this, and you only have one entry in the list, that’s awesome! You just found your webcam’s name is
video0. But if you
have multiple records showing up here - because you have multiple webcams connected or other reasons, keep reading.
If you have multiple video devices connected like me, this method might be more useful.
If I type the command above, this is what I get:
crw-rw----+ 1 root video 81, 0 máj 14 10:17 /dev/video0 crw-rw----+ 1 root video 81, 2 máj 14 10:17 /dev/video2 crw-rw----+ 1 root video 81, 1 máj 14 10:17 /dev/video1 crw-rw----+ 1 root video 81, 3 máj 14 10:17 /dev/video3 crw-rw----+ 1 root video 81, 5 máj 14 10:17 /dev/video5 crw-rw----+ 1 root video 81, 4 máj 14 10:17 /dev/video4
Because I have an integrated laptop webcam and also my external Logitech webcam connected.
But then why is it not only 2 video device entries (nodes)? The thing is, Linux creates more device nodes for each device to store additional metadata in them. So basically I have 6 of these files but only have 2 “real” devices. How am I supposed to know which two are my “real” devices?
The simplest way might be to use a package that can list your video devices by name:
sudo apt-get install v4l-utils v4l2-ctl --list-devices
Integrated Camera: Integrated C (usb-0000:00:14.0-8): /dev/video0 /dev/video1 /dev/video2 /dev/video3 HD Pro Webcam C920 (usb-0000:09:00.0-1.3.1): /dev/video4 /dev/video5
Now this should make things clear, regarding which device nodes belong to which webcam.
And to find out which exact node is the “real one” that you can use to reference the device when using the
uvcdynctrl command, you have two options:
- in my experience the first entry that the command above shows for the device is the “real one” (others are metadata only) - but I don’t have evidence it’s always the case.
- to 100% make sure you find the correct video device file, you can check more information about a device using this command:
udevadm info -n /dev/video0
P: /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.0/video4linux/video0 N: video0 L: 0 S: v4l/by-path/pci-0000:00:14.0-usb-0:8:1.0-video-index0 S: v4l/by-id/usb-Chicony_Electronics_Co._Ltd._Integrated_Camera_0001-video-index0 E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.0/video4linux/video0 E: DEVNAME=/dev/video0 E: MAJOR=81 E: MINOR=0 E: SUBSYSTEM=video4linux E: USEC_INITIALIZED=2754683 E: ID_V4L_VERSION=2 E: ID_V4L_PRODUCT=Integrated Camera: Integrated C E: ID_V4L_CAPABILITIES=:capture: E: ID_VENDOR=Chicony_Electronics_Co._Ltd. E: ID_VENDOR_ENC=Chicony\x20Electronics\x20Co.\x2cLtd. E: ID_VENDOR_ID=04f2 E: ID_MODEL=Integrated_Camera E: ID_MODEL_ENC=Integrated\x20Camera E: ID_MODEL_ID=b6cb E: ID_REVISION=5818 E: ID_SERIAL=Chicony_Electronics_Co._Ltd._Integrated_Camera_0001 E: ID_SERIAL_SHORT=0001 E: ID_TYPE=video E: ID_BUS=usb E: ID_USB_INTERFACES=:0e0100:0e0200:0e0101:0e0201:fe0101: E: ID_USB_INTERFACE_NUM=00 E: ID_USB_DRIVER=uvcvideo E: ID_PATH=pci-0000:00:14.0-usb-0:8:1.0 E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_8_1_0 E: ID_FOR_SEAT=video4linux-pci-0000_00_14_0-usb-0_8_1_0 E: COLORD_DEVICE=1 E: COLORD_KIND=camera E: DEVLINKS=/dev/v4l/by-path/pci-0000:00:14.0-usb-0:8:1.0-video-index0 /dev/v4l/by-id/usb-Chicony_Electronics_Co._Ltd._Integrated_Camera_0001-video-index0 E: TAGS=:uaccess:snap_zoom-client_zoom-client:seat:
This will spit out a bunch of information about that device node. The keyword you’re looking for here is
ID_V4L_CAPABILITIES=:capture:. If the
ID_V4L_CAPABILITIES value is set to
capture or anything similar, you can be sure this is a real device not just metadata. If you check the other metadata files, they don’t have anything set for the
After finding your video device name, you can use the command shown above:
uvcdynctrl -d video4 "--set=Power Line Frequency" 1