在C#中如何捕获Microsoft.CognitiveServices.Speech.SpeechSynthesizer发音完成时机
实现SpeechSynthesizer的状态监听与合成完成事件处理
一、注册SynthesisCompleted事件
SpeechSynthesizer.SynthesisCompleted事件会在语音合成任务完成(无论成功或失败)时触发,只需在初始化合成器后绑定事件处理方法即可:
- 初始化
SpeechSynthesizer实例后,通过+=关联事件处理逻辑; - 在事件处理方法中编写合成完成后的操作,比如更新状态、触发后续任务。
二、跟踪发音状态
SpeechSynthesizer没有直接提供IsSpeaking属性,你可以通过自定义字段结合事件和异步任务状态来维护:
- 启动合成前将自定义状态字段设为
true; - 在
SynthesisCompleted事件或异步任务完成后将字段设为false; - 后台线程定期检查该字段值即可获取当前是否正在发音。
完整示例代码
using Microsoft.CognitiveServices.Speech; using System; using System.Threading; using System.Threading.Tasks; class SpeechSynthesisDemo { // 自定义状态字段:标记是否正在发音 private static bool _isSpeaking; private static SpeechSynthesizer _synthesizer; static async Task Main(string[] args) { // 替换为你的Azure语音服务订阅密钥和区域 var speechConfig = SpeechConfig.FromSubscription("YOUR_SUBSCRIPTION_KEY", "YOUR_REGION"); _synthesizer = new SpeechSynthesizer(speechConfig); // 注册合成完成事件 _synthesizer.SynthesisCompleted += OnSynthesisCompleted; // 启动后台线程,定期检查发音状态 var statusMonitorThread = new Thread(MonitorSpeakingStatus) { IsBackground = true }; statusMonitorThread.Start(); // 执行文本转语音异步任务 string textToSpeak = "这是一段用于测试的文本转语音内容。"; _isSpeaking = true; var synthesisResult = await _synthesizer.SpeakTextAsync(textToSpeak); // 也可以通过Task结果直接判断合成状态 if (synthesisResult.Reason == ResultReason.SynthesizingAudioCompleted) { Console.WriteLine("合成任务完成(通过Task结果检测)"); } else if (synthesisResult.Reason == ResultReason.Canceled) { var cancellationDetails = SpeechSynthesisCancellationDetails.FromResult(synthesisResult); Console.WriteLine($"合成被取消:{cancellationDetails.Reason}"); if (cancellationDetails.Reason == CancellationReason.Error) { Console.WriteLine($"错误信息:{cancellationDetails.ErrorDetails}"); } _isSpeaking = false; } Console.ReadLine(); _synthesizer.Dispose(); } // 合成完成事件处理方法 private static void OnSynthesisCompleted(object sender, SynthesisEventArgs e) { _isSpeaking = false; Console.WriteLine("合成任务完成(通过SynthesisCompleted事件触发)"); // 这里可以添加自定义逻辑,比如通知其他模块、记录日志等 } // 后台线程状态监控逻辑 private static void MonitorSpeakingStatus() { while (true) { Thread.Sleep(1000); Console.WriteLine($"当前发音状态:{(_isSpeaking ? "正在发音" : "未发音")}"); } } }
关键说明
- 事件注册时机:必须在调用
SpeakTextAsync之前完成事件绑定,否则可能无法捕获合成完成事件; - UI线程注意:如果是WPF/WinForms等UI应用,在事件处理方法中更新UI时需要切换到UI线程(比如WPF用
Dispatcher.Invoke,WinForms用Control.Invoke); - 资源释放:使用完
SpeechSynthesizer后务必调用Dispose()释放资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者CodeMilian
相关产品推荐
相关产品推荐

