diff --git a/Makefile b/Makefile index f9418c9..2f81cc9 100644 --- a/Makefile +++ b/Makefile @@ -57,6 +57,9 @@ verify: test browser ## Tutti i controlli voci: ## Voci dei personaggi con XTTS sulla GPU: solo le battute nuove o cambiate (RIFAI='testo' per ritentarne una) $(NODE) tools/voci.mjs $(if $(RIFAI),--rifai "$(RIFAI)") +ascolta: ## Riascolta le voci con Whisper (mbot ascolta) e elenca quelle che dicono altro (SOLO='testo' per alcune) + $(NODE) tools/ascolta.mjs $(if $(SOLO),"$(SOLO)") + voci-elenco: ## Quali battute mancano di voce, senza generare niente $(NODE) tools/voci.mjs --dry diff --git a/assets/voices/andrea-01d1ccb933.mp3 b/assets/voices/andrea-01d1ccb933.mp3 new file mode 100644 index 0000000..091a9f3 Binary files /dev/null and b/assets/voices/andrea-01d1ccb933.mp3 differ diff --git a/assets/voices/andrea-0a30866235.mp3 b/assets/voices/andrea-0a30866235.mp3 index 4492594..447d5b3 100644 Binary files a/assets/voices/andrea-0a30866235.mp3 and b/assets/voices/andrea-0a30866235.mp3 differ diff --git a/assets/voices/andrea-0b1872ef8c.mp3 b/assets/voices/andrea-0b1872ef8c.mp3 new file mode 100644 index 0000000..628d759 Binary files /dev/null and b/assets/voices/andrea-0b1872ef8c.mp3 differ diff --git a/assets/voices/andrea-0b61233e59.mp3 b/assets/voices/andrea-0b61233e59.mp3 deleted file mode 100644 index d1ee54c..0000000 Binary files a/assets/voices/andrea-0b61233e59.mp3 and /dev/null differ diff --git a/assets/voices/andrea-131481b503.mp3 b/assets/voices/andrea-131481b503.mp3 new file mode 100644 index 0000000..8271b34 Binary files /dev/null and b/assets/voices/andrea-131481b503.mp3 differ diff --git a/assets/voices/andrea-15618ccedd.mp3 b/assets/voices/andrea-15618ccedd.mp3 new file mode 100644 index 0000000..2ab218c Binary files /dev/null and b/assets/voices/andrea-15618ccedd.mp3 differ diff --git a/assets/voices/andrea-1baedec826.mp3 b/assets/voices/andrea-1baedec826.mp3 deleted file mode 100644 index 3f48b6a..0000000 Binary files a/assets/voices/andrea-1baedec826.mp3 and /dev/null differ diff --git a/assets/voices/andrea-22477cfcba.mp3 b/assets/voices/andrea-22477cfcba.mp3 new file mode 100644 index 0000000..27986a0 Binary files /dev/null and b/assets/voices/andrea-22477cfcba.mp3 differ diff --git a/assets/voices/andrea-2442d01b65.mp3 b/assets/voices/andrea-2442d01b65.mp3 new file mode 100644 index 0000000..179b3f2 Binary files /dev/null and b/assets/voices/andrea-2442d01b65.mp3 differ diff --git a/assets/voices/andrea-2637918e77.mp3 b/assets/voices/andrea-2637918e77.mp3 new file mode 100644 index 0000000..f704b25 Binary files /dev/null and b/assets/voices/andrea-2637918e77.mp3 differ diff --git a/assets/voices/andrea-2d0e3c759e.mp3 b/assets/voices/andrea-2d0e3c759e.mp3 new file mode 100644 index 0000000..f924759 Binary files /dev/null and b/assets/voices/andrea-2d0e3c759e.mp3 differ diff --git a/assets/voices/andrea-35b92c1da8.mp3 b/assets/voices/andrea-35b92c1da8.mp3 index 0994db3..33f1d62 100644 Binary files a/assets/voices/andrea-35b92c1da8.mp3 and b/assets/voices/andrea-35b92c1da8.mp3 differ diff --git a/assets/voices/andrea-379131645c.mp3 b/assets/voices/andrea-379131645c.mp3 new file mode 100644 index 0000000..3f5a0e7 Binary files /dev/null and b/assets/voices/andrea-379131645c.mp3 differ diff --git a/assets/voices/andrea-3a253ec0a8.mp3 b/assets/voices/andrea-3a253ec0a8.mp3 new file mode 100644 index 0000000..5999496 Binary files /dev/null and b/assets/voices/andrea-3a253ec0a8.mp3 differ diff --git a/assets/voices/andrea-3a6af3897f.mp3 b/assets/voices/andrea-3a6af3897f.mp3 index 73fd8ab..0d207a9 100644 Binary files a/assets/voices/andrea-3a6af3897f.mp3 and b/assets/voices/andrea-3a6af3897f.mp3 differ diff --git a/assets/voices/andrea-4167cc8c5e.mp3 b/assets/voices/andrea-4167cc8c5e.mp3 index cd35411..8348e74 100644 Binary files a/assets/voices/andrea-4167cc8c5e.mp3 and b/assets/voices/andrea-4167cc8c5e.mp3 differ diff --git a/assets/voices/andrea-4270930279.mp3 b/assets/voices/andrea-4270930279.mp3 new file mode 100644 index 0000000..b52f6d3 Binary files /dev/null and b/assets/voices/andrea-4270930279.mp3 differ diff --git a/assets/voices/andrea-42b02eb9ea.mp3 b/assets/voices/andrea-42b02eb9ea.mp3 new file mode 100644 index 0000000..dcfce8e Binary files /dev/null and b/assets/voices/andrea-42b02eb9ea.mp3 differ diff --git a/assets/voices/andrea-481b81e3fe.mp3 b/assets/voices/andrea-481b81e3fe.mp3 new file mode 100644 index 0000000..ee13c96 Binary files /dev/null and b/assets/voices/andrea-481b81e3fe.mp3 differ diff --git a/assets/voices/andrea-4e98630ef3.mp3 b/assets/voices/andrea-4e98630ef3.mp3 new file mode 100644 index 0000000..b5f68d6 Binary files /dev/null and b/assets/voices/andrea-4e98630ef3.mp3 differ diff --git a/assets/voices/andrea-5594f1f70c.mp3 b/assets/voices/andrea-5594f1f70c.mp3 index 804ecb8..50e8c74 100644 Binary files a/assets/voices/andrea-5594f1f70c.mp3 and b/assets/voices/andrea-5594f1f70c.mp3 differ diff --git a/assets/voices/andrea-629bfcac17.mp3 b/assets/voices/andrea-629bfcac17.mp3 index eb9245c..59a3ff9 100644 Binary files a/assets/voices/andrea-629bfcac17.mp3 and b/assets/voices/andrea-629bfcac17.mp3 differ diff --git a/assets/voices/andrea-6496042236.mp3 b/assets/voices/andrea-6496042236.mp3 new file mode 100644 index 0000000..4770faa Binary files /dev/null and b/assets/voices/andrea-6496042236.mp3 differ diff --git a/assets/voices/andrea-6ebcf8e5de.mp3 b/assets/voices/andrea-6ebcf8e5de.mp3 new file mode 100644 index 0000000..09a48b8 Binary files /dev/null and b/assets/voices/andrea-6ebcf8e5de.mp3 differ diff --git a/assets/voices/andrea-7dba950893.mp3 b/assets/voices/andrea-7dba950893.mp3 new file mode 100644 index 0000000..bf2be57 Binary files /dev/null and b/assets/voices/andrea-7dba950893.mp3 differ diff --git a/assets/voices/andrea-7e9841c23a.mp3 b/assets/voices/andrea-7e9841c23a.mp3 new file mode 100644 index 0000000..1d405f6 Binary files /dev/null and b/assets/voices/andrea-7e9841c23a.mp3 differ diff --git a/assets/voices/andrea-8209ff51e1.mp3 b/assets/voices/andrea-8209ff51e1.mp3 new file mode 100644 index 0000000..284040e Binary files /dev/null and b/assets/voices/andrea-8209ff51e1.mp3 differ diff --git a/assets/voices/andrea-84a2614ea0.mp3 b/assets/voices/andrea-84a2614ea0.mp3 index 5c82c98..9da0931 100644 Binary files a/assets/voices/andrea-84a2614ea0.mp3 and b/assets/voices/andrea-84a2614ea0.mp3 differ diff --git a/assets/voices/andrea-872d650e46.mp3 b/assets/voices/andrea-872d650e46.mp3 deleted file mode 100644 index c3475bf..0000000 Binary files a/assets/voices/andrea-872d650e46.mp3 and /dev/null differ diff --git a/assets/voices/andrea-88aff362ec.mp3 b/assets/voices/andrea-88aff362ec.mp3 new file mode 100644 index 0000000..f49e065 Binary files /dev/null and b/assets/voices/andrea-88aff362ec.mp3 differ diff --git a/assets/voices/andrea-8927b87738.mp3 b/assets/voices/andrea-8927b87738.mp3 new file mode 100644 index 0000000..45790eb Binary files /dev/null and b/assets/voices/andrea-8927b87738.mp3 differ diff --git a/assets/voices/andrea-8945f1786d.mp3 b/assets/voices/andrea-8945f1786d.mp3 index f3c5792..fa1db16 100644 Binary files a/assets/voices/andrea-8945f1786d.mp3 and b/assets/voices/andrea-8945f1786d.mp3 differ diff --git a/assets/voices/andrea-8abb6148b1.mp3 b/assets/voices/andrea-8abb6148b1.mp3 index fa84f71..223c6fd 100644 Binary files a/assets/voices/andrea-8abb6148b1.mp3 and b/assets/voices/andrea-8abb6148b1.mp3 differ diff --git a/assets/voices/andrea-8ae8691b63.mp3 b/assets/voices/andrea-8ae8691b63.mp3 index 2c009a5..a36cefc 100644 Binary files a/assets/voices/andrea-8ae8691b63.mp3 and b/assets/voices/andrea-8ae8691b63.mp3 differ diff --git a/assets/voices/andrea-9f914e2a8b.mp3 b/assets/voices/andrea-9f914e2a8b.mp3 index 9e20f07..00f41e4 100644 Binary files a/assets/voices/andrea-9f914e2a8b.mp3 and b/assets/voices/andrea-9f914e2a8b.mp3 differ diff --git a/assets/voices/andrea-a16136da3a.mp3 b/assets/voices/andrea-a16136da3a.mp3 deleted file mode 100644 index 4da7baa..0000000 Binary files a/assets/voices/andrea-a16136da3a.mp3 and /dev/null differ diff --git a/assets/voices/andrea-a6e94b369c.mp3 b/assets/voices/andrea-a6e94b369c.mp3 new file mode 100644 index 0000000..6658917 Binary files /dev/null and b/assets/voices/andrea-a6e94b369c.mp3 differ diff --git a/assets/voices/andrea-a72d2697e3.mp3 b/assets/voices/andrea-a72d2697e3.mp3 new file mode 100644 index 0000000..715854f Binary files /dev/null and b/assets/voices/andrea-a72d2697e3.mp3 differ diff --git a/assets/voices/andrea-c41f9eaaf3.mp3 b/assets/voices/andrea-c41f9eaaf3.mp3 index ae5a005..8a89d99 100644 Binary files a/assets/voices/andrea-c41f9eaaf3.mp3 and b/assets/voices/andrea-c41f9eaaf3.mp3 differ diff --git a/assets/voices/andrea-cb7a4064f2.mp3 b/assets/voices/andrea-cb7a4064f2.mp3 new file mode 100644 index 0000000..2bd2611 Binary files /dev/null and b/assets/voices/andrea-cb7a4064f2.mp3 differ diff --git a/assets/voices/andrea-d129373272.mp3 b/assets/voices/andrea-d129373272.mp3 new file mode 100644 index 0000000..309e337 Binary files /dev/null and b/assets/voices/andrea-d129373272.mp3 differ diff --git a/assets/voices/andrea-d15c90f036.mp3 b/assets/voices/andrea-d15c90f036.mp3 new file mode 100644 index 0000000..aa42049 Binary files /dev/null and b/assets/voices/andrea-d15c90f036.mp3 differ diff --git a/assets/voices/andrea-d2ce5bb455.mp3 b/assets/voices/andrea-d2ce5bb455.mp3 new file mode 100644 index 0000000..d8807aa Binary files /dev/null and b/assets/voices/andrea-d2ce5bb455.mp3 differ diff --git a/assets/voices/andrea-d31f6e291b.mp3 b/assets/voices/andrea-d31f6e291b.mp3 new file mode 100644 index 0000000..8c7dab9 Binary files /dev/null and b/assets/voices/andrea-d31f6e291b.mp3 differ diff --git a/assets/voices/andrea-db75339f79.mp3 b/assets/voices/andrea-db75339f79.mp3 new file mode 100644 index 0000000..13ad0ac Binary files /dev/null and b/assets/voices/andrea-db75339f79.mp3 differ diff --git a/assets/voices/andrea-de371ab565.mp3 b/assets/voices/andrea-de371ab565.mp3 new file mode 100644 index 0000000..8fdb562 Binary files /dev/null and b/assets/voices/andrea-de371ab565.mp3 differ diff --git a/assets/voices/andrea-e4f78223c4.mp3 b/assets/voices/andrea-e4f78223c4.mp3 index 8140e04..3d6aa4f 100644 Binary files a/assets/voices/andrea-e4f78223c4.mp3 and b/assets/voices/andrea-e4f78223c4.mp3 differ diff --git a/assets/voices/andrea-e673c57e60.mp3 b/assets/voices/andrea-e673c57e60.mp3 new file mode 100644 index 0000000..7ee1f78 Binary files /dev/null and b/assets/voices/andrea-e673c57e60.mp3 differ diff --git a/assets/voices/andrea-e6bf7b3266.mp3 b/assets/voices/andrea-e6bf7b3266.mp3 new file mode 100644 index 0000000..ab6fe20 Binary files /dev/null and b/assets/voices/andrea-e6bf7b3266.mp3 differ diff --git a/assets/voices/andrea-f2ea95922d.mp3 b/assets/voices/andrea-f2ea95922d.mp3 index 812d802..af0d2af 100644 Binary files a/assets/voices/andrea-f2ea95922d.mp3 and b/assets/voices/andrea-f2ea95922d.mp3 differ diff --git a/assets/voices/andrea-f51c5ac76e.mp3 b/assets/voices/andrea-f51c5ac76e.mp3 new file mode 100644 index 0000000..8aa56d1 Binary files /dev/null and b/assets/voices/andrea-f51c5ac76e.mp3 differ diff --git a/assets/voices/castello-b87ef89eaf.mp3 b/assets/voices/castello-b87ef89eaf.mp3 index 2594c46..b65d41f 100644 Binary files a/assets/voices/castello-b87ef89eaf.mp3 and b/assets/voices/castello-b87ef89eaf.mp3 differ diff --git a/assets/voices/index.json b/assets/voices/index.json index 0df6c06..8765302 100644 --- a/assets/voices/index.json +++ b/assets/voices/index.json @@ -1,7 +1,7 @@ { "andrea|San Piero a Sieve, nel Mugello. Fine maggio 2007.": { "file": "andrea-4167cc8c5e.mp3", - "sec": 4.59 + "sec": 4.84 }, "andrea|In paese si prepara il Palio della Fortezza: i quattro rioni si sfidano, e chi vince si porta a casa il palio, il quadro dipinto dai ragazzi delle medie.": { "file": "andrea-fdeb17aa77.mp3", @@ -136,8 +136,8 @@ "sec": 5.94 }, "andrea|Nove bastioni, li volle Cosimo I. Per tenere fuori i nemici, dicono. Secondo me per tenere dentro il Regolo.": { - "file": "andrea-0b61233e59.mp3", - "sec": 9.95 + "file": "andrea-d31f6e291b.mp3", + "sec": 8.71 }, "andrea|Arrampicarmi sul bastione? Ho visto film che finivano meglio.": { "file": "andrea-625ef8dc45.mp3", @@ -257,7 +257,7 @@ }, "andrea|La Pieve di San Pietro. Il rione Pieve, quelli in bianco.": { "file": "andrea-c41f9eaaf3.mp3", - "sec": 4.86 + "sec": 4.44 }, "andrea|Il prete è a benedire le carrette del Palio. Torno dopo.": { "file": "andrea-bd4991b099.mp3", @@ -369,7 +369,7 @@ }, "andrea|Una gomma da masticare ancora incartata, persa davanti al palco. Qualcuno ha perso l'appetito.": { "file": "andrea-f2ea95922d.mp3", - "sec": 7.49 + "sec": 6.54 }, "andrea|Una gomma alla fragola. Me la tengo.": { "file": "andrea-7009fd9d71.mp3", @@ -469,7 +469,7 @@ }, "andrea|La panchina rossa. Qui si scambiavano le figurine: celo, celo, manca.": { "file": "andrea-84a2614ea0.mp3", - "sec": 5.7 + "sec": 6.03 }, "andrea|Laggiù le poste. Mia nonna ci andava a ritirare la pensione e tornava con tutte le notizie del paese.": { "file": "andrea-c716ab2381.mp3", @@ -521,11 +521,11 @@ }, "andrea|La chiavetta entra nel lucchetto... clic!": { "file": "andrea-35b92c1da8.mp3", - "sec": 3.91 + "sec": 3.04 }, "andrea|Prolunghe, prolunghe, prolunghe... e una torcia.": { "file": "andrea-8abb6148b1.mp3", - "sec": 5.98 + "sec": 4.54 }, "andrea|Chiusa col lucchetto. Il mistero resta.": { "file": "andrea-a8dfddbe65.mp3", @@ -560,12 +560,12 @@ "sec": 2.18 }, "andrea|Il capannone verde del padel.": { - "file": "andrea-a16136da3a.mp3", - "sec": 1.63 + "file": "andrea-d15c90f036.mp3", + "sec": 1.79 }, "andrea|Il padel, nel 2007, non so nemmeno cosa sia. Tra qualche anno ci giocheranno tutti, me compreso.": { - "file": "andrea-1baedec826.mp3", - "sec": 7.77 + "file": "andrea-4e98630ef3.mp3", + "sec": 7.9 }, "andrea|Chiuso. E poi non saprei nemmeno da che parte si tiene la racchetta.": { "file": "andrea-e47b3cebb5.mp3", @@ -661,7 +661,7 @@ }, "andrea|Un muro di sassi a secco, con la ringhiera sopra. Ne ha visti passare di pali.": { "file": "andrea-9f914e2a8b.mp3", - "sec": 5.35 + "sec": 5.4 }, "andrea|Una porta marrone, chiusa.": { "file": "andrea-29c2c930b4.mp3", @@ -757,7 +757,7 @@ }, "tosca|Eccomi, Andrea! Cosa ti do? Fanta, Coca, cedrata, spuma bionda... o un ghiacciolo?": { "file": "tosca-75db2f3b4e.mp3", - "sec": 8.26 + "sec": 9.26 }, "andrea|Il chiosco si apre da dentro. Basta chiamare la Tosca.": { "file": "andrea-acc1a379b7.mp3", @@ -813,7 +813,7 @@ }, "andrea|Il mercoledì sera è ancora lontano. Prima il palio.": { "file": "andrea-e4f78223c4.mp3", - "sec": 4.39 + "sec": 3.88 }, "andrea|Villa Adami. Gialla come un tuorlo, con le persiane verdi.": { "file": "andrea-225e29ed43.mp3", @@ -889,11 +889,11 @@ }, "andrea|Fare i ponti di sassi? Prima il palio. Poi le dighe.": { "file": "andrea-5594f1f70c.mp3", - "sec": 5.02 + "sec": 4.54 }, "andrea|La griglia. Ormai dentro ci sono solo foglie.": { "file": "andrea-0a30866235.mp3", - "sec": 3.6 + "sec": 3.63 }, "andrea|Dentro la griglia luccica qualcosa: una chiavetta! È caduta fra le sbarre.": { "file": "andrea-c6acc0d948.mp3", @@ -915,9 +915,9 @@ "file": "andrea-29863877af.mp3", "sec": 4.54 }, - "andrea|Presa!": { - "file": "andrea-872d650e46.mp3", - "sec": 0.69 + "andrea|Eccola, presa!": { + "file": "andrea-8209ff51e1.mp3", + "sec": 1.53 }, "andrea|Lo stecco ci arriva, ma la chiavetta non si attacca. Serve qualcosa di appiccicoso in cima.": { "file": "andrea-af37e73b26.mp3", @@ -957,7 +957,7 @@ }, "andrea|Se salgo, mi mettono ad apparecchiare. Prima il palio.": { "file": "andrea-8945f1786d.mp3", - "sec": 4.18 + "sec": 3.89 }, "andrea|Il prato sotto casa. Qui le porte le facevamo con le maglie per terra: due maglie, un palo ciascuna.": { "file": "andrea-4708fda5ef.mp3", @@ -989,7 +989,7 @@ }, "andrea|Tornare a scuola? A ventisette anni? Nemmeno per sogno.": { "file": "andrea-8ae8691b63.mp3", - "sec": 5.44 + "sec": 5.39 }, "andrea|Le palazzine gialle accanto alla scuola, con la scala arancione.": { "file": "andrea-528eda3257.mp3", @@ -1069,7 +1069,7 @@ }, "andrea|Leggere adesso? Prima il palio. E poi, a quanto pare, si fa presto.": { "file": "andrea-3a6af3897f.mp3", - "sec": 6.52 + "sec": 6.06 }, "andrea|Un ghiacciolo al limone. Si scioglie a guardarlo.": { "file": "andrea-8c9713081a.mp3", @@ -1081,7 +1081,7 @@ }, "andrea|Ghiacciolo dentro la cedrata... si scioglie, frizza, è verde e giallo insieme.": { "file": "andrea-629bfcac17.mp3", - "sec": 6.24 + "sec": 5.53 }, "andrea|Esagerato. Buonissimo. La merenda dei campioni.": { "file": "andrea-4a2ae1d92d.mp3", @@ -1167,6 +1167,30 @@ "file": "andrea-60cdae2e35.mp3", "sec": 5.1 }, + "andrea|Una Fanta.": { + "file": "andrea-8927b87738.mp3", + "sec": 0.65 + }, + "andrea|Una Coca.": { + "file": "andrea-15618ccedd.mp3", + "sec": 0.78 + }, + "andrea|Una spuma bionda.": { + "file": "andrea-db75339f79.mp3", + "sec": 1.21 + }, + "andrea|Una cedrata, da portare via.": { + "file": "andrea-3a253ec0a8.mp3", + "sec": 1.85 + }, + "andrea|Un ghiacciolo al limone.": { + "file": "andrea-2d0e3c759e.mp3", + "sec": 1.39 + }, + "andrea|Niente, grazie Tosca.": { + "file": "andrea-2637918e77.mp3", + "sec": 1.32 + }, "tosca|Eccola, ghiacciata.": { "file": "tosca-133c83efc3.mp3", "sec": 1.79 @@ -1181,7 +1205,7 @@ }, "tosca|Cedrata. Bella fresca.": { "file": "tosca-d6b114d197.mp3", - "sec": 2.24 + "sec": 2.31 }, "tosca|Al limone, l'ultimo della cassetta.": { "file": "tosca-376fbb9f17.mp3", @@ -1191,6 +1215,26 @@ "file": "tosca-db2da31cef.mp3", "sec": 2.31 }, + "andrea|Cinque.": { + "file": "andrea-0b1872ef8c.mp3", + "sec": 0.61 + }, + "andrea|Sette.": { + "file": "andrea-88aff362ec.mp3", + "sec": 0.7 + }, + "andrea|Nove.": { + "file": "andrea-22477cfcba.mp3", + "sec": 0.57 + }, + "andrea|Dodici.": { + "file": "andrea-2442d01b65.mp3", + "sec": 0.51 + }, + "andrea|Ci penso e torno.": { + "file": "andrea-d2ce5bb455.mp3", + "sec": 1.56 + }, "san_pietro|Cinque? Ne hai contati la metà. Vai a guardarli bene, lassù.": { "file": "san_pietro-4f6f201875.mp3", "sec": 6.53 @@ -1200,12 +1244,12 @@ "sec": 4.44 }, "san_pietro|Bravo! Nove, come li volle Cosimo I.": { - "file": "san_pietro-3a2e3a543b.mp3", - "sec": 4.25 + "file": "san_pietro-9bb2be5ec6.mp3", + "sec": 4.55 }, "san_pietro|Eccoti la chiave dell'oratorio. Trattala bene: è più vecchia di tuo nonno.": { "file": "san_pietro-9e24f3914e.mp3", - "sec": 6.14 + "sec": 6.11 }, "andrea|Grazie, San Pietro!": { "file": "andrea-149f790fa1.mp3", @@ -1219,6 +1263,22 @@ "file": "san_pietro-6c85ba44c5.mp3", "sec": 3.63 }, + "andrea|Avete visto chi ha preso il palio?": { + "file": "andrea-e673c57e60.mp3", + "sec": 1.65 + }, + "andrea|Avete notato niente di strano stanotte?": { + "file": "andrea-f51c5ac76e.mp3", + "sec": 2.41 + }, + "andrea|Come vi sembra il Palio di quest'anno?": { + "file": "andrea-379131645c.mp3", + "sec": 1.98 + }, + "andrea|Ci vediamo dopo.": { + "file": "andrea-7e9841c23a.mp3", + "sec": 0.95 + }, "vecchietta|È stato il Regolo! Quello che cadde dal cielo quando scavavano le fondamenta.": { "file": "vecchietta-e35443db85.mp3", "sec": 5.13 @@ -1259,6 +1319,18 @@ "file": "vecchietta-814e558af5.mp3", "sec": 1.47 }, + "andrea|Sono bloccato. Mi dai un consiglio?": { + "file": "andrea-42b02eb9ea.mp3", + "sec": 3.9 + }, + "andrea|Ma tu ce l'hai mai visto, il Regolo?": { + "file": "andrea-01d1ccb933.mp3", + "sec": 2.09 + }, + "andrea|Niente, volevo solo un po' di pace.": { + "file": "andrea-131481b503.mp3", + "sec": 2.79 + }, "castello|Siediti. Guarda il Mugello. Respira.": { "file": "castello-72e22c6b59.mp3", "sec": 4.92 @@ -1277,7 +1349,7 @@ }, "castello|Hai la luce, e sotto la Fortezza c'è il buio. Mettili insieme.": { "file": "castello-b87ef89eaf.mp3", - "sec": 6.25 + "sec": 5.59 }, "castello|Una chiavetta piccola apre una cosa piccola. All'area feste c'è una casetta che aspetta.": { "file": "castello-f6d0f19ad6.mp3", @@ -1322,5 +1394,49 @@ "castello|Quella qui non manca mai. Torna quando vuoi.": { "file": "castello-dc8a873d86.mp3", "sec": 4.36 + }, + "andrea|Niente di speciale.": { + "file": "andrea-6ebcf8e5de.mp3", + "sec": 1.04 + }, + "andrea|Non credo di poterlo prendere.": { + "file": "andrea-cb7a4064f2.mp3", + "sec": 1.69 + }, + "andrea|Non so proprio come usarlo.": { + "file": "andrea-de371ab565.mp3", + "sec": 1.57 + }, + "andrea|Non mi sembra un gran chiacchierone.": { + "file": "andrea-d129373272.mp3", + "sec": 1.84 + }, + "andrea|Non si apre.": { + "file": "andrea-481b81e3fe.mp3", + "sec": 0.95 + }, + "andrea|Non credo che lo voglia.": { + "file": "andrea-e6bf7b3266.mp3", + "sec": 1.37 + }, + "andrea|Non è roba mia da buttare.": { + "file": "andrea-7dba950893.mp3", + "sec": 1.62 + }, + "andrea|Non funziona.": { + "file": "andrea-a72d2697e3.mp3", + "sec": 0.95 + }, + "andrea|Ce l'ho già.": { + "file": "andrea-a6e94b369c.mp3", + "sec": 0.59 + }, + "andrea|Questo non mi serve: via.": { + "file": "andrea-4270930279.mp3", + "sec": 1.9 + }, + "andrea|Meglio tenerlo: potrebbe servirmi.": { + "file": "andrea-6496042236.mp3", + "sec": 2.4 } } diff --git a/assets/voices/san_pietro-3a2e3a543b.mp3 b/assets/voices/san_pietro-3a2e3a543b.mp3 deleted file mode 100644 index 52f2d7c..0000000 Binary files a/assets/voices/san_pietro-3a2e3a543b.mp3 and /dev/null differ diff --git a/assets/voices/san_pietro-9bb2be5ec6.mp3 b/assets/voices/san_pietro-9bb2be5ec6.mp3 new file mode 100644 index 0000000..7e64ca9 Binary files /dev/null and b/assets/voices/san_pietro-9bb2be5ec6.mp3 differ diff --git a/assets/voices/san_pietro-9e24f3914e.mp3 b/assets/voices/san_pietro-9e24f3914e.mp3 index eb03152..82b9f93 100644 Binary files a/assets/voices/san_pietro-9e24f3914e.mp3 and b/assets/voices/san_pietro-9e24f3914e.mp3 differ diff --git a/assets/voices/tosca-75db2f3b4e.mp3 b/assets/voices/tosca-75db2f3b4e.mp3 index 2fda4d2..66f6817 100644 Binary files a/assets/voices/tosca-75db2f3b4e.mp3 and b/assets/voices/tosca-75db2f3b4e.mp3 differ diff --git a/assets/voices/tosca-d6b114d197.mp3 b/assets/voices/tosca-d6b114d197.mp3 index 368d8cb..5a573a7 100644 Binary files a/assets/voices/tosca-d6b114d197.mp3 and b/assets/voices/tosca-d6b114d197.mp3 differ diff --git a/src/engine/game.js b/src/engine/game.js index b8e26cc..d78e253 100644 --- a/src/engine/game.js +++ b/src/engine/game.js @@ -15,6 +15,9 @@ const DEFAULT_LINES = { drop: 'Non è roba mia da buttare.', with: 'Non funziona.', }; +const HAVE_IT = 'Ce l\'ho già.', DROPPED = 'Questo non mi serve: via.', KEEP_IT = 'Meglio tenerlo: potrebbe servirmi.'; +// Le battute che il motore dice da sé (quando la storia non ne ha una): anche loro hanno la voce (make voci). +export const ENGINE_LINES = [...Object.values(DEFAULT_LINES).filter(Boolean), HAVE_IT, DROPPED, KEEP_IT]; const SPEED = 95; // Solo profilo, come i cicli di camminata: 'up' e 'down' lasciano il verso com'è. const FACING = { left: -1, right: 1 }; @@ -181,9 +184,9 @@ export class Game { } if (def.actions?.[verb]) return def.actions[verb]; if (verb === 'walk') return h?.exit ? [{ go: h.exit.scene, at: h.exit.at, face: h.exit.face }] : []; - if (verb === 'take' && !h) return [{ say: 'Ce l\'ho già.' }]; + if (verb === 'take' && !h) return [{ say: HAVE_IT }]; // Si butta solo quello che non serve alla storia (`droppable`): gli oggetti indispensabili restano. - if (verb === 'drop' && !h) return def.droppable ? [{ say: 'Questo non mi serve: via.' }, { drop: target }] : [{ say: 'Meglio tenerlo: potrebbe servirmi.' }]; + if (verb === 'drop' && !h) return def.droppable ? [{ say: DROPPED }, { drop: target }] : [{ say: KEEP_IT }]; return DEFAULT_LINES[verb] ? [{ say: DEFAULT_LINES[verb] }] : []; } diff --git a/src/engine/voices.js b/src/engine/voices.js index 593550d..3baf875 100644 --- a/src/engine/voices.js +++ b/src/engine/voices.js @@ -1,6 +1,8 @@ // Voci dei personaggi: un mp3 per battuta (generati da tools/voci.mjs), cercati per chi parla e testo. // Senza assets/voices/index.json, o per una battuta nuova non ancora generata, il gioco resta muto e va avanti. +import { ENGINE_LINES } from './game.js'; + export const voiceKey = (who, text) => `${who}|${text}`; // Tutte le battute della storia, ovunque stiano (scene, oggetti, dialoghi, rami `if`), più le righe dell'introduzione @@ -12,12 +14,15 @@ export function voiceLines(story) { if (Array.isArray(value)) return value.forEach(visit); if (!value || typeof value !== 'object') return; if (typeof value.say === 'string') add(value.who ?? 'andrea', value.say); + // Le scelte dei dialoghi: Andrea ripete a voce l'opzione scelta (quando non ha una `say` sua). + if (Array.isArray(value.options)) for (const o of value.options) if (typeof o.text === 'string' && o.say == null) add('andrea', o.text); Object.values(value).forEach(visit); }; for (const line of story.intro ?? []) for (const text of typeof line === 'string' ? [line] : Object.values(line.rione)) add('andrea', text); visit(story.scenes); visit(story.items); visit(story.dialogues); + for (const text of ENGINE_LINES) add('andrea', text); return [...seen.values()]; } diff --git a/src/story/story.js b/src/story/story.js index 7a89a22..af7b400 100644 --- a/src/story/story.js +++ b/src/story/story.js @@ -1509,7 +1509,7 @@ export const story = { take: [{ if: 'chiavetta_presa', then: [{ say: 'Non c\'è più niente da prendere.' }], else: [{ say: 'Le dita non passano fra le sbarre. Ci vorrebbe qualcosa di lungo e sottile... e appiccicoso.' }] }], }, with: { - stecco_gomma: [{ if: 'chiavetta_presa', then: [{ say: 'La chiavetta l\'ho già ripescata.' }], else: [{ say: 'Giù lo stecco, piano piano... la gomma tocca la chiavetta...' }, { say: 'Presa!' }, { give: 'chiavetta' }, { set: 'chiavetta_presa' }] }], + stecco_gomma: [{ if: 'chiavetta_presa', then: [{ say: 'La chiavetta l\'ho già ripescata.' }], else: [{ say: 'Giù lo stecco, piano piano... la gomma tocca la chiavetta...' }, { say: 'Eccola, presa!' }, { give: 'chiavetta' }, { set: 'chiavetta_presa' }] }], stecco: [{ say: 'Lo stecco ci arriva, ma la chiavetta non si attacca. Serve qualcosa di appiccicoso in cima.' }], gomma: [{ say: 'La gomma da sola non ci arriva. Serve qualcosa per spingerla giù.' }], }, diff --git a/tests/voices.test.mjs b/tests/voices.test.mjs index b280a24..3db55c5 100644 --- a/tests/voices.test.mjs +++ b/tests/voices.test.mjs @@ -2,7 +2,8 @@ import test from 'node:test'; import assert from 'node:assert/strict'; import { existsSync, readFileSync } from 'node:fs'; import { story } from '../src/story/story.js'; -import { Game } from '../src/engine/game.js'; +import { Game, VERBS } from '../src/engine/game.js'; +import { solution } from '../src/story/solution.js'; import { voiceLines, voiceKey, Voices } from '../src/engine/voices.js'; import { settle } from './helpers.mjs'; @@ -29,6 +30,30 @@ test('ogni battuta ha la sua voce (sennò: make voci) e ogni personaggio una voc } }); +// Quello che si sente davvero giocando: la soluzione completa, e ogni verbo su ogni cosa di ogni scena (anche le +// risposte che il motore dà da sé, e le scelte dei dialoghi ripetute da Andrea). Nessuna battuta resta muta. +test('giocando, ogni battuta pronunciata ha la sua voce', () => { + const mute = new Set(), listen = said => { for (const s of said) if (s.text.trim() && !/^[.…!?\s]+$/.test(s.text) && !index[voiceKey(s.who, s.text)]) mute.add(`${s.who}: ${s.text}`); }; + const g = new Game(story); + g.go(story.start.scene, story.start.at); + listen(settle(g)); + for (const [verb, target, item] of solution) { + if (verb === 'choose') g.choose(g.options().findIndex(o => o.text === target)); else g.act(verb, target, item); + listen(settle(g)); + } + for (const id of Object.keys(story.scenes)) { + const fresh = () => { const t = new Game(story); t.go(id); settle(t); return t; }; + for (const h of fresh().hotspots()) for (const verb of VERBS) { + if (h.exit && verb === 'walk') continue; + const t = fresh(); + t.act(verb, h.id); + listen(settle(t)); + if (t.dialogue) for (let i = 0; i < 6 && t.dialogue && t.options().length; i++) { t.choose(0); listen(settle(t)); } + } + } + assert.deepEqual([...mute], [], 'battute senza voce (make voci)'); +}); + test('il castello e il leone hanno voci diverse da tutti gli altri', () => { for (const special of ['castello', 'leone']) for (const [who, v] of Object.entries(voci)) diff --git a/tools/ascolta.mjs b/tools/ascolta.mjs new file mode 100644 index 0000000..1ce88bc --- /dev/null +++ b/tools/ascolta.mjs @@ -0,0 +1,44 @@ +// Riascolta le voci del gioco (make ascolta): ogni mp3 di assets/voices/ passa da `mbot ascolta` (faster-whisper sulla +// GPU, skill «trascrittore») e si confronta col testo letto dalla voce. Elenca quelle che dicono altro: si rifanno +// con `node tools/voci.mjs --rifai 'pezzo di testo'`, oppure si aggiunge una riga a tools/pronuncia.json. +// node tools/ascolta.mjs [--min 0.8] [testo...] (con un testo: solo le battute che lo contengono) +import { execFileSync } from 'node:child_process'; +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { tmpdir } from 'node:os'; +import { spoken } from './pronuncia.mjs'; + +const ROOT = new URL('..', import.meta.url).pathname; +const index = JSON.parse(readFileSync(join(ROOT, 'assets/voices/index.json'), 'utf8')); +const args = process.argv.slice(2), at = args.indexOf('--min'); +const min = at >= 0 ? args.splice(at, 2)[1] : '0.8'; +const only = args; +// I numeri Whisper li scrive in cifre («Nove.» → «9.»): per il confronto le cifre tornano parole. +const NUMERI = ['zero', 'uno', 'due', 'tre', 'quattro', 'cinque', 'sei', 'sette', 'otto', 'nove', 'dieci', 'undici', 'dodici']; +const plain = t => t.toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/[^a-z0-9]+/g, ' ').trim(); + +const jobs = Object.entries(index) + .map(([key, e]) => ({ who: key.split('|')[0], text: key.slice(key.indexOf('|') + 1), file: join(ROOT, 'assets/voices', e.file) })) + .filter(j => !only.length || only.some(o => j.text.includes(o))) + .map(j => ({ ...j, expect: spoken(j.text) })); +const dir = join(tmpdir(), 'leggenda-regolo-ascolto'); +mkdirSync(dir, { recursive: true }); +writeFileSync(join(dir, 'ascolto.json'), JSON.stringify(jobs.map(({ file, expect }) => ({ file, expect })))); + +let out = ''; +try { + out = execFileSync('mbot', ['ascolta', '--jobs', join(dir, 'ascolto.json'), '--json', '--min', min], + { encoding: 'utf8', maxBuffer: 64 << 20, stdio: ['ignore', 'pipe', 'inherit'] }); +} catch (e) { out = e.stdout ?? ''; } + +const byFile = new Map(jobs.map(j => [j.file, j])); +const bad = []; +for (const line of out.split('\n').filter(l => l.startsWith('{'))) { + const r = JSON.parse(line); + if (r.ok !== false) continue; + const j = byFile.get(r.file), heard = r.text ?? r.heard ?? ''; + if (j && plain(heard.replace(/\b(\d{1,2})\b/g, (m, n) => NUMERI[+n] ?? m)) === plain(j.expect)) continue; + bad.push({ ...j, heard, score: r.score ?? r.similarity }); +} +for (const b of bad) console.log(`${b.score ?? '?'} ${b.who}: «${b.text}»\n sentito: «${b.heard}»`); +console.log(`${jobs.length} voci ascoltate, ${bad.length} da guardare`); diff --git a/tools/pronuncia.json b/tools/pronuncia.json index d816cc8..8a055d1 100644 --- a/tools/pronuncia.json +++ b/tools/pronuncia.json @@ -1,4 +1,6 @@ { "_nota": "Parole che XTTS legge male in italiano: a sinistra come sono scritte nella storia (e nel fumetto), a destra come vanno lette dalla voce. Si cerca la parola intera, senza badare alle maiuscole. Cambiare una riga rigenera solo le battute che la contengono (make voci). Esempio: «celo» (ce l'ho, delle figurine) XTTS lo legge «cielo».", - "celo": "ce l'ho" + "celo": "ce l'ho", + "Cosimo I": "Cosimo primo", + "padel": "pàdel" }