下面代码运行报错 无法在流的结尾之外进行读取 // 枚举所有音频设备 var enumerator = new MMDeviceEnumerator(); var devices = enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active); // 遍历所有设备并输出设备名称 foreach (var device in devices) { Console.WriteLine(device.FriendlyName); } // 初始化SpeechSynthesizer对象 var synthesizer = new SpeechSynthesizer(); var format = new WaveFormat(16000, 16, 1); // 将文本转换为语音并输出到指定设备 void Speak(string text, MMDevice device) { using (var stream = new MemoryStream()) { // 将语音输出到流中 synthesizer.SetOutputToWaveStream(stream); synthesizer.Speak(text); // 将流转换为音频流 stream.Seek(0, SeekOrigin.Begin); var conversionStream = new WaveFormatConversionStream(format, new WaveFileReader(stream)); // 播放音频流 var output = new WasapiOut(device, AudioClientShareMode.Shared, true, 100); output.Init(conversionStream); output.Play(); while (output.PlaybackState == PlaybackState.Playing); } } // 创建多个线程,每个线程输出到不同的设备 foreach (var device in devices) { var thread = new Thread(() => Speak("Hello world!", device)); thread.Start(); }
时间: 2024-02-06 09:02:54 浏览: 32
这个错误通常是由于流已经被完全读取而导致的。在代码中,问题可能出现在语音合成器(SpeechSynthesizer)对象的初始化中,因为该对象是全局的,而且只初始化了一次,当第二个线程尝试使用该对象时,它已经结束语音合成并将其输出到流中,这时候第二个线程再尝试从流中读取数据时,就会遇到流的结尾。
解决这个问题可以将语音合成器的初始化放到 Speak 方法中,并在每个线程中重新创建一个语音合成器对象。修改后的代码如下:
```
// 遍历所有设备并输出设备名称
foreach (var device in devices)
{
Console.WriteLine(device.FriendlyName);
}
// 将文本转换为语音并输出到指定设备
void Speak(string text, MMDevice device)
{
var synthesizer = new SpeechSynthesizer(); // 创建语音合成器对象
using (var stream = new MemoryStream())
{
// 将语音输出到流中
synthesizer.SetOutputToWaveStream(stream);
synthesizer.Speak(text);
// 将流转换为音频流
stream.Seek(0, SeekOrigin.Begin);
var conversionStream = new WaveFormatConversionStream(format, new WaveFileReader(stream));
// 播放音频流
var output = new WasapiOut(device, AudioClientShareMode.Shared, true, 100);
output.Init(conversionStream);
output.Play();
while (output.PlaybackState == PlaybackState.Playing) ;
}
}
// 创建多个线程,每个线程输出到不同的设备
foreach (var device in devices)
{
var thread = new Thread(() => Speak("Hello world!", device));
thread.Start();
}
```
这样更好地控制了语音合成器对象的生命周期,并且可以避免多个线程同时访问同一个对象。
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)