我有一个asp.net MVC应用程序,该应用程序具有 Controller 操作,该操作将字符串作为输入并发送合成语音的响应wav文件。这是一个简化的示例:

    public async Task<ActionResult> Speak(string text)
    {
        Task<FileContentResult> task = Task.Run(() =>
        {
            using (var synth = new System.Speech.Synthesis.SpeechSynthesizer())
            using (var stream = new MemoryStream())
            {
                synth.SetOutputToWaveStream(stream);
                synth.Speak(text);
                var bytes = stream.GetBuffer();
                return File(bytes, "audio/x-wav");
            }
        });
        return await task;
    }

该应用程序(尤其是该操作方法)在2008 R2服务器,2012(非R2)服务器和我的8.1 ​​dev PC上的服务器环境中运行良好。它还可以在标准Azure 2012 R2虚拟机上正常运行。但是,当我将其部署到三台2012 R2服务器(最终成为永久宿主)时,该操作方法永远不会产生HTTP响应-IIS Worker进程会无限期地最大化一个CPU内核。使用Procmon观看服务器时,事件查看器中没有任何内容,也没有任何提示。我已经通过远程调试附加到了该过程,并且synth.Speak(text)从不返回。执行synth.Speak(text)调用后,我立即在服务器的任务管理器中看到w3wp.exe失控的进程。

我的第一个倾向是相信服务器上的某些过程通常会干扰语音合成,但是Windows Narrator可以正常工作,并且像这样的简单控制台应用程序也可以正常工作:
static void Main(string[] args)
{
    var synth = new System.Speech.Synthesis.SpeechSynthesizer();
    synth.Speak("hello");
}

因此,很明显,我一般不能怪服务器的语音合成。因此,也许我的代码有问题,或者IIS配置有些奇怪?如何使此 Controller 操作在这些服务器上正常工作?

这是测试操作方法的一种简单方法(只需为路由正确获得url值):
<div>
    <input type="text" id="txt" autofocus />
    <button type="button" id="btn">Speak</button>
</div>

<script>
    document.getElementById('btn').addEventListener('click', function () {
        var text = document.getElementById('txt').value;
        var url = window.location.href + '/speak?text=' + encodeURIComponent(text);
        var audio = document.createElement('audio');
        var canPlayWavFileInAudioElement = audio.canPlayType('audio/wav');
        var bgSound = document.createElement('bgsound');
        bgSound.src = url;
        var canPlayBgSoundElement = bgSound.getAttribute('src');

        if (canPlayWavFileInAudioElement) {
            // probably Firefox and Chrome
            audio.setAttribute('src', url);
            audio.setAttribute('autoplay', '');
            document.getElementsByTagName('body')[0].appendChild(audio);
        } else if (canPlayBgSoundElement) {
            // internet explorer
            document.getElementsByTagName('body')[0].appendChild(bgSound);
        } else {
            alert('This browser probably can\'t play a wav file');
        }
    });
</script>

最佳答案

我认为问题是返回类型。 IIS Express可以让您摆脱它,但是IIS不能:

Task<FileContentResult>

因此,如果您尝试:
public async Task<FileContentResult> Speak(string text)
{
    Task<FileContentResult> task = Task.Run(() =>
    {
        using (var synth = new System.Speech.Synthesis.SpeechSynthesizer())
        using (var stream = new MemoryStream())
        {
            synth.SetOutputToWaveStream(stream);
            synth.Speak(text);
            var bytes = stream.GetBuffer();
            return File(bytes, "audio/x-wav");
        }
    });
    return await task;
}

我敢打赌,您还需要在IIS中添加音频/音频MIME类型。

关于c# - System.Speech.Synthesis在2012 R2上的高CPU挂起,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32236923/

10-13 04:09