From 7f17f8da9fc7ee2aeccf0b535b4d492b58219752 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Fri, 9 Jun 2023 22:54:11 +0200 Subject: [PATCH] nixos/wyoming/piper: init --- nixos/modules/module-list.nix | 1 + .../modules/services/audio/wyoming/piper.nix | 174 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 nixos/modules/services/audio/wyoming/piper.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 83b2a45dbd3..858252c4ba1 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -328,6 +328,7 @@ ./services/audio/spotifyd.nix ./services/audio/squeezelite.nix ./services/audio/tts.nix + ./services/audio/wyoming/piper.nix ./services/audio/ympd.nix ./services/backup/automysqlbackup.nix ./services/backup/bacula.nix diff --git a/nixos/modules/services/audio/wyoming/piper.nix b/nixos/modules/services/audio/wyoming/piper.nix new file mode 100644 index 00000000000..ed50bd9f48e --- /dev/null +++ b/nixos/modules/services/audio/wyoming/piper.nix @@ -0,0 +1,174 @@ +{ config +, lib +, pkgs +, ... +}: + +let + cfg = config.services.wyoming.piper; + + inherit (lib) + escapeShellArgs + mkOption + mdDoc + mkEnableOption + mkPackageOptionMD + types + ; + + inherit (builtins) + toString + ; + +in + +{ + meta.buildDocsInSandbox = false; + + options.services.wyoming.piper = with types; { + package = mkPackageOptionMD pkgs "wyoming-piper" { }; + + servers = mkOption { + default = {}; + description = mdDoc '' + Attribute set of piper instances to spawn. + ''; + type = types.attrsOf (types.submodule ( + { ... }: { + options = { + enable = mkEnableOption (mdDoc "Wyoming Piper server"); + + piper = mkPackageOptionMD pkgs "piper-tts" { }; + + voice = mkOption { + type = str; + example = "en-us-ryan-medium"; + description = mdDoc '' + Name of the voice model to use. See the following website for samples: + https://rhasspy.github.io/piper-samples/ + ''; + }; + + uri = mkOption { + type = strMatching "^(tcp|unix)://.*$"; + example = "tcp://0.0.0.0:10200"; + description = mdDoc '' + URI to bind the wyoming server to. + ''; + }; + + speaker = mkOption { + type = ints.unsigned; + default = 0; + description = mdDoc '' + ID of a specific speaker in a multi-speaker model. + ''; + apply = toString; + }; + + noiseScale = mkOption { + type = float; + default = 0.667; + description = mdDoc '' + Generator noise value. + ''; + apply = toString; + }; + + noiseWidth = mkOption { + type = float; + default = 0.333; + description = mdDoc '' + Phoneme width noise value. + ''; + apply = toString; + }; + + lengthScale = mkOption { + type = float; + default = 1.0; + description = mdDoc '' + Phoneme length value. + ''; + apply = toString; + }; + + extraArgs = mkOption { + type = listOf str; + default = [ ]; + description = mdDoc '' + Extra arguments to pass to the server commandline. + ''; + apply = escapeShellArgs; + }; + }; + } + )); + }; + }; + + config = let + inherit (lib) + mapAttrs' + mkIf + nameValuePair + ; + in mkIf (cfg.servers != {}) { + systemd.services = mapAttrs' (server: options: + nameValuePair "wyoming-piper-${server}" { + description = "Wyoming Piper server instance ${server}"; + after = [ + "network-online.target" + ]; + wantedBy = [ + "multi-user.target" + ]; + serviceConfig = { + DynamicUser = true; + User = "wyoming-piper"; + StateDirectory = "wyoming/piper"; + # https://github.com/home-assistant/addons/blob/master/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/run + ExecStart = '' + ${cfg.package}/bin/wyoming-piper \ + --data-dir $STATE_DIRECTORY \ + --download-dir $STATE_DIRECTORY \ + --uri ${options.uri} \ + --piper ${options.piper}/bin/piper \ + --voice ${options.voice} \ + --speaker ${options.speaker} \ + --length-scale ${options.lengthScale} \ + --noise-scale ${options.noiseScale} \ + --noise-w ${options.noiseWidth} ${options.extraArgs} + ''; + CapabilityBoundingSet = ""; + DeviceAllow = ""; + DevicePolicy = "closed"; + LockPersonality = true; + MemoryDenyWriteExecute = true; + PrivateDevices = true; + PrivateUsers = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectControlGroups = true; + ProtectProc = "invisible"; + ProcSubset = "pid"; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_UNIX" + ]; + RestrictNamespaces = true; + RestrictRealtime = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + ]; + UMask = "0077"; + }; + }) cfg.servers; + }; +}