• 一步到位!!百度大脑语音合成快速搞定会员到访提醒功能


    每次会员到访都需要。会员自主结账或找导购才能被发现。或者需要一个人员站在门口,并且对会员都全部了解,才能对会员到访进行更好服务的接待。
    
    小帅为了免去这些操作呢。就想到了百度AI。语音合成。再结合第三方的人脸库会员到访推送。做了一个简单的会员到访语音提醒推送小工程。
    
    下面我们就一起看一下整体流程吧~

    实现步骤
     Step1:成为百度AI开放平台的开发者

    我们有账号之后登录,并且点击此处(百度语音)创建一个应用,如下图

    然后就能看到创建完的应用和 APPID、API KEY 以及 Secret KEY

    Step2:准备数据

    语音合成是将文本转换为可以播放的音频文件的服务,我们从大姚的订单库中找一段订单信息的文本如下:

    三分钟前,由北京市顺义区二经路与二纬路交汇处北侧,北京首都国际机场T3航站楼 去往 东城区北三环东路36号喜来登大酒店(北京金隅店)
    Step3: 编写一个语音合成示例程序

    有 第一步 的 API KEY 以及 Secret KEY,以及 第二步 的数据,我们就可以写一个示例代码调用百度AI开放平台的文字识别能力
    准备开发环境

    小帅选择用 Java来快速搭建一个原型,关于如何安装Java。可以参考百度经验哦~。百度AI有很完善的API文档、和封装调用更方便的工具包。接下来小帅就用Maven搭建工程环境

    pom.xml配置如下:

    xml请自行访问网页 复制
    

    编写代码
    粘贴以下内容,不要忘记替换你的 APPID APIKEY 以及 SECRETKEY 和 图片文件

    运行main方法即可

    import com.baidu.aip.speech.AipSpeech;
    import com.baidu.aip.speech.TtsResponse;
    import com.baidu.aip.util.Util;
    import org.json.JSONObject;
     
    import java.util.HashMap;
     
    public class Sample {
        //第一步创建应用获取的三个值
        private static String APPID = "你的 App ID";
        private static String APIKEY = "你的 Api Key";
        private static String SECRETKEY = "你的 Secret Key";
     
        public static void main(String[] args) {
            // 初始化一个AipSpeech 
            AipSpeech client = new AipSpeech(APPID,APIKEY,SECRETKEY);
            // 调用接口 第二步准备的图片
            HashMap options = new HashMap<>();
            //合成的文本内容
            String text = "三分钟前,由北京市顺义区二经路与二纬路交汇处北侧,北京首都国际机场T3航站楼 去往 东城区北三环东路36号喜来登大酒店(北京金隅店)";
            //发音人选择
            /**
             * 度小宇=1,度小美=0,度逍遥=3,度丫丫=4
             * 度博文=106,度小童=110,度小萌=111,度米朵=103,度小娇=5
             **/
            options.put("per","0");
            //语速,取值0-9,默认为5中语速
            options.put("spd", "3");
            TtsResponse res = client.synthesis(text , "zh", 1, options);
     byte[] data = res.getData();
            JSONObject res1 = res.getResult();
            if (data != null) {
                try {
                    Util.writeBytesToFileSystem(data, "F:\testaudio\度小美Demooutput.mp3");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (res1 != null) {
                System.out.println(res1.toString());
            }
        }
    }

    保存接口返回语音byte[] 转存为MP3格式文件。这里说明一下默认返回就是MP3格式的数据哦。如果想要其他格式

    //3为mp3格式(默认); 
    //4为pcm-16k;
    //5为pcm-8k;
    //6为wav(内容同pcm-16k); 
    //注意aue=4或者6是语音识别要求的格式,但是音频内容不是语音识别要求的自然人发音,所以识别效果会受影响。
     
    options.put("aue","3");

    点击访问合成的示例MP3文件 https://www.ydxiaoshuai.cn/demo.mp3

    语音合成 单例加载。10次测试耗时如下(单位:ms(毫秒))。第一次需要加载一次AUTH。耗时多了一些。后续基本都持平在710ms以内

    发送请求到返回数据耗时:1493
    发送请求到保存文件耗时:1495
     
    发送请求到返回数据耗时:611
    发送请求到保存文件耗时:612
     
    发送请求到返回数据耗时:609
    发送请求到保存文件耗时:610
     
    发送请求到返回数据耗时:473
    发送请求到保存文件耗时:474
     
    发送请求到返回数据耗时:549
    发送请求到保存文件耗时:550
     
    发送请求到返回数据耗时:673
    发送请求到保存文件耗时:674
     
    发送请求到返回数据耗时:754
    发送请求到保存文件耗时:755
     
    发送请求到返回数据耗时:676
    发送请求到保存文件耗时:676
     
    发送请求到返回数据耗时:582
    发送请求到保存文件耗时:582
     
    发送请求到返回数据耗时:662
    发送请求到保存文件耗时:663
     
    发送请求到返回数据平均耗时:708.2ms
    发送请求到保存文件平均耗时:709.1ms
            for (int i = 0; i < 10; i++) {
                // 调用接口
                String text = "三分钟前,由北京市顺义区二经路与二纬路交汇处北侧,北京首都国际机场T3航站楼 去往 东城区北三环东路36号喜来登大酒店(北京金隅店)";
                HashMap options = new HashMap();
                options.put("per", "0");
                options.put("spd", "3");
                long startTime = System.currentTimeMillis();
                TtsResponse res = client.synthesis(text, "zh", 1, options);
                byte[] data = res.getData();
                if (data != null) {
                    long endTime = System.currentTimeMillis();
                    System.out.println("发送请求到返回数据耗时:"+(endTime - startTime));
                    try {
                        Util.writeBytesToFileSystem(data, "F:\testaudio\度小美Demooutput.mp3");
                        long saveEndTime = System.currentTimeMillis();
                        System.out.println("发送请求到保存文件耗时:"+(saveEndTime - startTime));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                JSONObject res1 = res.getResult();
                if (res1 != null) {
                    System.out.println(res1.toString());
                }
                System.out.println();
            }

    系统配置-小帅认为速度和配置 带宽都存在一定的因素

    以上数据可以看出。平均耗时在0.7s上下。如果服务器配置贼6、带宽也贼宽。应该耗时还会更低哦

    接下来。咱们就拿语音合成的服务。来结合实际业务做一个小的功能哦~

    会员到访语音提醒搞起来

    简单看一下业务流程图。主要看语音合成、语音提醒部分即可
    
    人脸会员识别可以看百度AI的官方解决方案 https://ai.baidu.com/solution/faceidentify
    
    本业务中人脸识别、摄像头厂商暂时没用百度AI。这一点我也很无奈。迫于公司要求呀。如果再来一次选择。绝对强制提议选择百度AI(怕太便宜而告终 你懂得)

    会员信息采集

    会员到访提示音发音类型默认 度米多。也可以根据会员不同给不同的发音类型哦~

    下拉框

    后端会员人脸信息处理

     /**
      * 会员人脸信息添加
      * @param csFace
      * @return
      */
     @AutoLog(value = "会员人脸信息添加")
     @ApiOperation(value="会员人脸信息添加", notes="会员人脸信息添加")
     @PostMapping(value = "/add")
     public Result add(@RequestBody CsFace csFace) {
    	 Result result = new Result();
    	 csFaceGroup group = new csFaceGroup();
    	 try {
                     //这里存人脸信息到人脸库就不演示了。人脸库存入成功后业务系统再记录
    		 csFaceService.save(csFace);
                     //把会员人脸信息提交给JOB等待后续执行。方便前端页面交互不等待
                     //人脸会员信息只是在一个JobFace类中增加一个List容器 public static List vipFaceMap=new ArrayList();
    		 JobFace.vipFaceMap.add(csFace);
    		 result.success("添加成功!");
    	 } catch (Exception e) {
    		 log.info(e.getMessage());
    		 result.error500("操作失败-人脸服务存在异常");
    	 }
    	 return result;
     }

    会员到访定制提示音频合成定时任务

    import cn.hutool.core.date.DatePattern;
    import cn.hutool.core.date.DateUtil;
    import cn.netand.common.factory.BDFactory;
    import cn.netand.modules.csface.entity.CsFace;
    import cn.netand.modules.csface.service.ICsFaceService;
    import com.baidu.aip.speech.AipSpeech;
    import com.baidu.aip.speech.TtsResponse;
    import com.baidu.aip.util.Util;
    import lombok.extern.slf4j.Slf4j;
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
     
    import java.io.File;
    import java.text.SimpleDateFormat;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
     
    /**
     * @Description 人脸会员音频生成
     * @author 小帅丶
     * @className VipVoiceJob 
     * @Date 2019/11/20 22:11
     **/
    @Slf4j
    public class VipVoiceJob implements Job {
        @Value(value = "${xiaoshuai.path.upload}")
        private String uploadpath;
        @Autowired
        private GeneralDealBeanUtil generalDealBeanUtil;
        @Autowired
        private ICsFaceService csFaceService;
        //获取音频合成的客户端
        AipSpeech aipSpeech = BDFactory.getAipSpeech();
        @Value(value = "${xiaoshuai.domainVoice}")
        private String domainVoice;
     
        /**
         * 度小宇=1,度小美=0,度逍遥=3,度丫丫=4
         * 度博文=106,度小童=110,度小萌=111,度米朵=103,度小娇=5
         **/
        private static final List audioType = Arrays.asList("1","0","3","4","106","110","111","103","5");
        private static final String LANGUAGE_ZH = "zh";
        private static final Integer CTP = 1;
        private static final String AUDIO = ".mp3";
        //任务执行详情
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            System.out.println("execute VipVoiceJob = " + DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
            List vipFaceMap = JobFace.vipFaceMap;
            int vipFaceSize = vipFaceMap.size();
            if(vipFaceSize>0){
                vipFaceMap.forEach(csFace -> {
                    //获取会员信息
                    try {
                        generalAudio(csFace);
                        csFace.setVoiceStatus(1);
                        csFaceService.updateById(csFace);
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                        csFace.setVoiceStatus(2);
                        csFaceService.updateById(csFace);
                    }
                });
                JobFace.vipFaceMap.clear();
            }
        }
        /**
         * @Description 生成全部音库音频文件
         * @Author 小帅丶
         * @Date  2019/11/20 23:28
         * @param face 会员人脸数据
         * @return void
         **/
        public void generalAudio(CsFace face){
            String ctxPath = uploadpath;
            String bizPath = "audios";
            File file = new File(ctxPath + File.separator + bizPath + File.separator + face.getId());
            if (!file.exists()) {
                file.mkdirs();// 创建文件根目录
            }
            long startTime = System.currentTimeMillis();
            audioType.forEach(audioTypeStr->{
                HashMap options = new HashMap<>();
                //合成的文本内容
                String text = "XX门店提醒 "+face.getName()+" 会员到访";
               //发音人选择
               options.put("per",audioTypeStr);
               //语速,取值0-9,默认为5中语速
               options.put("spd", "3");
               String fileName = audioTypeStr+AUDIO;
               TtsResponse response = aipSpeech.synthesis(text,LANGUAGE_ZH,CTP,options);
                byte[] data = response.getData();
                if (data != null) {
                    try {
                        String savePath = file.getPath() + File.separator +fileName;
                        String filePath = bizPath + File.separator + face.getId() + File.separator + fileName;
                        if(null!=face.getVoiceType()&&face.getVoiceType().equals(Integer.parseInt(audioTypeStr))){
                            filePath = filePath.replace("\", "/");
                            face.setVoicePath(filePath);
                            face.setVoiceUrl(domainVoice+filePath);
                        }
                        Util.writeBytesToFileSystem(data, savePath);
                    } catch (Exception e) {
                       System.out.println(e.getMessage());
                    }
                }
            });
            long endTime = System.currentTimeMillis();
            System.out.println("总耗时 = " + (endTime - startTime) + "ms");
        }
    }

    添加一条定时任务

    这里是5秒执行一次。其实可以根据自我需求来定义。定时任务形式也不是必须。

    会员音频提示文件生成

    数字代表的是发音类型。每添加一个会员。则会生成所有发音类型的音频文件哦。方便后续给每个到访会员给定不同声音的提醒

    会员到访APP推送

    非百度AI人脸会员解决方案哦~ 不要问为什么不用百度AI的。上面已经给出说明了。
    
    1.摄像头抓怕推送到人脸库系统
    
    2.人脸库系统对比并推送结果到内部业务系统
    
    3.内部业务系统|人脸库系统推送给APP(小帅使用前者)
    
    下图是一个gif。会演示app收到推送弹窗并播放语音提醒。带声音的等小帅后续上传到第三方网站方便大家查看效果。
    

    视频录屏APP推送会员到访并播放会员专属语音

    链接: https://pan.baidu.com/s/1psqYLmYNqYa4fpqyKS2Xng 提取码: vbf2 复制这段内容后打开百度网盘手机App,操作更方便哦  

  • 相关阅读:
    牛客练习赛51 D题
    Educational Codeforces Round 72 (Rated for Div. 2) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Educational Codeforces Round 72 (Rated for Div. 2) B题
    Educational Codeforces Round 72 (Rated for Div. 2) A题
    《DSP using MATLAB》Problem 7.2
    《DSP using MATLAB》Problem 7.1
    《DSP using MATLAB》Problem 6.24
  • 原文地址:https://www.cnblogs.com/AIBOOM/p/12604287.html
Copyright © 2020-2023  润新知