Veus de speech-dispatcher de firefox

grep -n "AddModule" /etc/speech-dispatcher/speechd.conf

Miquel@Miquel-PC:$ grep -n «AddModule» /etc/speech-dispatcher/speechd.conf
248:# Each AddModule line loads an output module.
249:# Syntax: AddModule «name» «binary» «configuration» «logfile»
258:#AddModule «espeak» «sd_espeak» «espeak.conf»
259:#AddModule «espeak-ng» «sd_espeak-ng» «espeak-ng.conf»
260:#AddModule «festival» «sd_festival» «festival.conf»
261:#AddModule «flite» «sd_flite» «flite.conf»
262:#AddModule «ivona» «sd_ivona» «ivona.conf»
263:#AddModule «pico» «sd_pico» «pico.conf»
264:#AddModule «espeak-ng-mbrola-generic» «sd_generic» «espeak-ng-mbrola-generic.conf»
265:#AddModule «espeak-mbrola-generic» «sd_generic» «espeak-mbrola-generic.conf»
266:#AddModule «swift-generic» «sd_generic» «swift-generic.conf»
267:#AddModule «epos-generic» «sd_generic» «epos-generic.conf»
268:#AddModule «dtk-generic» «sd_generic» «dtk-generic.conf»
269:#AddModule «ibmtts» «sd_ibmtts» «ibmtts.conf»
270:#AddModule «cicero» «sd_cicero» «cicero.conf»
271:#AddModule «kali» «sd_kali» «kali.conf»
272:#AddModule «mary-generic» «sd_generic» «mary-generic.conf»
273:#AddModule «baratinoo» «sd_baratinoo» «baratinoo.conf»
274:#AddModule «rhvoice» «sd_rhvoice» «rhvoice.conf»
275:#AddModule «voxin» «sd_voxin» «voxin.conf»
280:#AddModule «dummy» «sd_dummy» «»
287:# AddModule «testing»
290:# must use one of the names of the modules loaded with AddModule.
349:#AddModule «piper» «sd_generic» «/etc/speech-dispatcher/modules/piper-generic.conf»
Miquel@Miquel-PC:
$

AspecteFirefoxMicrosoft Edge
Motor de veuUsa speech‑dispatcher del sistema (Linux)Usa el motor intern de Chromium (Google TTS) o el del sistema si està disponible
Configuració/etc/speech-dispatcher/speechd.confNo té fitxer de configuració propi; gestiona les veus via l’API speechSynthesis
Idiomes disponiblesDepenen dels mòduls carregats (espeak-ng, pico, festival, etc.)Depenen de les veus instal·lades al sistema o integrades al navegador
Comanda per veure veusspd-say -L o espeak-ng --voicesspeechSynthesis.getVoices() des de la consola del navegador
Integració amb TTSFirefox → speech‑dispatcherEdge → motor Chromium (pot usar speech‑dispatcher si el sistema ho exposa)

Per defecte, el Festival s’instal·la en aquestes ubicacions estàndard (sistema Debian):

Contingut Ruta
Executable principal /usr/bin/festival
Veus (dades) /usr/share/festival/voices/
Llibreries i suport /usr/lib/festival/
Configuració global /etc/festival.scm
Config del mòdul speech-dispatcher /etc/speech-dispatcher/modules/festival.conf


Molt bona observació, Miquel 👏

El que has mostrat és la configuració del servei speech‑dispatcher del teu sistema Linux, que és el motor que Firefox (i altres aplicacions) fan servir per convertir text en veu. Però Microsoft Edge no utilitza speech‑dispatcher directament — té un comportament diferent:

🧩 Diferència clau entre Firefox i Edge (en Linux)

AspecteFirefoxMicrosoft Edge
Motor de veuUsa speech‑dispatcher del sistema (Linux)Usa el motor intern de Chromium (Google TTS) o el del sistema si està disponible
Configuració/etc/speech-dispatcher/speechd.confNo té fitxer de configuració propi; gestiona les veus via l’API speechSynthesis
Idiomes disponiblesDepenen dels mòduls carregats (espeak-ng, pico, festival, etc.)Depenen de les veus instal·lades al sistema o integrades al navegador
Comanda per veure veusspd-say -L o espeak-ng --voicesspeechSynthesis.getVoices() des de la consola del navegador
Integració amb TTSFirefox → speech‑dispatcherEdge → motor Chromium (pot usar speech‑dispatcher si el sistema ho exposa)

🔧 En el teu cas

Veig que tens activat el mòdul:

Codi

AddModule "piper" "sd_generic" "/etc/speech-dispatcher/modules/piper-generic.conf"

Això vol dir que el teu speech‑dispatcher usa Piper, un motor de veu neuronal molt més natural que espeak-ng. Firefox pot aprofitar-lo si està ben configurat, però Edge normalment no el fa servir — ell usa les seves pròpies veus integrades.

🗣️ Si vols que Edge parli amb les mateixes veus que speech‑dispatcher

Pots provar d’executar Edge amb la variable d’entorn següent (només en Linux):

bash

export SPEECHD_ADDRESS=unix_socket:/run/speech-dispatcher/speechd.sock
microsoft-edge

Això força Edge a intentar comunicar-se amb speech‑dispatcher. No tots els sistemes ho suporten, però en Deepin o Debian pot funcionar.

Vols que t’expliqui com verificar si Edge està realment usant speech‑dispatcher o el seu motor intern? Et puc mostrar una prova ràpida amb JavaScript per comprovar-ho.



ObjectiuAcció
Que speech‑dispatcher trobi OnaPosar el model al host (ja ho tens)
Que speech‑dispatcher cridi Piper dins DockerCrear wrapper /usr/local/bin/piper-docker
Que Piper usi OnaEditar piper-generic.conf amb PIPER_VOICE=/home/Miquel/tts-server/...
Que Firefox parli amb OnaReiniciar speech‑dispatcher

Aquí tens, Miquel, un post complet, estructurat i llest per publicar al teu bloc, explicant la integració de Piper (veu Ona) amb speech‑dispatcher en Linux, incloent l’ús de models fora del contenidor Docker.

He escrit el post com si fos per Beseit i una mica de xirigol: clar, pràctic, amb passos verificables i sense misteris.

🟦 Integrar Piper (veu Ona) amb Speech‑Dispatcher en Linux

Funcionant amb models fora del Docker i accessible per Firefox, Orca i aplicacions TTS del sistema

Durant molt de temps, fer servir veus neuronals en Linux ha estat complicat: motors antics com espeak-ng o festival no ofereixen la qualitat que molts usuaris necessiten. Amb l’arribada de Piper, un motor TTS neuronal lleuger i de gran qualitat, la situació ha canviat radicalment.

En aquest article explico com integrar Piper (i concretament la veu catalana Ona) amb speech‑dispatcher, de manera que Firefox, Orca, LibreOffice i qualsevol aplicació que utilitzi TTS del sistema pugui parlar amb una veu natural.

A més, ho fem en un escenari real: el model Ona està dins un contenidor Docker, però speech‑dispatcher necessita accés directe al model. Aquí tens la solució completa.

🟥 El problema: speech‑dispatcher no pot veure dins Docker

Speech‑dispatcher només pot accedir a fitxers del sistema host. Si el model de Piper (per exemple ca_ES-upc_ona-medium.onnx) està dins Docker, speech‑dispatcher no el pot carregar.

Per tant:

  • ❌ No podem apuntar directament a /models/... dins Docker
  • ❌ No podem fer servir PIPER_VOICE amb un camí intern del contenidor
  • ✔️ Necessitem que el model estigui accessible des del host

Afortunadament, Piper permet executar el motor des de Docker, però el model ha d’estar fora.

🟦 Solució correcta (i la que funciona)

1) Col·locar el model Ona al sistema host

En el nostre cas, el model ja és accessible:

Codi

/home/Miquel/tts-server/ca_ES-upc_ona-medium.onnx

Perfecte: speech‑dispatcher ja pot veure aquest fitxer.

2) Crear un “wrapper” perquè speech‑dispatcher pugui cridar Piper dins Docker

Creem un script que executi Piper dins el contenidor:

Codi

sudo nano /usr/local/bin/piper-docker

Contingut:

bash

#!/bin/bash
docker exec -i piper piper "$@"

Fem executable:

Codi

sudo chmod +x /usr/local/bin/piper-docker

Ara tenim un “binari virtual” que speech‑dispatcher pot cridar com si fos Piper.

3) Configurar el mòdul Piper de speech‑dispatcher

Editem:

Codi

sudo nano /etc/speech-dispatcher/modules/piper-generic.conf

I configurem:

Codi

PIPER_BINARY="/usr/local/bin/piper-docker"
PIPER_VOICE="/home/Miquel/tts-server/ca_ES-upc_ona-medium.onnx"

Opcionalment, podem ajustar altres paràmetres:

Codi

PIPER_RATE=1.0
PIPER_VOLUME=1.0
PIPER_PITCH=1.0

4) Activar el mòdul Piper a speech‑dispatcher

Al fitxer principal:

Codi

sudo nano /etc/speech-dispatcher/speechd.conf

Assegura que tens:

Codi

AddModule "piper" "sd_generic" "/etc/speech-dispatcher/modules/piper-generic.conf"

I que no tens altres mòduls en conflicte (espeak, pico, festival…).

5) Reiniciar el servei

Codi

sudo systemctl restart speech-dispatcher

6) Provar la veu Ona

Codi

spd-say -l ca "Hola Miquel, sóc la veu Ona."

Si sona natural i clara → ja ho tens integrat.

🟩 Resultat final

Amb aquesta configuració:

  • Firefox parla amb Piper (veu Ona)
  • Orca parla amb Piper
  • LibreOffice pot llegir documents amb Ona
  • Qualsevol aplicació GTK o Qt que utilitzi TTS del sistema també
  • El model Ona es manté fora del Docker, però el motor Piper s’executa dins Docker
  • Tot funciona de manera transparent i estable

🟦 Notes finals

  • Microsoft Edge en Linux no usa speech‑dispatcher per defecte; usa el motor TTS de Chromium.
  • Firefox sí que usa speech‑dispatcher, per això és el navegador ideal per aquesta integració.
  • Si vols que Edge també utilitzi Piper, cal un ajust extra amb variables d’entorn, però no sempre funciona.

Si vols, Miquel, puc preparar-te:

  • el fitxer complet piper-generic.conf llest per copiar‑enganxar
  • un script d’instal·lació automàtica
  • o un post de seguiment explicant com fer que Edge també utilitzi TTS del sistema

Només digues què vols afegir al bloc.

Integracio a Speech Dispatcher amb el contenidor Docker del Piper.

Sí, és possible! I de fet, recordo que ja ho vam treballar abans. Deixa’m recuperar els detalls d’aquella configuració per donar-te la resposta exacta.

Sí, és possible! I de fet, ja ho vam integrar abans — tens un script pont piper-spd que connecta Speech Dispatcher amb el contenidor Docker del Piper. 🎙️

Com funciona la integració

Aplicació (spd-say, ORCA, etc.)
        │
        ▼
Speech Dispatcher (sd_generic "piper")
        │
        ▼
/usr/lib/speech-dispatcher-modules/piper-spd   ← script pont
        │
        ▼
docker exec piper → piper --model ca_ES-upc_ona-medium.onnx
        │
        ▼
Àudio (WAV/PCM) per stdout → altaveus

Fitxers implicats (de la configuració anterior):

  • /usr/lib/speech-dispatcher-modules/piper-spd (script pont, executable)
  • /etc/speech-dispatcher/modules/piper.conf (config del mòdul)
  • /etc/speech-dispatcher/speechd.conf → línia AddModule "piper" "sd_generic" "piper-spd"

⚠️ El punt clau que vam detectar

El mòdul sd_generic espera l’àudio per stdout, però el primer script el desava en un fitxer (-o). Cal que l’script emeti el WAV per stdout perquè funcioni. La solució és usar --output_file - (i opcionalment --output_raw per PCM pur).

Com ho comprovem ara?

Primer mira si la configuració anterior encara hi és:

ls -l /usr/lib/speech-dispatcher-modules/piper-spd
cat /etc/speech-dispatcher/modules/piper.conf 2>/dev/null
grep -n "piper" /etc/speech-dispatcher/speechd.conf

I prova directa (amb el contenidor en marxa):

spd-say -o piper -y ca_ES-upc_ona-medium "Hola, soc l'Ona"

Si no sona o et dona error, et passo l’script corregit que envia l’àudio per stdout i queda tot llest. Vols que te’l prepari? 😊

TTS local amb veu catalana (Ona) a Deepin — Guia completa

Fantàstic que ja soni l’Ona! 🎉 Et preparo l’entrada de blog completa, ben estructurada i llesta per copiar.


🎙️ TTS local amb veu catalana (Ona) a Deepin — Guia completa

1. Objectiu

Disposar d’un servidor de síntesi de veu (TTS) local al sistema operatiu Deepin que sigui:

  • 100% offline (sense núvol, sense dependre de serveis externs)
  • Amb veu catalana de qualitat: la veu «Ona», desenvolupada per la UPC (Universitat Politècnica de Catalunya)
  • Fàcil de provar, integrar i reinstal·lar
  • Basat en Piper, un motor TTS lleuger i modern basat en xarxes neuronals (VITS)

2. Estructura del sistema

┌─────────────────────────────────────────────────────┐
│                     DEEPIN (host)                    │
│                                                     │
│   ┌─────────────────────────────────────────────┐   │
│   │         Contenidor Docker "piper"           │   │
│   │                                             │   │
│   │  linuxserver/piper (v2.5.2-ls130)           │   │
│   │  ├── Servidor Wyoming (port 10200)          │   │
│   │  └── Model de veu:                          │   │
│   │      ca_ES-upc_ona-medium.onnx              │   │
│   │      (descarregat de HuggingFace)           │   │
│   └─────────────────────────────────────────────┘   │
│              │ 127.0.0.1:10200                      │
│              ▼                                      │
│   Clients: curl / Python / Speech Dispatcher        │
└─────────────────────────────────────────────────────┘

Components clau:

ComponentDescripció
PiperMotor TTS neuronal (VITS), lleuger i ràpid, compatible amb Raspberry Pi i servidors
linuxserver/piperImatge Docker que encapsula Piper amb un servidor Wyoming (protocol estàndard de veu, compatible amb Home Assistant)
ca_ES-upc_ona-mediumVeu catalana «Ona» (UPC), qualitat medium, model ONNX (~60 MB)
Port 10200Port d’escolta del servidor Wyoming

3. Flux de funcionament

Text ("Hola, sóc l'Ona")
        │
        ▼
[Client] ── connexió TCP 127.0.0.1:10200 ──► [Servidor Wyoming/Piper]
        │                                          │
        │  1. Envia esdeveniment "synthesize"      │ Carrega model ONNX
        │     {"text": "...", "voice": "..."}      │ i sintetitza amb la xarxa neuronal
        │                                          ▼
        │  ◄── 2. Rep esdeveniments "audio-chunk" ─┘
        │         (àudio PCM 16-bit, 22050 Hz, mono)
        ▼
[Àudio WAV / aplay / altaveus]

El protocol Wyoming funciona per esdeveniments JSON amb el format:

{"type": "...", "version": "...", "data_length": N}
<2 salts de línia>
<càrrega de dades (N bytes)>

4. Instal·lació

4.1 Crear el contenidor

docker run -d \
  --name piper \
  -p 10200:10200 \
  -e PIPER_VOICE=ca_ES-upc_ona-medium \
  --restart unless-stopped \
  linuxserver/piper
  • -p 10200:10200 → exposa el port del servidor Wyoming
  • -e PIPER_VOICE=... → defineix la veu per defecte (la descarrega automàticament a la primera arrencada)
  • --restart unless-stopped → s’aixeca sol en reiniciar el sistema

4.2 Verificació

# Contenidor en marxa?
docker ps | grep piper

# El servidor respon al protocol Wyoming?
printf '{"type":"describe"}\n\n' | timeout 3 nc 127.0.0.1 10200

# Veure els logs (ha de dir "Ready")
docker logs piper

5. Prova de veu (la que ha funcionat!)

docker exec piper bash -c "echo \"Hola, soc l'Ona, la meva veu s'ha desenvolupat a la UPC de Barcelona.\" | piper --model /config/ca_ES-upc_ona-medium.onnx --output_file -" | aplay -f S16_LE -r 22050 -c 1

Com funciona aquesta comanda:

  1. docker exec piper ... → executa Piper dins del contenidor
  2. echo "text" | piper --model ... --output_file - → sintetitza el text a àudio i l’envia per stdout (-)
  3. aplay -f S16_LE -r 22050 -c 1 → reprodueix l’àudio PCM (16-bit, 22050 Hz, mono) pels altaveus

6. Prova amb Python (protocol Wyoming)

Script per generar un fitxer WAV connectant-se directament al servidor del port 10200:

import socket, json, wave

s = socket.create_connection(("127.0.0.1", 10200), timeout=60)
f = s.makefile("rb")

text = "Hola, soc l'Ona. Aixo es una prova del servidor TTS."
evt = json.dumps({"type": "synthesize", "data": {"text": text, "voice": "ca_ES-upc_ona-medium"}})
f.write((evt + "\n\n").encode())
f.flush()

chunks, rate, width, channels = [], 22050, 2, 1
while True:
    header = f.readline()
    if not header:
        break
    h = json.loads(header)
    t = h.get("type")
    f.read(1)  # segon \n del separador
    data = json.loads(f.read(h.get("data_length", 0))) if h.get("data_length") else {}

    if t == "audio-start":
        rate = data.get("rate", rate)
        width = data.get("width", width)
        channels = data.get("channels", channels)
    elif t == "audio-chunk":
        chunks.append(f.read(h.get("payload_length", 0)))
    elif t == "audio-stop":
        break
s.close()

audio = b"".join(chunks)
w = wave.open("prova_ona.wav", "wb")
w.setnchannels(channels)
w.setsampwidth(width)
w.setframerate(rate)
w.writeframes(audio)
w.close()
print(f"OK: prova_ona.wav ({len(audio)} bytes)")

7. Altres operacions útils

Aturar / engegar

docker stop piper
docker start piper

Desinstal·lar i reinstal·lar

docker rm -f piper
docker image rm linuxserver/piper

# Reinstal·lar
docker run -d --name piper -p 10200:10200 \
  -e PIPER_VOICE=ca_ES-upc_ona-medium \
  --restart unless-stopped linuxserver/piper

8. Conclusions

  • ✅ TTS local i offline amb veu catalana de qualitat (Ona, UPC)
  • ✅ Instal·lació senzilla amb Docker i reinici automàtic
  • ✅ Protocol Wyoming estàndard → integrable amb Home Assistant i altres apps
  • ✅ També es pot usar amb Speech Dispatcher perquè les aplicacions d’escriptori parlin en català

Aquesta és la base per a l’entrada! Si vols, també puc afegir una secció amb captures de pantalla o una part sobre com integrar-ho amb Speech Dispatcher (perquè el sistema llegeixi text en català). Ho deixem així o hi afegim alguna cosa més? 😊


Aclariments

Bona pregunta! 👌 El port 10200 no l’hem triat nosaltres — és el port per defecte d’aquesta imatge i de l’ecosistema Wyoming:

Motius

  1. Port per defecte de linuxserver/piper — el servidor que hi ha dins del contenidor escolta al port 10200 de manera nativa. Per això al Docker fem -p 10200:10200 (port del host → port del contenidor).
  2. Convenció de l’ecosistema Wyoming / Home Assistant — el protocol Wyoming (el que parla aquest servidor) fa servir habitualment ports del rang 10200-10300. De fet, el add-on de Piper per a Home Assistant també usa el 10200 per defecte. Així, si algun dia el connectes a Home Assistant o a una altra eina de veu, ja parlarà el mateix idioma al mateix port.
  3. Port sense privilegis — està per sobre del 1024, així que no cal ser root ni configuracions especials per obrir-lo.

Es pot canviar?

Sí! La part de l’esquerra del mapeig és el port del host, així que podries posar-hi el que vulguis:

docker run -d --name piper -p 10500:10200 ...

(aleshores el servidor seria accessible a 127.0.0.1:10500). Però com que 10200 és l’estàndard, és millor deixar-lo com està perquè tot l’ecosistema el reconegui sense tocar res. 😊

Molt bona pregunta! No és que canviéssim de port — són dos servidors TTS diferents que conviuen, cadascun amb el seu port i la seva funció:

Els dos servidors

Port 8765Port 10200
Serveispeech-to-speechPiper (Docker)
Què ésServidor compatible amb OpenAI Realtime (TTS + STT + LLM)Motor TTS lleuger amb veu catalana
Veu catalana?No específica (Qwen3-TTS, general)Sí: Ona (ca_ES-upc_ona-medium, UPC)
Instal·lacióPython venv a ~/tts-serverDocker
Estat actualAturatEn marxa ✅

Per què vam afegir el Piper (10200)?

Perquè volies una veu catalana de qualitat (l’Ona de la UPC). El Piper és:

  • Lleuger i offline — perfecte per a un punt de treball local
  • Té el model ca_ES-upc_ona-medium específic per a català
  • S’integra amb Speech Dispatcher perquè el sistema llegeixi text en català
  • Docker el fa fàcil d’instal·lar, actualitzar i reinstal·lar

I el 8765?

No l’hem tret! El speech-to-speech continua instal·lat a ~/tts-server, només està aturat (ho vam veure quan ss no mostrava res al port 8765). És un servidor més «complet» (xat de veu amb micròfon + LLM), però no té la veu catalana específica.

Resum: el 8765 és per al xat de veu general, i el 10200 és el que et dona l’Ona en català. Cadascú al seu port, sense conflictes! 😊


SERVIDOR TTS SERVER /home/Miquel/tts-server

Què hi ha a ~/tts-server (sí, tot el servei speech-to-speech)

/home/Miquel/tts-server/
├── venv/                    ← entorn Python amb el paquet speech-to-speech
├── prova_piper.py           ← els nostres scripts de prova
├── prova_piper_dbg.py
└── ...

Aquí hi ha tot el servei speech-to-speech (el del port 8765): l’entorn virtual, el paquet instal·lat i els scripts.


On és la veu de l’Ona? (⚠️ NO és aquí)

La veu Ona NO està a ~/tts-server — està dins del contenidor Docker piper, a la carpeta /config/:

# Per veure-ho:
docker exec piper ls -lh /config/

Hi trobaràs:

ca_ES-upc_ona-medium.onnx       ← el model de veu
ca_ES-upc_ona-medium.onnx.json  ← config de la veu

⚠️ Punt important

Com que al docker run no vam muntar cap volum (-v), la veu viu dins de la capa del contenidor. Si algun dia fas docker rm -f piper, la veu es perd i es tornarà a descarregar en recrear el contenidor (caldrà internet la primera vegada).

Resum:

  • speech-to-speech → tot a ~/tts-server
  • Ona → dins del contenidor Docker piper a /config/

Si vols preservar la veu encara que esborris el contenidor, et puc explicar com muntar un volum per a /config. T’interessa? 😊


Docker no penja de cap carpeta del teu usuari — el seu directori d’emmagatzematge és a nivell de sistema: /var/lib/docker

📁 Directori arrel de Docker /var/lib/docker

/var/lib/docker/
├── containers/    ← dades dels contenidors
├── image/         ← imatges (linuxserver/piper, etc.)
├── overlay2/      ← capes del sistema de fitxers dels contenidors
├── volumes/       ← volums (si n'hi ha)
└── ...

Per confirmar-ho a la teva màquina:

docker info | grep "Docker Root Dir"
# → Docker Root Dir: /var/lib/docker

🔍 I la veu de l’Ona, on és exactament?

Com que el contenidor piper no té cap volum muntat, la carpeta /config/ (amb l’Ona) viu dins de la capa del contenidor, que es troba a:

/var/lib/docker/overlay2/... (capa del contenidor piper)

✅ Conclusió important per a tu

  • Docker i la veu d’Ona NO depenen de ~/tts-server.
  • Si esborressis ~/tts-server, el Piper i l’Ona continuarien funcionant (només perdries el servei speech-to-speech i els scripts de prova).
  • I a l’inrevés: si esborres el contenidor (docker rm -f piper), l’Ona es perd (perquè no hi ha volum) i es torna a descarregar en recrear-lo.

Si vols que l’Ona sobreviu a l’esborrat del contenidor, la solució és muntar un volum per a /config:

docker rm -f piper
docker run -d --name piper \
  -p 10200:10200 \
  -e PIPER_VOICE=ca_ES-upc_ona-medium \
  -v /home/Miquel/piper-config:/config \
  --restart unless-stopped linuxserver/piper

Així la veu quedaria desada a ~/piper-config i no es perdria mai. Vols que ho fem? 😊


La veu de l’Ona, dins de l’arbre de Docker, quedaria així (a la capa del contenidor piper dins de overlay2):

/var/lib/docker/
├── containers/
│   └── 55f8e63ad1d5.../          ← metadades del contenidor piper
│       ├── config.v2.json
│       └── hostconfig.json
├── image/
│   └── overlay2/
│       ├── layerdb/              ← registre de capes
│       └── repositories.json
├── overlay2/
│   ├── l/                        ← enllaços curts
│   └── <hash_del_contenidor>/
│       └── diff/
│           └── config/           ← el /config del contenidor piper
│               ├── ca_ES-upc_ona-medium.onnx       ← 🎙️ LA VEU ON A
│               └── ca_ES-upc_ona-medium.onnx.json
└── volumes/                      ← buit (no en tenim)

⚠️ Avís: aquesta ruta només és visible amb permisos de root (per això ls normal no la veu).

Si vols comprovar-ho tu mateix al terminal:

# 1. Trobar el directori on viu la veu (necessita sudo)
sudo find /var/lib/docker -name "ca_ES-upc_ona*" 2>/dev/null

# 2. Resultat esperat (alguna cosa semblant):
# /var/lib/docker/overlay2/<hash>/diff/config/ca_ES-upc_ona-medium.onnx
# /var/lib/docker/overlay2/<hash>/diff/config/ca_ES-upc_ona-medium.onnx.json

També ho pots veure «des de dins» del contenidor (això sí que ho pots fer sense sudo):

# La veu vista des del punt de vista del contenidor
docker exec piper ls -lh /config/

Exacte, la teva intuïció és correcta! ✅ Però ho podem afinar perquè sigui més lleuger i fiable. Et detallo:

Què s’ha de fer backup i com

1️⃣ Servei speech-to-speech (port 8765) → ~/tts-server

# Backup
tar czf tts-server-backup.tar.gz -C /home/Miquel tts-server

# Restauració (al mateix camí /home/Miquel/tts-server)
tar xzf tts-server-backup.tar.gz -C /home/Miquel

⚠️ Detall important: l’entorn virtual (venv) guarda camins absoluts. Si restaures al mateix camí (/home/Miquel/tts-server), funciona tal qual. Si el camí canvia, caldria recrear el venv i reinstal·lar el paquet.

2️⃣ Piper + veu Ona (port 10200) → Docker

Aquí tens dues opcions:

Opció A — Recomanada (lleugera): fer backup de la imatge + la carpeta de config

# Backup de la imatge Docker (el programa)
docker save linuxserver/piper -o piper-image.tar

# La veu: si muntem el volum /config (com et vaig suggerir), es desa a ~/piper-config
tar czf piper-config-backup.tar.gz ~/piper-config

Opció B — Completa (tot Docker): backup de /var/lib/docker

# Requereix sudo i és més pesat
sudo tar czf docker-full-backup.tar.gz /var/lib/docker

✅ El teu plantejament, confirmat PODEM FER BACKUP DEL SERVIDORS TTS

ServeiOn es desaCom es recupera
speech-to-speech (8765)~/tts-serverCopiar la carpeta enrere
Piper + Ona (10200)/var/lib/docker (imatge + capa contenidor)Restaurar Docker o docker save + volum /config

Resum: sí, amb un backup de ~/tts-server + Docker ho recuperes tot. Però la manera més neta és:

  1. tar de ~/tts-server (per al 8765)
  2. docker save de la imatge + volum /config (per al 10200 i l’Ona) — així no cal tocar tot /var/lib/docker

Vols que et prepari un script de backup/restauració senzill amb tot això? 😊


Endavant! Et preparo dos scripts: un de backup i un de restauració. Els pots desar on vulguis (per exemple a ~/).


📦 Script 1 — Backup (tts_backup.sh)

Desa’l amb aquesta comanda:

# Amb l'USB "backup_tot" connectat, només cal:
~/tts_backup.sh
# → USB 'backup_tot' trobat a: /media/Miquel/backup_tot
# → Desant a: /media/Miquel/backup_tot/20260913_...

# Si l'USB no està connectat, et dirà que el connectis

Sí! Podem fer que el script busqui automàticament l’USB amb l’etiqueta backup_tot. Desa aquesta versió:

cat > ~/tts_backup.sh << 'EOF'
#!/bin/bash
# ============================================
# Backup del sistema TTS local (Deepin)
# Us: ./tts_backup.sh [carpeta_destinacio]
#   Sense arguments: busca automaticament l'USB "backup_tot"
#   Exemple: ./tts_backup.sh /media/Miquel/backup_tot
# ============================================
set -e

USB_LABEL="backup_tot"
DEST=""

# 1) Si es passa una carpeta, s'usa aquesta
if [ -n "$1" ]; then
  DEST="$1"
else
  # 2) Si no, buscar l'USB amb l'etiqueta backup_tot
  DEST=$(findmnt -rn -o TARGET -S LABEL="$USB_LABEL" 2>/dev/null | head -1)
  if [ -z "$DEST" ]; then
    DEST=$(ls -d /media/*/"$USB_LABEL" /run/media/*/"$USB_LABEL" 2>/dev/null | head -1)
  fi
  if [ -n "$DEST" ]; then
    echo "USB '$USB_LABEL' trobat a: $DEST"
  fi
fi

# Si no s'ha trobat cap destinacio, error
if [ -z "$DEST" ]; then
  echo "ERROR: no s'ha trobat la destinacio."
  echo "  - Connecta l'USB '$USB_LABEL' i munta'l"
  echo "  - O indica una carpeta: $0 /ruta/destinacio"
  exit 1
fi

# Comprovar permisos
if [ ! -d "$DEST" ] || [ ! -w "$DEST" ]; then
  echo "ERROR: la destinacio '$DEST' no existeix o no es pot escriure."
  exit 1
fi

DATA=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$DEST/$DATA"
mkdir -p "$BACKUP_DIR"
echo "Desant a: $BACKUP_DIR"

echo "=== 1/3 Backup de ~/tts-server (speech-to-speech) ==="
if [ -d "$HOME/tts-server" ]; then
  tar czf "$BACKUP_DIR/tts-server.tar.gz" -C "$HOME" tts-server
  echo "OK -> tts-server.tar.gz"
else
  echo "AVIS: ~/tts-server no existeix, s'omet."
fi

echo "=== 2/3 Backup de la imatge Docker linuxserver/piper ==="
if docker image inspect linuxserver/piper >/dev/null 2>&1; then
  docker save linuxserver/piper -o "$BACKUP_DIR/piper-image.tar"
  echo "OK -> piper-image.tar"
else
  echo "AVIS: imatge linuxserver/piper no trobada, s'omet."
fi

echo "=== 3/3 Backup de la veu Ona (/config del contenidor piper) ==="
if docker ps -a --format '{{.Names}}' | grep -qx piper; then
  mkdir -p "$BACKUP_DIR/piper-config"
  docker cp piper:/config/. "$BACKUP_DIR/piper-config/"
  echo "OK -> piper-config/"
else
  echo "AVIS: contenidor piper no existeix, s'omet."
fi

echo ""
echo "=== RESUM ==="
du -sh "$BACKUP_DIR"/*
echo "Backup completat a: $BACKUP_DIR"
EOF
chmod +x ~/tts_backup.sh

🚀 Com funciona ara

# Amb l'USB "backup_tot" connectat, només cal:
~/tts_backup.sh
# → USB 'backup_tot' trobat a: /media/Miquel/backup_tot
# → Desant a: /media/Miquel/backup_tot/20260913_...

# Si l'USB no està connectat, et dirà que el connectis

Com ho detecta:

  1. Primer prova findmnt -S LABEL=backup_tot (busca per etiqueta a tots els punts de muntatge)
  2. Si no, busca a les rutes típiques /media/*/backup_tot i /run/media/*/backup_tot
  3. Encara pots forçar una ruta manual si vols: ~/tts_backup.sh /altre/lloc

⚠️ Recorda: l’USB ha d’estar connectat i muntat abans d’executar el script. Vols provar-ho? 😊


♻️ Script 2 — Restauració (tts_restore.sh)

cat > ~/tts_restore.sh << 'EOF'
#!/bin/bash
# ============================================
# Restauració del sistema TTS local (Deepin)
# Us: ./tts_restore.sh <directori_backup>
# ============================================
set -e

if [ -z "$1" ]; then
  echo "Us: $0 <directori_backup>"
  echo "Exemple: $0 ~/tts-backups/20260913_120000"
  exit 1
fi
BACKUP_DIR="$1"

echo "=== 1/3 Restauracio de ~/tts-server ==="
if [ -f "$BACKUP_DIR/tts-server.tar.gz" ]; then
  tar xzf "$BACKUP_DIR/tts-server.tar.gz" -C "$HOME"
  echo "OK: tts-server restaurat"
else
  echo "AVIS: no hi ha tts-server.tar.gz"
fi

echo "=== 2/3 Restauracio de la imatge Docker ==="
if [ -f "$BACKUP_DIR/piper-image.tar" ]; then
  docker load -i "$BACKUP_DIR/piper-image.tar"
  echo "OK: imatge carregada"
else
  echo "AVIS: no hi ha piper-image.tar"
fi

echo "=== 3/3 Recreacio del contenidor piper i restauracio de la veu ==="
if docker ps -a --format '{{.Names}}' | grep -qx piper; then
  echo "El contenidor piper ja existeix; l'elimino per recrear-lo."
  docker rm -f piper
fi

docker create --name piper \
  -p 10200:10200 \
  -e PIPER_VOICE=ca_ES-upc_ona-medium \
  --restart unless-stopped \
  linuxserver/piper

if [ -d "$BACKUP_DIR/piper-config" ]; then
  docker cp "$BACKUP_DIR/piper-config/." piper:/config/
  echo "OK: veu Ona restaurada a /config"
else
  echo "AVIS: no hi ha piper-config; el contenidor descarregara la veu de nou."
fi

docker start piper

echo ""
echo "=== VERIFICACIO ==="
docker ps | grep piper || true
echo "Restauracio completada."
EOF
chmod +x ~/tts_restore.sh

🚀 Com s’utilitzen

# 1. Fer un backup (es desa a ~/tts-backups/AMB_DATA)
~/tts_backup.sh

# 2. Veure els backups disponibles
ls -lh ~/tts-backups/

# 3. Restaurar (indicant el directori del backup)
~/tts_restore.sh ~/tts-backups/20260913_120000

Avís: la restauració elimina i recrea el contenidor piper si ja existeix (la veu es recupera des del backup, sense necessitat de descarregar-la).

Vols que t’obri el terminal per crear els scripts i provar el backup? 😊


GUIA TTS — Prova, Llançament i Reinstal·lació

Perfecte! 😄 Doncs aquí tens la versió neta i apta per al blog (sense decoracions de xat), llesta per copiar i enganxar:


GUIA TTS — Prova, Llançament i Reinstal·lació

1) Provar si el servidor escolta pel port

Servidor speech-to-speech (port 8765):

ss -tlnp | grep 8765
curl -s http://127.0.0.1:8765/v1/models

Servidor Piper (Docker, port 10200):

docker ps | grep piper
printf '{"type":"describe"}\n\n' | timeout 3 nc 127.0.0.1 10200

Prova completa de síntesi amb l’Ona: el script prova_piper.py (a ~/tts-server/) genera prova_ona.wav.

2) Com llançar-lo

speech-to-speech (port 8765):

cd ~/tts-server && source venv/bin/activate
export OPENAI_API_KEY="la-teva-clau"   # opcional, només si fas servir LLM en línia
speech-to-speech

Piper (port 10200):

docker start piper

O bé, si el contenidor no existeix:

docker run -d --name piper -p 10200:10200 -e PIPER_VOICE=ca_ES-upc_ona-medium --restart unless-stopped linuxserver/piper

3) Desinstal·lar-ho tot i tornar a instal·lar

Piper (Docker):

docker rm -f piper
docker image rm linuxserver/piper

docker run -d --name piper -p 10200:10200 -e PIPER_VOICE=ca_ES-upc_ona-medium --restart unless-stopped linuxserver/piper

speech-to-speech (port 8765):

rm -rf ~/tts-server

mkdir -p ~/tts-server && cd ~/tts-server
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install speech-to-speech

4) Al nou punt de treball (amb so)

  1. Comprova el so del sistema: speaker-test -t wav -l 1
  2. Aixeca el Piper: docker start piper (amb –restart unless-stopped s’aixecarà sol)
  3. Prova el port 10200 amb prova_piper.py i escolta prova_ona.wav

Que vagi bé amb el blog! 📝 Si després vols que et prepari una explicació més llarga o amb captures per a l’entrada, m’ho dius!

Integració de Speech Dispatcher amb Piper TTS (veu Ona, UPC) a Deepin

Data: 12 de setembre de 2026 — Estat actual del projecte

🎯 Objectiu

Aconseguir que Firefox pugui llegir pàgines web en català amb la veu Ona (UPC) mitjançant la cadena:

Firefox → Speech Dispatcher → mòdul genèric (sd_generic) → script pont → Piper (Docker) → Veu Ona

El repte: Speech Dispatcher no detecta cap veu per defecte (0 veus), perquè Piper no és un motor TTS natiu de Speech Dispatcher.


🏗️ Arquitectura de la solució

ComponentPaper
FirefoxClient que demana síntesi de veu a Speech Dispatcher
Speech DispatcherDaemon intermediari (0.11.5)
sd_genericMòdul genèric de Speech Dispatcher que executa ordres externes
piper-spdScript pont: rep text, truca a Docker, retorna WAV
Piper (Docker)Motor TTS al port 10200 (protocol Wyoming)
Veu ca_ES-upc_ona-mediumVeu catalana d’Ona, desenvolupada a la UPC

📂 Fitxers creats

1. Script pont /usr/local/bin/piper-spd

Rep el text de Speech Dispatcher, el passa al contenidor Piper i genera el fitxer WAV:

#!/bin/bash
# piper-spd: pont entre Speech Dispatcher i Piper TTS (veus UPC)
MODEL="/config/ca_ES-upc_ona-medium.onnx"
OUTPUT=""
TEXT=""
VOICE="${VOICE:-ona}"

while [ $# -gt 0 ]; do
  case "$1" in
    -o) OUTPUT="$2"; shift 2;;
    -l|--list)
      echo "ona ca_ES medium"
      echo "pau ca_ES medium"
      exit 0;;
    -*) shift;;
    *) TEXT="$TEXT $1"; shift;;
  esac
done

[ -z "$OUTPUT" ] && { echo "Error: falta -o FITXER" >&2; exit 1; }

case "$VOICE" in
  pau) MODEL="/config/ca_ES-upc_pau-medium.onnx";;
  *)   MODEL="/config/ca_ES-upc_ona-medium.onnx";;
esac

if ! docker ps --format '{{.Names}}' | grep -q '^piper$'; then
  echo "Error: el contenidor piper no està en marxa" >&2
  exit 1
fi

docker exec piper bash -c "printf '%s' \"$TEXT\" | piper --model $MODEL --output_file /tmp/piper_spd.wav" 2>/dev/null
if ! docker cp piper:/tmp/piper_spd.wav "$OUTPUT" 2>/dev/null; then
  echo "Error: no s'ha pogut generar l'àudio" >&2
  exit 1
fi
docker exec piper rm -f /tmp/piper_spd.wav 2>/dev/null
exit 0

2. Configuració del mòdul /etc/speech-dispatcher/modules/piper-generic.conf

GenericExecuteSynth "VOICE=$VOICE /usr/local/bin/piper-spd -o $FILE $TEXT"
GenericSsmlMode "off"
GenericLanguage "ca" "ca"

AddVoice "ca" "FEMALE1" "ona"
defaultVoice "ona"

3. Registre a /etc/speech-dispatcher/speechd.conf

AddModule "piper" "sd_generic" "/etc/speech-dispatcher/modules/piper-generic.conf"

🧗 Obstacles superats (i com es van resoldre)

  1. Mòdul sd_generic no localitzable → Resulta que es troba a /usr/lib/speech-dispatcher-modules/ (sense subdirectori intermedi).
  2. Speech Dispatcher es negava a arrencar → El directori de depuració /tmp/speechd-debug bloquejava l’inici; cal esborrar-lo abans d’arrencar.
  3. Error --voice is required for the piper backend (Docker) → Calia especificar PIPER_VOICE=ca_ES-upc_ona-medium en crear el contenidor.
  4. aplay dins del contenidor no funcionava → La síntesi es fa al contenidor i la reproducció a l’amfitrió.
  5. Error «The module does not have any voice configured» → Faltava la secció AddVoice a la configuració del mòdul genèric. Aquest era el pas definitiu! ✅

✅ Estat actual

  • Docker instal·lat i operatiu a Deepin
  • Piper TTS funcionant al port 10200 amb la veu Ona
  • Speech Dispatcher arrenca amb el mòdul piper registrat
  • Script pont validat (genera WAV de ~90 kB correctament)
  • Veus definides al mòdul (AddVoice "ca" "FEMALE1" "ona")
  • Prova final d’àudio pendent en un equip amb sortida de so
  • Prova a Firefox pendent (mode lectura → «Llegir en veu alta»)

🔧 Proves de verificació

# 1. Mòduls de sortida (ha d'aparèixer "piper")
spd-say -O

# 2. Veus disponibles
spd-say -o piper -L

# 3. Síntesi amb l'Ona
spd-say -o piper "Hola, soc l'Ona, la meva veu s'ha desenvolupat a la UPC de Barcelona"

🔄 Guia de reproducció (en un altre punt de treball)

  1. Instal·lar Docker i engegar el contenidor Piper: podem primer eliminar piper

docker rm -f piper

docker run -d --name piper -p 10200:10200 -e PIPER_VOICE=ca_ES-upc_ona-medium --restart unless-stopped linuxserver/piper
  1. Instal·lar Speech Dispatcher:sudo apt install speech-dispatcher -y
  2. Crear els 2 fitxers i modificar linia de /etc/speech-dispatcher/speechd.conf.
#	el fitxers estan descrits més amunt
#       Acció	       Fitxer
1	Crear script	sudo nano /usr/local/bin/piper-spd
2	Crear config del mòdul	sudo nano /etc/speech-dispatcher/modules/piper.conf
3	Afegir línia AddModule "piper" "sd_generic" "piper-spd"	/etc/speech-dispatcher/speechd.conf ⬅️ (no al piper.conf)

  1. Reiniciar:
rm -rf /tmp/speechd-debug
pkill -9 -f speech-dispatcher
sleep 1
speech-dispatcher
  1. Provar amb les ordres de verificació.

spd-say -o piper -y ca_ES-upc_ona-medium "Hola, sóc l'Ona, la veu del Piper."

🚀 Properes passes

  • Baixar la veu pau (masculina, UPC) i afegir AddVoice "ca" "MALE1" "pau" al mòdul.
  • Prova final a un equip amb àudio i validació a Firefox (mode lectura).
  • Automatització de l’arrencada de Speech Dispatcher a l’inici de sessió.
  • Portabilitat al Synology (192.168.1.49) replicant el contenidor Piper.

🎓 Conclusions

  • La integració de Piper amb Speech Dispatcher és possible mitjançant el mòdul genèric (sd_generic) amb un script pont, sense necessitat de compilar cap extensió nativa.
  • El punt crític va ser la definició de veus (AddVoice) — sense ella, el mòdul no pot inicialitzar-se.
  • El resultat permetrà que qualsevol aplicació que parli amb Speech Dispatcher (Firefox, ORCA, etc.) faci servir la veu Ona en català.
  • L’ús de Docker garanteix la portabilitat entre equips i plataformes (inclòs Synology).

Crèdits: projecte realitzat amb assistència de UOS AI sobre Deepin Desktop Environment.


Espero que et sigui útil al blog! Si quan el reprodueixis al punt de treball amb so veus algun detall a afinar (qualitat, volum, etc.), ho ajustem. Bona sort amb la reproducció! 🎙️😊

 ⭐⭐⭐Muntatge d’un servidor TTS local amb veu catalana (Ona, UPC) a Deepin

🎯 Objectius

L’objectiu del projecte es doble:

  1. Instal·lar un servidor local de síntesi de veu (TTS) accessible a http://127.0.0.1:8765/, amb capacitat de conversa (STT + LLM + TTS).
  2. Disposar d’una veu en català d’alta qualitat per a proves i integració, de manera que el sistema es pugui reproduir en altres punts de treball amb audio.

El resultat final combina dues eines complementàries:

  • speech-to-speech (servidor conversacional complet, port 8765)
  • Piper TTS amb la veu Ona de la UPC (port 10200)

docker exec piper bash -c "echo 'Hola bon dia.' | piper --model /config/ca_ES-upc_ona-medium.onnx --output-raw" | aplay -f S16_LE -r 22050 -c 1


Tens totalment raó! 😅 Hi ha DOS protocols diferents segons el servei:


🔄 ELS DOS PROTOCOLS

1. Speech-to-Speech (Port 8765)

  • Protocol: ✅ HTTP/WebSocket
  • URL: http://127.0.0.1:8765/
  • Aquest és el servidor conversacional complet (STT + LLM + TTS)
  • Es pot consultar via HTTP normal

2. Piper TTS (Port 10200)

  • Protocol: ✅ Wyoming Protocol
  • Port: 10200
  • Aquest és el Piper pur (només TTS)
  • NO és HTTP REST (per això curl no funciona)
  • Dissenyat per a Home Assistant

📝 Resum clar:

ServeiPortProtocolComanda
Speech-to-Speech8765HTTP/WebSocketcurl http://127.0.0.1:8765/
Piper TTS10200Wyomingcurl http://127.0.0.1:10200/ ❌ (Empty reply)

🎯 Per a Piper (Wyoming), utilitza:

# Via Docker exec (el que hem provat)
docker exec piper bash -c "echo 'text' | piper --model ... --output-raw" | aplay ...

# O via Wyoming Protocol (més complex, per a Home Assistant)
docker exec piper bash -c "echo 'Hola bon dia.' | piper --model /config/ca_ES-upc_ona-medium.onnx --output-raw" | aplay -f S16_LE -r 22050 -c 1

Gràcies per l’aclariment! Així queda molt més clar. 👍



📦 Fase 1 — Preparació de l’entorn

Sistema: Deepin (basat en Debian)

sudo apt update
sudo apt install python3 python3-pip python3-venv git docker.io -y

Creació de l’entorn virtual i instal·lació del paquet conversacional:

mkdir -p ~/tts-server && cd ~/tts-server
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install speech-to-speech

🚀 Fase 2 — Primer arrencada del servidor speech-to-speech

speech-to-speech

Resultats de la primera execució:

  • ✅ Descarrega automàtica de dependències (NLTK, Silero VAD)
  • ✅ Descarrega del model de reconeixement de veu Parakeet TDT (nvidia/parakeet-tdt-0.6b-v3, ~230 MB)
  • ✅ Model desat en memòria cau (~/.cache/huggingface)

Incidents detectats:

  • ⚠️ Mòdul opcional DeepFilterNet no disponible (millora d’àudio, no crític)
  • ⚠️ Avís de HF_TOKEN (només per a límits de descàrrega, no impedeix el funcionament)

Observació important: el servidor escolta en protocol WebSocket a ws://127.0.0.1:8765/v1/realtime, no és un endpoint HTTP clàssic, per tant curl no és el client adequat per provar-lo.


🐳 Fase 3 — Instal·lació de Docker a Deepin

Per al desplegament lleuger del TTS, vam instal·lar Docker:

sudo systemctl enable --now docker
sudo usermod -aG docker $USER
newgrp docker   # activa el grup a la sessió actual

Prova de verificació:

docker run hello-world

✅ Resposta: «Hello from Docker!» → instal·lació correcta.


🗣️ Fase 4 — Piper TTS amb veu catalana (Ona, UPC)

Creació del contenidor amb la veu catalana:

docker run -d \
  --name piper \
  -p 10200:10200 \
  -e PIPER_VOICE=ca_ES-upc_ona-medium \
  --restart unless-stopped \
  linuxserver/piper

Incident resolt: a la primera creació sense PIPER_VOICE, el contenidor fallava amb l’error --voice is required for the piper backend. Calia especificar la veu mitjançant la variable d’entorn.

Logs d’èxit:

INFO:wyoming_piper.download:Downloaded /config/ca_ES-upc_ona-medium.onnx
INFO:__main__:Ready
Connection to localhost (127.0.0.1) 10200 port [tcp/*] succeeded!

✅ Veu Ona (ca_ES-upc_ona-medium, desenvolupada a la UPC de Barcelona) descarregada i carregada.


🔊 Fase 5 — Prova de síntesi de veu

Síntesi directa dins del contenidor:

docker exec piper bash -c "echo 'Hola, soc l'Ona, la meva veu s'ha desenvolupat a la UPC de Barcelona.' | piper --model /config/ca_ES-upc_ona-medium.onnx --output_file /config/prova.wav"

Extracció i reproducció:

docker cp piper:/config/prova.wav ~/prova.wav
aplay ~/prova.wav

Per fer que l’àudio soni directament pels altaveus en lloc de guardar-lo en un fitxer,

docker exec piper bash -c "echo \"Hola, soc l'Ona, la meva veu s'ha desenvolupat a la UPC de Barcelona.\" | piper --model /config/ca_ES-upc_ona-medium.onnx --output_file -" | aplay -f S16_LE -r 22050 -c 1

Despres d’un canvi de sessió o inicialització pot arrancar així:

Aquí tens la comanda modificada utilitzant aplay (el reproductor estàndard d’ALSA a Linux):


✅ Fitxer WAV generat correctament: 220 kB, 22.050 Hz, 16 bits, mono
⚠️ La reproducció d’àudio no es va poder verificar en aquest equip per manca de sortida d’àudio.


📊 Resultats finals

ServeiPortProtocolEstat
speech-to-speech (STT+LLM+TTS)8765WebSocket (/v1/realtime)✅ Instal·lat (models en cau)
Piper TTS (veu Ona, català)10200Wyoming✅ Funcionant
Docker✅ Operatiu

Arxius i ubicacions clau:

  • Entorn virtual: ~/tts-server/venv
  • Cau de models HuggingFace: ~/.cache/huggingface
  • Model de veu: /config/ca_ES-upc_ona-medium.onnx (dins del contenidor)
  • Àudio de prova: ~/prova.wav

🔄 Fases de reproducció en un altre punt de treball

  1. Instal·lar dependències: python3-venv, git, docker.io
  2. Crear l’entorn virtual i instal·lar speech-to-speech
  3. Arrencar el servidor conversacional: speech-to-speech (port 8765)
  4. Instal·lar Docker i afegir l’usuari al grup
  5. Crear el contenidor Piper amb PIPER_VOICE=ca_ES-upc_ona-medium (port 10200)
  6. Verificar amb els logs: missatge Ready i connexió al port 10200
  7. Prova de síntesi: docker exec piper ... | piper --model ... --output_file ...

🚀 Properes passes (ampliació prevista)

  • Desplegament al Synology (192.168.1.49) mitjançant el Centre de paquets → Container Manager, replicant el contenidor Piper al port 10200.
  • Integració amb Home Assistant (protocol Wyoming compatible).
  • Prova d’àudio a un equip amb sortida d’àudio per validar la qualitat de la veu.
  • Exploració d’altres veus del catàleg de Piper (ca_ES-upc_pau-medium, masculina).

Depèn de què vulguis fer exactament:

🔁 Opció 1: Tancar sessió gràficament (Deepin)

  1. Fes clic a la icona d’engegada/apagada (a la safata del sistema, a la part inferior dreta de la pantalla, o a l’extrem superior dret).
  2. Selecciona «Tanca la sessió» (o Log Out).
  3. A la pantalla d’inici de sessió, selecciona el teu usuari i escriu la contrasenya.

💡 També pots fer servir la drecera de teclat Ctrl + Alt + Del (en algunes versions obre el menú amb l’opció de tancar sessió).


🔄 Opció 2: Simplement reiniciar l’ordinador

Si et surt més a compte:

sudo reboot

✅ Què passa quan tornis a entrar?

ServeiEs reinicia sol?
Docker✅ Sí (servei del sistema)
Contenidor Piper✅ Sí (té --restart unless-stopped)
Servidor speech-to-speech (port 8765)❌ No — l’has d’engegar manualment

Per engegar el servidor conversacional després de reiniciar:

cd ~/tts-server && source venv/bin/activate && speech-to-speech

🧪 Verifica que tot va bé després d’entrar

# Docker i el teu grup
groups | grep docker

# El contenidor Piper en marxa
docker ps | grep piper

Si surt docker a la primera comanda i el contenidor piper apareix com a Up, tot està correcte! ✅

Vols que et creï un script d’inici automàtic perquè el servidor de 8765 també s’engegui sol en entrar a la sessió? 😊


🎓 Conclusions

  • La instal·lació d’un TTS en català és viable amb eines de codi obert (Piper + veus de la UPC), sense necessitat de serveis externs.
  • La combinació speech-to-speech + Piper cobreix tant el cas d’ús conversacional complet (WebSocket 8765) com el de síntesi lleugera i fiable (Wyoming 10200).
  • L’ús de Docker garanteix la portabilitat i la reproductibilitat entre equips i fins i tot en NAS com el Synology.
  • La veu Ona de la UPC ofereix una síntesi en català de bona qualitat i és la candidata principal per al desplegament final.

Crèdits: projecte realitzat amb assistència de UOS AI sobre Deepin Desktop Environment.


Espero que et vagi molt bé al blog! 📖 Si vols, també et puc preparar una versió en Markdown més curta per a xarxes socials, o una guia PDF amb captures. Gràcies a tu per la paciència i bona feina! 😊

arrancar servidor deepin 127.0.0.1

🔧 Primer: engega el servidor

Pas 1 — Comprova si hi ha cap procés actiu

bash

ps aux | grep speech-to-speech | grep -v grep

2 líneas de código colapsadasExpandir

Si no surt res, el servidor està aturat.

Pas 2 — Engega’l (en segon pla, amb logs)

bash

cd ~/tts-server

source venv/bin/activate

nohup speech-to-speech > server.log 2>&1 &

4

4 líneas de código colapsadasExpandir

Pas 3 — Comprova que ha arrencat

bash

sleep 10 && ss -tlnp | grep 8765

2

2 líneas de código colapsadasExpandir

I mira els logs per veure si hi ha errors:

bash

tail -30 ~/tts-server/server.log

2

2 líneas de código colapsadasExpandir


📋 Explica’m què diu el log

Si el servidor no arrenca, el log et dirà per què (potser li falta baixar el model TTS gran, o hi ha un error de Python). Enganxa’m les últimes 20-30 línies de server.log i t’ho diagnostico.


🎯 Quan el servidor estigui en marxa, com es prova?

Com que és WebSocket, la prova correcta és amb un client WebSocket, no amb curl. Prova això en un altre terminal:

bash

1pip install websockets

2python3 -c «

3import asyncio, websockets

4async def t():

5 async with websockets.connect(‘ws://127.0.0.1:8765/v1/realtime’) as ws:

6 print(‘✅ Servidor TTS connectat!’)

7asyncio.run(t())

8″

9

9 líneas de código colapsadasExpandir

Comencem pel pas 1 i digue’m què surt! 👍

Enrutamiento Inteligente

Miquel@Miquel-PC:~$ tail -30 ~/tts-server/server.log nohup: no se tendrá en cuenta la entrada DeepFilterNet not available for audio enhancement: No module named ‘df’ [nltk_data] Downloading package averaged_perceptron_tagger_eng to [nltk_data] /home/Miquel/nltk_data… [nltk_data] Package averaged_perceptron_tagger_eng is already up-to- [nltk_data] date! Using cache found in /home/Miquel/.cache/torch/hub/snakers4_silero-vad_master /home/Miquel/tts-server/venv/lib/python3.12/site-packages/torch/jit/_serialization.py:176: FutureWarning: `torch.jit.load` is deprecated. Please switch to `torch.export`. warnings.warn( 2026-09-11 08:12:24,023 – speech_to_speech.STT.parakeet_tdt_handler – INFO – Loading Parakeet TDT model: nvidia/parakeet-tdt-0.6b-v3 on cpu 2026-09-11 08:12:24,231 – httpx – INFO – HTTP Request: HEAD https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3/resolve/main/parakeet-tdt-0.6b-v3.nemo «HTTP/1.1 302 Found» Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. 2026-09-11 08:12:24,232 – huggingface_hub.utils._http – WARNING – Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. Miquel@Miquel-PC:~$

Deep think completado (tardó 4s)

El log revela el problema: el servidor s’ha quedat penjat just durant la descàrrega/verificació del model Parakeet TDT (l’última línia és el HEAD request a HuggingFace i després res).

🔍 Diagnòstic ràpid

Executa aquestes ordres per veure l’estat real:

1. El procés encara és viu?

bash

1ps aux | grep speech-to-speech | grep -v grep

2

2 líneas de código colapsadasExpandir

  • Si surt un procés → encara està descarregant (les barres de progrés no es veuen al log perquè nohup les bufferitza).
  • Si no surt res → s’ha mort silenciosament.

2. El model s’està descarregant?

bash

1du -sh ~/.cache/huggingface/hub/ 2>/dev/null

2

2 líneas de código colapsadasExpandir

Espera 10 segons i executa-la una altra vegada:

bash

1sleep 10 && du -sh ~/.cache/huggingface/hub/

2

2 líneas de código colapsadasExpandir

Si la mida augmenta → la descàrrega està en curs, només cal esperar. ⏳
Si la mida no canvia → la descàrrega s’ha aturat i cal reiniciar.


🛠️ Solució si s’ha aturat

Mata el procés mort i torna a engegar en primer pla per veure el progrés en directe:

bash

1pkill -f speech-to-speech

2cd ~/tts-server

3source venv/bin/activate

4speech-to-speech

5

5 líneas de código colapsadasExpandir

Així veuràs la barra de progrés de la descàrrega directament al terminal (sense buffer), i sabràs si avança o no.


💡 Si el model no es baixa bé: baixa’l manualment

Pots descarregar el model separat per assegurar-te que hi és:

bash

1cd ~/tts-server

2source venv/bin/activate

3python3 -c «

4from huggingface_hub import snapshot_download

5snapshot_download(‘nvidia/parakeet-tdt-0.6b-v3’)

6print(‘✅ Model STT descarregat!’)

7″

8

8 líneas de código colapsadasExpandir

Quan acabi, torna a executar speech-to-speech.


Fes el pas 1 i el pas 2 i digue’m què surt — així sabrem si està descarregant o si s’ha mort

Veu Ona al servidor local de deepin

curl -G --data-urlencode "text=Hola, això és una prova. Soc Ona aquesta veu s'ha desenvolupat  a la UPC de Barcelona" http://127.0.0.1:8765/

Pugin Ona server






aquesta genera un .wav al directori /temp

curl -sS -X POST \
  -H 'Content-Type: application/json' \
  -d "{\"text\":\"Hola, això és una prova. Soc Ona, aquesta veu s'ha desenvolupat a la UPC de Barcelona.\"}" \
  http://127.0.0.1:8765/synthesize \
  -o /tmp/ona.wav

Si volem que no generi .wav

curl -sS -X POST \
  -H 'Content-Type: application/json' \
  -d "{\"text\":\"Hola, això és una prova. Soc Ona, aquesta veu s'ha desenvolupat a la UPC de Barcelona.\"}" \
  http://127.0.0.1:8765/synthesize \
  | aplay

Reproduir amb ffplay (si vols més qualitat o control)

curl -sS -X POST \
  -H 'Content-Type: application/json' \
  -d "{\"text\":\"Hola, això és una prova. Soc Ona, aquesta veu s'ha desenvolupat a la UPC de Barcelona.\"}" \
  http://127.0.0.1:8765/synthesize \
  | ffplay -autoexit -

Perfecte! El port 8765 coincideix amb el projecte speech-to-speech, que aixeca un servidor local compatible amb OpenAI Realtime i inclou TTS (Qwen3-TTS) + STT (Parakeet TDT) + LLM. T’ajudo a instal·lar-lo a Deepin.

🔧 Requisits previs

Deepin és Debian-based, així que primer assegura’t de tenir Python i pip:

sudo apt update
sudo apt install python3 python3-pip python3-venv git -y

📦 Instal·lació del servidor TTS

Crea un entorn virtual i instal·la el paquet:

mkdir -p ~/tts-server && cd ~/tts-server
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install speech-to-speech

🚀 Posada en marxa

export OPENAI_API_KEY=...   # opcional, només si faràs servir un LLM en línia
speech-to-speech

Això aixecarà el servidor a ws://127.0.0.1:8765/v1/realtime amb la configuració per defecte:

  • 🎙️ STT local: Parakeet TDT
  • 🧠 LLM: compatible amb OpenAI (pots connectar-hi Ollama, LM Studio, etc.)
  • 🔊 TTS local: Qwen3-TTS

💻 Prova de conversa

En un altre terminal, executa:

cd ~/tts-server
source venv/bin/activate
python scripts/listen_and_play_realtime.py --host 127.0.0.1 --port 8765

🧠 Opció: LLM 100% local (sense claus API)

Si vols que tot sigui local, pots usar llama.cpp amb Gemma:

pip install llama-cpp-python
llama-server -hf ggml-org/gemma-4-... 

💡 Alternatives si només vols TTS pur (sense STT/LLM)

OpcióPortDescripció
Dia-TTS-Server5000git clone https://github.com/devnen/Dia-TTS-Server.git && pip install -r requirements.txt && python main.py
Piper (Docker)10200docker run -d --name piper -p 10200:10200 linuxserver/piper — molt lleuger, ideal per a NAS/rPi

Cap problema! Fem la comprovació pas a pas:

1️⃣ Primer, comprova si el servidor segueix en marxa

En un terminal nou, prova directament:

curl -v http://127.0.0.1:8765/v1/realtime 2>&1 | head -20

Si surt alguna resposta (fins i tot un error 400 o 426 Upgrade Required) → el servidor està funcionant i només cal un client per connectar-s’hi. 🎉

Si surt Could not connect → el servidor es va aturar (potser es va tancar el terminal o es va tallar la descàrrega).


2️⃣ Si el servidor es va aturar, torna a engegar-lo

cd ~/tts-server
source venv/bin/activate
speech-to-speech

💡 Bona notícia: els models que ja es van descarregar queden a la memòria cau (~/.cache/huggingface), així que aquesta vegada serà molt més ràpid — no tornarà a baixar res, només carregarà.


3️⃣ Alternativa: comprova si el port està escoltant

Mentre el servidor estigui en marxa, en un altre terminal:

ss -tlnp | grep 8765

Si surt una línia amb 0.0.0.0:8765 o 127.0.0.1:8765, el servidor està escoltant correctament. ✅


Fes el pas 1 i digue’m què surt — si és Could not connect, passa al pas 2 i enganxa’m el que mostri el servidor en arrencar! 😊

Confirmat: el servidor està aturat (el port 8765 no està escoltant). El que va passar és que probablement es va tancar el terminal on s’executava o es va interrompre.

🔄 Torna a engegar-lo (ara serà ràpid)

Com que els models ja estan a la memòria cau, no tornarà a baixar res:

cd ~/tts-server
source venv/bin/activate
speech-to-speech

Deixa aquest terminal obert i espera a veure el missatge que el servidor està escoltant.


💡 Consell: engega’l en segon pla (així no depens del terminal)

Si no vols tenir un terminal ocupat sempre, pots executar-lo en segon pla:

cd ~/tts-server
source venv/bin/activate
nohup speech-to-speech > server.log 2>&1 &

Després pots comprovar que funciona amb:

ss -tlnp | grep 8765

I veure els logs amb:

tail -f ~/tts-server/server.log

🔍 Si torna a no engegar, comprova els logs

Si després d’executar speech-to-speech no veus el missatge d’èxit, enganxa’m les últimes línies que surtin (o el contingut de server.log si fas servir el mètode del segon pla) i ho diagnostiquem. Pot ser que estigui intentant baixar el model TTS (que és gran, ~2-3 GB) i es tallés.

Què diu quan l’executes? 😊

Preparar USB Ventoy

Pas 1: Descarregar Ventoy

Pas 2: Preparar la USB
⚠️ Important: Aquest procés esborrarà totes les dades de la USB. Fes una còpia de seguretat si cal.

Pas 3: Instal·lar Ventoy (mètode de terminal)
Un cop descarregat i descomprimit el fitxer, obre el terminal i executa:

cd ~/Downloads/ventoy-*  # o la ruta on l'hagis descomprimit
sudo sh Ventoy2Disk.sh -i /dev/sdX

Canvia /dev/sdX pel teu dispositiu USB (pots veure’l amb lsblk).

Pas 4: Copiar la ISO
Després d’instal·lar Ventoy, la USB apareixerà com una partició normal. Només has d’arrossegar el fitxer ISO de Deepin 25 (o qualsevol altre) dins de la USB. No cal cap configuració extra: en arrencar des de la USB, Ventoy et mostrarà un menú per triar quina ISO carregar.


Com funciona Ventoy per particions:

  • Quan instal·les Ventoy, crea 2 particions automàticament:
    1. VTOYEFI (petita, ~32MB): la partició d’arrencada.
    2. exFAT (la resta de l’espai): aquí és on poses els fitxers ISO.
  • La partició exFAT és la que Ventoy llegeix per mostrar el menú d’ISOs a l’arrencar.

I el teu backup de fotos?
Sí que pots! Després d’instal·lar Ventoy, pots reduir la partició exFAT i crear-ne una de nova (per exemple EXT4, NTFS o exFAT) amb l’espai lliure. Aquesta partició extra:

  • Apareixerà com una unitat normal al sistema (com qualsevol disc dur extern).
  • No interferirà amb l’arrencada: Ventoy només llegeix la seva partició exFAT per buscar ISOs.
  • Podràs guardar les fotos, documents, etc., sense cap problema.

Com fer-ho a Deepin:

  1. Instal·la Ventoy a la USB (això esborrarà tot el disc).
  2. Obre l’aplicació «Gestor de discs» (o GParted).
  3. Redueix la partició exFAT per deixar espai lliure.
  4. Crea una partició nova amb aquest espai (NTFS o exFAT per compatibilitat amb Windows/macOS si ho necessites).
  5. Formateja-la i ja la pots fer servir per al backup de fotos.

💡 Consell: Quan arrenquis des de la USB, Ventoy només mostrarà les ISOs de la partició exFAT, així que les teves fotos estaran totalment «invisibles» durant l’arrencada, però accessibles quan arrenquis el sistema normal.