Functions/GenXdev.Console/Start-TextToSpeech.ps1
################################################################################ <# .SYNOPSIS Converts text to speech using the Windows Speech API. .DESCRIPTION Uses the Windows Speech API to convert text to speech. Supports different voices and locales, with options for synchronous or asynchronous playback. .PARAMETER Lines The text to be spoken. Can be a single string or array of strings. .PARAMETER Locale The language locale ID to use (e.g., 'en-US', 'es-ES'). .PARAMETER VoiceName The specific voice name to use for speech synthesis. .PARAMETER PassThru When specified, outputs the text being spoken to the pipeline. .PARAMETER Wait When specified, waits for speech to complete before continuing. .EXAMPLE Start-TextToSpeech "Hello World" -Locale "en-US" .EXAMPLE "Hello World" | say -Wait #> function Start-TextToSpeech { [CmdletBinding()] [Alias("say")] param( ######################################################################## [Parameter( Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromRemainingArguments = $false, ParameterSetName = "strings", HelpMessage = "Text to be spoken" )] [string[]] $Lines, ######################################################################## [Parameter( Mandatory = $false, HelpMessage = "The language locale id to use, e.g. 'en-US'" )] [string] $Locale = $null, ######################################################################## [Parameter( Mandatory = $false, HelpMessage = "Name of the voice to use for speech" )] [string] $VoiceName = $null, ######################################################################## [Parameter( Mandatory = $false, HelpMessage = "Output the text being spoken to the pipeline" )] [switch] $PassThru, ######################################################################## [Parameter( Mandatory = $false, HelpMessage = "Wait for speech to complete before continuing" )] [switch] $Wait ######################################################################## ) begin { Write-Verbose "Initializing text-to-speech with Locale: $Locale, Voice: $VoiceName" } process { # process each line of text @($Lines) | ForEach-Object { $text = $PSItem # convert non-string objects to string if ($text -isnot [string]) { $text = "$text" } try { # output text if passthru is enabled if ($PassThru) { $text } # clean up text by removing special characters $text = $text.Replace("`r", ' ').Replace("`n", ' ').Replace("`t", ' ') Write-Verbose "Processing text: $text" # handle default voice scenario if ([string]::IsNullOrWhiteSpace($Locale)) { if ([string]::IsNullOrWhiteSpace($VoiceName)) { # use default voice with optional wait if ($Wait) { Write-Verbose "Speaking synchronously with default voice" $null = [GenXdev.Helpers.Misc]::Speech.Speak($text) return } Write-Verbose "Speaking asynchronously with default voice" $null = [GenXdev.Helpers.Misc]::Speech.SpeakAsync($text) return } # use specified voice name without locale try { $voice = [GenXdev.Helpers.Misc]::SpeechCustomized.GetInstalledVoices() | Where-Object { if ([string]::IsNullOrWhiteSpace($VoiceName) -or ($PSItem.VoiceInfo.Name -like "* $VoiceName *")) { $PSItem } } | Where-Object Name | Select-Object -First 1 [GenXdev.Helpers.Misc]::SpeechCustomized.SelectVoice($voice) } catch { Write-Warning "Could not set voice: $VoiceName" } $null = [GenXdev.Helpers.Misc]::SpeechCustomized.Speak($text) return } # use specified locale and optional voice name try { $voice = [GenXdev.Helpers.Misc]::SpeechCustomized.GetInstalledVoices($Locale) | Where-Object { if ([string]::IsNullOrWhiteSpace($VoiceName) -or ($PSItem.VoiceInfo.Name -like "* $VoiceName *")) { $PSItem } } | Where-Object Name | Select-Object -First 1 [GenXdev.Helpers.Misc]::SpeechCustomized.SelectVoice($voice) } catch { Write-Warning "Could not set voice for locale: $Locale" } $null = [GenXdev.Helpers.Misc]::SpeechCustomized.Speak($text) } catch { Write-Error "Speech synthesis failed: $($PSItem.Exception.Message)" $null = [GenXdev.Helpers.Misc]::Speech.Speak($text) } } } end { } } ################################################################################ |