分类:
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-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:
50010702506256
50010702506256
欢迎加群交流技术