我正在寻找的是使用powershell并将文件内容读取到语音合成模块中。
此示例的文件名为echo 'arr=(' > temp
add() { echo item >> temp; }
...
export -f add
...
add &
...
echo ')' > temp
source temp
rm temp
。
“语音”模块的开始:
read.txt
这一次起作用。我喜欢在每次初次读取后使用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
,让powershell等待,直到将新行添加到read.txt
文件中,然后再次对其进行处理以说出内容。我相信我也可以使用read.txt
非常感谢您的协助。
斯科特
答案 0 :(得分:1)
我不认为循环是答案,我将使用FileSystemWatcher来检测文件何时已更改。试试这个:
$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 :(得分:0)
您唯一的问题是您意外地在$Contents
(where
)脚本块中使用了先前分配的Where-Object
变量,而不是$_
(代表< em>当前管道对象:
Get-Content $Location -Wait -Tail 2 | Where-Object { $Narrator1.Speak($_) }
Get-Content $Location -Wait
将每秒轮询输入文件(此处为$Location
)以检查新内容,并将其通过管道(仅-Tail
参数)适用于文件的初始读取;添加新行后,它们会通过 all 传递。)
管道将无限期存活-直到您删除 $Location
文件或中止处理。
由于命令是 blocking ,因此您显然需要另一个会话/进程才能将内容添加到文件$Location
,例如另一个PowerShell窗口或具有打开和修改文件的文本编辑器其内容。
您可以使用>>
将追加保留到文件中,但这将使文件不断增长。
要丢弃文件的先前内容,您确实必须使用Clear-Content
,正如您所说的那样,它会截断现有文件无需重新创建,因此可以使管道保持活动状态;例如:
Clear-Content $Location
'another line to speak' > $Location
注意事项:特殊字符。 !
和?
之类的语音似乎会导致静音。如果有人知道为什么,请告诉我们。 docs没有立即提供线索。
关于后台操作:
具有后台工作,奇怪的是,Clear-Content
/ >
组合似乎无法正常工作;如果有人知道为什么,请告诉我们。
但是,使用>>
-会增大文件大小-确实可以。
以下代码段演示了使用后台作业来保持语音输入的状态,即将其添加到指定文件中(有一定延迟),直到发送特殊的输入结束字符串为止:
# 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