🌟Clonació

Aquí tens un exemple típic amb rsync que conserva l’estructura de directoris, els permisos i els enllaços:

rsync -aH --progress /ruta/original/ /ruta/desti/

És clar que sí, Miquel. Si estàs pensant en aquella comanda que clona una carpeta amb tota la seva estructura interna i ajusta els enllaços simbòlics o relatius… probable que estiguem parlant d’un rsync ben afinat, o potser d’una combinació amb cp o fins i tot algun script que tu mateix hagis personalitzat.

Aquí tens un exemple típic amb rsync que conserva l’estructura de directoris, els permisos i els enllaços:

rsync -aH --progress /http://192.168.0.49/ /http://192.168.0.49/00-sapi_tts/ 

Situat a urqtejmi@Synology_sec:/volume1/web/edge_tts$, pots executar: syn_sec-> beseit

rsync -aH –progress ./ urqtejmi@81.0.60.116:/volume1/web/edge_tts/ (beseit)

rsync -aH --progress ./ /volume1/web/edge_tts/  (ruta actual-> desti)

🧠 Desglossant la comanda:

  • -a → mode arxiu: preserva permisos, timestamps, propietats, etc.
  • -H → conserva enllaços durs (si n’hi ha)
  • --progress → mostra el progrés durant la còpia
  • El / final és important per copiar el contingut dins /ruta/original/ i no la carpeta en si.

Si en canvi parlaves d’enllaços simbòlics específics que s’han de convertir o ajustar durant la clonació (per exemple, convertint relatius en absoluts, o viceversa), això podria requerir un script més sofisticat. En aquest cas, pots fer servir cp amb opcions o bé utilitzar find + readlink + ln -s per reestructurar-los.

Vols que et recuperi una versió concreta que hagis usat abans o que mirem de crear una variant més a mida? També podria ajudar-te a convertir la comanda en un petit script reutilitzable.

🌟 Configurar un entorn virtual de Python al meu Synology NAS (Network Attached Storage)

🌟 Configurar un entorn virtual de Python al meu Synology NAS (Network Attached Storage)

Crear entorn virtual de Python utilitzant SSH. Quan s’utilitzen en un entorn virtual, les eines d’instal·lació comunes com a pip instal·laran automàticament els paquets de Python en l’entorn virtual, en lloc d’instal·lar-los globalment en el sistema.

Això li permet crear un entorn aïllat amb el seu propi conjunt de paquets, independentment de la instal·lació global de Python del sistema o de qualsevol altre entorn virtual que pugui tenir.

Pasos:

Iniciar sessió amb SSH
En el seu PC, utilitzi SSH per iniciar sessió al seu NAS amb privilegis de root.

sudo -i 

urqtejmi@Synology_sec:/$ sudo -i
Password:
root@Synology_sec:~#

Seleccioni la versió de Python
Introdueixi el següent comandament per comprovar quines versions de paquets de Python estan instal·lades al seu NAS

compgen -c python

compgen: és una eina interna del shell que genera llistes de comandes

compgen -c python
-c: indica que volem veure comandes disponibles

python: és el prefix que estem cercant

📁 Canvia-te a la carpeta on vols crear l’entorn1

cd /volume1/web/ssh_prova

urqtejmi@Synology_sec:/volume1/web/00-sapi_tts$ -> /volume1/web/edge_tts$

rsync -aH –progress ./ /volume1/web/edge_tts/


🔧 Crea l’entorn virtual amb Python 3.9

python3.9 -m venv myenv

Això crearà una carpeta anomenada myenv (pots canviar el nom si vols) amb una còpia aïllada de Python 3.9 i pip.


Quan crees un entorn virtual amb:

python3.9 -m venv env_tts

python3.9 -m venv venv_web

🔌 Activa l’entorn virtual

source env_tts/bin/activate

esborrar entorn: rm -r myenv

Canvia de nom: env_tts/bin/activate

root@syn_beseit:/volume1/web/edge_tts# source myenv/bin/activate
(myenv) root@syn_beseit:/volume1/web/edge_tts# python –version
Python 3.9.14
(myenv) root@syn_beseit:/volume1/web/edge_tts#

deactivate

…l’entorn ja ve amb pip i setuptools instal·lats per defecte , des de Python 3.4 en endavant (que és quan es va afegir el mòdul venv).


instal·lar edge_tts i gtts al entorn

pip install edge-tts gTTS
edge-ttsUtilitza el servei de veu sintetitzada de Microsoft Azure (gratuït, sense clau d’API).
gTTSGoogle Text-to-Speech: genera àudio a partir de text utilitzant els serveis de Google.

🔍 Llista de veus disponibles a edge-tts

Executa gTTS amb idioma català (codi ca):

Quan executes aquesta comanda dins de l’entorn virtual activat ((env_tts)

pip install gTTS dins de env_tts, la biblioteca s’ha instal·lat en:

/volume1/web/edge_tts/env_tts/lib/python3.9/site-packages/gtts
Quan fas python -c "...gTTS(...)", el Python que estàs usant és el de

/volume1/web/edge_tts/env_tts/bin/python3.9

python -c "from gtts import gTTS; gTTS(text='Hola, soc de Sant Cugat', lang='ca').save('tts.mp3')"

(env_tts) root@Synology_sec:/volume1/web/edge_tts/env_tts# python -c "from gtts import gTTS; gTTS(text='Hola, soc de Sant Cugat', lang='ca').save('tts.mp3')"
(env_tts) root@Synology_sec:/volume1/web/edge_tts/env_tts#

Edge & Google TTS Web App

Edge & Google TTS Web App

Aquest projecte proporciona una aplicació web lleugera per convertir text en veu en diferents idiomes, mitjançant tecnologies de Microsoft (Edge TTS) i Google (gTTS).


📁 Estructura del projecte

/edge_tts_clean/
│
├── app.py (o serve_gtts.py)      ← Servidor Flask que processa les peticions web
├── generar_gtts.py               ← Conversió de text a veu amb Google TTS (gTTS)
│
├── /audio/                       ← Conté els fitxers d’àudio generats (tts.mp3)
│
├── /venv/                        ← Entorn virtual Python (Flask, edge_tts, gtts, etc.)
│
├── index.php                     ← Interfície web: formulari per introduir text i seleccionar veu
│                                 (executa generar_gtts.py o generar_tts.py segons la veu escollida)
└── ...


(venv_web) root@Synology_sec:/volume1/web/edge_tts_clean# dir
total 48
drwxrwxr-x+ 1 urqtejmi http    176 Jul 12 16:33 .
dr-xr-xr-x+ 1 root     root   1780 Jul 12 12:32 ..
dr-xr-xr-x+ 1 urqtejmi users     0 Jul 12 12:37 app
dr-xr-xr-x+ 1 urqtejmi users   420 Jul 12 13:56 audio
-r-xr-xr-x+ 1 urqtejmi users   603 Jul 12 12:36 estructura.php
-r-xr-xr-x+ 1 urqtejmi users   531 Jul 12 16:34 generar_gtts.py
-r-xr-xr-x+ 1 root     root  15984 Jul 12 13:37 hola.mp3
-r-xr-xr-x+ 1 urqtejmi users  3344 Jul 12 17:07 index.php
-r-xr-xr-x+ 1 urqtejmi users  3723 Jul 12 15:48 serve_tts.py
-r-xr-xr-x  1 urqtejmi users   420 Jul 12 13:35 setup.sh
-rwxrwxr-x+ 1 http     http  10224 Jul 12 17:10 tts.mp3
dr-xr-xr-x+ 1 root     root     56 Jul 12 13:31 venv
dr-xr-xr-x+ 1 urqtejmi users     0 Jul 12 12:37 web
(venv_web) root@Synology_sec:/volume1/web/edge_tts_clean#

✨ Característiques

  • Conversió de text a veu en català, castellà, anglès i francès
  • Suport per a veus de Microsoft Edge i Google
  • Interfície web simple (Flask) amb selector de veu
  • Opcionalment integrable amb PHP (index.php)

⚙️ Requisits

  • Python 3.9
  • Entorn virtual creat amb python -m venv venv

Paquets necessaris:

pip install flask edge-tts gtts

🚀 Execució

  1. Activa l’entorn virtual:
source venv/bin/activate
  1. Inicia el servidor:
python serve_gtts.py
  1. Accedeix a l’aplicació web:
http://<IP-del-servidor>:8000

🌍 Veus disponibles

Català

  • gtts-ca → Google TTS (Català)
  • ca-ES-JoanaNeural → Microsoft Edge TTS

Castellà

  • es-ES-ElviraNeural
  • es-ES-AlvaroNeural

Anglès

  • en-US-JennyNeural
  • en-GB-RyanNeural

Francès

  • fr-FR-DeniseNeural
  • fr-FR-HenriNeural

📄 Fitxers clau

  • serve_gtts.py: Aplicació Flask que gestiona la interfície i genera l’àudio.
  • generar_tts.py: Utilitza edge-tts per generar veu.
  • generar_gtts.py: Utilitza gtts per generar veu.
  • index.php: Versió alternativa amb PHP per entorns web que ho requereixin.

🚫 Notes de seguretat

  • Valida les entrades si s’exposa públicament.
  • Revisa permisos d’escriptura a la carpeta audio/.

📍 Desenvolupat a

  • Synology NAS (amb Python i entorns virtuals)
  • Accés LAN via IP local (p. ex. http://192.168.0.49:8000)

🎓 Llicència

Projecte privat per a finalitats educatives o de prova. No distribuïble com a servei comercial sense llicències de veus.


✏️ Contacte

Per a preguntes o ampliacions: [Afegeix les dades de contacte si cal]

Publicat dins de Veus

ssh comandes utils

versions instal·lades de pytho


urqtejmi@Synology_sec:~$ sudo -i
Password:
root@Synology_sec:~# compgen -c python
python3
python3.8
python
python3
python3.8
python
python3.9
python2
python2.7
root@Synology_sec:~#

prova de veus

  • 🗣️ Veu Elvira (Edge TTS en castellà): http://192.168.0.49/00-sapi_tts/?text=Hola+bon+dia&voice=es-ES-ElviraNeural
  • 🇫🇷 Veu Henri (Edge TTS en francès): http://192.168.0.49/00-sapi_tts/?text=Bonjour,+comment+ça+va?&voice=fr-FR-HenriNeural
  • 🇬🇧 Veu Jenny (Edge TTS en anglès): http://192.168.0.49/00-sapi_tts/?text=Good+morning!&voice=en-US-JennyNeural
http://192.168.0.49/00-sapi_tts/?text=Bon+dia&voice=gtts-ca

script Python intel·ligent

Detecta si el text és en català o anglès

Tria automàticament la veu adequada per a edge-tts

Genera un fitxer .mp3 amb veu natural

tts_auto.py
import sys
import subprocess
from langdetect import detect

# 🔧 Configura les veus segons l'idioma
VOICES = {
    'ca': 'ca-ES-JoanaNeural',
    'en': 'en-GB-LibbyNeural'
}

def detect_language(text):
    try:
        lang = detect(text)
        return lang if lang in VOICES else 'en'
    except:
        return 'en'

def synthesize(text, output_file):
    lang = detect_language(text)
    voice = VOICES[lang]
    print(f"Idioma detectat: {lang} → Veu: {voice}")
    
    command = [
        '/var/services/homes/urqtejmi/.local/bin/edge-tts',
        '--text', text,
        '--voice', voice,
        '--write-media', output_file
    ]
    
    subprocess.run(command)

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Ús: python tts_auto.py \"Text a llegir\"")
        sys.exit(1)

    text = sys.argv[1]
    output = "sortida.mp3"
    synthesize(text, output)
    print(f"Àudio generat: {output}")

python 9

ssh urqtejmi@192.168.0.49
ls -l /volume1/@appstore/

drwxr-xr-x 1 root       root              44 May 28 00:15 Apache2.4
drwxr-xr-x 1 root       ContainerManager 114 Jul  8 18:09 ContainerManager
drwxr-xr-x 1 root       HyperBackup       58 Jun  4 12:03 HyperBackup
drwxr-xr-x 1 root       root              74 Jun 17 18:24 HyperBackupVault
drwxr-xr-x 1 root       root             152 May 28 00:15 MariaDB10
drwxr-xr-x 1 root       root              12 Jul  8 18:11 Node.js_v14
drwxr-xr-x 1 root       root              12 Jul  8 18:10 Node.js_v16
drwxr-xr-x 1 root       root              12 Jul  8 18:10 Node.js_v18
drwxr-xr-x 1 root       root              12 Jul  8 18:10 Node.js_v20
drwxr-xr-x 1 root       root              20 May 28 09:34 PHP7.4
drwxr-xr-x 1 root       root              20 May 28 00:15 PHP8.0
drwxr-xr-x 1 phpMyAdmin phpMyAdmin        46 May 28 08:46 phpMyAdmin
drwxr-xr-x 1 root       root              38 Jul  8 17:53 Python3.9
drwxr-xr-x 1 root       root             186 May 28 00:14 WebStation
drwxr-xr-x 1 WordPress  WordPress         70 May 28 00:16 WordPress

reservar ip

Què vol dir “reservar una IP”?

Reservar una IP (també anomenat reserva DHCP o IP estàtica assignada per MAC) vol dir que el router sempre assignarà la mateixa IP al dispositiu (en aquest cas, el Synology) quan es connecti, basant-se en la seva adreça MAC.

🛠️ Com reservar la IP al router

🔍 Pas previ: Troba l’adreça MAC del Synology

  1. Entra al DSM (http://192.168.0.49:5000).
  2. Ves a Panel de control → Red → Interfaz de red → LAN 1 → Detalles.
  3. Copia l’adreça MAC (ex: 00:11:32:AB:CD:EF).

🛜 A cada router (un per cada domicili):

🔧 Router 1 (xarxa 192.168.0.x)

  1. Entra a la configuració del router (normalment http://192.168.0.1).
  2. Ves a la secció DHCP o LAN Settings.
  3. Busca una opció com “Reservar IP”, “Static DHCP”, “Address Reservation” o similar.
  4. Afegeix:
    • MAC: la del Synology
    • IP: 192.168.0.49
  5. Desa i reinicia el router si cal.

🔧 Router 2 (xarxa 192.168.1.x)

  1. Quan estiguis a l’altre domicili, repeteix el procés:
  2. Entra al router (http://192.168.1.1).
  3. Ves a la secció DHCP i reserva:
    • MAC: la mateixa
    • IP: 192.168.1.49

Instal·la eSpeak-ng i i ffmpeg (Calibre) al teu Synology

s’ha de substituir gTTS per eSpeak-ng, et mostro com adaptar-la pas a pas per fer servir aquest motor localment i afegir un selector de veus reals.


🛠️ 1. Instal·la espeak-ng i ffmpeg al teu Synology

Si tens accés a apt o ipkg:

sudo apt install espeak-ng ffmpeg

🐍 2. Modifica generar_tts.py per fer servir espeak-ng

import sys
import os
import subprocess

text = sys.argv[1] if len(sys.argv) > 1 else "Text per defecte"
voice = sys.argv[2] if len(sys.argv) > 2 else "ca"  # idioma per defecte: català

base_dir = os.path.dirname(os.path.abspath(__file__))
output_wav = os.path.join(base_dir, "tts.wav")
output_mp3 = os.path.join(base_dir, "tts.mp3")

# 🗣️ Generar WAV amb eSpeak-ng
espeak_cmd = ["espeak-ng", "-v", voice, text, "--stdout"]
with open(output_wav, "wb") as wav_file:
    subprocess.run(espeak_cmd, stdout=wav_file)

# 🎧 Convertir a MP3 amb ffmpeg
subprocess.run(["ffmpeg", "-y", "-i", output_wav, output_mp3])

🌍 3. Actualitza index.php amb idiomes/veus disponibles

Substitueix la llista de veus per idiomes compatibles amb eSpeak-ng:

$voices = [
    "ca", // Català
    "es", // Espanyol
    "en", // Anglès
    "fr", // Francès
    "de", // Alemany
    "it", // Italià
    "pt", // Portuguès
    "ru", // Rus
    "ja", // Japonès
];

Pots afegir variants com ca+f3 o en+m1 per canviar el timbre (masculí/femení) si vols més control.


🧪 4. Prova-ho

Ara, quan seleccionis una veu (en realitat, un idioma o variant) des del formulari, es passarà com a paràmetre a espeak-ng, que generarà l’àudio amb la veu corresponent.


🎯 Vols més personalització?

  • Puc ajudar-te a llistar totes les veus disponibles amb espeak-ng --voices
  • O afegir un selector de velocitat i to
  • O fins i tot fer que el sistema recordi l’última veu usada

Vols que et prepari un script per mostrar totes les veus disponibles al teu sistema?

Text to Speech (amb Python)

Estr/00-sapi_tts/
├── exec_script_py.php     ← Crida el Python
├── generar_tts.py ← Script Python que genera l'àudio 
|                    des de Synology
├── index.php              ← Interfície web
└── tts.mp3                ← Fitxer generatuctura

index.php

<?php
// Llista de veus
$voices = [
    "Microsoft Helena Desktop",
    "Microsoft Hazel Desktop",
    "Microsoft Zira Desktop",
    "Microsoft Hortense Desktop",
    "Vocalizer Expressive Jordi Harpo 22kHz"
];

// Carrega valors antics per mantenir-los al formulari
$lastText = isset($_GET['text']) ? htmlspecialchars($_GET['text']) : '';
$lastVoice = isset($_GET['voice']) ? $_GET['voice'] : '';
?>
<!DOCTYPE html>
<html lang="ca">
<head>
    <meta charset="UTF-8">
    <title>Generador TTS</title>
</head>
<body>
    <h1>Text-to-Speech (amb Python)</h1>
    <form action="exec_script_py.php" method="POST">

        <label for="text">Introdueix el text:</label><br>
        <textarea name="text" id="text" rows="4" cols="50"><?= $lastText ?></textarea><br><br>

        <label for="voice">Selecciona una veu:</label><br>
        <select name="voice" id="voice">
            <?php foreach ($voices as $voice): ?>
                <option value="<?= htmlspecialchars($voice) ?>" <?= ($voice == $lastVoice ? 'selected' : '') ?>>
                    <?= htmlspecialchars($voice) ?>
                </option>
            <?php endforeach; ?>
        </select><br><br>

        <input type="submit" value="Generar àudio">
    </form>

    <?php if (isset($_GET['error'])): ?>
        <p style="color:red;">❌ Error: <?= htmlspecialchars($_GET['error']) ?></p>
    <?php endif; ?>

    <?php if (file_exists("tts.mp3")): ?>
        <h2>Resultat:</h2>
        <audio controls>
            <source src="tts.mp3?<?= time() ?>" type="audio/mpeg">
            El teu navegador no suporta àudio.
        </audio>
    <?php endif; ?>
</body>
</html>

generar_tts.py

import sys
import os

# 🔧 Elimina rutes locals que poden interferir
sys.path = [p for p in sys.path if ".local" not in p and "urqtejmi" not in p]

print("🔍 sys.path netejat:")
for p in sys.path:
    print("  -", p)

# 📦 Comprovació de la importació
try:
    import gtts
    print("📦 gtts importat des de:", getattr(gtts, '__file__', '❌ No definit'))
    from gtts import gTTS
    print("✅ gTTS importat correctament")
except Exception as e:
    print("❌ Error important gTTS:", e)
    raise

# 📄 Preparació del fitxer de sortida
base_dir = os.path.dirname(os.path.abspath(__file__))
output_path = os.path.join(base_dir, "tts.mp3")

# 📝 Recollir text i veu
text = sys.argv[1] if len(sys.argv) > 1 else "Text per defecte"
voice = sys.argv[2] if len(sys.argv) > 2 else "default"

print(f"▶ Text: {text}")
print(f"▶ Veu seleccionada: {voice} (no utilitzada per gTTS)")
print(f"▶ Fitxer a guardar: {output_path}")

# 🔊 Generar MP3
tts = gTTS(text=text, lang='ca')
tts.save(output_path)

exec_script_py.php

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $textRaw = $_POST['text'] ?? '';
    $voiceRaw = $_POST['voice'] ?? '';

    $text = escapeshellarg($textRaw);
    $voice = escapeshellarg($voiceRaw);

    // ✅ Ruta al Python de l'entorn virtual
    $python = '/volume2/web/00-sapi_tts/venv/bin/python';

    // ✅ Comanda per executar el script Python
    $command = "$python generar_tts.py $text $voice 2>&1";

    // 🔁 Executa el script i captura la sortida
    $output = shell_exec($command);

    echo "<pre>📤 Comanda executada:\n$command\n\n📄 Sortida:\n$output</pre>";

    // ❌ Si no s'ha generat l'àudio, redirigeix amb error
    if (!file_exists("tts.mp3")) {
        $error = "No s'ha pogut generar l'àudio. Sortida: $output";
        header("Location: index.php?error=" . urlencode($error) . "&text=" . urlencode($textRaw) . "&voice=" . urlencode($voiceRaw));
        exit();
    }

    // ✅ Si tot ha anat bé, redirigeix amb els valors conservats
    header("Location: index.php?text=" . urlencode($textRaw) . "&voice=" . urlencode($voiceRaw));
    exit();
}
?>

🛠️ Historial de passos per solucionar l’error amb gtts

1. Diagnòstic inicial

  • El teu script Python donava aquest error:
  ImportError: cannot import name 'gTTS' from 'gtts' (unknown location)
  • El mòdul gtts semblava instal·lat, però gtts.__file__ retornava None.

2. Depuració del sistema

  • Vam comprovar que hi havia múltiples versions de gtts instal·lades:
  • Una a /usr/lib/python3.8/site-packages
  • Una altra a ~/.local/lib/python3.8/site-packages ❌ (interferia)
  • Vam eliminar la versió local conflictiva:
  rm -rf ~/.local/lib/python3.8/site-packages/gtts
  rm -rf ~/.local/lib/python3.8/site-packages/gTTS-*.dist-info

3. Reinstal·lació neta

  • Vam reinstal·lar gtts globalment:
  sudo /bin/python3 -m pip install --no-cache-dir gtts
  • Tot i això, l’error persistia perquè el servidor web seguia usant el Python del sistema, amb rutes contaminades.

4. Creació d’un entorn virtual

  • Vam crear un entorn virtual aïllat:
  python3 -m virtualenv venv
  source venv/bin/activate
  pip install gtts
  • Això va instal·lar gtts netament a:
  /volume2/web/00-sapi_tts/venv/lib/python3.8/site-packages

5. Modificació del script PHP

  • Vam modificar exec_script_py.php per cridar el Python del virtualenv:
  $python = '/volume2/web/00-sapi_tts/venv/bin/python';
  $command = "$python generar_tts.py $text $voice 2>&1";
  • Això va assegurar que el servidor web executés el Python correcte, amb el mòdul gtts funcional.

6. Èxit final

  • El fitxer tts.mp3 es va generar correctament.
  • El reproductor d’àudio es va mostrar a la pàgina.
  • El text “bona nit” es va convertir en veu 🎉

🔜 Què queda pendent?

  • La veu no sona com la del “Jordi” de Vocalizer: això és perquè gtts fa servir la veu de Google Translate, no veus locals com Vocalizer.
  • Si vols fer servir veus com la del Jordi, caldrà integrar motors com:
  • eSpeak NG
  • Festival
  • Vocalizer TTS (si tens llicència)
  • Microsoft Azure, Google Cloud TTS, etc.

Vols que demà explorem com fer servir una veu real com la del Jordi amb un motor TTS local o en el núvol? O vols que et prepari una comparativa de motors TTS amb veus catalanes?

Publicat dins de Veus