Windows应用程序SDK:SpeechSynthesizer需要很长时间进行合成

baubqpgj  于 2023-03-13  发布在  Windows
关注(0)|答案(1)|浏览(191)

正如我所描述的here
我有一个方法async SpeakAsync(string language, string text)

var synth = new SpeechSynthesizer();
 var player = new MediaPlayer();
 SetVoice(language, ref synth);
 var source = await synth.SynthesizeTextToStreamAsync(text);
 player.SetStreamSource(source);
 synth.Dispose();
 player.MediaEnded += (_, _) => { source.Dispose(); player.Dispose(); }
 player.Play();

如果我调用这个方法两次,后面跟着.Wait(),我的应用将在第二次调用时永远停留在var source = await synth.SynthesizeTextToStreamAsync(text);(第一次调用运行完美)。
我按照@DarranRowe所说的那样,在类的一个字段中存储了一个MediaPlayer示例和一个SpeechSynthesisStream示例,每次调用该方法时,我都将SpeechSynthesisStream示例设置为null,但问题仍然存在,我不知道为什么这会解决我的问题。
完整的再现可以在here中找到。

  • 请在这里评论或回答,我上面提到的GitHub讨论不适合这个问题。*
kkih6yb8

kkih6yb81#

这个问题与SpeechSynthetizer无关,而是与您用来调用方法的代码有关:

private void OnClick(object _sender, RoutedEventArgs _e)
{
    SpeakAsync("en-US", "Test 1").Wait();
    SpeakAsync("en-US", "Test 2").Wait();
}

它正在使用async方法和来自UI线程的任务Wait(),这会导致死锁。
这是一个典型的错误(与Winforms或WPF相同),请参阅本网站上的How to avoid WinForm freezing using Task.WaitWinforms call to async method hangs up programDon't Block on Async Code以获得更详细的答案。
因此,解决方案是这样做:

private async void OnClick(object _sender, RoutedEventArgs _e)
{
    await SpeakAsync("en-US", "Test 1");
    await SpeakAsync("en-US", "Test 2");
}

请注意,对于现有代码,两个短语将一起播放,下面是一个可以选择等待播放结束的版本:

private Task SpeakAsync(string language, string text, bool waitForEnd = true)
{
    if (waitForEnd)
    {
        var tsc = new TaskCompletionSource();
        Task.Run(() => Do(tsc));
        return tsc.Task;
    }
    return Do(null);

    async Task Do(TaskCompletionSource tsc)
    {
        var player = new MediaPlayer();
        using var synth = new SpeechSynthesizer();
        synth.Voice = SpeechSynthesizer.AllVoices.FirstOrDefault(v => v.Language == language) ?? SpeechSynthesizer.DefaultVoice;
        var source = await synth.SynthesizeTextToStreamAsync(text);
        player.MediaEnded += (sender, _) =>
        {
            source.Dispose();
            tsc?.SetResult();
        };
        player.SetStreamSource(source);
        player.Play();
    }
}

相关问题