利用华为云的语音合成实现智能语音提醒客户端

举报
神龙居市 发表于 2022/11/30 11:30:51 2022/11/30
【摘要】 缘起公司上班下班都需要打卡,发现总有人忘记,一天的劳动不能白费啊,如果有个设备能够提醒打卡最好了,而且需要智能一些,在设定的时间内,对出现在门口的人,精准的喊出他的名字,提醒Ta改上班或下班打卡了。 功能分析人脸的注册与识别见上一篇《利用华为云FRS+OpenCv共同完成人脸识别场景》语音提醒,根据识别到的人脸,正确喊出“张三不要忘记打卡”,如果是Windows平台那就不用云了,因为Win...

缘起

公司上班下班都需要打卡,发现总有人忘记,一天的劳动不能白费啊,如果有个设备能够提醒打卡最好了,而且需要智能一些,在设定的时间内,对出现在门口的人,精准的喊出他的名字,提醒Ta改上班或下班打卡了。

功能分析

  1. 人脸的注册与识别
    见上一篇《利用华为云FRS+OpenCv共同完成人脸识别场景
  2. 语音提醒,根据识别到的人脸,正确喊出“张三不要忘记打卡”,如果是Windows平台那就不用云了,因为Windows自带了TTS,直接通过Api发送文字,就可以朗读。一个小小的Linux内核开发板没有内置,但是可以播放声音,那就需要帮助把文字转换成语音。
    image.png

逻辑实现

– 为了节省资源和有效提醒,在具体逻辑上还有控制一些

  1. 本地保存对应的合成语音,员工是有限的且重复的,下次再次提醒这个员工就不用第二次语音合成了。
  2. 人来人往,出现在摄像头的人也多,同一个人也可以多次,防止造成打扰,提醒的时间设定好,再上下班附近的一小段时间,而且每个人只提醒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

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。