Skip to content

Commit e826a31

Browse files
Add PowerShell TTS voiceover and narration metadata to screenshot catalog
1 parent 22ef524 commit e826a31

2 files changed

Lines changed: 298 additions & 101 deletions

File tree

scripts/speak.ps1

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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+
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
50+
)
51+
52+
Set-StrictMode -Version Latest
53+
$ErrorActionPreference = 'Stop'
54+
55+
try {
56+
Add-Type -AssemblyName System.Speech
57+
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+
}
70+
}
71+
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+
}
80+
81+
$synth.SetOutputToWaveFile($OutputPath)
82+
$synth.Speak($Text)
83+
$synth.SetOutputToDefaultAudioDevice() # reset so the object is reusable
84+
$synth.Dispose()
85+
86+
Write-Host "Audio saved: $OutputPath"
87+
exit 0
88+
89+
} catch {
90+
Write-Error "speak.ps1 failed: $_"
91+
exit 1
92+
}

0 commit comments

Comments
 (0)