【问题标题】:Getting XDocument to recognize embedded SSML让 XDocument 识别嵌入式 SSML
【发布时间】:2019-08-12 17:14:16
【问题描述】:

我正在使用文字转语音向视频教程添加语音。目前所有文本都在一个文件中,并被读入 C# 应用程序并解析为多个步骤。我想做的是将 ssml 添加到文本文件中,特别是在整个特定指令中(暂停)的能力。我正在使用来自Cognitive-Speech-TTS 的示例代码。这段代码使用了一种很好的干净方法

private string GenerateSsml(string locale, string gender, string name, string text)
    {
        var ssmlDoc = new XDocument(
                          new XElement("speak",
                              new XAttribute("version", "1.0"),
                              new XAttribute(XNamespace.Xml + "lang", "en-US"),
                              new XElement("voice",
                                  new XAttribute(XNamespace.Xml + "lang", locale),
                                  new XAttribute(XNamespace.Xml + "gender", gender),
                                  new XAttribute("name", name),
                                  text)));


        return ssmlDoc.ToString();
    }

例如,如果我将“文本”设置为

string text = @"During this video we will refer to this as the lens, 
                <break time=""1000ms"" />  this as the headband  
                 <break time=""1000ms"" />, and these as the frame arms 
                <break time=""1000ms"" />. " };
Content = new StringContent(GenerateSsml(inputOptions.Locale, genderValue, inputOptions.VoiceName, text))

它不会识别嵌入的 xml。有没有办法让 XDocument 识别文本中的 xml。请注意,在实际应用程序中,文本是从数据文件中填充的。

【问题讨论】:

    标签: c# .net ssml


    【解决方案1】:

    您正在传递一个字符串,因此 LINQ to XML 认为您希望它是一个文本节点,并适当地转义文本。

    看起来您确实想要包含多个节点 - 一些文本和一些元素。

    我建议像这样更改您的GenerateSsml

    private string GenerateSsml(string locale, string gender, string name, IEnumerable<XNode> nodes)
    {
        var ssmlDoc = new XDocument(
                          new XElement("speak",
                              new XAttribute("version", "1.0"),
                              new XAttribute(XNamespace.Xml + "lang", "en-US"),
                              new XElement("voice",
                                  new XAttribute(XNamespace.Xml + "lang", locale),
                                  new XAttribute(XNamespace.Xml + "gender", gender),
                                  new XAttribute("name", name),
                                  nodes)));
        return ssmlDoc.ToString();
    }
    

    然后将你的调用方法改为:

    var nodes = new XNode[]
    {
        new XText("During this video we will refer to this as the lens,"),
        new XElement("break", new XAttribute("time", "1000ms")),
        new XText(" this as the headband"),
        new XElement("break", new XAttribute("time", "1000ms")),
        new XText(", and these as the frame arms"),
        new XElement("break", new XAttribute("time", "1000ms"))
        new XText("."),
    };
    Content = new StringContent(
        GenerateSsml(inputOptions.Locale, genderValue, inputOptions.VoiceName, nodes));
    

    如果你真的想使用字符串表示,你可以写:

    string text = ...; // Code as before
    var element = XElement.Parse($"<root>{text}</root>");
    Content = new StringContent(
        GenerateSsml(inputOptions.Locale, genderValue, inputOptions.VoiceName, element.Nodes()));
    

    【讨论】:

    • 感谢您的回复。一般来说,这两种选择都可以。但是,我的目标是能够将 SSML 标记添加到带有脚本的文本文件中,这样将来当脚本更改时,我们只需要修改文本文件。看来,一旦我读入文件,我将不得不解析标记标签。我希望类似于使用'@'的东西可以让文本读入。实际上,再次查看第二个选项可能会起作用。我试过了,但没有添加 元素,所以出现错误。
    • @Doc:所以只是为了澄清一下,第二种方法是否适合您,还是您还在寻找其他方法?
    • 我实际上正在处理以下错误

      System.Xml.XmlException Message=Name 不能以“1”字符开头,十六进制值 0x31。第 1 行,位置 74。

      我使用的实际输入字符串是:

      “在拿起 HoloLens 之前,了解非触摸区域很重要。避免触摸镜头。镜头只能接触柔软的表面。如果您尚未移除 HoloLens,请暂停此视频并立即执行 。"
    • @Doc:鉴于该字符串在任何地方都不包含字符“1”,听起来问题出在其他地方。我建议您创建一个简短但完整的示例,然后将其放入一个新问题中。
    • 我想通了。我正在阅读具有 的另一行。这种方法不需要双引号
    猜你喜欢
    • 2011-07-14
    • 2014-12-09
    • 2015-06-28
    • 2019-10-27
    • 1970-01-01
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多