|
1 | | -<# |
2 | | -.SYNOPSIS |
3 | | - Generates a WAV audio file from text using Windows built-in TTS. |
4 | | -
|
5 | | -.DESCRIPTION |
6 | | - Uses System.Speech.Synthesis.SpeechSynthesizer (built into Windows — no |
7 | | - external API key or installation required) to convert a narration string |
8 | | - into a WAV file. |
9 | | -
|
10 | | - Called by the Playwright screenshots spec after each page.screenshot() call |
11 | | - so that every blog screenshot has a matching narration audio file. |
12 | | -
|
13 | | -.PARAMETER Text |
14 | | - The narration text to speak. Keep to 1-3 sentences for best pacing. |
15 | | -
|
16 | | -.PARAMETER OutputPath |
17 | | - Full path for the output WAV file (e.g. screenshots-output\series-1\dashboard.wav). |
18 | | - Parent directory must already exist. |
19 | | -
|
20 | | -.PARAMETER Voice |
21 | | - Optional. Name of an installed Windows TTS voice. |
22 | | - Run: Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).GetInstalledVoices() | Select -ExpandProperty VoiceInfo | Select Name |
23 | | - Defaults to the system default voice. |
24 | | -
|
25 | | -.PARAMETER Rate |
26 | | - Speech rate: -10 (slowest) to 10 (fastest). Default: -1 (slightly slower |
27 | | - than default for clearer narration in video). |
28 | | -
|
29 | | -.PARAMETER Volume |
30 | | - Volume: 0-100. Default: 100. |
31 | | -
|
32 | | -.EXAMPLE |
33 | | - .\speak.ps1 -Text "The dashboard loads immediately after login." -OutputPath "screenshots-output\series-1\dashboard.wav" |
34 | | -
|
35 | | -.EXAMPLE |
36 | | - .\speak.ps1 -Text "Here we can see the AI insights card." -OutputPath "out.wav" -Voice "Microsoft David Desktop" -Rate -2 |
37 | | -#> |
38 | | - |
39 | | -[CmdletBinding()] |
40 | 1 | param( |
41 | | - [Parameter(Mandatory = $true)] |
42 | | - [string] $Text, |
43 | | - |
44 | | - [Parameter(Mandatory = $true)] |
45 | | - [string] $OutputPath, |
46 | | - |
47 | | - [string] $Voice = "", |
48 | | - [int] $Rate = -1, |
49 | | - [int] $Volume = 100 |
| 2 | + [Parameter(Mandatory=$true)][string]$Text, |
| 3 | + [Parameter(Mandatory=$true)][string]$OutputPath, |
| 4 | + [string]$Voice = "", |
| 5 | + [int]$Rate = -1, |
| 6 | + [int]$Volume = 100 |
50 | 7 | ) |
51 | 8 |
|
52 | 9 | Set-StrictMode -Version Latest |
53 | 10 | $ErrorActionPreference = 'Stop' |
54 | 11 |
|
55 | | -try { |
56 | | - Add-Type -AssemblyName System.Speech |
| 12 | +Add-Type -AssemblyName System.Speech |
| 13 | +$synth = New-Object System.Speech.Synthesis.SpeechSynthesizer |
57 | 14 |
|
58 | | - $synth = New-Object System.Speech.Synthesis.SpeechSynthesizer |
59 | | - |
60 | | - # Select voice if specified; otherwise use system default |
61 | | - if ($Voice -ne "") { |
62 | | - try { |
63 | | - $synth.SelectVoice($Voice) |
64 | | - } catch { |
65 | | - Write-Warning "Voice '$Voice' not found — using system default. Available voices:" |
66 | | - $synth.GetInstalledVoices() | ForEach-Object { |
67 | | - Write-Warning (" " + $_.VoiceInfo.Name) |
68 | | - } |
69 | | - } |
| 15 | +if ($Voice -ne "") { |
| 16 | + try { |
| 17 | + $synth.SelectVoice($Voice) |
| 18 | + } catch { |
| 19 | + Write-Warning "Voice '$Voice' not found, using system default." |
70 | 20 | } |
| 21 | +} |
71 | 22 |
|
72 | | - $synth.Rate = [Math]::Max(-10, [Math]::Min(10, $Rate)) |
73 | | - $synth.Volume = [Math]::Max(0, [Math]::Min(100, $Volume)) |
74 | | - |
75 | | - # Ensure output directory exists |
76 | | - $dir = Split-Path -Parent $OutputPath |
77 | | - if ($dir -and -not (Test-Path $dir)) { |
78 | | - New-Item -ItemType Directory -Path $dir -Force | Out-Null |
79 | | - } |
| 23 | +$synth.Rate = [Math]::Max(-10, [Math]::Min(10, $Rate)) |
| 24 | +$synth.Volume = [Math]::Max(0, [Math]::Min(100, $Volume)) |
80 | 25 |
|
81 | | - $synth.SetOutputToWaveFile($OutputPath) |
82 | | - $synth.Speak($Text) |
83 | | - $synth.SetOutputToDefaultAudioDevice() # reset so the object is reusable |
84 | | - $synth.Dispose() |
| 26 | +$dir = Split-Path -Parent $OutputPath |
| 27 | +if ($dir -and -not (Test-Path $dir)) { |
| 28 | + New-Item -ItemType Directory -Path $dir -Force | Out-Null |
| 29 | +} |
85 | 30 |
|
86 | | - Write-Host "Audio saved: $OutputPath" |
87 | | - exit 0 |
| 31 | +$synth.SetOutputToWaveFile($OutputPath) |
| 32 | +$synth.Speak($Text) |
| 33 | +$synth.SetOutputToDefaultAudioDevice() |
| 34 | +$synth.Dispose() |
88 | 35 |
|
89 | | -} catch { |
90 | | - Write-Error "speak.ps1 failed: $_" |
91 | | - exit 1 |
92 | | -} |
| 36 | +Write-Host "Audio saved: $OutputPath" |
| 37 | +exit 0 |
0 commit comments