我有一个 asp.net MVC 应用程序,它有一个控制器操作,该操作将字符串作为输入并发送合成语音的响应 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 开发 PC 上的服务器环境中运行良好。它在标准 Azure 2012 R2 虚拟机上也运行良好。然而,当我将其部署到三台 2012 R2 服务器(其最终的永久宿主)时,操作方法永远不会生成 HTTP 响应 - IIS 工作进程无限期地最大化其中一个 CPU 核心。事件查看器中没有任何内容,当我使用 Procmon 观看服务器时,也没有任何内容跳出我的视线。我已通过远程调试附加到该进程,并且synth.Speak(text)
永远不会回来。当。。。的时候synth.Speak(text)
调用执行后我立即在服务器的任务管理器中看到失控的 w3wp.exe 进程。
我的第一反应是相信某些进程通常会干扰服务器上的语音合成,但 Windows 讲述人可以正常工作,并且像这样的简单控制台应用程序也可以正常工作:
static void Main(string[] args)
{
var synth = new System.Speech.Synthesis.SpeechSynthesizer();
synth.Speak("hello");
}
所以显然我不能总体上责怪服务器的语音合成。那么也许我的代码有问题,或者 IIS 配置有问题?如何使该控制器操作在这些服务器上正常工作?
这是测试操作方法的简单方法(只需获取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>