Unverified Commit 056fc213 authored by Danilo Reyes's avatar Danilo Reyes Committed by GitHub
Browse files

modules/obs-studio: optionally enable v4l2loopback (#312112)

* modules/obs-studio: optionally enable v4l2loopback

* add test

* added documentation to 24.11 changelog
parent e9c3b079
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -155,6 +155,8 @@

- [Immich](https://github.com/immich-app/immich), a self-hosted photo and video backup solution. Available as [services.immich](#opt-services.immich.enable).

- [obs-studio](https://obsproject.com/), Free and open source software for video recording and live streaming. Available as [programs.obs-studio.enable](#opt-programs.obs-studio.enable).

## Backward Incompatibilities {#sec-release-24.11-incompatibilities}

- The `sound` options have been removed or renamed, as they had a lot of unintended side effects. See [below](#sec-release-24.11-migration-sound) for details.
+1 −0
Original line number Diff line number Diff line
@@ -259,6 +259,7 @@
  ./programs/oblogout.nix
  ./programs/oddjobd.nix
  ./programs/openvpn3.nix
  ./programs/obs-studio.nix
  ./programs/partition-manager.nix
  ./programs/plotinus.nix
  ./programs/pqos-wrapper.nix
+64 −0
Original line number Diff line number Diff line
{
  pkgs,
  lib,
  config,
  ...
}:

let
  cfg = config.programs.obs-studio;
in
{
  options.programs.obs-studio = {
    enable = lib.mkEnableOption "Free and open source software for video recording and live streaming";

    package = lib.mkPackageOption pkgs "obs-studio" { example = "obs-studio"; };

    finalPackage = lib.mkOption {
      type = lib.types.package;
      visible = false;
      readOnly = true;
      description = "Resulting customized OBS Studio package.";
    };

    plugins = lib.mkOption {
      default = [ ];
      example = lib.literalExpression "[ pkgs.obs-studio-plugins.wlrobs ]";
      description = "Optional OBS plugins.";
      type = lib.types.listOf lib.types.package;
    };

    enableVirtualCamera = lib.mkOption {
      type = lib.types.bool;
      default = false;
      description = ''
        Installs and sets up the v4l2loopback kernel module, necessary for OBS
        to start a virtual camera.
      '';
    };
  };

  config = lib.mkIf cfg.enable {
    programs.obs-studio.finalPackage = pkgs.wrapOBS.override { obs-studio = cfg.package; } {
      plugins = cfg.plugins;
    };

    environment.systemPackages = [ cfg.finalPackage ];

    boot = lib.mkIf cfg.enableVirtualCamera {
      kernelModules = [ "v4l2loopback" ];
      extraModulePackages = [ config.boot.kernelPackages.v4l2loopback ];

      extraModprobeConfig = ''
        options v4l2loopback devices=1 video_nr=1 card_label="OBS Cam" exclusive_caps=1
      '';
    };

    security.polkit.enable = lib.mkIf cfg.enableVirtualCamera true;
  };

  meta.maintainers = with lib.maintainers; [
    CaptainJawZ
    GaetanLepage
  ];
}
+1 −0
Original line number Diff line number Diff line
@@ -717,6 +717,7 @@ in {
  nzbhydra2 = handleTest ./nzbhydra2.nix {};
  ocis = handleTest ./ocis.nix {};
  oddjobd = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./oddjobd.nix {};
  obs-studio = handleTest ./obs-studio.nix {};
  oh-my-zsh = handleTest ./oh-my-zsh.nix {};
  ollama = runTest ./ollama.nix;
  ollama-cuda = runTestOn ["x86_64-linux" "aarch64-linux"] ./ollama-cuda.nix;
+40 −0
Original line number Diff line number Diff line
import ./make-test-python.nix (
  { ... }:

  {
    name = "obs-studio";

    nodes.machine =
      { pkgs, ... }:
      {
        imports = [
          ./common/x11.nix
          ./common/user-account.nix
        ];

        programs.obs-studio = {
          enable = true;
          plugins = with pkgs.obs-studio-plugins; [
            wlrobs
            obs-vkcapture
          ];
          enableVirtualCamera = true;
        };
      };

    testScript = ''
      machine.wait_for_x()
      machine.succeed("obs --version")

      # virtual camera tests
      machine.succeed("lsmod | grep v4l2loopback")
      machine.succeed("ls /dev/video1")
      machine.succeed("obs --startvirtualcam >&2 &")
      machine.wait_for_window("OBS")
      machine.sleep(5)

      # test plugins
      machine.succeed("which obs-vkcapture")
    '';
  }
)