首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Powershell实时读取文件并输出到语音

Powershell实时读取文件并输出到语音
EN

Stack Overflow用户
提问于 2018-07-27 02:15:38
回答 2查看 374关注 0票数 0

我正在寻找的是采取powershell和读出的文件内容到语音合成模块。

本例的文件名为read.txt

语音模块的开始部分:

代码语言:javascript
复制
Add-Type -AssemblyName System.speech

$Narrator1 = New-Object System.Speech.Synthesis.SpeechSynthesizer

$Narrator1.SelectVoice('Microsoft Zira Desktop')

$Narrator1.Rate = 2

$Location = "$env:userprofile\Desktop\read.txt"

$Contents = Get-Content $Location

Get-Content $Location -wait -Tail 2 | where {$Narrator1.Speak($Contents)}

这只有效一次。我喜欢在每次初始读取后使用Clear-Content擦除read.txt,并让powershell等待read.txt文件中添加新行,然后再次处理它以读出内容。我相信我也可以用-windowstyle hidden让它在后台运行

感谢您对我的帮助。

史考特

EN

回答 2

Stack Overflow用户

发布于 2018-07-27 05:18:54

我不认为循环是解决问题的办法,我会使用FileSystemWatcher来检测文件什么时候发生了变化。试试这个:

代码语言:javascript
复制
$fsw = New-Object System.IO.FileSystemWatcher
$fsw.Path = "$env:userprofile\Desktop"
$fsw.Filter = 'read.txt'

Register-ObjectEvent -InputObject $fsw -EventName Changed  -Action {
    Add-Type -AssemblyName System.speech
    $Narrator1 = New-Object System.Speech.Synthesis.SpeechSynthesizer
    $Narrator1.SelectVoice('Microsoft Zira Desktop')
    $Narrator1.Rate = 2

    $file = $Event.SourceEventArgs.FullPath

    $Contents = Get-Content $file
    $Narrator1.Speak($Contents)
} 
票数 1
EN

Stack Overflow用户

发布于 2018-07-27 09:49:25

唯一的问题是,您意外地在where (Where-Object)脚本块中使用了先前分配的$Contents变量,而不是$_,后者是表示当前管道对象的自动变量

代码语言:javascript
复制
Get-Content $Location -Wait -Tail 2 | Where-Object { $Narrator1.Speak($_) }

Get-Content $Location -Wait 将每秒轮询输入文件(此处为**$Location**),以检查新的内容并通过管道传递它( -Tail参数仅适用于文件的初始读取;当添加新行时,它们都会被传递)。

在删除$Location文件或中止处理之前,流水线将无限期地保持活动状态。

由于该命令是阻塞的,因此您显然需要另一个会话/进程来将内容添加到文件$Location,例如另一个PowerShell窗口或文本编辑器,该编辑器打开文件并修改其内容。

您可以继续使用>>将其附加到文件中,但这会使其不断增长。

要丢弃文件以前的Clear-Content,,您确实必须像您所说的那样使用content,这会截断现有文件而不重新创建它,从而使管道保持活动状态;例如:

代码语言:javascript
复制
Clear-Content $Location
'another line to speak' > $Location

警告:特殊字符。例如!?,似乎会导致无法说话。如果有人知道为什么,一定要告诉我们。docs没有提供直接的线索。

至于后台操作

奇怪的是,Clear-Content > /的组合<代码>E251<代码>E152而不是<代码>E253<代码>E154出现在<代码>E255中;如果有人知道原因,请告诉我们。

但是,使用 >> 的确实可以工作。

下面的代码片段演示了如何使用后台作业在将语音输入添加到指定文件时保持语音输入(有一些延迟),直到发送特殊的输入结束字符串:

代码语言:javascript
复制
# Determine the input file (on the user's desktop)
$file = Join-Path ([environment]::GetFolderPath('Desktop')) 'read.txt'

# Initialize the input file.
$null > $file

# Define a special string that acts as the end-of-input marker.
$eofMarker = '[quit]'

# Start the background job (PSv3+ syntax)
$job = Start-Job { 
  Add-Type -AssemblyName System.speech

  $Narrator1 = New-Object System.Speech.Synthesis.SpeechSynthesizer

  $Narrator1.SelectVoice('Microsoft Zira Desktop')

  $Narrator1.Rate = 2

  while ($true) { # A dummy loop we can break out of on receiving the end-of-input marker
    Get-Content $using:file -Wait | Where-Object { 
      if ($_ -eq $using:eofMarker) { break } # End-of-input marker received -> exit the pipeline.
      $Narrator1.Speak($_) 
    }
  }

  # Remove the input file.
  Remove-Item -ErrorAction Ignore -LiteralPath $using:file

}

# Speak 1, 2, ..., 10
1..10 | ForEach-Object {
  Write-Verbose -Verbose $_
  # !! Inexplicably, using Clear-Content followed by > to keep
  # !! replacing the file content does *not* work with a background task.
  # !! >> - which *appends* to the file - does work, however.
  $_ >> $file
}

# Send the end-of-input marker to make the background job stop reading.
$eofMarker >> $file

# Wait for background processing to finish.
# Note: We'll get here long before the background job has finished speaking.
Write-Verbose -Verbose 'Waiting for processing to finish to cleanup...'
$null = Receive-Job $job -wait -AutoRemoveJob
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51545201

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档