利用华为云的语音合成实现智能语音提醒客户端
【摘要】 缘起公司上班下班都需要打卡,发现总有人忘记,一天的劳动不能白费啊,如果有个设备能够提醒打卡最好了,而且需要智能一些,在设定的时间内,对出现在门口的人,精准的喊出他的名字,提醒Ta改上班或下班打卡了。 功能分析人脸的注册与识别见上一篇《利用华为云FRS+OpenCv共同完成人脸识别场景》语音提醒,根据识别到的人脸,正确喊出“张三不要忘记打卡”,如果是Windows平台那就不用云了,因为Win...
缘起
公司上班下班都需要打卡,发现总有人忘记,一天的劳动不能白费啊,如果有个设备能够提醒打卡最好了,而且需要智能一些,在设定的时间内,对出现在门口的人,精准的喊出他的名字,提醒Ta改上班或下班打卡了。
功能分析
- 人脸的注册与识别
见上一篇《利用华为云FRS+OpenCv共同完成人脸识别场景》 - 语音提醒,根据识别到的人脸,正确喊出“张三不要忘记打卡”,如果是Windows平台那就不用云了,因为Windows自带了TTS,直接通过Api发送文字,就可以朗读。一个小小的Linux内核开发板没有内置,但是可以播放声音,那就需要帮助把文字转换成语音。
逻辑实现
– 为了节省资源和有效提醒,在具体逻辑上还有控制一些
- 本地保存对应的合成语音,员工是有限的且重复的,下次再次提醒这个员工就不用第二次语音合成了。
- 人来人往,出现在摄像头的人也多,同一个人也可以多次,防止造成打扰,提醒的时间设定好,再上下班附近的一小段时间,而且每个人只提醒3次,这也要做好本地记录。
– 主工作方法入口
/// <summary>
///
/// </summary>
/// <param name="stoppingToken"></param>
/// <returns></returns>
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var capOnWork = GetFaceCapture(_settings.CameraOnWork, VideoCaptureAPIs.DSHOW);
var capOffWork = GetFaceCapture(_settings.CameraOffWork, VideoCaptureAPIs.DSHOW);
Mat image = new Mat();
while (!stoppingToken.IsCancellationRequested)
{
var time = DateTime.Now;
if (time.Hour == 0 && time.Minute < 2)
{
//把昨天的记录删除
for (int i = _alerts.Count; i > 1; i--)
{
if (_alerts[i].Today !=DateTime.Now.Date)
_alerts.RemoveAt(i);
}
}
//
if (time.Hour > 8 && time.Hour < 9)
{
capOnWork.Read(image);
capOnWork.Read(image);
capOnWork.Read(image);
if (image.Empty())
continue;
var (Result, FaceId, UserName) = await FaceDetectionAsync2(image);
if (Result)
{
// 播放人名
if (string.IsNullOrEmpty(UserName))
{
// 播放陌生人
await PlayText2Voice($"有陌生人来访");
}
else
{
var myalert = _alerts.FirstOrDefault(p => p.Today == DateTime.Now.Date && p.FaceId == FaceId && p.Category == 1);
if (myalert != null)
{
if (myalert.Count < 3)
{
myalert.Count++;
await PlayText2Voice($"{UserName}不要忘记打卡");
}
}
else
{
_alerts.Add(new AlertRecord { Category = 1, Count = 1, FaceId = FaceId, Name = UserName, Today = DateTime.Now });
await PlayText2Voice($"{UserName}不要忘记打卡");
}
}
}
}
if (time.Hour > 17 && time.Hour < 18)
{
capOffWork.Read(image);
capOffWork.Read(image);
capOffWork.Read(image);
if (image.Empty())
continue;
var (Result, FaceId, UserName) = await FaceDetectionAsync(image);
if (Result)
{
// 播放人名
if (string.IsNullOrEmpty(UserName))
{
// 播放陌生人
await PlayText2Voice($"有陌生人来访,{FaceId}");
}
else
{
var myalert = _alerts.FirstOrDefault(p => p.Today.Date == DateTime.Now && p.FaceId == FaceId && p.Category == 2);
if (myalert != null)
{
if (myalert.Count < 3)
{
myalert.Count++;
_logger.LogInformation($"打卡提醒 {myalert.Count}次:{FaceId},{UserName}");
await PlayText2Voice($"{UserName}不要忘记打卡");
}
}
else
{
_alerts.Add(new AlertRecord { Category = 2, Count = 1, FaceId = FaceId, Name = UserName, Today = DateTime.Now.Date });
_logger.LogInformation($"打卡提醒 {1}次:{FaceId},{UserName}");
await PlayText2Voice($"{UserName}不要忘记打卡");
}
}
}
}
await Task.Delay(1000, stoppingToken);
}
}
– 播放声音使用了组件 NetCoreAudio.Player
async Task PlayText2Voice(string text)
{
try
{
var path = Path.Combine(Environment.CurrentDirectory, "Audio");
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
var file = Path.Combine(path, $"{text}.wav");
if (!File.Exists(file))
{
var voice = await HWCloudHelper.GetTTS(text);
File.WriteAllBytes(file, Convert.FromBase64String(voice));
}
await PlayWaveFile(file);
}
catch (Exception ex)
{
_logger.LogError("PlayVoice", ex);
}
}
/// <summary>
/// 播放声音文件
/// </summary>
/// <param name="file"></param>
/// <param name="waitSeconds"></param>
async Task PlayWaveFile(string file, int waitSeconds = 2)
{
await _speeker.Play(file);
await Task.Delay(waitSeconds * 1000);
while (_speeker.Playing)
{
await Task.Delay(50);
}
}
– 语音合成的核心方法
使用了华为类库 HuaweiCloud.SDK.Sis
/// <summary>
/// 文字合成语音
/// </summary>
/// <param name="text"></param>
/// <returns>base64</returns>
public static async Task<string> GetTTS(string text)
{
var config = HttpConfig.GetDefaultConfig();
config.IgnoreSslVerification = true;
var auth = new BasicCredentials(_AK, _SK);
var client = SisAsyncClient.NewBuilder()
.WithCredential(auth)
.WithRegion(SisRegion.ValueOf("cn-north-4"))
.WithHttpConfig(config)
.Build();
var req = new RunTtsRequest
{
};
req.Body = new PostCustomTTSReq()
{
Text = text,
Config = new TtsConfig { }
};
try
{
var resp = await client.RunTtsAsync(req);
var respStatusCode = resp.HttpStatusCode;
return resp.Result.Data;
}
catch (Exception ex)
{
_logger.Error("GetTTS", ex);
}
return String.Empty;
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)