7

目前ChromiumFirefoxWeb Speech API 规范实现不支持在实例属性设置 SSML并传递给调用时解析语音合成标记语言(SSML) ;请参阅浏览器中的 SSML 解析实现5.2.3 SpeechSynthesisUtterance 属性如何设置浏览器调用的命令选项?.textSpeechSyntheisUtterancewindow.speechSynthesis.speak()

unix 套接字连接到连接的 Chromium 源代码speech-dispatcher似乎位于/src/chrome/browser/speech/tts_linux.cc

  {
    // spd_open has memory leaks which are hard to suppress.
    // http://crbug.com/317360
    ANNOTATE_SCOPED_MEMORY_LEAK;
    conn_ = libspeechd_loader_.spd_open(
        "chrome", "extension_api", NULL, SPD_MODE_THREADED);
  }

这似乎反映在/run/user/1000/speech-dispatcher/log

speechd: Updating client specific settings "linux:chrome:extension_api"

Chromium 源代码位于/src/third_party/speech-dispatcher/libspeechd.h

似乎定义了文档中的SSML_DATA_MODE描述speech-dispatcher

speech-dispatcher文档指出,用户配置文件可用于为特定客户端设置参数

4.1.6 参数设置命令

可以使用以下参数设置命令。对于配置和历史客户端,还有一些功能可以为其他连接和所有连接设置值。它们在下面单独列出。

C API 函数:int spd_set_data_mode(SPDConnection *connection, SPDDataMode mode)设置 Speech Dispatcher 数据模式。目前支持纯文本和 SSML。如果您想使用索引标记或在文本中包含语音参数的更改,SSML 特别有用。

mode 是请求的数据模式:SPD_DATA_TEXTSPD_DATA_SSML.

SPD_DATA_SSMLon在建立从 Chromium 到 的SSIP连接时未设置为speech-dispatcher,例如 @xmash 在“如何在“语音调度程序”中使用索引标记?

spd_execute_command_wo_mutex( m_connection, "SET SELF SSML_MODE on" );

也不可能将选项传递给默认语音合成模块mforespeak-xfor spd-say

LogLevel设置为45 /run/user/1000/speech-dispatcher/log列出 Chromium(客户端)和speech-dispatcher

speechd:    Module set parameters

(server) 也可以在stdout使用PIDinside/run/user/1000/speech-dispatcher/pidstrace查看,请参阅Is there a way to interception interprocess communication in Unix/Linux?

$ sudo strace -ewrite -p $PID

write(22, "216 OK OUTPUT MODULE SET\r\n", 26) = 26

似乎没有一个选项可以将 SSML 解析设置为在运行中speechd.confespeak.conf运行之后

$ spd-conf -u

SpeechSynthesisSSMLParser尝试使用 JavaScript 解析 SSML时,在尝试解析元素时在 Chromium中遇到了一个错误<break>,其中不清楚spd-say是调用还是默认输出模块,例如,在被浏览器调用espeak时运行;window.speechSynthesis.speak()/src/out/Debug/gen/library_loaders/libspeechd.h

创建了一种用于php调用的方法,espeak使用shell_exec()该方法返回预期结果

// JavaScript
async function SSMLStream({ssml="", options=""}) {
  const fd = new FormData();
  fd.append("ssml", ssml);
  fd.append("options", options);

  const request = await fetch("speak.php", {method:"POST", body:fd});
  const response = await request.arrayBuffer();
  return response;
}

let ssml = `<speak version="1.0" xml:lang="en-US"> 
             Here are <say-as interpret-as="characters">SSML</say-as> samples. 
             Hello universe, how are you today? 
             Try a date: <say-as interpret-as="date" format="dmy" detail="1">10-9-1960</say-as> 
             This is a <break time="2500ms" /> 2.5 second pause. 
             This is a <break /> sentence break</prosody> <break />
             <voice name="us-en+f3" rate="x-slow" pitch="0.25">espeak using</voice> 
             PHP and <voice name="en-us+f2"> <sub alias="JavaScript">JS</sub></voice>
           </speak>`;

SSMLStream({ssml, options:"-v en-us+f1"})
.then(async(data) => {

    let context = new AudioContext();
    let source = context.createBufferSource();
    source.buffer = await context.decodeAudioData(data);
    source.connect(context.destination);
    source.start()

})
// PHP
<?php 
  if(isset($_POST["ssml"])) {
    header("Content-Type: audio/x-wav");
    $options = $_POST["options"];
    echo shell_exec("espeak -m --stdout " . $options . " '" . $_POST["ssml"] . "'");
  };

要求:

通过使用默认浏览器功能的输出模块使用SpeechSynthesisUtterance调用的本机程序的现有功能将文本转换为语音的文本属性中设置的 SSML 解析。speech-dispatcher

问题:

1)如何以编程方式侦听Chromium 浏览器调用的时间,然后使用已建立的 unix 套接字连接作为客户端(Chromium)调用PID或调用服务器,并作为第二个参数打开对Chromium 浏览器的所有调用的 SSML 解析?speech-dispatcher --spawn-communication-method unix_socket --socket-path /run/user/1000/speech-dispatcher/speechd.sockspd_execute_command_wo_mutexspd_execute_command_wo_mutexspeech-dispatcher"SET SELF SSML_MODE on"window.speechSynthesis.speak()

2) 如果 1) 不可行,需要在 Chromium 源代码中调整哪些内容才能为 unix 套接字连接打开 SSML 解析,例如在tools/generate_library_loader/generate_library_loader.py中?

3) 如果 1) 和 2) 都不可行,如何将 JavaScript 和 PHP 代码转换为 Chromium 浏览器使用格式的 C++ 代码;以及如何使用包含的补丁构建 Chromium;为了公开一个speak带有接受参数的函数,该参数可以传递给本地语音合成应用程序,在该应用程序中解析 SSML,并将生成的音频输出作为ArrayBuffer?

4) 如果 1)、2) 和 3) 以外的选项可用且能够满足要求,我们如何以编程方式解决查询;无需手动启动本地服务器terminal

4

0 回答 0