Hassleless Droidcam v4l2loopback Config

Description

I have DroidCam and v4l2loopback installed and I can use them. However, each reboot requires that I run nix-shell -p linuxKernel.packages.linux_latest_libre.v4l2loopback, then v4l2loopback-ctl set-caps /dev/video<n> "YU12:<width>x<height>" in order for DroidCam not not fail to launch with the bellow error:

Fatal: droidcam video device reported pixel format 34524742 (BGR4), expected 32315559 (YU12/I420)
Try 'v4l2loopback-ctl set-caps "video/x-raw, format=I420, width=640, height=480" /dev/video<N>'

Goal(s)

  1. Not have to run v4l2loopback-ctl after each reboot (this is the primary goal).
  2. Install v4l2loopback-ctl via my configuration so I don’t have to use nix-shell each time I would like to change resolution of a loopback device.

My Setup

{ config, ... }: {
  # TODO: Get install of v4l2loopback-ctl working.
  environment.systemPackages = with config.boot.kernelPackages; [
    v4l2loopback <--_______________________________________________________ 
  ];              / Everything works the same without this. I only added    \
                  | this in an attempt to install v4l2loopback. It didn't   |
                  | work even though v4l2loopback in Nix packages says it   |
                  | includes it. Note that config.boot.kernelPackages is    |
                  | used so I get the same version as my kernel.            |
                  | Specifying pkgs.linuxKernel.packages.linux_latest_libre |
                  | also behaves the same.                                  |
  boot = {        \_________________________________________________________/
    # Make v4l2loopback kernel module available to NixOS.
    extraModulePackages = with config.boot.kernelPackages; [
      v4l2loopback
    ];
    # Activate kernel modules.
    kernelModules = [
      # Virtual camera.
      "v4l2loopback"
      # Virtual microphone, built-in.
#     "snd-aloop" <-- Not worried about getting this working right now.
    ];
    # Set initial kernel module settings.
    extraModprobeConfig = ''
      options v4l2loopback video_nr=2,3 width=640,1920 max_width=1920 height=480,1080 max_height=1080 format=YU12,YU12 exclusive_caps=1,1 card_label=Phone,Laptop debug=1
    '';                        ^          ^               ^              ^                ^              ^                    ^                ^                    ^
  };                           |          |               |              |                |              |                    |                |                    |
}                            Works,       ?,            Works,           ?,             Works,           ?,                 Works,           Works,               Works

What Works

I’ve confirmed that the bellow options set by boot.extraModprobeConfig work by checking the values in /sys/module/v4l2loopback/parameters/*, then changing the values and rebooting:

  • video_nr
  • max_width
  • max_height
  • exclusive_caps
  • debug

I’ve confirmed that card_label works through just using them and seeing those labels show up.

What Doesn’t Work

I have to manually set format and resolution of each virtual device after each reboot.

Potential Solution(s)

Maybe I could make a systemd service that configures this. My issues with this are:

  • Given that boot.extraModprobeConfig exists, I’d like to use it to do this if possible.
  • I’ve never created a systemd service, so it would likely take a while.

Note(s)

I’ve seen this thread by @tobiasBora. That’s where I got the idea that a systemd service might be needed. I also tried un-loading v4l2loopback and re-loading it, but to no avail.

I’ve done my testing by rebooting after each change.

I haven’t attempted to use DroidCam’s v4l2loopback-dc version because I’d like to figure this out first.

I’m using flakes, and Home Manager as a NixOS module. However, everything related to this, other than installing DroidCam, has been done via NixOS not Home Manager. I’ve tried switching over to using NixOS to install DroidCam, but it didn’t change anything.

Here is my config and this is the file that deals with v4l2loopback.

1 Like

You may want to look at v4l2 relayd options

1 Like

So v4l2-relayd connects a Gstreamer video source to v4l2loopback device. I presume this would mean I would need to setup a Gstreamer pipeline that accepted input from DroidCam (I don’t really understand what I just said)?

1 Like

Did you ever figure your issue out? I’m just trying to research the best way to go about this atm.

I’m new to nixos, but I just managed to make DroidCam work on my own, and tested it out in Zoom, Telegram and discord, and some other apps.

My setup was super simple:

`# webcam/android cam`

boot.extraModulePackages = with config.boot.kernelPackages; [v4l2loopback];
boot.kernelModules = [“v4l2loopback”];

programs.adb.enable = true; # enable android proper data tethering

And I think you don’t have to open these ports, but I did anyway.

networking.firewall.allowedTCPPorts = [ 4747 ];
networking.firewall.allowedUDPPorts = [ 4747 ];

Also my wacky videocard settings were causing Droidcam to turn off and flicker and act strange, but I realized that those were my nvidia config settings and I rebuilt my system and got rid of some settings that were mentioned in NixOS nvidia manual and had only this nvidia line remaining:

hardware.opengl = { # Enable OpenGL
enable = true;
driSupport = true;
driSupport32Bit = true;
};
services.xserver.videoDrivers = [“nvidia”];

I installed DroidCam app from an unstable branch. I’m relatively new to whole linux and NixOS and maybe I didn’t understand the issue you’re running into, but the above mentioned setup works for me, and the only issue that I ran into were graphics card related.

2 Likes

Fyi, if you are on Android 14, you can these days just connect it to your computer via USB, tap the “charging via USB” notification, and switch it to webcam mode.

There’s probably still use cases for droidcam, but I figure the built-in Android feature covers most of your video conferencing needs.

1 Like

It sounds like this feature may be gated by the USB version your device supports, as I’ve got Android 14 but don’t have this option.

1 Like

Right, yeah: https://www.howtogeek.com/how-to-use-android-phone-as-webcam/

At the time of writing in February 2024, the feature is not yet available to all devices running Android 14 or later. It’s currently available to Google Pixel and Motorola phones, not Samsung Galaxy or OnePlus devices. We hope to see the feature implemented on more devices in the future.

Guess as usual the various manufacturers will be playing catch-up for a while.

@MeshVoid we gone and done it (mostly)!

Background

My situation is a little different from most people here. I use iOS and and an old, very old, AMD GPU. Specifically a AMD Radeon R9 290X. However, I suspect the solution may still be useful to others.

Solution

After reading @MeshVoid’s implementation I decided to take a look at the values available to services.xserver.videoDrivers. I noticed that one of them was ati witch I remembered from back in the day when I build my machine. After switching from amdgpu to ati, rebuilding, and rebooting, v4l2loopback device worked! I no longer had to run v4l2loopback-ctl set-caps /dev/video<n> "YU12:<width>x<height>" after each reboot.

Lessens Learned

I think the most common cause of this issue is GPU driver related, so look there first.

Problem(s)

After changing GPU driver Steam takes a loooooong time to start. Once it does, it launches in the background and gives an error popup saying steamwebhelper, a critical Steam component, is not responding. The Steam UI will not be usable. Click here for more information.. Although Steam still works, it’s annoying how long it takes to launch.

I passed in -vgui when launching it (ex. com.valvesoftware.Steam -vgui) as suggested here, but to no avail. I also turned off GPU acceleration in Steam settings, as well as hardware acceleration.

Finally, I removed the Steam flatpak, deleted all local data (ran flatpak uninstall --unused --delete-data, sudo flatpak repair, and flatpak repair), and reinstalled it. Needless to say, this also didn’t work.

To be clear, Steam works just fine, other than the six and a half years it takes to launch. If anyone has any ideas, I’m all ears.

My Configuration

Generic GPU Configuration

{ user, ... }: {
  programs.corectrl = {
    enable = true;
    gpuOverclock.enable = true;
  };

  users.users."${user.name}".extraGroups = [ "corectrl" ];
}

v4l2loopback Configuration

{ config, pkgs, ... }: {
  environment.systemPackages = with pkgs; [
    # Enables v4l2loopback GUI utilities.
    v4l-utils
  ];

  boot = {
    # Make v4l2loopback kernel module available to NixOS.
    extraModulePackages = with config.boot.kernelPackages; [
      v4l2loopback
    ];
    # Activate kernel module(s).
    kernelModules = [
      # Virtual camera.
      "v4l2loopback"
      # Virtual Microphone. Custom DroidCam v4l2loopback driver needed for audio.
#    "snd-aloop"
    ];
  };
}

Host Machine Specific Hardware Configuration

{ config, lib, pkgs, modulesPath, ... }: {
  boot.initrd.availableKernelModules = [ "ahci" "ohci_pci" "ehci_pci" "pata_atiixp" "xhci_pci" "firewire_ohci" "usb_storage" "usbhid" "sd_mod" "sr_mod" ];
  boot.kernelModules = [ "kvm-amd" ];

  hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

GPU Specific Configuration

{ pkgs, ... }: {
  boot = {
    initrd.kernelModules = [ "amdgpu" ];
    # Enable support for my old ass AMD ATI R9 290X GPU.
    kernelParams = [ "radeon.cik_support=0" "amdgpu.cik_support=1" ];
  };

 hardware.opengl.extraPackages = [ pkgs.amdvlk ];

  # Enable GPU hardware acceleration.
  # Note(s):
  #   - This doesn't turn x11 on.
  #   - This is used even when running under Wayland.
  #   - `amdgpu` also works, but it breaks v4l2loopback and seems to perform worse.
  services.xserver.videoDrivers = [ "ati" ];
}

Note(s)

  • @MeshVoid I’m as sure as I can be that there’s no need to open ports.
  • For anyone wondering, an option being under xserver doesn’t mean it won’t work or doesn’t apply when running under Wayland.
  • I needed no changes to support iOS via USB because I’m using WiFi.
  • @zaiquiriw I would pay special attention to what video drivers you’re loading. Feel free to post GPU info here as well as your current configuration of boot.extraModulePackages, boot.kernelModules, boot.initrd.kernelModules, boot.kernelParams, and services.xserver.videoDrivers.
2 Likes

@ReedClanton I’m glad that my post helped you to look into that direction and fix some problems on your end! I noticed that gpu settings were making my droidcam work incorrectly, thought it would be beneficial to mention that.

And also thank you for the tips about open ports, I’m not good at networks, servers and all that jazz, I’ll make sure to correct those settings in my next build!