Added voice-control.ps1

This commit is contained in:
Markus Fleschutz 2021-01-05 13:55:54 +01:00
parent 502b3ca7ca
commit c22f7460d2
4 changed files with 48 additions and 150 deletions

View File

@ -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

1 Filename Description
76 turn-volume-down.ps1 turns the audio volume down (-10% by default)
77 txt2wav.ps1 converts text into a audio .WAV file
78 unmute-audio.ps1 unmutes audio
79 voice-control.ps1 executes the PowerShell scripts by voice
80 weather.ps1 prints the current weather forecast
81 weather-alert.ps1 checks the current weather for critical values
82 weather-report.ps1 prints the local weather report

View File

@ -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

View File

@ -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

46
Scripts/voice-control.ps1 Executable file
View File

@ -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