Video4linux
A collection of device drivers, APIs, and utils for video, radio etc. on linux.
Enables manual configuration of video/recording devices.
Also known as v4l.
NOTE:
The default video device is whichever device is registered to /dev/video0
.
Documentation
git (v4l, dvb) https://git.linuxtv.org/media_tree.git/tree git (v4l-utils) https://git.linuxtv.org/v4l-utils.git/tree
Tutorials
arch-wiki: webcam setup https://wiki.archlinux.org/title/Webcam_setup
Locations
/dev/v4l/*
v4l devices symlinked here
Install
pacman -S v4l-utils # archlinux usermod -a -G video will # add your user to group 'video'
Usage
Tools
v4l2-ctl # control v4l2 devices v4l2-compliance # test video4linux drivers v4l2-sysfs-path # information about available devices v4l2-dbg # information to debug driversv4l2-ctl
# map avail devices, and their `/dev/video*` devices v4l2-ctl --list-devices # list available controls (general, and specific to devices) v4l2-ctl --list-ctrls v4l2-ctl -d /dev/video0 --list-ctrls # get control configuration v4l2-ctl -d /dev/video0 --get-ctrl=backlight_compensation v4l2-ctl -d /dev/video0 --set-ctrl=backlight_compensation=1
Configuration
Set Default Webcam
Setting a default webcam under systemd is tricky because:
- Your default webcam is generally the device at
/dev/video0
./dev/video0
is chosen bysystemd-udev
systemd-udev
does not directly support overwriting device names in udev rules.
You can however use udev rules to start a systemd service that renames devices so they appear properly.
I wrote a script that renames devices to make a webcam the default.
set-default-webcam.sh
#!/usr/bin/env bash set -e # # DESCRIPTION: # remaps devices associated with a `v4l2` exposed webcam # to `/dev/video0` so they become the system default webcam. # # All remapped devices are renamed to `/dev/video${N}.orig` # then are symlinked to the desired `video${N}` number. VERBOSE= validate_has_v4l2_utils() { if ! which v4l2-ctl 2>&1 > /dev/null ; then echo "[ERROR] you must install 'v4l2-utils'" exit 1 fi } match_video_device_ids() { # """ return newline-separated list of devices associated with provided device-name # # Args: # $1: a device-name, as listed by `v4l2-ctl --list-devices` # """ v4l2-ctl --list-devices \ | grep -Pzo "$1"'[^\n]+(\n\t.*)+' `# match target, and it's /dev/* entries` \ | grep -a '/dev/video' `# ignore /dev/media or others` \ | sed 's/ <-.*//' `# get real source, not symlinks` \ | awk '{$1=$1};1' } rename_video_device() { # """ renames video device, adding '.orig' suffix # # Args: # $1: a device path (ex: /dev/video2) # Returns: # the new path '/dev/video2.orig' # """ local device="$1" # avoids creating '/dev/video0.orig.orig' # if target is a device already renamed if echo "${device}" | grep '\.orig$' 2>&1 > /dev/null ; then echo "${device}" else local NEW_PATH="${device}.orig" # if source not symlink, and target doesn't exist if ! test -L "${device}" && ! test -e "${NEW_PATH}" ; then mv "${device}" "${NEW_PATH}" fi echo "${NEW_PATH}" fi } video_links_to_path() { # """ Find '/dev/video[0-9]+' entries that link against provided '/dev/video[0-9]+.orig' # # Args: # $1: a '/dev/video[0-9]+.orig' path, to find symlinks for # # Returns: # newline separated list of matching '/dev/video[0-9]+' paths # """ ls -l /dev/video* \ | grep '\->' \ | grep "$1" \ | awk -F' ' '{ print $9 }' } link_video_device() { # """ `ln -s $1 $2` -- removing $2 if it already exists and is symlink # # Args: # $1: link source # $2: link dest # """ local src="$1" local dst="$2" # if target is already a symlink, delete it if test -L "${dst}" ; then local orphan_device=$(realpath "${dst}") rm "${dst}" elif test -e "${dst}" ; then echo "[ERROR] ${dst} already exists and is not symlink" exit 1 fi ln -s "${src}" "${dst}" } main() { validate_has_v4l2_utils if [ $# -lt 1 ] ; then echo "[ERROR] requires a single argument (string matching a 'v4l2-ctl --list-devices' device name')" echo echo "EXAMPLE:" echo " ./set-default-webcam.sh 'Logitech Webcam C930e'" echo exit 1 fi local V4L2_DEVICE_MATCHER while [ $# -gt 0 ] ; do case $1 in -h|--help) echo "set-default-webcam.sh [-h] [-v] [V4L2_DEVICE_NAME]" echo echo "DESCRIPTION:" echo " remaps devices associated with a 'v4l2' exposed webcam" echo " to '/dev/video0' so they become the system default webcam." echo echo " All remapped devices are renamed to '/dev/video#.orig'" echo " then are symlinked to the desired 'video#' number." echo echo "PARAMS:" echo " V4L2_DEVICE_NAME:" echo " a full or partial device name, as returned by 'v4l2-ctl --list-devices'" echo echo " -v" echo " debug logging" echo echo " -h --help" echo " print this help screen" echo echo echo "EXAMPLE:" echo " ./set-default-webcam.sh 'Logitech Webcam C930e'" exit 0 ;; -v|--verbose) VERBOSE=1 shift ;; *) V4L2_DEVICE_MATCHER="$1" shift ;; esac done # 0-indexed MATCHING_CAM_DEVICES=($(match_video_device_ids "${V4L2_DEVICE_MATCHER}")) # if webcam is already /dev/video0, nothing to do if [[ "$(realpath /dev/video0)" == "${MATCHING_CAM_DEVICES[0]}" ]] ; then test -n "$VERBOSE" && echo "Nothing to do" exit 0 # otherwise, swap as many video devices as required # to satisfy MATCHING_CAM_DEVICES # starting with /dev/video0 else for i in "${!MATCHING_CAM_DEVICES[@]}"; do if test -L "/dev/video${i}" ; then prev_device=$(realpath "/dev/video${i}") else prev_device=$(rename_video_device "/dev/video${i}") fi new_device="$(rename_video_device ${MATCHING_CAM_DEVICES[$i]})" new_device_target="/dev/video${i}" prev_device_target="$(video_links_to_path ${new_device} | head -n 1)" if test -z "${prev_device_target}" ; then prev_device_target="$(echo ${MATCHING_CAM_DEVICES[$i]} | sed 's/\.orig$//')" fi test -n "$VERBOSE" \ && echo "[dev-${i} symlink-1] ${new_device} /dev/video${i}" link_video_device "${new_device}" "${new_device_target}" test -n "$VERBOSE" \ && echo "[dev-${i} symlink-2] ${prev_device} ${old_link}" link_video_device "${prev_device}" "${prev_device_target}" done fi } main "$@"
/etc/systemd/system/set-default-webcam.service
Systemd service that calls our script.
You don't need to enable this service, it will be called by udev.[Unit] Description=Set default webcam [Service] Type=oneshot ExecStart=/home/will/.bash/bin/set-default-webcam.sh -v Logitech StandardOutput=journal [Install] WantedBy=multi-user.target
/etc/udev/rules.d/50-set-default-webcam.rules
Any time a 'video4linux' device is detected,
runset-default-webcam.service
to try to set the default.ACTION=="add", SUBSYSTEM=="video4linux", TAG+="systemd", ENV{SYSTEMD_WANTS}="set-default-webcam.service"
You can test your default webcam
pacman -S vlc zvbi # install vlc/deps vlc v4l2:// # stream from default webcamManual VideoDevice Config
Use udev rules to run
v4l2-ctl
commands that configure your device.
See arch wiki.