diff --git a/Data/scripts.csv b/Data/scripts.csv index 9123b6e9..394d935d 100644 --- a/Data/scripts.csv +++ b/Data/scripts.csv @@ -76,6 +76,7 @@ turn-volume-up.ps1, turns the audio volume up (+10% by default) turn-volume-down.ps1, turns the audio volume down (-10% by default) txt2wav.ps1, converts text into a audio .WAV file unmute-audio.ps1, unmutes audio +voice-control.ps1, executes the PowerShell scripts by voice weather.ps1, prints the current weather forecast weather-alert.ps1, checks the current weather for critical values weather-report.ps1, prints the local weather report diff --git a/README.md b/README.md index f3fd52de..6be34d77 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ The following PowerShell scripts can be found in the [Scripts/](Scripts/) subfol * [turn-volume-down.ps1](Scripts/turn-volume-down.ps1) - turns the audio volume down (-10% by default) * [txt2wav.ps1](Scripts/txt2wav.ps1) - converts text into a audio .WAV file * [unmute-audio.ps1](Scripts/unmute-audio.ps1) - unmutes audio +* [voice-control.ps1](Scripts/voice-control.ps1) - executes the PowerShell scripts by voice * [weather.ps1](Scripts/weather.ps1) - prints the current weather forecast * [weather-alert.ps1](Scripts/weather-alert.ps1) - checks the current weather for critical values * [weather-report.ps1](Scripts/weather-report.ps1) - prints the local weather report diff --git a/Scripts/test.ps1 b/Scripts/test.ps1 deleted file mode 100755 index dc7e6ee3..00000000 --- a/Scripts/test.ps1 +++ /dev/null @@ -1,150 +0,0 @@ -$null = [Reflection.Assembly]::LoadWithPartialName("System.Speech") - -## Create the two main objects we need for speech recognition and synthesis -if (!$global:SpeechModuleListener) { - ## For XP's sake, don't create them twice... - $global:SpeechModuleSpeaker = New-Object System.Speech.Synthesis.SpeechSynthesizer - $global:SpeechModuleListener = New-Object System.Speech.Recognition.SpeechRecognizer -} - -$script:SpeechModuleMacros = @{} -## Add a way to turn it off -$script:SpeechModuleMacros.Add("Stop Listening", {$script:listen = $false; Suspend-Listening}) -$script:SpeechModuleComputerName = ${env:ComputerName} - -function Update-SpeechCommands { - #.Synopsis - # Recreate the speech recognition grammar - #.Description - # This parses out the speech module macros, - # and recreates the speech recognition grammar and semantic results, - # and then updates the SpeechRecognizer with the new grammar, - # and makes sure that the ObjectEvent is registered. - $choices = New-Object System.Speech.Recognition.Choices - foreach ($choice in $script:SpeechModuleMacros.GetEnumerator()) { - New-Object System.Speech.Recognition.SemanticResultValue $choice.Key, $choice.Value.ToString() | - ForEach-Object { $choices.Add($_.ToGrammarBuilder()) } - } - - if ($VerbosePreference -ne "SilentlyContinue") { - $script:SpeechModuleMacros.Keys | - ForEach-Object { Write-Host"$Computer, $_" -Fore Cyan } - } - - $builder = New-Object System.Speech.Recognition.GrammarBuilder"$Computer, " - $builder.Append((New-ObjectSystem.Speech.Recognition.SemanticResultKey"Commands", $choices.ToGrammarBuilder())) - $grammar = New-Object System.Speech.Recognition.Grammar $builder - $grammar.Name = "Power VoiceMacros" - - ## Take note of the events, but only once (make sure to remove the old one) - Unregister-Event"SpeechModuleCommandRecognized" -ErrorAction SilentlyContinue - $null = Register-ObjectEvent $grammar SpeechRecognized ` - -SourceIdentifier"SpeechModuleCommandRecognized" ` - -Action {iex $event.SourceEventArgs.Result.Semantics.Item("Commands").Value} - - $global:SpeechModuleListener.UnloadAllGrammars() - $global:SpeechModuleListener.LoadGrammarAsync($grammar) -} - -function Add-SpeechCommands { - #.Synopsis - # Add one or more commands to the speech-recognition macros, and update the recognition - #.Parameter CommandText - # The string key for the command to remove - [CmdletBinding()] - Param([hashtable]$VoiceMacros,[string]$Computer=$Script:SpeechModuleComputerName) - - ## Add the new macros - $script:SpeechModuleMacros += $VoiceMacros - ## Update the default if they change it, so they only have to do that once. - $script:SpeechModuleComputerName = $Computer - Update-SpeechCommands -} - -function Remove-SpeechCommands { - #.Synopsis - # Remove one or more command from the speech-recognition macros, and update the recognition - #.Parameter CommandText - # The string key for the command to remove - Param([string[]]$CommandText) - foreach ($command in $CommandText) { - $script:SpeechModuleMacros.Remove($Command) - } - Update-SpeechCommands -} - -function Clear-SpeechCommands { - #.Synopsis - # Removes all commands from the speech-recognition macros, and update the recognition - #.Parameter CommandText - # The string key for the command to remove - $script:SpeechModuleMacros = @{} - ## Default value: A way to turn it off - $script:SpeechModuleMacros.Add("Stop Listening", {Suspend-Listening}) - Update-SpeechCommands -} - -function Start-Listening { - #.Synopsis - # Sets the SpeechRecognizer to Enabled - $global:SpeechModuleListener.Enabled = $true - Say "Speech Macros are $($Global:SpeechModuleListener.State)" - Write-Host "Speech Macros are $($Global:SpeechModuleListener.State)" -} - -function Suspend-Listening { - #.Synopsis - # Sets the SpeechRecognizer to Disabled - $global:SpeechModuleListener.Enabled = $false - Say "Speech Macros are disabled" - Write-Host "Speech Macros are disabled" -} - - -function Out-Speech { - #.Synopsis - # Speaks the input object - #.Description - # Uses the default SpeechSynthesizer settings to speak the string representation of the InputObject - #.Parameter InputObject - # The object to speak - # NOTE: this should almost always be a pre-formatted string, - # most objects don't render to very speakable text. - Param([Parameter(ValueFromPipeline=$true)][Alias("IO")]$InputObject) - $null = $global:SpeechModuleSpeaker.SpeakAsync(($InputObject | Out-String)) -} - -function Remove-SpeechXP { - #.Synopis - # Dispose of the SpeechModuleListener and SpeechModuleSpeaker - $global:SpeechModuleListener.Dispose(); $global:SpeechModuleListener = $null - $global:SpeechModuleSpeaker.Dispose(); $global:SpeechModuleSpeaker = $null -} - -#Set-Alias asc Add-SpeechCommands -#Set-Alias rsc Remove-SpeechCommands -#Set-Alias csc Clear-SpeechCommands -Set-Alias say Out-Speech -#Set-Alias listen Start-Listener -#Export-ModuleMember -Function * -Alias * -VariableSpeechModuleListener, SpeechModuleSpeaker - -#Clear-SpeechCommands -Add-SpeechCommands @{ - "What time is it?" = { Say "It is $(Get-Date -f "h:mm tt")" } - "What day is it?" = { Say $(Get-Date -f "dddd, MMMM dd") } - "What's running?" = { - $proc = ps | sort ws -desc - Say $("$($proc.Count) processes, including $($proc[0].name), which is using " + - "$([int]($proc[0].ws/1mb)) megabytes of memory") - } -} -Computer "Laptop" -Verbose - -Add-SpeechCommands @{ - "Open Notepad"= { & "C:\Programs\DevTools\Notepad++\notepad++.exe"} -} - -Start-Listening - -start-sleep 10 - -exit 0 diff --git a/Scripts/voice-control.ps1 b/Scripts/voice-control.ps1 new file mode 100755 index 00000000..208221a9 --- /dev/null +++ b/Scripts/voice-control.ps1 @@ -0,0 +1,46 @@ +#!/snap/bin/powershell +<# +.SYNTAX ./voice-control.ps1 +.DESCRIPTION executes the PowerShell scripts by voice +.LINK https://github.com/fleschutz/PowerShell +.NOTES Author: Markus Fleschutz / License: CC0 +#> + +write-output "Initializing the speech recognition engine..." +$speechRecogEng = [System.Speech.Recognition.SpeechRecognitionEngine]::new(); +$speechRecogEng.InitialSilenceTimeout = 15 +$speechRecogEng.SetInputToDefaultAudioDevice(); + +write-output "Loading the grammar..." +$grammar1 = [System.Speech.Recognition.GrammarBuilder]::new(); +$grammar1.Append("hello"); +$speechRecogEng.LoadGrammar($grammar1); + +$grammar2 = [System.Speech.Recognition.GrammarBuilder]::new(); +$grammar2.Append("open notepad"); +$speechRecogEng.LoadGrammar($grammar2); + +$grammar3 = [System.Speech.Recognition.GrammarBuilder]::new(); +$grammar3.Append("exit"); +$speechRecogEng.LoadGrammar($grammar3); + +write-output "Listening now..." +$done = $false; +while (!$done) { + $recognized = $speechRecogEng.Recognize() + write-host -nonewline "." + if ($recognized.confidence -lt 0.30) { continue } + $myWords = $recognized.text + write-host -nonewline "$myWords ($($recognized.confidence) %)" + if ($myWords -match "hello") { + continue + } + if ($myWords -match "open notepad") { + continue + } + if ($myWords -match "exit") { + $done = $true + } +} + +exit 0