diff --git a/nixos/doc/manual/release-notes/rl-2411.section.md b/nixos/doc/manual/release-notes/rl-2411.section.md index 23143a4fb027..0e74514eaab8 100644 --- a/nixos/doc/manual/release-notes/rl-2411.section.md +++ b/nixos/doc/manual/release-notes/rl-2411.section.md @@ -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. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 7f6fa1c8e73b..5d80f23dd23b 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -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 diff --git a/nixos/modules/programs/obs-studio.nix b/nixos/modules/programs/obs-studio.nix new file mode 100644 index 000000000000..ee9ec520d1fb --- /dev/null +++ b/nixos/modules/programs/obs-studio.nix @@ -0,0 +1,64 @@ +{ + 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 + ]; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index ee63fbd9371f..d10efd01113a 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -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; diff --git a/nixos/tests/obs-studio.nix b/nixos/tests/obs-studio.nix new file mode 100644 index 000000000000..a1b5bacf0428 --- /dev/null +++ b/nixos/tests/obs-studio.nix @@ -0,0 +1,40 @@ +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") + ''; + } +)