Unity 讯飞实时语音转写(三)—— 分析转写结果
(应该没有后续了)
说在前面
这段时间一直在忙其他事情,所以语音识别的工作暂时交接到了同事手中,今天同事将后边的工作完成了,我就把源代码要了过来,也在此做一下记录。
分析结果如下:
上面是原文,下面是解析语音后的结果。
这个是加上了热词高亮的样子
正文
一、连接字符串
在上一篇文中说到,我们已经可以得到讯飞返回给我们的转写结果,只不过是某种格式的json字符串,可读性差,那么就需要我们将该json字符串中有用的字段提取出来。
/// <summary>
/// 获取识别并返回字符串
/// </summary>
/// <param name="data">所获取的识别的Json字符串</param>
/// <returns>所识别的连贯的一句话</returns>
void AnalysisResult(string data)
{
Data result = JsonUtility.FromJson<Data>(data); // 等效于 JsonConvert.DeserializeObject<Data>(data)
StringBuilder stringBuilder = new StringBuilder();
//Debug.Log(result.cn.st.rt[0].ws.Length);
for (int i = 0; i < result.cn.st.rt[0].ws.Length; i++)
{
//******只有w字段有用,将其提取出来即可******
stringBuilder.Append(result.cn.st.rt[0].ws[i].cw[0].w);
}
string _thisType = result.cn.st.type;
string testing = stringBuilder.ToString();
//Debug.Log(stringBuilder + "***" + _thisType);
//type 结果类型标识 0-最终结(即这句话说完了);1-中间结果(即这句话没说完,下一句转写结果可能推翻前面的内容)
if (_thisType.Equals("0"))
{
endText = endText + testing;
_text.text = endText;
}
else
{
_text.text = endText + testing;
}
}
这样我们就能得到一段连续的,可读性非常好的一句话。
二、个性化热词
下一步我们想要能够在转写的结果中找到一些热词,这些热词可以是当前流行的,或是某个行业的(金融、游戏等等),也可以是我们自定义的一些热词。
那如何设置自定义热词呢,讯飞官方已经给我们提供了一些接口。
打开讯飞开放平台,以此找到:语音识别-实时语音转写-个性化热词,然后按照要求填写热词,然后保存热词即可。
官方要求:
热词配置格式:每行一句热词(2000行以内,每行不多于10个字),以回车键隔开。
热词内容要求:限UTF-8 编码中文字符,不能有数字和字母。
需要注意的是中英文都是各占一个字符,比如hologarment是11个字符,就不能作为热词,可以拆分成holo,garment两个关键词。
三、热词筛选
有了热词后,接下来就是如何在程序中识别热词,并高亮显示热词。
- 首先在工程中新建一个txt文档,然后将网站上的热词保存进去。之后让Unity以文本资源的形式读取成字符串。
void Start()
{
path = Application.streamingAssetsPath + "/hologarment.txt";
ReadText();
}
- 然后按行读取文本,并存储到一个字符串中
public void ReadText()
{
string line;
using (StreamReader stream = new StreamReader(path))
{
while ((line=stream.ReadLine())!=null)
{
//Debug.Log(line);
keyWord.Add(line.Trim());//keyWord就是热词的集合
readText.text = readText.text + "\n" + line;
}
}
}
- 识别热词算法如下:
/// <summary>
/// 关键词标识
/// </summary>
/// <param name="content">待处理文本</param>
/// <param name="keyWord">关键字集合</param>
/// <param name="befordLabel">关键词前加入string</param>
/// <param name="afterLabel">关键词后加入</param>
/// <returns></returns>
public string SclectKeyWord(string content,List<string> keyWord,string befordLabel, string afterLabel)
{
char[] charArr = content.ToCharArray();
List<string> keyArr = keyWord;
List<char> listArr = new List<char>();
int matchCount = 0;
string buffWord = "";
for (int i = 0; i < charArr.Length; i++)
{
matchCount = keyArr.Where(r => r.StartsWith(buffWord + charArr[i].ToString())).Count();
if (matchCount == 0)
{
if (buffWord.Length > 0)
{
if (keyArr.Contains(buffWord))
{
listArr.AddRange((befordLabel + buffWord + afterLabel).ToCharArray());
}
else
{
listArr.AddRange(buffWord.ToCharArray());
}
buffWord = "";
matchCount = keyArr.Where(r => r.StartsWith(buffWord + charArr[i].ToString())).Count();
if (matchCount > 0)
{
buffWord += charArr[i];
}
else
{
listArr.Add(charArr[i]);
}
}
else
{
listArr.Add(charArr[i]);
}
}
else
{
if (matchCount == 1)
{
if (keyArr.Contains(buffWord + charArr[i]))
{
listArr.AddRange((befordLabel + buffWord + charArr[i] + afterLabel).ToCharArray());
buffWord = "";
}
else
{
buffWord += charArr[i];
}
}
else
{
buffWord += charArr[i];
}
}
//收尾判断
if (i == charArr.Length - 1)
{
if (keyArr.Contains(buffWord))
{
listArr.AddRange((befordLabel + buffWord + afterLabel).ToCharArray());
}
else
{
listArr.AddRange(buffWord.ToCharArray());
}
}
}
return string.Join("", listArr);
}
- 使用Unity的富文本红色高亮显示热词
public string SetKeyWordColor(string contont)
{
string resutl= SclectKeyWord(contont, keyWord, "<color=#FF0000>", "</color>");
return resutl;
}
至此,功能暂时告一段落。
这是我们老板的一段演讲词,我们以这段话为例
可能有小伙伴发现并非所有的热词都被识别出来了,表明热词识别算法有待优化,以后有时间再搞吧。。。
三、示例工程
考虑了一下,还是附上完整的工程文件吧,希望可以帮助正在测试该功能的小伙伴们。加油哦!如何测试
- 下载后解压工程,Unity打开工程(我使用的是Unity 2019.4.9f1,需要Crack的同学可以看下我这篇文章)
- 找到脚本VisualCommunication.cs,在166,167行修改appid,appkey为你自己项目的对应值
- 启动工程,点击“开始转写”,然后对着麦克风说话;说完后点击“结束转写”,或者直接关闭程序都行,讯飞官方会在15s内没有接到转写请求时,自动关闭WebSocket连接,不用担心时长被意外耗尽