您现在的位置是:首页 > 文章详情

APP收款语音播报功能讲解

日期:2018-06-14点击:388

一、背景

比起主动扫码能确定收款多少与是否到账,扫二维码支付场景不能直接确认,需要核对客户付款截屏,目前微信、支付宝在扫二维码支付后,均支持收款方自动播报收款到账信息,为了秦丝APP有更好体验,也需要加入该功能。

二、方案

目前实现的收款语音播报功能采用片段组合读音的方案,简单的解释就是根据收款的金额,提取相应数值语音播报,分别包括0-9,十-亿及一些单位或者标注发音等19个语音文件。
比起传统语音合成方案,无需幅度增加app的大小,灵活控制语速。

三、实现

1、触发:在收到收款单号推送后,请求收款金额

2、解析:根据收款金额,解析成一个语音文件对象的数组
以999999.99为例,拆解小数点左右两边部分后分开解析,小数点左边部分又以万为单位拆分,先解析万以内数字,然后再讲万以上的部分又当成万以内的解析加万语音片段,亿、兆类似。小数点后面的部分则从不加单位解析。

// 获取数字转语音文件的队列 function getArrayByNumber(num) { num = num + ""; if (/^(0|[1-9]\d*)(.\d*[1-9])?$/.test(num)) { var nums = num.split("."), pointAfter = nums[1], flag = 0; num = Number(nums[0]); num = dealNum(num); num.unshift(unitsOther.get); if(pointAfter) { nums = pointAfter.split(''); num.push(unitsOther.point); nums.map(function (val) { num.push(units[Number(val)]); }); num.push(unitsOther.yuan); } else { num.push(unitsOther.yuan); num.push(unitsOther.it); } return num; } else { return [audios.zero]; } } // 获取万以上的解析数组 function dealNum(num) { var currNum, level = 0; var arr = [],arrTemp, addZero; if(num === 0){ return [units[0]]; } while (num > 0) { currNum = num % WAN; if (currNum) { if (addZero) { arr.unshift(units[0]); } if (level === 2) { arr = [unitsUpWan[2]].concat(arr); } else if (level) { arr = [unitsUpWan[1]].concat(arr); } arrTemp = dealNumInWan(currNum); addZero = arrTemp[0]; arr = arrTemp[1].concat(arr); } level++; num = Math.floor(num / WAN); } return arr; } // 获取万以内的解析数组 function dealNumInWan(num) { var zero, firstIsZero = num / QIAN < 1 && num > 0; var arr = [], currNum, unit = 0; while (num > 0) { currNum = num % SHI; if (currNum) { zero === undefined && (zero = false); if (unit) { if (zero) { arr.unshift(units[0]); zero = false; } arr.unshift(unitsInWan[unit]); } arr.unshift(units[currNum]); } else { zero === false && (zero = true); } unit++; num = Math.floor(num / SHI); } return [firstIsZero, arr]; }

Audio 对象是一个语音文件对象,每个语音对应有个对象,里面有文件的路径与播放时长,时长是自己设置的每个语音对应有个对象,里面有文件的路径与播放时长,时长是自己设置,时间极短的语音如果有了延时就不会连续播放,时间duration这里需要稍微根据实际情况进行调整

// 语音文件路径与语音文件需用时间的钩子 var audios = { zero: { src: "media/0.wav", duration: 800 }, one: { src: "media/1.wav", duration: 800 }, two: { src: "media/2.wav", duration: 800 }, three: { src: "media/3.wav", duration: 800 } …… nine: { src: "media/9.wav", duration: 800 }, point: { src: "media/point.wav", duration: 800 }, ten: { src: "media/ten.wav", duration: 700 }, hd: { src: "media/hd.wav", duration: 700 }, td: { src: "media/td.wav", duration: 700 }, ttd: { src: "media/ttd.wav", duration: 700 }, hm: { src: "media/hm.wav", duration: 700 }, yuan: { src: "media/yuan.wav", duration: 700 }, it: { src: "media/it.wav", duration: 700 }, get: { src: "media/get.wav", duration: 1800 } }; // 数字转换成语音文件的数组方案 var unitsInWan = ["", audios.ten, audios.hd, audios.td]; var unitsUpWan = ["", audios.ttd, audios.hm, audios.ttd]; var units = [audios.zero, audios.one, audios.two, audios.three, audios.four, audios.five, audios.six, audios.seven, audios.eight, audios.nine]; var unitsOther = { "point": audios.point, "yuan": audios.yuan, "it": audios.it, "get": audios.get };

3、播报:递归方式逐个播放片段

function startAAudio(number, index, audiosArr) { audiosArr || (audiosArr = getArrayByNumber(number)); realMedia = new Media(extUrl + audiosArr[index].src); setTimeout(function () { realMedia.stop(); realMedia.release(); index++; if (audiosArr[index]) { startAAudio(number, index, audiosArr); } else { realMedia = undefined; if(number = audioList.shift()) { // 如果有队列中有新的语音则播放下一则语音 setTimeout(function () { // 连续收款加点时间间隔 startAAudio(number, 0); },2000); } } }, audiosArr[index].duration); realMedia.play(); }

注意

需要用到媒体播放插件cordova-plugin-media

原文链接:https://yq.aliyun.com/articles/602558
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章