我正在尝试通过 ssh 在运行 ubuntu 20.04.1 LTS 的机器上使用文本转语音程序 balabolka 及其命令行版本 Balcon。首先,我从http://www.cross-plus-a.com/fr/bconsole.htm,然后经过一番研究,我设法让它工作,这需要安装 Wine、winetricks、Microsoft SpeechPlatformRuntime、speechsdk 和 msxml6。我还安装了一些 SAPI 5 TTS 语音。我按照Wine:如何使用 SAPI 5 语音为 TTS 应用程序“Balabolka”?
我在测试时使用这个命令行:WINEPREFIX="$HOME/prefix32" wine "$HOME/prefix32/drive_c/Program Files/balcon/balcon/balcon.exe" -f text.txt -n Daniel_Full_22kHz -w audiooutput.wav
此命令在主机上直接运行时可以完美运行,但是我的目标是从另一台机器通过 ssh 运行此命令。为了测试目的,我尝试直接从 Windows 命令行建立 ssh 连接,并且使用 python + paramiko。
奇怪的是:重新启动 Ubuntu 机器后,使用任何上述方法的第一次尝试都会成功,但后续尝试总是失败。
在 Windows cmd 中使用直接 ssh 连接时,出现以下错误:
~$ WINPREFIX="$HOME/prefix32" wine "$HOME/prefix32/drive_c/Program Files/balcon/balcon/balcon.exe " -f text.txt -n Daniel_Full_22kHz -w audiooutput.wav 0009:err:winediag:nodrv_CreateWindow 应用程序尝试创建一个窗口,但无法加载驱动程序。 0009:err:winediag:nodrv_CreateWindow 确保您的 X 服务器正在运行并且 $DISPLAY 设置正确。 0009:err:ole:CoGetClassObject 类 {d941651c-44e6-4c17-badf-c36826fc3424} 未注册 0009:err:ole:create_server 类 {d941651c-44e6-4c17-badf-c36826fc3424} 未注册 0009:err:ole:CoGetClassObject 无法为上下文 0x5 创建类对象 {d941651c-44e6-4c17-badf-c36826fc3424} 0009:err:ole:CoGetClassObject 类 {cb96b400-c743-11cd-80e5-00aa003e4b50} 未注册 0009:err:ole:CoGetClassObject 类{cb96b400-c743-11cd-80e5-00aa003e4b50} 未注册 0009:err:ole:create_server 类 {cb96b400-c743-11cd-80e5-00aa003e4b50} 未注册 0009:err:ole:CoGetClassObject 无法为上下文创建类对象 {cb96b400-c743-11cd-80e5-00aa003e4b50} 0x7 错误:未选择语音
该错误表明 $DISPLAY 环境变量存在问题。使用 echo $DISPLAY 时,我发现该变量未在 ssh 控制台中设置,因此我使用 export DISPLAY=:0 对其进行设置,值 :0 是通过在 ubuntu ssh 服务器上本地运行 echo $DISPLAY 获得的。经过此修改后,所有后续尝试均能正常工作。
我尝试使用 python+paramiko 做同样的事情,这是我的脚本:
import os
import shell
import paramiko
def connectSSH(key,host,user):
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
print("connecting")
c.connect( hostname = host, username = user, pkey = k )
ftp_client = c.open_sftp()
print("connected")
filet = open("./text.txt","w")
filet.write("Hi this is a text to speech test with daniel voice")
filet.close()
ftp_client.put("./text.txt","./text.txt")
env_dict = {"DISPLAY":":0"}
cmd = "WINPREFIX=\"$HOME/prefix32\" wine \"$HOME/prefix32/drive_c/Program Files/balcon/balcon/balcon.exe \" -f %s -n %s -w %s" % ("kesra2.txt", "Daniel_Full_22kHz","audiooutput.wav")
print(cmd)
stdin,stdout,stderr=c.exec_command(cmd,environment=env_dict)
print(stdout.readlines())
print(stderr.readlines())
ftp_client.get("audiooutput.wav","audiooutput.wav")
ftp_client.close()
起初我得到了相同的 $DISPLAY 错误,因此我使用它添加它env_dict = {"DISPLAY":":0"}
并允许在服务器 sshd 配置上修改这个变量,但现在我总是收到错误:
0009:err:ole:CoGetClassObject 类 {d941651c-44e6-4c17-badf-c36826fc3424} 未注册 0009:err:ole:create_server 类 {d941651c-44e6-4c17-badf-c36826fc3424} 未注册 0009:err:ole:CoGetClassObject 无法为上下文 0x5 创建类对象 {d941651c-44e6-4c17-badf-c36826fc3424} 0009:err:ole:CoGetClassObject 类 {cb96b400-c743-11cd-80e5-00aa003e4b50} 未注册 0009:err:ole:CoGetClassObject 类{cb96b400-c743-11cd-80e5-00aa003e4b50} 未注册 0009:err:ole:create_server 类 {cb96b400-c743-11cd-80e5-00aa003e4b50} 未注册 0009:err:ole:CoGetClassObject 无法为上下文创建类对象 {cb96b400-c743-11cd-80e5-00aa003e4b50} 0x7 错误:未选择语音
错误的最后一部分Error: voice not selected
并不重要,因为相同的 cmd 在其他情况下有效,其他东西失败了,但我找不到它。另外,我不明白为什么无论使用哪种方法(ssh 控制台或 python + paramiko),服务器重启后的第一次尝试都能正常工作
我尝试使用 paramiko 的invokeshell(),结果相同
任何帮助都感激不尽
答案1
经过进一步研究,该问题似乎与“WINEPREFIX”变量有关。通过将其移动到 env_dict 内部并使用绝对路径,该问题不再可重现
env_dict = {"DISPLAY:":0", "WINEPREFIX":"absolute/path/to/prefix"}