{"id":16547,"date":"2025-07-05T18:02:48","date_gmt":"2025-07-05T16:02:48","guid":{"rendered":"https:\/\/www.beseit.net\/?p=16547"},"modified":"2025-07-14T18:34:51","modified_gmt":"2025-07-14T16:34:51","slug":"tts-a-192-168-1-49-00-sapi_tts","status":"publish","type":"post","link":"http:\/\/www.beseit.net\/?p=16547","title":{"rendered":"?\u00a0Generador de veu amb Edge TTS i Google TTS?\u00a0tts a 192.168.0.49\/00-sapi_tts\/ &amp; tts a 192.168.1.49\/00-sapi_tts\/"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"515\" height=\"406\" src=\"https:\/\/www.beseit.net\/wp-content\/uploads\/2025\/07\/image-4.png\" alt=\"\" class=\"wp-image-16629\" srcset=\"http:\/\/www.beseit.net\/wp-content\/uploads\/2025\/07\/image-4.png 515w, http:\/\/www.beseit.net\/wp-content\/uploads\/2025\/07\/image-4-300x237.png 300w, http:\/\/www.beseit.net\/wp-content\/uploads\/2025\/07\/image-4-381x300.png 381w\" sizes=\"auto, (max-width: 515px) 100vw, 515px\" \/><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>\/edge_tts\n\u251c\u2500\u2500 <mark style=\"background-color:rgba(0, 0, 0, 0);color:#eb0e0e\" class=\"has-inline-color\">exec_script_py.php<\/mark>         \u2190 Script PHP que crida Python des de la web\n\u251c\u2500\u2500 <mark style=\"background-color:rgba(0, 0, 0, 0);color:#f00303\" class=\"has-inline-color\">generar_tts.py<\/mark>             \u2190 Genera l'\u00e0udio amb Edge TTS\n\u251c\u2500\u2500 <mark style=\"background-color:rgba(0, 0, 0, 0);color:#f41010\" class=\"has-inline-color\">generar_gtts.p<\/mark>y            \u2190 Versi\u00f3 que utilitza Google TTS\n\u251c\u2500\u2500 generar_veu.py             \u2190 Alternativa o prova per generar veu\n\u251c\u2500\u2500 <mark style=\"background-color:rgba(0, 0, 0, 0);color:#f01212\" class=\"has-inline-color\">diagnostic_edge_tts.py<\/mark>     \u2190 Diagn\u00f2stic o comprovaci\u00f3 del servei TTS\n\u251c\u2500\u2500 <mark style=\"background-color:rgba(0, 0, 0, 0);color:#e91010\" class=\"has-inline-color\">index.php <\/mark>                 \u2190 Interf\u00edcie web principal del projecte\n\u251c\u2500\u2500 tts.mp3                    \u2190 Fitxer d\u2019\u00e0udio generat (resultat final)\n\u251c\u2500\u2500 \n\u251c\u2500\u2500 env_tts\/                   \u2190 Entorn virtual Python dedicat a TTS\n\u251c\u2500\u2500 venv\/                      \u2190 Possible entorn virtual duplicat\n\u251c\u2500\u2500 venv_web\/                  \u2190 Potser creat per a la web; revisa si s\u2019usa\n\u2514\u2500\u2500 edge_tts\/                  \u2190 Pot contenir recursos o m\u00f2duls complementaris\n <\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Entorn<\/h2>\n\n\n\n<p>la carpeta t\u00e9  crear un entorn virtual amb una versi\u00f3 espec\u00edfica de Python especifica:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">index.php<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\/\/ Llista de veus\n$voices = &#91;\n    \"Microsoft Helena Desktop\",\n    \"Microsoft Hazel Desktop\",\n    \"Microsoft Zira Desktop\",\n    \"Microsoft Hortense Desktop\",\n    \"Vocalizer Expressive Jordi Harpo 22kHz\"\n];\n\n\/\/ Carrega valors antics per mantenir-los al formulari\n$lastText = isset($_GET&#91;'text']) ? htmlspecialchars($_GET&#91;'text']) : '';\n$lastVoice = isset($_GET&#91;'voice']) ? $_GET&#91;'voice'] : '';\n?&gt;\n&lt;!DOCTYPE html&gt;\n&lt;html lang=\"ca\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;title&gt;Generador TTS&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;Text-to-Speech (amb Python)&lt;\/h1&gt;\n    &lt;form action=\"exec_script_py.php\" method=\"post\"&gt;\n        &lt;label for=\"text\"&gt;Introdueix el text:&lt;\/label&gt;&lt;br&gt;\n        &lt;textarea name=\"text\" id=\"text\" rows=\"4\" cols=\"50\"&gt;&lt;?= $lastText ?&gt;&lt;\/textarea&gt;&lt;br&gt;&lt;br&gt;\n\n        &lt;label for=\"voice\"&gt;Selecciona una veu:&lt;\/label&gt;&lt;br&gt;\n        &lt;select name=\"voice\" id=\"voice\"&gt;\n            &lt;?php foreach ($voices as $voice): ?&gt;\n                &lt;option value=\"&lt;?= htmlspecialchars($voice) ?&gt;\" &lt;?= ($voice == $lastVoice ? 'selected' : '') ?&gt;&gt;\n                    &lt;?= htmlspecialchars($voice) ?&gt;\n                &lt;\/option&gt;\n            &lt;?php endforeach; ?&gt;\n        &lt;\/select&gt;&lt;br&gt;&lt;br&gt;\n\n        &lt;input type=\"submit\" value=\"Generar \u00e0udio\"&gt;\n    &lt;\/form&gt;\n\n    &lt;?php if (isset($_GET&#91;'error'])): ?&gt;\n        &lt;p style=\"color:red;\"&gt;\u274c Error: &lt;?= htmlspecialchars($_GET&#91;'error']) ?&gt;&lt;\/p&gt;\n    &lt;?php endif; ?&gt;\n\n    &lt;?php if (file_exists(\"tts.mp3\")): ?&gt;\n        &lt;h2&gt;Resultat:&lt;\/h2&gt;\n        &lt;audio controls&gt;\n            &lt;source src=\"tts.mp3?&lt;?= time() ?&gt;\" type=\"audio\/mpeg\"&gt;\n            El teu navegador no suporta \u00e0udio.\n        &lt;\/audio&gt;\n    &lt;?php endif; ?&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">generar_tts.py<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>\nimport sys\nimport os\nfrom gtts import gTTS\n\n# Agafa el directori actual del fitxer Python\nbase_dir = os.path.dirname(os.path.abspath(__file__))\noutput_path = os.path.join(base_dir, \"tts.mp3\")\n\n# Recollir text i veu\ntext = sys.argv&#91;1] if len(sys.argv) &gt; 1 else \"Text per defecte\"\nvoice = sys.argv&#91;2] if len(sys.argv) &gt; 2 else \"default\"\n\nprint(f\"\u25b6 Text: {text}\")\nprint(f\"\u25b6 Veu seleccionada: {voice} (no utilitzada per gTTS)\")\nprint(f\"\u25b6 Fitxer a guardar: {output_path}\")\n\n# Generar MP3\ntts = gTTS(text=text, lang='ca')\ntts.save(output_path)\n\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">exec_script_py.php <\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\nif ($_SERVER&#91;'REQUEST_METHOD'] === 'POST') {\n    $textRaw = $_POST&#91;'text'] ?? '';\n    $voiceRaw = $_POST&#91;'voice'] ?? '';\n\n    \/\/ Guarda per reenviar despr\u00e9s\n    $text = escapeshellarg($textRaw);\n    $voice = escapeshellarg($voiceRaw);\n\n    \/\/ DEBUG: mostra quin python s'est\u00e0 usant\n    $pythonPath = shell_exec(\"where python3\");\n    echo \"&lt;pre&gt;Python detectat:\\n$pythonPath&lt;\/pre&gt;\";\n\n\n\n    \/\/ Crida python del synology? o pytho windows 11 amb la comanda real\n    $command = \"\/bin\/python3 generar_tts.py $text $voice 2&gt;&amp;1\";\n    $output = shell_exec($command);\n\n    echo \"&lt;pre&gt;Sortida execuci\u00f3:\\n$command\\n\\n$output&lt;\/pre&gt;\"; \/\/ Ajuda per depuraci\u00f3\n\n    \/\/ Comprova si s'ha creat l'\u00e0udio\n    if (!file_exists(\"tts.mp3\")) {\n        $error = \"No s'ha pogut generar l'\u00e0udio. Sortida: $output\";\n        header(\"Location: index.php?error=\" . urlencode($error) . \"&amp;text=\" . urlencode($textRaw) . \"&amp;voice=\" . urlencode($voiceRaw));\n        exit();\n    }\n\n    \/\/ Redirigeix a index amb el text i veu conservats\n    header(\"Location: index.php?text=\" . urlencode($textRaw) . \"&amp;voice=\" . urlencode($voiceRaw));\n    exit();\n}\n?&gt;\n\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Entorn la carpeta t\u00e9 crear un entorn virtual amb una versi\u00f3 espec\u00edfica de Python especifica: index.php generar_tts.py exec_script_py.php<\/p>\n","protected":false},"author":2,"featured_media":3170,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[185],"tags":[],"class_list":["post-16547","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-veus"],"_links":{"self":[{"href":"http:\/\/www.beseit.net\/index.php?rest_route=\/wp\/v2\/posts\/16547","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.beseit.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.beseit.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.beseit.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.beseit.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=16547"}],"version-history":[{"count":20,"href":"http:\/\/www.beseit.net\/index.php?rest_route=\/wp\/v2\/posts\/16547\/revisions"}],"predecessor-version":[{"id":16642,"href":"http:\/\/www.beseit.net\/index.php?rest_route=\/wp\/v2\/posts\/16547\/revisions\/16642"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/www.beseit.net\/index.php?rest_route=\/wp\/v2\/media\/3170"}],"wp:attachment":[{"href":"http:\/\/www.beseit.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=16547"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.beseit.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=16547"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.beseit.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=16547"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}