Text-To-Speech using PowerShell

Just a little fun thing for a Friday, text-to-speech! We used this many years ago at the office, sending this to the laptop of a colleague and having fun while he’s trying to figure out where the voice is coming from 🙂

Table Of Contents
show

How it works

There is a System.Speech assembly, which can be used to convert text to speech, I made an Invoke-TextToSpeech function that accepts a -Text and a -Computername parameter. The -Computername starts an Invoke-Command to the computer name you specify and starts talking on the remote computer. It doesn’t have a volume control function (Yet. If anyone knows how… Let me know! ), so the speaker shouldn’t be muted on that target 🙂

Below is an example of running it locally:

Invoke-TextToSpeech -Text 'PowerShell is fun'

The voice is based on your local setting. In my case, it sounds pretty good in English. You can also output text from a variable in your script by running this:

$variable | Invoke-TextToSpeech

In the example below, it connects to a remote computer (Laptop-001) and outputs the text to that speaker:

Invoke-TextToSpeech -Text 'PowerShell is fun' -Computername Laptop-001

Note: There could be WinRM/Firewall settings preventing this on the remote computer

The script

Below is the Function that I made. Run it in your PowerShell session, and have fun 🙂

function Invoke-TextToSpeech {
    param (
        [parameter(Mandatory = $true, ValueFromPipeline = $true)][ValidateNotNullOrEmpty()][string]$Text,
        [parameter(Mandatory = $false)][string]$Computername
    )
    
    #If Computername is not specified, run local convert text to speech and output it
    if (-not $Computername) {
        try {
            Add-Type -AssemblyName System.Speech
            $synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
            $synth.Speak($text)
        }
        catch {
            Write-Warning ("Could not output text to speech")
        }
    }

    #try to connect to remote computer, convert to speech and output it
    if ($computername) {
        try {
            Invoke-Command -ScriptBlock {
                Add-Type -AssemblyName System.Speech
                $synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
                $synth.Speak($Using:Computername)
            } -ComputerName $Computername -ErrorAction Stop
        }
        catch {
            Write-Warning ("Could not connect to {0}" -f $Computername)
        }
    }
}

Download the script(s) from GitHub here

4 thoughts on “Text-To-Speech using PowerShell

    • You can only select the ones available on the system, you can find more information here about it : https://learn-powershell.net/2013/12/04/give-powershell-a-voice-using-the-speechsynthesizer-class/

      I could choose between these two, David or Zira.

      C:\Users\HarmVeenstra> $speak.GetInstalledVoices().VoiceInfo

      Gender : Male
      Age : Adult
      Name : Microsoft David Desktop
      Culture : en-US
      Id : TTS_MS_EN-US_DAVID_11.0
      Description : Microsoft David Desktop – English (United States)
      SupportedAudioFormats : {}
      AdditionalInfo : {[Age, Adult], [Gender, Male], [Language, 409], [Name, Microsoft David Desktop]…}

      Gender : Female
      Age : Adult
      Name : Microsoft Zira Desktop
      Culture : en-US
      Id : TTS_MS_EN-US_ZIRA_11.0
      Description : Microsoft Zira Desktop – English (United States)
      SupportedAudioFormats : {}
      AdditionalInfo : {[Age, Adult], [Gender, Female], [Language, 409], [Name, Microsoft Zira Desktop]…}

      I switched using the how-to on the page to $speak.SelectVoice(‘Microsoft Zira Desktop’) and got the female voice.

      In the script, you could change:

      $synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
      $synth.Speak($text)

      to

      $synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
      $synth.SelectVoice(‘Microsoft Zira Desktop’)
      $synth.Speak($text)

      but first check which ones you have available by:

      Add-Type -AssemblyName System.Speech$synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
      $synth.GetInstalledVoices().VoiceInfo

      The $synth.GetInstalledVoices().VoiceInfo shows you the options

      • Good stuff.
        My only critique is the best practices of formatting your PS code as recommended.
        The form prescribed requires multi line comments and specified help keywords.
        The multi line comments both documents your code and they also act as a help page for your users.
        The syntax of multi-line comments is this:

        help keyword b:
        help keyword c:

        #>

        The multi line comment block is not interpreted nor run…well…nearly so..?!
        As example let’s use the built in command Get-Help:
        DESCRIPTION: … (a brief description of the purpose of the function, script block etc.) .
        SYNOPSIS: …( details about your function, script block etc) .
        EXAMPLES: … ( the syntax and parameters that are used in the code) ie, Get-Help * .
        LINKS: …(allows the code to access online resources) .
        INPUTS: …
        OUTPUTS: …
        NOTES: …
        This then is the traditional format for commenting your code.
        There is much more to commenting and formatting your PS code and as such deserves an entire volume of content to be fair and thorough.
        The proper use of comment based help is not trivial and is not to be regarded as unimportant.
        The judicious use of comments will both help you with your code development as well as deployment, and it will help others who will use or who will maintain your code.

      • I totally understand what you’re saying, I’m using my blog post as help file but should include the help in the scripts… Retro updating them is a bit of work 😅

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.