Aquí tens l’entrada de blog completa, llesta per publicar (en Markdown):
--- title: "Text del navegador a veu amb Piper TTS en Docker" date: "2026-09-20" tags: ["docker", "piper", "tts", "python", "flask"] --- # Text del navegador a veu amb Piper TTS en Docker Vols escriure text en una pàgina web i que es converteixi en àudio (WAV) amb una veu sintètica? En aquest post et mostro com muntar un **contenidor Docker** que fa exactament això: un HTML envia el text, i el contenidor el passa al **Piper** (motor de text-a-veu) per retornar-te el fitxer WAV directament al navegador. ## Arquitectura El flux és senzill: 1. L'usuari escriu text a un formulari HTML. 2. JavaScript envia el text a una API (Flask) mitjançant `POST /api/tts`. 3. Flask executa `piper` dins del contenidor amb el text rebut. 4. Piper genera un fitxer `.wav`. 5. L'àudio es retorna al navegador i es reprodueix automàticament.
Navegador (HTML) ──POST text──▶ Flask API ──▶ Piper CLI ──▶ WAV ──▶ Navegador
## Requisits - Docker i Docker Compose instal·lats. - Connexió a internet per baixar les imatges i el model de veu. ## Estructura de fitxers
piper-tts/
├── app.py
├── Dockerfile
├── docker-compose.yml
└── templates/
└── index.html
## Pas 1: l'API amb Flask (`app.py`)
L'aplicació exposa la pàgina principal i l'endpoint `/api/tts`, que rep el text, l'executa amb Piper i retorna el WAV:
```python
from flask import Flask, request, render_template, send_file
import subprocess
app = Flask(__name__)
MODEL = "/models/zh_CN-huayan-medium.onnx"
OUTPUT = "/app/output/resultat.wav"
@app.route("/")
def index():
return render_template("index.html")
@app.route("/api/tts", methods=["POST"])
def tts():
data = request.get_json()
text = data.get("text", "")
if not text:
return {"error": "text buit"}, 400
subprocess.run(
["piper", "--model", MODEL, "--output_file", OUTPUT],
input=text.encode("utf-8")
)
return send_file(OUTPUT, mimetype="audio/wav")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Pas 2: la pàgina HTML (templates/index.html)
Un textarea per escriure, un botó per sintetitzar i un reproductor d’àudio:
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="UTF-8">
<title>Piper TTS</title>
</head>
<body>
<h1>Piper TTS — text a veu</h1>
<textarea id="text" rows="4" cols="60">Hola, benvingut al servei de veu!</textarea>
<br><br>
<button onclick="sintetitza()">Sintetitza</button>
<br><br>
<audio id="audio" controls style="display:none"></audio>
<script>
async function sintetitza() {
const text = document.getElementById("text").value;
const res = await fetch("/api/tts", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text: text })
});
const blob = await res.blob();
const url = URL.createObjectURL(blob);
const audio = document.getElementById("audio");
audio.src = url;
audio.style.display = "block";
audio.play();
}
</script>
</body>
</html>
Pas 3: el Dockerfile
Instal·la Flask i Piper, baixa el model de veu i defineix l’arrencada:
FROM python:3.11-slim
# Instal·la dependències
RUN apt-get update && apt-get install -y wget espeak-ng && \
pip install flask piper-tts
# Baixa el model de veu (exemple: xinès huayan; canvia'l pel que vulguis)
RUN mkdir -p /models && cd /models && \
wget https://huggingface.co/rhasspy/piper-voices/resolve/main/zh/zh_CN/huayan/medium/zh_CN-huayan-medium.onnx && \
wget https://huggingface.co/rhasspy/piper-voices/resolve/main/zh/zh_CN/huayan/medium/zh_CN-huayan-medium.onnx.json
WORKDIR /app
COPY app.py .
COPY templates ./templates
RUN mkdir -p output
EXPOSE 5000
CMD ["python", "app.py"]
💡 Per a veus en català o castellà, consulta els models a huggingface.co/rhasspy/piper-voices i canvia les URLs del Dockerfile.
Pas 4: docker-compose.yml
services:
piper-tts:
build: .
container_name: piper-tts
ports:
- "5000:5000"
volumes:
- ./models:/models
- ./output:/app/output
restart: unless-stopped
Pas 5: posada en marxa
cd piper-tts docker compose up -d --build
Obre http://localhost:5000 al navegador i:
- Escriu el text al quadre HTML.
- Prem Sintetitza.
- Rep el WAV i el reprodueix automàticament.
Prova ràpida amb curl
curl -X POST http://localhost:5000/api/tts \
-H "Content-Type: application/json" \
-d '{"text": "Hola, això és una prova"}' \
--output prova.wav
Alternativa: imatge ja preparada
Si no vols construir res, existeixen imatges com loderunner84/piper-rest (Flask + Piper). Ara bé, muntar-ho tu mateix et dona control total sobre el model, els endpoints i la interfície.
Conclusió
Amb quatre fitxers tens un servei de text-a-veu complet dins d’un contenidor Docker: text des del navegador entra, WAV en surt. Pots ampliar-lo fàcilment: suport de múltiples idiomes, cua de peticions o desar historial d’àudios. Bon blog i bona sintetització! 🎙️
--- Aquest és el post complet en Markdown. Si vols, puc: 1. **Adaptar-lo al teu blog** (canviar títol, tags, to, afegir captures). 2. **Traduir-lo al castellà** o a l'anglès. 3. **Crear la carpeta del post** perquè el desis directament (recorda que per crear fitxers necessito que em diguis com vols fer-ho, o t'obro l'editor). Què prefereixes?