Powershell может говорить, но может ли он писать, если я говорю? - PullRequest
19 голосов
/ 20 февраля 2012

Ниже приведен способ заставить PowerShell говорить.

Add-Type -AssemblyName System.Speech
$synthesizer = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
$synthesizer.Speak('Hey, I can speak!')

На самом деле я хотел бы сделать наоборот. Если я говорю, может PowerShell конвертировать его в буквы.

Если я скажу в своем диктофоне «Эй, я могу говорить», он преобразуется в текст?

Если возможно, подскажите, пожалуйста, как этого добиться?

Ответы [ 3 ]

10 голосов
/ 20 февраля 2012

Похоже, что вы можете с System.Speech.Recognition. Вот даже пример использования, написанный на PowerShell:

http://huddledmasses.org/control-your-pc-with-your-voice-and-powershell/

Эта ссылка перешла на 404, поэтому я откопал ее обратно, машина.

управляйте своим ПК с помощью голоса ... и PowerShell

Джоэл Джайкуль Беннетт 25 июня 2009 года

Вы когда-нибудь хотели иметь возможность задавать вопросы о вашем компьютере и отвечать на него вслух? Задумывались ли вы, может ли ваш компьютер быть больше похож на тот, на котором работает Star Trek Enterprise, отвечая на голосовые запросы и команды? Вы играли с домашней автоматизацией ZWave или X10 и думали, что голосовое управление вашими устройствами станет очевидным следующим шагом?

Ну, ладно ... Я не собираюсь показывать вам, как включать свет или работать с домашней автоматизацией, - но это главное, что заставляет меня задуматься над этим средством распознавания голоса. Какой гик не хочет заходить в гостиную и говорить «Компьютер: свет горит», и это работает?

Вместо этого, в качестве первого шага ко всему этому, позвольте мне показать вам, как использовать PowerShell для создания простых сценариев распознавания голосовых команд… которые могут запустить любой сценарий PowerShell, который вы захотите написать! Приведенный ниже код на самом деле является модулем, хотя вы можете просто поставить его в виде сценария, и для событий ему действительно требуется PowerShell 2.0, хотя было бы несложно реорганизовать его для работы в PowerShell 1.0 с помощью библиотеки PSEventing Oisin.

$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

Здесь есть только одна функция, о которой вам нужно беспокоиться: New-VoiceCommands. Вы передаете ему хеш-таблицу, которая отображает строки в блоки сценариев, и если вы используете ключ -Listenswitch, это все, что нужно сделать. Вы также можете вызвать функцию прослушивания Startart Listening вручную, и, конечно, я предоставил функцию Say, чтобы упростить разговор на компьютере ...

Как только компьютер «слушает» ... вы просто произносите его имя, а затем одну из ваших команд. Мне это нравится, потому что это гарантирует, что я не запускаю сценарии случайно, но вы можете удалить строку ${Env:ComputerName}, из начала GrammarBuilder, если считаете, что в этом нет необходимости, или вы можете жестко закодировать ее как-то иначе, чем ваш имя компьютера, как, скажем, «Хэл, пожалуйста, я вас умоляю ...» или «Компьютер, пожалуйста» или что-то еще?

С этим можно многое сделать ... что угодно, правда ... но, чтобы дать вам пример, который вы можете легко понять, я собираюсь сделать что-то очень простое, и мой компьютер просто ответит Поговорите со мной несколько основных вопросов, а затем добавьте несколько команд, чтобы запустить приложение или веб-страницу.

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 @{
    "Run Notepad"= { & "C:\Programs\DevTools\Notepad++\notepad++.exe"}
}
Add-SpeechCommands @{
    "Check Gee Mail" = { Start-Process"https://mail.google.com" }
}

Вы видите, как это легко? Вы можете использовать «Say» для произнесения любого текста (хотя некоторые тексты получат лучшие результаты, чем другие), и вы можете вызывать любые другие команды powershell, включая команды HttpRest для извлечения веб-данных, или команды WASP для автоматизации Windows, или команды PowerBoots для отображения вывод большого текста или командлетов для управления устройствами X10 или ZWave ... знаете, что-нибудь?

2 голосов
/ 20 февраля 2012

Распознавание речи все еще является экспериментальной технологией. Существуют некоторые .Net Framework ресурсы , даже с примером . Впрочем, не надейтесь в ближайшее время создать PowerShiri.

1 голос
/ 20 февраля 2012

Технология немного позади "экспериментальной", но далеко не надежной.

Exchange делает это сейчас с опцией «Предварительный просмотр голосовой почты» единой системы обмена сообщениями. Результаты могут варьироваться от довольно хороших до веселых, в зависимости от динамика.

...