nixos/tts: init
Provide a module to configure Coqui TTS, available as `tts` in nixpkgs for a few releases already. The module supports multiple servers in parallel, so multiple languages and testing scenarios can be covered, without affecting any production usage.
This commit is contained in:
parent
2d84e9d646
commit
198713cf82
3 changed files with 154 additions and 0 deletions
|
@ -40,6 +40,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [goeland](https://github.com/slurdge/goeland), an alternative to rss2email written in golang with many filters. Available as [services.goeland](#opt-services.goeland.enable).
|
||||
|
||||
- [tts](https://github.com/coqui-ai/TTS), a battle-tested deep learning toolkit for Text-to-Speech. Mutiple servers may be configured below [services.tts.servers](#opt-services.tts.servers).
|
||||
|
||||
- [atuin](https://github.com/ellie/atuin), a sync server for shell history. Available as [services.atuin](#opt-services.atuin.enable).
|
||||
|
||||
- [networkd-dispatcher](https://gitlab.com/craftyguy/networkd-dispatcher), a dispatcher service for systemd-networkd connection status changes. Available as [services.networkd-dispatcher](#opt-services.networkd-dispatcher.enable).
|
||||
|
|
|
@ -314,6 +314,7 @@
|
|||
./services/audio/snapserver.nix
|
||||
./services/audio/spotifyd.nix
|
||||
./services/audio/squeezelite.nix
|
||||
./services/audio/tts.nix
|
||||
./services/audio/ympd.nix
|
||||
./services/backup/automysqlbackup.nix
|
||||
./services/backup/bacula.nix
|
||||
|
|
151
nixos/modules/services/audio/tts.nix
Normal file
151
nixos/modules/services/audio/tts.nix
Normal file
|
@ -0,0 +1,151 @@
|
|||
{ config
|
||||
, lib
|
||||
, pkgs
|
||||
, ...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.tts;
|
||||
in
|
||||
|
||||
{
|
||||
options.services.tts = let
|
||||
inherit (lib) literalExpression mkOption mdDoc mkEnableOption types;
|
||||
in {
|
||||
servers = mkOption {
|
||||
type = types.attrsOf (types.submodule (
|
||||
{ ... }: {
|
||||
options = {
|
||||
enable = mkEnableOption (mdDoc "Coqui TTS server");
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
example = 5000;
|
||||
description = mdDoc ''
|
||||
Port to bind the TTS server to.
|
||||
'';
|
||||
};
|
||||
|
||||
model = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "tts_models/en/ljspeech/tacotron2-DDC";
|
||||
example = null;
|
||||
description = mdDoc ''
|
||||
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 = mdDoc ''
|
||||
Whether to offload computation onto a CUDA compatible GPU.
|
||||
'';
|
||||
};
|
||||
|
||||
extraArgs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = mdDoc ''
|
||||
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 = mdDoc ''
|
||||
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_INET"
|
||||
"AF_INET6"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
}) cfg.servers;
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue