UWP的SpeakProgress事件处理程序?

时间:2018-01-29 04:23:29

标签: c# uwp

如何在具有SpeechSynthesis类的UWP下实现SpeakProgressEvent的等价物? WPF / .NET有这个事件我可以挂钩,但是,我很困惑他们在UWP框架中隐藏这个功能的位置? .NET SpeakProgressEvent是否以某种方式映射到UWP的MediaElement事件?

// NOTE: This is a windows 10 UWP Application (Not WPF/.NET)
using Windows.Media.SpeechSynthesis;
using System.Threading.Tasks;

//XAML: <MediaElement Name="mediaElement"/>

namespace App1
{
    public sealed partial class MainPage : Page
    {
        SpeechSynthesizer            synth;

        public MainPage()
        {
            this.InitializeComponent();
            synth = new SpeechSynthesizer();

           // Doesn't Exist for UWP
            synth.SpeakProgress 
                 += new EventHandler<SpeakProgressEventArgs>
                    (synthesizer_SpeakProgress);

           // Doesn't Exist for UWP
            synth.SpeakStarted 
                 += new EventHandler<SpeakStartedEventArgs>
                    (synthesizer_SpeakStarted);

           // Doesn't Exist for UWP
            synth.SpeakCompleted 
                 += new EventHandler<SpeakCompletedEventArgs>
                    (synthesizer_SpeakCompleted);
        } //MainPage

        async Task Speak(string text)
        {
             SpeechSynthesisStream speech;
             speech = await synth.SynthesizeTextToStreamAsync(text);
             mediaElement.SetSource(speech, speech.ContentType);
        }

        void synthesizer_SpeakProgress(
               object sender, SpeakProgressEventArgs e)
        {
            //show the synthesizer's current progress 
            //labelProgress.Content = e.Text;
            //SolidColorBrush highlightColor 
            //   = new SolidColorBrush(Colors.Yellow);
            //HighlightWordInRichTextBox(
            //    richTextBox1, e.Text, highlightColor);
        }


    } //class
} //namespace

3 个答案:

答案 0 :(得分:2)

这里的难点在于,当WPF System.Speech.Synthesis.SpeechSynthesizer处理音频输出本身时,UWP Windows.Media.SpeechSynthesis.SpeechSynthesizer将其结果呈现为一个流,然后由MediaElement播放。这样,大多数元数据都会丢失,MediaElement无法确定当前正在说哪个单词,因此无法提供与SpeakProgress类似的事件。

你能做什么:

首先,通过设置以下SpeechSynthesizer选项,确保在流合成期间维护所有元数据:

synth = new SpeechSynthesizer
{
    Options = { IncludeWordBoundaryMetadata = true, IncludeSentenceBoundaryMetadata = true }
};

请注意,synth.SynthesizeTextToStreamAsync(...)创建的流不是常见的IRandomAccessStream,而是SpeechSynthesisStream,它提供了一些其他属性。例如,分析流的TimedMetadataTracks:通常,这将包含两个项目,一个包含单词边界元数据的轨道和一个包含句子边界元数据的轨道。

这些TimedMetadataTrack对象最有趣的属性可能是Cues:这是一个包含Windows.Media.Core.SpeechCue类型元素的集合,其中每个项目对应于一个句子/单词原文。每个项目包括以下信息:

  1. 字符位置(检查提示的StartPositionInInputEndPositionInInput属性)
  2. 音频位置(请参阅StartTime属性)
  3. 这意味着:

    不幸的是,如前所述,没有方便的事件通知您进度,但您应该能够通过这些元数据属性检索有关当前状态/位置的必要信息。

答案 1 :(得分:0)

答案 2 :(得分:0)

我假设您正在尝试从流中获取视位信息以使角色的嘴动画。

一种可行的方法是使用语音合成流提示来创建媒体标记。然后连接到媒体播放器标记到达事件。

使用CMU词典获取音素信息,然后查找与音素关联的视位。

在播放媒体流时,将到达标记,然后您可以更改角色的嘴形。