📁 Estructura del projecte
C:\
├── tts\
│ ├── tts-to-wav.ps1 ← Script PowerShell per generar l’àudio
│ └── list-voices.ps1 ← Script PowerShell per llistar veus
└── AppServ\
└── www\
└── tts\
├── index.php ← Interfície web
└── tts.wav ← Fitxer d’àudio generat
📄 Què és un fitxer .ps1
?
Un fitxer .ps1
és un script de PowerShell, el llenguatge de línia de comandes i automatització de Windows. S’utilitza per executar ordres, scripts i automatitzar tasques del sistema.
📘 Documentació dels components
1. list-voices.ps1
— Llista de veus SAPI5
Add-Type -AssemblyName System.Speech
$synth = New-Object System.Speech.Synthesis.SpeechSynthesizer
$synth.GetInstalledVoices() | ForEach-Object {
$info = $_.VoiceInfo
$label = "SAPI5|$($info.Name)"
Write-Output $label
}
🔹 Funció: Detecta totes les veus SAPI5 instal·lades i les imprimeix amb el prefix SAPI5|
.
2. tts-to-wav.ps1
— Generació d’àudio
param (
[string]$text = "Hola món",
[string]$voiceName,
[string]$outputPath = "C:\tts\tts.wav"
)
try {
if ($voiceName -like "SAPI5|*") {
$realVoice = $voiceName.Substring(6)
Add-Type -AssemblyName System.Speech
$synth = New-Object System.Speech.Synthesis.SpeechSynthesizer
$synth.SelectVoice($realVoice)
$synth.SetOutputToWaveFile($outputPath)
$synth.Speak($text)
} else {
Write-Error "Format de veu desconegut: $voiceName"
exit 1
}
}
catch {
Write-Error "Error inesperat: $_"
exit 1
}
🔹 Funció: Rep un text i una veu, i genera un fitxer .wav
amb la veu seleccionada.
3. index.php
— Interfície web
<?php
// Obtenim la llista de veus
$voiceListCmd = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -ExecutionPolicy Bypass -File C:\\tts\\list-voices.ps1";
exec($voiceListCmd, $voices, $voiceStatus);
// Depuració: mostra les veus detectades
echo "<pre><strong>Veus detectades:</strong>\n";
print_r($voices);
echo "</pre>";
// Si falla, usem una llista per defecte
if ($voiceStatus !== 0 || empty($voices)) {
$voices = [
"SAPI5|Microsoft Helena Desktop",
"SAPI5|Microsoft Hazel Desktop",
"SAPI5|Microsoft Zira Desktop"
];
}
?>
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="UTF-8">
<title>Conversió TTS</title>
</head>
<body>
<h2>🔊 Conversió de text a veu (SAPI5)</h2>
<form method="get">
<label for="text">Text a llegir:</label><br>
<textarea name="text" rows="4" cols="60"><?= htmlspecialchars($_GET['text'] ?? '') ?></textarea><br><br>
<label for="voice">Selecciona una veu:</label><br>
<select name="voice">
<?php foreach ($voices as $v): ?>
<option value="<?= htmlspecialchars($v) ?>" <?= ($v === ($_GET['voice'] ?? '')) ? 'selected' : '' ?>>
<?= htmlspecialchars($v) ?>
</option>
<?php endforeach; ?>
</select><br><br>
<button type="submit">▶️ Generar àudio</button>
</form>
<?php
$text = $_GET['text'] ?? '';
$voice = $_GET['voice'] ?? '';
$audioFile = '/tts/tts.wav';
if ($text && $voice) {
$escapedText = escapeshellarg($text);
$escapedVoice = escapeshellarg($voice);
$escapedOutput = escapeshellarg(__DIR__ . DIRECTORY_SEPARATOR . 'tts.wav');
$cmd = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -ExecutionPolicy Bypass -File C:\\tts\\tts-to-wav.ps1 -text $escapedText -voiceName $escapedVoice -outputPath $escapedOutput";
// 🔍 DEBUG: Mostra la comanda que s'executarà
echo "<pre><strong>Comanda PowerShell:</strong>\n$cmd\n</pre>";
exec($cmd, $outputLines, $status);
if ($status === 0 && file_exists(__DIR__ . '/tts.wav')) {
echo "<h3>✅ Àudio generat:</h3>";
echo "<audio controls autoplay style='margin-top:10px;'>
<source src=\"$audioFile\" type=\"audio/wav\">
El teu navegador no suporta àudio.
</audio>";
} else {
echo "<p style='color:red;'>❌ Error generant l’àudio.</p>";
echo "<pre><strong>Sortida PowerShell:</strong>\n";
print_r($outputLines);
echo "\nCodi de sortida: $status</pre>";
}
}
?>
</body>
</html>