Giochi di carte dopo la revisione di Codex sui tre insieme; player dei video «Come si gioca» e primo copione
Esito che vale e si salva appena deciso, per tutti i minigiochi (anche tornando al titolo dalla schermata del risultato); briscola: uscire durante il conteggio non perde più la vittoria; tressette: si esce ai 21 col primo evento che ci porta, accusa compresa (prima vinceva sempre Andrea se ci arrivavano tutte e due), il carico che fa vincere si dà anche se è il 2, accuse che non escono dal tavolo, convenzioni scritte nell'aiuto; scopa: primiera valutata per quel che migliora, finale esatto a mazzo finito, presa sulla tavola al rilascio con scelta e conferma, frecce e Invio sempre sulla presa scelta. Tastiera: Invio e Spazio giocano sempre la carta scelta. Tavola descritta a parole. Classi CSS comuni ai tre giochi. Video: player nel gioco (pulsante «Guarda il video» nel «Come si gioca», compare quando il video esiste), video/narra.py per la voce del narratore, pezzi comuni dei copioni e il copione della briscola; scaletta in video/SCALETTA-CARTE.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A1dxvtsZx8NE9fwjXUNDBr
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
"""La voce del narratore dei video «Come si gioca» (video/SCALETTA-CARTE.md), PRIMA di girare.
|
||||
|
||||
python3 video/narra.py video/tutorial-briscola.mjs
|
||||
|
||||
Legge le battute del copione (cues, «it»), le fa dire a XTTS con `mbot parla` (voce del narratore, diversa da
|
||||
quelle dei personaggi), le controlla con `mbot ascolta` e scrive video/out/<clip>-narrazione.json con file e
|
||||
durata di ognuna. Il copione aspetta che la frase sia finita prima di passare alla successiva; monta.py la mette
|
||||
nel video all'inizio della sua battuta. Le frasi già fatte si saltano (per rifarne una: cancellare il file).
|
||||
"""
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
VIDEO = Path(__file__).resolve().parent
|
||||
GIOCO = VIDEO.parent
|
||||
OUT = VIDEO / "out"
|
||||
NARRATORE = "Claribel Dervla"
|
||||
PRONUNCIA = GIOCO / "tools" / "pronuncia.json"
|
||||
|
||||
|
||||
def durata(f: Path) -> float:
|
||||
return float(subprocess.run(["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "csv=p=0", str(f)],
|
||||
capture_output=True, text=True, check=True).stdout)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
copione = Path(sys.argv[1]).resolve()
|
||||
clip = copione.stem
|
||||
cues = json.loads(subprocess.run(["node", "--input-type=module", "-e",
|
||||
f"const m = await import({json.dumps(copione.as_uri())}); console.log(JSON.stringify(m.cues))"],
|
||||
capture_output=True, text=True, check=True, cwd=GIOCO).stdout)
|
||||
cartella = OUT / f"{clip}-narrazione"
|
||||
cartella.mkdir(parents=True, exist_ok=True)
|
||||
# XTTS dice «punto» se la frase finisce col punto: si toglie, come fa narrate.py del tour.
|
||||
lavori = [{"text": c["it"].rstrip(". "), "out": str(cartella / f"{c['id']}.wav"), "lang": "it", "speaker": NARRATORE} for c in cues]
|
||||
(cartella / "lavori.json").write_text(json.dumps(lavori, ensure_ascii=False, indent=1))
|
||||
pron = ["--pronounce", str(PRONUNCIA)] if PRONUNCIA.exists() else []
|
||||
subprocess.run(["mbot", "parla", "--jobs", str(cartella / "lavori.json"), *pron], check=True)
|
||||
ascolto = [{"file": l["out"], "expect": l["text"]} for l in lavori]
|
||||
(cartella / "ascolto.json").write_text(json.dumps(ascolto, ensure_ascii=False, indent=1))
|
||||
subprocess.run(["mbot", "ascolta", "--jobs", str(cartella / "ascolto.json")])
|
||||
voci = [{"id": c["id"], "src": str(Path(l["out"]).relative_to(GIOCO)), "sec": round(durata(Path(l["out"])), 2)} for c, l in zip(cues, lavori)]
|
||||
(OUT / f"{clip}-narrazione.json").write_text(json.dumps({"voci": voci}, ensure_ascii=False, indent=1))
|
||||
print(f"-> {OUT / f'{clip}-narrazione.json'}: {len(voci)} frasi, {sum(v['sec'] for v in voci):.0f} s di voce")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user