转换python espeak + subprocess代码直接播放输出音频
Convert python espeak + subprocess code to play output audio directly
我正在使用一个现有程序,该程序从套接字读取 xml,将文本转换为 wav 文件,然后通过音频输出设备播放。
我想将其剥离,以便它直接播放文本到音频。
现在我很难弄清楚我是否有正确的代码并理解它是否真的在创建 wav 文件。
调用文字转语音功能的函数
def generate_audio(self, language, voice=None):
info = self.get_first_info(language, bestmatch=False)
if info is None:
self.media_info[language] = None
return False
truncate = not self.broadcast_immediately() and bcastplayer.Config.setting('alerts_truncate')
message_text = info.get_message_text(truncate)
location = bcastplayer.ObData.get_datadir() + "/alerts"
if os.access(location, os.F_OK) == False:
os.mkdir(location)
filename = self.reference(self.sent, self.identifier) + "-" + language + ".wav"
resources = info.get_resources('audio')
if resources:
if resources[0].write_file(os.path.join(location, filename)) is False:
return False
elif message_text:
self.write_tts_file(os.path.join(location, filename), message_text, voice)
else:
return False
这个可以改成直接播放音频吗?
def write_tts_file(self, path, message_text, voice=None):
if not voice:
voice = 'en'
proc = subprocess.Popen([ 'espeak', '-m', '-v', voice, '-s', '130', '--stdout' ], stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
(stdout, stderr) = proc.communicate(message_text.encode('utf-8') + b" <break time=\"2s\" /> " + message_text.encode('utf-8') + b" <break time=\"3s\" /> ")
proc.wait()
with open(path, 'wb') as f:
f.write(stdout)
我从未见过这样的代码使用 process
、subprocess
、stdout
、PIPE
。
在不创建 wav 文件的情况下,将子流程代码更改为仅通过管道或将输出重定向到 aplay
的内容是否容易?
还有另一个答案可能会提供线索 - 但同样,我的新手理解不确定如何将此代码转换为该答案
您可以 link 使用 subprocess.PIPE
将两个进程一起使用。这是 write_tts_file
函数的修改版本:
def write_tts_file(self, path, message_text, voice=None):
if not voice:
voice = 'en'
proc = subprocess.Popen(['espeak', '-m', '-v', voice, '-s', '130', '--stdout' ], stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
aplay = subprocess.Popen(['aplay', '-D', 'sysdefault'], stdin=proc.stdout)
proc.stdin.write(message_text.encode('utf-8') + b" <break time=\"2s\" /> " + message_text.encode('utf-8') + b" <break time=\"3s\" /> \n")
proc.stdin.close()
proc.wait()
发送要说的消息后,关闭 proc
的 stdin
很重要。这将使 proc
在发送完数据后退出,并关闭其对 aplay
的输出,而 aplay
将在播放结束后退出。如果proc
的输入没有关闭,他们都不会退出。
我正在使用一个现有程序,该程序从套接字读取 xml,将文本转换为 wav 文件,然后通过音频输出设备播放。
我想将其剥离,以便它直接播放文本到音频。
现在我很难弄清楚我是否有正确的代码并理解它是否真的在创建 wav 文件。
调用文字转语音功能的函数
def generate_audio(self, language, voice=None):
info = self.get_first_info(language, bestmatch=False)
if info is None:
self.media_info[language] = None
return False
truncate = not self.broadcast_immediately() and bcastplayer.Config.setting('alerts_truncate')
message_text = info.get_message_text(truncate)
location = bcastplayer.ObData.get_datadir() + "/alerts"
if os.access(location, os.F_OK) == False:
os.mkdir(location)
filename = self.reference(self.sent, self.identifier) + "-" + language + ".wav"
resources = info.get_resources('audio')
if resources:
if resources[0].write_file(os.path.join(location, filename)) is False:
return False
elif message_text:
self.write_tts_file(os.path.join(location, filename), message_text, voice)
else:
return False
这个可以改成直接播放音频吗?
def write_tts_file(self, path, message_text, voice=None):
if not voice:
voice = 'en'
proc = subprocess.Popen([ 'espeak', '-m', '-v', voice, '-s', '130', '--stdout' ], stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
(stdout, stderr) = proc.communicate(message_text.encode('utf-8') + b" <break time=\"2s\" /> " + message_text.encode('utf-8') + b" <break time=\"3s\" /> ")
proc.wait()
with open(path, 'wb') as f:
f.write(stdout)
我从未见过这样的代码使用 process
、subprocess
、stdout
、PIPE
。
在不创建 wav 文件的情况下,将子流程代码更改为仅通过管道或将输出重定向到 aplay
的内容是否容易?
还有另一个答案可能会提供线索 - 但同样,我的新手理解不确定如何将此代码转换为该答案
您可以 link 使用 subprocess.PIPE
将两个进程一起使用。这是 write_tts_file
函数的修改版本:
def write_tts_file(self, path, message_text, voice=None):
if not voice:
voice = 'en'
proc = subprocess.Popen(['espeak', '-m', '-v', voice, '-s', '130', '--stdout' ], stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
aplay = subprocess.Popen(['aplay', '-D', 'sysdefault'], stdin=proc.stdout)
proc.stdin.write(message_text.encode('utf-8') + b" <break time=\"2s\" /> " + message_text.encode('utf-8') + b" <break time=\"3s\" /> \n")
proc.stdin.close()
proc.wait()
发送要说的消息后,关闭 proc
的 stdin
很重要。这将使 proc
在发送完数据后退出,并关闭其对 aplay
的输出,而 aplay
将在播放结束后退出。如果proc
的输入没有关闭,他们都不会退出。