1{ lib, ... }:
2let
3 port = 59126;
4in
5{
6 name = "marytts";
7 meta.maintainers = with lib.maintainers; [ pluiedev ];
8
9 nodes.machine =
10 { pkgs, ... }:
11 {
12 networking.firewall.enable = false;
13 networking.useDHCP = false;
14
15 services.marytts = {
16 enable = true;
17 inherit port;
18
19 voices = [
20 (pkgs.fetchzip {
21 url = "https://github.com/marytts/voice-bits1-hsmm/releases/download/v5.2/voice-bits1-hsmm-5.2.zip";
22 hash = "sha256-1nK+qZxjumMev7z5lgKr660NCKH5FDwvZ9sw/YYYeaA=";
23 })
24 ];
25
26 userDictionaries = [
27 (pkgs.writeTextFile {
28 name = "userdict-en_US.txt";
29 destination = "/userdict-en_US.txt";
30 text = ''
31 amogus | @ - ' m @U - g @ s
32 Nixpkgs | n I k s - ' p { - k @ - dZ @ s
33 '';
34 })
35 ];
36 };
37 };
38
39 testScript = ''
40 from xml.etree import ElementTree
41 from urllib.parse import urlencode
42
43 machine.wait_for_unit("marytts.service")
44
45 with subtest("Checking health of MaryTTS server"):
46 machine.wait_for_open_port(${toString port})
47 assert 'Mary TTS server' in machine.succeed("curl 'localhost:${toString port}/version'")
48
49 with subtest("Generating example MaryXML"):
50 query = urlencode({
51 'datatype': 'RAWMARYXML',
52 'locale': 'en_US',
53 })
54 xml = machine.succeed(f"curl 'localhost:${toString port}/exampletext?{query}'")
55 root = ElementTree.fromstring(xml)
56 text = " ".join(root.itertext()).strip()
57 assert text == "Welcome to the world of speech synthesis!"
58
59 with subtest("Detecting custom voice"):
60 assert "bits1-hsmm" in machine.succeed("curl 'localhost:${toString port}/voices'")
61
62 with subtest("Finding user dictionary"):
63 query = urlencode({
64 'INPUT_TEXT': 'amogus',
65 'INPUT_TYPE': 'TEXT',
66 'OUTPUT_TYPE': 'PHONEMES',
67 'LOCALE': 'en_US',
68 })
69 phonemes = machine.succeed(f"curl 'localhost:${toString port}/process?{query}'")
70 phonemes_tree = ElementTree.fromstring(phonemes)
71 print([i.get('ph') for i in phonemes_tree.iter('{http://mary.dfki.de/2002/MaryXML}t')])
72 assert ["@ - ' m @U - g @ s"] == [i.get('ph') for i in phonemes_tree.iter('{http://mary.dfki.de/2002/MaryXML}t')]
73
74 with subtest("Synthesizing"):
75 query = urlencode({
76 'INPUT_TEXT': 'Nixpkgs is a collection of over 100,000 software packages that can be installed with the Nix package manager.',
77 'INPUT_TYPE': 'TEXT',
78 'OUTPUT_TYPE': 'AUDIO',
79 'AUDIO': 'WAVE_FILE',
80 'LOCALE': 'en_US',
81 })
82 machine.succeed(f"curl 'localhost:${toString port}/process?{query}' -o ./audio.wav")
83 machine.copy_from_vm("./audio.wav")
84 '';
85}