Azure文本转语音API添加停顿问题求助
解决Azure文本转语音API中SSML停顿标签无效的问题
问题根源
你当前的代码使用createTextNode将包含<break>等SSML标签的$mytext直接作为文本节点插入DOM树,DOMDocument会自动将标签中的特殊字符转义为HTML实体(例如<变成<)。这导致Azure文本转语音API无法识别这些标签,只会把它们当成普通文本朗读。而在Speech Studio中直接使用未转义的原始SSML,所以能正常解析停顿。
解决方案
需要将$mytext中的普通文本和SSML标签拆分,分别创建对应的文本节点和元素节点,避免标签被转义。以下提供两种可行的实现方式:
方式1:基于自定义标记拆分处理
假设你用[break]作为停顿标记(可根据需求替换为你的特定字符),先将文本拆分,再逐个创建节点:
// 替换原来的$text = $doc->createTextNode( "$mytext" ); 及后续append代码 // 拆分文本,按自定义标记分割 $parts = explode('[break]', $mytext); foreach ($parts as $index => $part) { // 添加普通文本节点 if (!empty($part)) { $textNode = $doc->createTextNode($part); $prosody->appendChild($textNode); } // 不是最后一个部分,添加break标签 if ($index < count($parts) - 1) { $breakNode = $doc->createElement('break'); $breakNode->setAttribute('strength', 'medium'); // 可根据需求调整停顿强度 $prosody->appendChild($breakNode); } }
方式2:直接解析文本中的SSML标签
如果你的$mytext已经包含<break>等SSML标签,可以用DOMDocument加载文本片段,再导入节点:
// 替换原来的$text = $doc->createTextNode( "$mytext" ); 及后续append代码 // 创建临时DOM文档加载文本片段 $tempDoc = new DOMDocument(); // 包装成一个临时元素,避免XML格式问题 $tempDoc->loadXML("<temp>$mytext</temp>"); // 将临时元素的子节点导入到当前文档,并添加到prosody中 foreach ($tempDoc->documentElement->childNodes as $node) { $importedNode = $doc->importNode($node, true); $prosody->appendChild($importedNode); }
验证修改效果
修改后生成的SSML中,<break>标签会作为正常的XML元素存在,而不是转义后的实体。例如正确的SSML结构应该是:
<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="it-IT"> <voice name="en-US-JennyNeural"> <mstts:express-as style="whispering"> <prosody rate="xx.00%" pitch="xx.00%"> 1. first point: <break strength="medium" /> lore lipso bla bla. </prosody> </mstts:express-as> </voice> </speak>
内容的提问来源于stack exchange,提问作者fedep11
相关产品推荐
相关产品推荐

