depot/third_party/nixpkgs/nixos/modules/services/audio/tts.nix

179 lines
4.9 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.tts;
in
{
options.services.tts =
let
inherit (lib)
literalExpression
mkOption
mkEnableOption
types
;
in
{
servers = mkOption {
type = types.attrsOf (
types.submodule (
{ ... }:
{
options = {
enable = mkEnableOption "Coqui TTS server";
port = mkOption {
type = types.port;
example = 5000;
description = ''
Port to bind the TTS server to.
'';
};
model = mkOption {
type = types.nullOr types.str;
default = "tts_models/en/ljspeech/tacotron2-DDC";
example = null;
description = ''
Name of the model to download and use for speech synthesis.
Check `tts-server --list_models` for possible values.
Set to `null` to use a custom model.
'';
};
useCuda = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Whether to offload computation onto a CUDA compatible GPU.
'';
};
extraArgs = mkOption {
type = types.listOf types.str;
default = [ ];
description = ''
Extra arguments to pass to the server commandline.
'';
};
};
}
)
);
default = { };
example = literalExpression ''
{
english = {
port = 5300;
model = "tts_models/en/ljspeech/tacotron2-DDC";
};
german = {
port = 5301;
model = "tts_models/de/thorsten/tacotron2-DDC";
};
dutch = {
port = 5302;
model = "tts_models/nl/mai/tacotron2-DDC";
};
}
'';
description = ''
TTS server instances.
'';
};
};
config =
let
inherit (lib)
mkIf
mapAttrs'
nameValuePair
optionalString
concatMapStringsSep
escapeShellArgs
;
in
mkIf (cfg.servers != { }) {
systemd.services = mapAttrs' (
server: options:
nameValuePair "tts-${server}" {
description = "Coqui TTS server instance ${server}";
after = [
"network-online.target"
];
wantedBy = [
"multi-user.target"
];
path = with pkgs; [
espeak-ng
];
environment.HOME = "/var/lib/tts";
serviceConfig = {
DynamicUser = true;
User = "tts";
StateDirectory = "tts";
ExecStart =
"${pkgs.tts}/bin/tts-server --port ${toString options.port}"
+ optionalString (options.model != null) " --model_name ${options.model}"
+ optionalString (options.useCuda) " --use_cuda"
+ (concatMapStringsSep " " escapeShellArgs options.extraArgs);
CapabilityBoundingSet = "";
DeviceAllow =
if options.useCuda then
[
# https://docs.nvidia.com/dgx/pdf/dgx-os-5-user-guide.pdf
"/dev/nvidia1"
"/dev/nvidia2"
"/dev/nvidia3"
"/dev/nvidia4"
"/dev/nvidia-caps/nvidia-cap1"
"/dev/nvidia-caps/nvidia-cap2"
"/dev/nvidiactl"
"/dev/nvidia-modeset"
"/dev/nvidia-uvm"
"/dev/nvidia-uvm-tools"
]
else
"";
DevicePolicy = "closed";
LockPersonality = true;
# jit via numba->llvmpipe
MemoryDenyWriteExecute = false;
PrivateDevices = true;
PrivateUsers = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectControlGroups = true;
ProtectProc = "invisible";
ProcSubset = "pid";
RestrictAddressFamilies = [
"AF_UNIX"
"AF_INET"
"AF_INET6"
];
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
];
UMask = "0077";
};
}
) cfg.servers;
};
}