分类:
C#
最近由于工作中需要语音读取消息文本,达到现场通知效果,故而研究了下C#语音播放功能:
开始崎岖之路
BEGIEN:
首先测试,写一个接口,按照同步方式读文本
using EasyTeam.Problem.Web.Api.Models; using SpeechLib; using System; using System.Collections.Generic; using System.Linq; using System.Speech.Synthesis; using System.Web; using System.Web.Http; using System.Web.Mvc; using HttpGetAttribute = System.Web.Http.HttpGetAttribute; namespace EasyTeam.VoicePlay.Controllers { public class VoicePlayController : ApiController { public OperationResult result = new OperationResult(); /// <summary> /// 外部调用接口 /// </summary> /// <param name="msg">消息体(文本内容)</param> /// <returns></returns> [HttpGet] public OperationResult Index(string msg) { Paly(msg); return result; } /// <summary> /// 内部实现方法 /// </summary> /// <param name="msg"></param> private void Paly(string msg) { try { //创建实例 var reader = new SpeechSynthesizer(); /*下面的代码为一些SpeechSynthesizer的属性,看实际情况是否需要使用*/ //reader.Rate = -1; //设置语速,[-10,10] //reader.Volume = 100; //设置音量,[0,100] //reader.SpeakAsync("Hellow Word"); //播放指定的字符串,这是异步朗读 //reader.Speak("Hellow Word"); //同步朗读 //reader.Dispose(); //释放所有语音资源 //reader.SpeakAsyncCancelAll(); //取消朗读 //reader.Pause(); //暂停朗读 //reader.Resume(); //继续朗读 if (string.IsNullOrEmpty(msg)) { result.Message = "Please enter some text"; result.ResultType = OperationResultType.ValidError; result.Data = null; reader.Dispose(); } else { //reader.SpeakAsync(msg); reader.Speak(msg); //回调(同步读文本时,不会进入此委托) reader.SpeakCompleted += new EventHandler<SpeakCompletedEventArgs>(reader_SpeakCompleted); reader.Dispose(); } } catch (Exception e) { result.Message = e.Message; result.ResultType = OperationResultType.Error; result.Data = null; } } void reader_SpeakCompleted(object sender, SpeakCompletedEventArgs e) { var reader = (SpeechSynthesizer)sender; result.Message = "成功!"; result.ResultType = OperationResultType.Success; } } }
嗯。。。 跑一下。。。默默的带上耳机,希望有声音。
哇撒 ,进断点了,哇撒,有声音了,看来有戏
what?f**k!
都跑完了,为啥还在Loading?难道没释放资源?但是确实有写Dispose(),那换个异步读试试。
改一下Paly方法:
private void Paly(string msg) { try { //创建实例 var reader = new SpeechSynthesizer(); /*下面的代码为一些SpeechSynthesizer的属性,看实际情况是否需要使用*/ //reader.Rate = -1; //设置语速,[-10,10] //reader.Volume = 100; //设置音量,[0,100] //reader.SpeakAsync("Hellow Word"); //播放指定的字符串,这是异步朗读 //reader.Speak("Hellow Word"); //同步朗读 //reader.Dispose(); //释放所有语音资源 //reader.SpeakAsyncCancelAll(); //取消朗读 //reader.Pause(); //暂停朗读 //reader.Resume(); //继续朗读 if (string.IsNullOrEmpty(msg)) { result.Message = "Please enter some text"; result.ResultType = OperationResultType.ValidError; result.Data = null; reader.Dispose(); } else { //现在是异步 reader.SpeakAsync(msg); //reader.Speak(msg); //回调 reader.SpeakCompleted += new EventHandler<SpeakCompletedEventArgs>(reader_SpeakCompleted); reader.Dispose(); } } catch (Exception e) { result.Message = e.Message; result.ResultType = OperationResultType.Error; result.Data = null; } }
再跑一下,嗯 ,异步能进入到委托中。
但是,牙刷,直接没声了,再检查下代码,想了想,考虑到异步,会不会是还没开始读,资源就被释放了?
再改一下代码,把 reader.Dispose()放到读完后的委托中:
private void Paly(string msg) { try { //创建实例 var reader = new SpeechSynthesizer(); /*下面的代码为一些SpeechSynthesizer的属性,看实际情况是否需要使用*/ //reader.Rate = -1; //设置语速,[-10,10] //reader.Volume = 100; //设置音量,[0,100] //reader.SpeakAsync("Hellow Word"); //播放指定的字符串,这是异步朗读 //reader.Speak("Hellow Word"); //同步朗读 //reader.Dispose(); //释放所有语音资源 //reader.SpeakAsyncCancelAll(); //取消朗读 //reader.Pause(); //暂停朗读 //reader.Resume(); //继续朗读 if (string.IsNullOrEmpty(msg)) { result.Message = "Please enter some text"; result.ResultType = OperationResultType.ValidError; result.Data = null; reader.Dispose(); } else { reader.SpeakAsync(msg); //reader.Speak(msg); //回调(同步读文本时,不会进入此委托) reader.SpeakCompleted += new EventHandler<SpeakCompletedEventArgs>(reader_SpeakCompleted); } } catch (Exception e) { result.Message = e.Message; result.ResultType = OperationResultType.Error; result.Data = null; } } void reader_SpeakCompleted(object sender, SpeakCompletedEventArgs e) { var reader = (SpeechSynthesizer)sender; result.Message = "成功!"; result.ResultType = OperationResultType.Success; reader.Dispose();//现在释放在这里 }
再跑一下,嗯。。有声音,但是还是没有返回结果!!!
问题还是没解决,此时,就触及到我的知识盲区了,百度。。百度
然后找到一篇文章:https://blog.csdn.net/lphbtm/article/details/19475093 一直稀里糊涂看下去,然后。。what?文章末尾说了句 无解!!!
哎,人家说不行,咱也得试试再说,用GC释放下,看看行不行,再改,在内部方法和回调方法上都加上GC.Collect()释放资源:
有关GC的介绍:https://www.cnblogs.com/yunfeifei/p/3995342.html
再试!!!发现还是不行。
--------------------
然后,通过各种自己的调试,改代码,百度都没找到解决方法
既然这条路走不通,不如考虑换个实现方式,终于,让我找到了一个替代方法。用SpVoice实现,代码如下:
private void Paly1(string msg) { try { if (string.IsNullOrEmpty(msg)) { result.Message = "Please enter some text in the textbox"; result.ResultType = OperationResultType.ValidError; } else { SpeechVoiceSpeakFlags flag = SpeechVoiceSpeakFlags.SVSFlagsAsync; SpVoice voice = new SpVoice(); string voice_txt = msg; voice.Voice = voice.GetVoices(string.Empty, string.Empty).Item(0); int result = voice.Speak(voice_txt, flag); } } catch (Exception e) { result.Message = e.Message; result.ResultType = OperationResultType.Error; } }
然后调试调用:
Nice!!有声音,终于看到这个画面了!
大半天时间就过去了,爱研究的童鞋,可以研究下上面无法释放那个问题,mark一下,分享分享!
END
评价
排名
6
文章
6
粉丝
16
评论
8
{{item.articleTitle}}
{{item.blogName}} : {{item.content}}
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2024TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术