PowerShell speaks
So, a buddy was showing off the “say” command in the Mac OS X terminal the other day (my 3 year old daughter was vastly entertained) and I wondered what it would take to do the same thing in Windows PowerShell … it turns out the answer is, not much.
You just type this into the console:
$Voice = new-object -com SAPI.SpVoice
$Voice.Speak( "Hello World!", 1 )
The cool thing about this is that it’s async, unlike the Mac “say” command, so you can go on typing the next command while it’s speaking. On top of that, you can have it read a text file by just changing that 1 to a 5:
$Voice = new-object -com SAPI.SpVoice
$Voice.Speak( "C:\Text\HolyGrail.txt", 5 )
Now, being who I am, and what I am, I wasn’t content with that, so I wrote myself up a script, Out-Speech, that will speak whatever it’s given (an array of objects as an argument, or the pipeline objects … ) and exposes most of the options of the underlying Speech API.
I’ll post the code here, but I thought I’d just mention … I’m not really using this in very many places, but it’s really fun with the Select-Random script I posted earlier. I alias that to “rand” and this to “say” ... so I can do: cat quotes.txt | rand | say How fun is that? Yeah, well, or you could use it to report on the progress of long-running scripts, or something else more useful. :-|
# Out-Speech
param([array]$Collection, [switch]$wait, [switch]$purge, [switch]$readfiles, [switch]$readxml, [switch]$notxml)
begin
{
if ($args -eq '-?') {
''
'Usage: Out-Speech [[-Collection] <array>]'
''
'Parameters:'
' -Collection : A collection of items to speak.'
' -? : Display this usage information'
' Switches:'
' -wait : Wait for the machine to read each item (NOT asynchronous).'
' -purge : Purge all other speech requests before making this call.'
' -readfiles : Read the contents of the text files indicated.'
' -readxml : Treat input as speech XML markup.'
' -notxml : Do NOT parse XML (if text starts with "<" but is not XML).'
''
'Examples:'
' PS> Out-Speech "Hello World"'
' PS> Select-RandomLine quotes.txt | Out-Speech -wait'
' PS> Out-Speech -readfiles "Hitchhiker''s Guide To The Galaxy.txt"'
''
exit
}
# To override this default, use the other flag values given below.
$SPF_DEFAULT = 0 # Specifies that the default settings should be used.
## The defaults are:
#~ * Speak the given text string synchronously
#~ * Not purge pending speak requests
#~ * Parse the text as XML only if the first character is a left-angle-bracket (<)
#~ * Not persist global XML state changes across speak calls
#~ * Not expand punctuation characters into words.
$SPF_ASYNC = 1 # Specifies that the Speak call should be asynchronous.
$SPF_PURGEBEFORESPEAK = 2 # Purges all pending speak requests prior to this speak call.
$SPF_IS_FILENAME = 4 # The string passed is a file name, and the file text should be spoken.
$SPF_IS_XML = 8 # The input text will be parsed for XML markup.
$SPF_IS_NOT_XML= 16 # The input text will not be parsed for XML markup.
$SPF = $SPF_DEFAULT
if(!$wait){ $SPF += $SPF_ASYNC }
if($purge){ $SPF += $SPF_PURGEBEFORESPEAK }
if($readfiles){ $SPF += $SPF_IS_FILENAME }
if($readxml){ $SPF += $SPF_IS_XML }
if($notxml){ $SPF += $SPF_IS_NOT_XML }
$Voice = new-object -com SAPI.SpVoice
if ($collection.count -gt 0) {
foreach( $item in $collection ) {
$exit = $Voice.Speak( ($item | out-string), $SPF )
}
}
}
process
{
if ($_)
{
$exit = $Voice.Speak( ($_ | out-string), $SPF )
}
}