function jd_audio(content, startTime) { var res = content; Vue.prototype.axios = axios; window.vm = new Vue({ el: "#audio_app", data: { // new start playIndex: 0, // 开始的段落索引 progressArr: [], isLoadding: true, // loadding效果 totolStr: "", //页面的总内容, 用户求卷取值 isFirstCut:true,// 第一次文章分段 initArr:[],// 最多内容数组 runningIndex:0,//播放索引卷曲页面使用 isIOS:false,// 是否是IOS // new end linsteningProIndex: 0,// 处于下载阶段的段落索引 lisProIndex: 0, //正在听的段落的索引, lisInnerIndex: 0, // 当前在听的段落的第几部分 needRequest_speed: false, //是否需要重新请求: 调节语速,音色时true needRequest_sound: false, //是否需要重新请求: 调节语速,音色时true readType: 0, // 听书1 还是 阅读0 isListening: false, startFlag: true, //整章第一次加载true readStartTime: 0, // 开始阅读的时间(毫秒) newSpeed: 1.0,// 调整后的速度 speed: 1.0, // 播放速度控制 timeout: 0, // 定时时间 timeId: 0,// 定时器id activeTime: 0, timearr: [15, 30, 60, 90],// 定时器时间 activeSoundCode: "1", newVoiceCode: "", soundarr: [ { kind: '温柔女声', code: '0', }, { kind: '磁性男声', code: '1', }, { kind: '自然女生', code: '3', } ],// 音色 flags: false, position: { x: 0, y: 0 }, nx: '', ny: '', dx: '', dy: '', xPum: '', yPum: '', blog: "", // 全部文章内容 audioSrc: "", abortMissionsArr: [], // 终止请求函数的存放数组 isFirstRequest: true, // 是否是第一次请求, 第一次jd请求时,只发送一次axios请求, 第二次开始, 批量发送请求 blogArr: [], // 文章内容数组 base64ResultArr: [], // base64响应容器 , key: 请求时的时间戳, val:响应的base64 // baseURL: "https://stream-tts.jd.com/tts/stream", // -dev // baseURL: "http://stream-tts.jd.com/tts/stream", // -dev baseURL:"https://stream-tts-dev.jd.com/tts/range", // IOS新接口 appkey: "a42b852ceccba1b98462a43c78ab899a", // JD测试接口免费购买a42b852ceccba1b98462a43c78ab899a secretKey: "2badb3eb77b3e6eaec78915354df224f", // JD测试接口免费购买2badb3eb77b3e6eaec78915354df224f timeStamp: 0, req: { method: "POST", // url: "https://stream-tts-dev.jd.com/tts/stream", url: "https://stream-tts.jd.com/tts/stream", headers: { "Service-Type": "synthesis", //固定值, 服务类型 "Request-Id": "2c4dc6e2-e1c5-11e8-a867-040973d59110", // 请求语音串标识码 "Sequence-Id": -1, // 1标识非流式,一次性合成返回 "Protocol": 1, // 通信协议版本号,这里设置固定值1 "Net-State": 1, //客户端网络状态:1:WIFI,2:移动,3:联通,4:电信,5:其他 js获取不到运营商状态, 但是可以拿到网络状态, TODO:用户体验上做提醒"非wifi环境" "Applicator": 1, // 外部业务 "Property": "" } }, headPro: { "platform": 'Windows&Win64&10.0', // {平台}&{机型}&{系统版本号} "version": "1.0.0", "parameters": { "tt": 0, // UTF-8 "aue": 3, // wav 1:pcm 2:opus 3:mp3 "tim": 1, // "桃桃女声" "vol": "1.0", //音量 "sp": "1.0", //语速 "sr": 24000 //采样率 } } }, methods: { // new start // 1 开始请求:设置audiosrc为内容 且添加用户偏好设置 start_new: function () { var _this = this; // 创建src赋值给audio $("#audio_new1").attr({ src: _this.setAudioSrc(_this.progressArr[_this.playIndex]) }); // 如果是IOS,3秒后触发点击屏幕,不然不播放 if(this.isIOS){ window.setTimeout(function(){ try { // $("#audio_new1")[0].play(); $(".read_main_p").trigger('click'); } catch (error) { alert("网络异常稍后重试"); window.location.reload(); } },3000); } // 第一次给第一个audio设置src时,加载完成自动播放canplaythrough // $("#audio_new1")[0].addEventListener("canplay", function (e) { // var attr = $(this).data("isplaying"); // if (!attr) { // _this.isLoadding = false; // 隐藏gif // this.play(); //开始播放 // _this.playIndex+=1; // window.playingAudioId = "audio_new1"; // 保存正在播放的audio的id // $("#audio_mask1").toggleClass('menu_box');// 隐藏 语音配置 // $(e.target).siblings('audio').attr({ // 给另一个audiosrc赋值 // src: _this.setAudioSrc(_this.progressArr[_this.playIndex] ) // }); // $(this).data("isplaying", true); // 修改正在播放状态属性,防止第二次预加载完成自动播放 // } // }); // $('#audio_new1').on('loadstart',function(){ // alert(1) // }) //canplaythrough window.disAbale = window.setTimeout(function(){ if(_this.isLoadding){ alert('网络异常,请稍后重试.'); _this.quitAudio_new(); window.clearTimeout(window.disAbale); } } , 5000); $("#audio_new1").on('canplaythrough' , function(e){ window.clearTimeout(window.disAbale); var attr = $(this).data("isplaying"); if (!attr) { _this.isLoadding = false; // 隐藏gif this.play(); //开始播放 _this.playIndex+=1; window.playingAudioId = "audio_new1"; // 保存正在播放的audio的id $("#audio_mask1").toggleClass('menu_box');// 隐藏 语音配置 $(e.target).siblings('audio').attr({ // 给另一个audiosrc赋值 src: _this.setAudioSrc(_this.progressArr[_this.playIndex] ) }); $(this).data("isplaying", true); // 修改正在播放状态属性,防止第二次预加载完成自动播放 } }); }, // 9. 断网检测 scanNetConnect() { var _this = this; // 页面进入网状态 if (window.navigator.onLine) { netType = '1'; } else { netType = '0'; } // 监听网络状态 function updateOnlineStatus(event) { netType = (event.type == 'offline' ? '0' : '1'); if(netType == '0'){ _this.quitAudio_new(); } } window.addEventListener('online', updateOnlineStatus); window.addEventListener('offline', updateOnlineStatus); }, // 8.获取uuid generateUUID() { var d = new Date().getTime(); var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); }); return uuid; }, // 7.1 页面滚动 setScrollTop(scroll_top) { document.documentElement.scrollTop = scroll_top; window.pageYOffset = scroll_top; document.body.scrollTop = scroll_top; }, // 7. 读书页面随动 获取所读内容所在的p标签,求卷曲值 pageMove:function(){ var _this = this; var percent = (_this.runningIndex / _this.initArr.length).toFixed(2); var scrollTop = ($('.read_main_p').height()*percent).toFixed(2); _this.setScrollTop(scrollTop); }, // 6, 修改设置后重新阅读 changeSet: function () { var _this = this; _this.isLoadding = true; if (_this.playIndex == 0) { var currentIndex = _this.playIndex; } else { var currentIndex = _this.playIndex - 1; } var newProgressArr = _this.progressArr.slice(currentIndex); _this.progressArr = newProgressArr; _this.playIndex = 0; $("#audio_new1").data("isplaying", false); window.hobyIsChanged = false; // 开始播放时,清除全局判断偏好设置是否修改 _this.start_new(); }, // 5.退出朗读 quitAudio_new: function () { var _this = this; window.lisFlag = "false"; $('audio').each(function (index, item) { item.pause(); item.src = ""; }); _this.readStartTime = 0; _this.currentPageReaddingCostTime = 0; _this.playIndex = 0; _this.runningIndex = 0; _this.initArr = []; window.localStorage.removeItem('isReading'); $(".menu_hide").removeClass('menu_box'); $("#audio_new1").data("isplaying", false); // _this.readType = 0 // _this.isListening = false window.location.reload(); }, // 4 切换音频资源src changeAudioSource_new: function (e) { var _this = this; _this.pageMove(); // 修改页面卷取值 _this.playIndex += 1; _this.runningIndex+=1; // TODO: 开始播放下一章,数据初始化 console.log((_this.playIndex - 1) +'==='+ _this.progressArr.length); if ((_this.playIndex - 1) == _this.progressArr.length) { // 开启了自动播放 window.autoPlayFlag = true; $('.read_nex_but').trigger("click"); return; }; var sibAudio = $(e.target).siblings('audio')[0]; try { sibAudio.play(); } catch (error) { alert("语音资源加载失败,请重试!"); } window.playingAudioId = sibAudio.id; // 更新正在播放的audio的id $(e.target).attr({ src: _this.setAudioSrc(_this.progressArr[_this.playIndex]) }); }, // 3 设置audioSrc setAudioSrc: function (content) { var _this = this; var timestamp = (new Date()).getTime(); // 时间戳 var id = this.generateUUID(); var hoby = window.localStorage.getItem('listenHoby'); // 偏好设置 var hobyObj = {}; if (hoby) { hoby = JSON.parse(hoby); for (var key in hoby) { hobyObj[key] = hoby[key]; } } return (_this.baseURL + "?" + "appkey=" + _this.appkey + "×tamp=" + timestamp + "&sign=" + md5(_this.secretKey + timestamp) + "&id=" + id + "&sp=" + (hobyObj.sp || "1.0") + "&sr=" + (hobyObj.sr || 24000) + "&vol=" + (hobyObj.vol || "1.0") + "&tim=" + (hobyObj.tim || 0) + "&text=" + encodeURIComponent(content)); }, // 2 内容切块 cutProgressNew: function (contentStr) { var _this = this; var progressArr = []; if (contentStr.length > 0) { var arrtemp = contentStr.split('
'); arrtemp.forEach(function (item, index) { if (index != 0) { progressArr.push(item.replace('
', '')); } }); }; progressArr.splice(0, 1); // 去掉章节标题 _this.pageProgressArr = progressArr; // 每段内容 不足80就加入数组,超出80的分段加入 var tmpArr = []; progressArr.forEach(function(item , index){ if(item.length <= 80){ tmpArr.push(item); }else{ var itemArr = item.split(''); while(itemArr.length > 80){ tmpArr.push(itemArr.splice(0,80).join('')); } tmpArr.push(itemArr.join('')); } }); if(_this.isFirstCut){ _this.initArr = tmpArr; _this.isFirstCut = false; } var tmpArr2 = []; tmpArr.forEach(function(item , index){ if(/[\u4e00-\u9fff]/.test(item) || /[a-zA-Z]/i.test(item) || /\d/.test(item)){ tmpArr2.push(item); } }); _this.progressArr = tmpArr2; }, bardown(e) { this.flags = true; var touch; if (e.touches) { touch = e.touches[0]; } else { touch = e.target; } this.position.x = touch.offsetLeft; this.dx = touch.offsetLeft; }, barmove(e) { if (this.flags) { var touch; if (e.touches) { touch = e.touches[0]; } else { touch = e.target; } var base = audio_speed_bar.offsetLeft; var ebase = touch.clientX; var max = audio_speed_bar.offsetWidth - e.target.offsetWidth; var current; if (ebase - base > max) { current = max; } else if (ebase - base < 0) { current = 0; } else { current = ebase - base; } speed_bar_dot.style.left = current + "px"; // 求比例值 this.newSpeed = (current * 1.5 / max ).toFixed(2) - 0; // + 0.5 } }, barend(e) { this.flags = false; var current = this.newSpeed; console.log(current); if(current >= 0 && current < 0.19){ this.newSpeed = 0.5; speed_bar_dot.style.left = "0%"; }else if(current >= 0.19 && current < 0.56){ this.newSpeed = 0.75; speed_bar_dot.style.left = "23%"; }else if(current >= 0.56 && current < 0.94){ this.newSpeed = 1.0; speed_bar_dot.style.left = "48%"; }else if(current >= 0.94 && current < 1.3){ this.newSpeed = 1.25; speed_bar_dot.style.left = "73%"; }else if(current >= 1.3 && current <= 1.5){ this.newSpeed = 1.5; speed_bar_dot.style.left = "96%"; } this.ctrlSpeed(this.newSpeed); }, ctrlSpeed(newSpeed) { var _this = this; _this.newSpeed = newSpeed; window.newSpeed = newSpeed; _this.updateUserHoby({ sp: newSpeed }); }, ctrlSpeed_dot(sp , left){ speed_bar_dot.style.left = left; this.ctrlSpeed(sp); }, voiceChoice(newVoiceCode) { var _this = this; _this.newVoiceCode = newVoiceCode; window.newVoiceCode = newVoiceCode; _this.updateUserHoby({ tim: newVoiceCode }); }, setTimeOut(minit) { var _this = this; window.localStorage.setItem('timeout', minit); window.clearTimeout(_this.timeId); _this.activeTime = minit; window.localStorage.setItem('startTime' , (new Date()).getTime()); if (minit == '0') { _this.clearTimeOut(); return; } minit = minit * 60 * 1000; _this.timeId = window.setTimeout(function () { _this.quitAudio_new(); // _this.audioSrc = "" // _this.abortMission(); // _this.clearAll(); }, minit); }, clearTimeOut() { var _this = this; window.clearTimeout(_this.timeout); }, updateUserHoby(newHoby) { var _this = this; var hoby = window.localStorage.getItem('listenHoby'); hoby = hoby ? JSON.parse(hoby) : {}; for (var key in newHoby) { hoby[key] = newHoby[key]; } window.localStorage.setItem('listenHoby', JSON.stringify(hoby)); window.localStorage.setItem('timeout', _this.activeTime); }, // new end listenNextPart() { var _this = this; _this.blog = "下一章的文章内容"; _this.base64ResultArr = []; _this.initBlogContent(); }, // 突发首次请求 suddenRequest: function () { var _this = this; _this.isLoadding = true; _this.startFlag = true; _this.isListening = false; _this.base64ResultArr = []; _this.progressArr = _this.progressArr.slice(_this.lisProIndex); _this.lisProIndex = 0; _this.linsteningProIndex = 0; _this.audioSrc = ""; _this.$forceUpdate(); _this.initBlogContent(); }, startListen() { var _this = this; // 修改阅读状态 if (_this.readType == 1) return; _this.blog = res; _this.readType = 1; _this.isListening = false; // _this.suddenRequest() // new start _this.cutProgressNew(res); if (typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function") { _this.start_new(); }else{ //監聽客户端抛出事件"WeixinJSBridgeReady" if (document.addEventListener) { document.addEventListener("WeixinJSBridgeReady", function(){ _this.start_new(); }, false); } else if (document.attachEvent) { document.attachEvent("WeixinJSBridgeReady", function(){ _this.start_new(); }); document.attachEvent("onWeixinJSBridgeReady", function(){ _this.start_new(); }); } } // new end if (startTime == 0) { _this.setTimeOut(_this.activeTime); //48 6635 _this.readStartTime = (new Date()).getTime() - 0; window.localStorage.setItem('startTime', _this.readStartTime); } else { // 如果开始听书是上一张自动读下来的,就另开一个定时器,为更新定时器时间 var leftTime = (new Date()).getTime() - startTime; var total = (window.localStorage.getItem('timeout') - 0) * 1000 * 60; if(total == 0){ return; } var timeout = total - leftTime; console.log('总时差'+total); console.log('剩余时差'+timeout); _this.timeId = window.setTimeout(function () { _this.quitAudio_new(); }, timeout); } // 增加localStorage中isReading状态值为自动听书加标志 window.localStorage.setItem('isReading', 'true'); }, // var hobyIsChange = (_this.newVoiceCode != _this.activeSoundCode || _this.speed != _this.newSpeed) // // 有做修改的就重新请求 // if (hobyIsChange) { // _this.isListening && // _this.activeSoundCode = _this.newVoiceCode // _this.speed = _this.newSpeed // _this.abortMission() // _this.suddenRequest() // } else { // // 没有资源加载时可以切换播放状态 // _this.isListening = !_this.isListening // } // $(".menu_hide").addClass('menu_box'); // return false//"audioWorking" // } else { // return true //"notAudioWorking" // } quitAudio() { var _this = this; _this.clearAll(); _this.$refs.audio.src = ""; _this.base64ResultArr = []; _this.readType = 0; _this.isListening = false; _this.readStartTime = 0; _this.readNext = 0; _this.currentPageReaddingCostTime = 0; _this.abortMission(); window.localStorage.setItem('isReading', 'false'); }, cutProgress(contentStr) { var _this = this; var progressArr = []; if (contentStr.length > 0) { var arrtemp = contentStr.split(''); arrtemp.forEach(function (item, index) { if (index != 0) { progressArr.push({ index: index - 1, content: item.replace('
', '') }); } }); _this.progressArr = progressArr; return 0; } else { return 1; } }, initBlogContent() { var _this = this; // 初始化阅读状态 _this.clearAll(); // 获取资源,中途修改偏好设置不用重新处理数据, 从之前的数组中截取然后请求 if (_this.progressArr.length == 0) { //如果是整章从头处理 if (_this.cutProgress(_this.blog)) return; _this.progressArr.forEach((function (item, index) { _this.string2audio(item.content, item.index); })); } _this.progressArr.forEach(function (item, index) { if (index == _this.linsteningProIndex) { item.blogArr.forEach(function (itemInner, indexInner) { // 请求JD语音接口 _this.audioAjax(itemInner, indexInner, index); }); } }); }, clearAll() { var _this = this; _this.abortMissionsArr = []; }, string2audio(content, index) { var _this = this; // 拆分数组 _this.progressArr[index].blogArr = _this.getContentParts(content); }, getContentParts(content) { var contentArr = content.split(''); var arr = []; var flag = true; var len = 80; // 掐段递增单位 var maxLen = 200; // 最大的字符个数 while (flag) { if (contentArr.length >= maxLen) { arr.push(contentArr.splice(0, len).join('')); len = len * 2 > maxLen ? maxLen : len * 2; } else { arr.push(contentArr.join('')); flag = false; } } return arr; }, audioAjax(contentData, index, progressIndex) { var _this = this; // 准备数据 _this.timeStamp = (new Date()).getTime(); // 本次请求的时间戳 var timeStampCurrentNow = _this.timeStamp; // 局部变量在响应时做记录 var index = index; // 字符串的索引 _this.req.url = `${_this.baseURL}/?appkey=${this.appkey}×tamp=${this.timeStamp}&sign=${md5(this.secretKey + this.timeStamp)}`; _this.req.headers['Request-Id'] = _this.generateUUID(); // 获取用户偏好设置 var hoby = window.localStorage.getItem('listenHoby'); if (hoby) { hoby = JSON.parse(hoby); for (var key in hoby) { _this.headPro.parameters[key] = hoby[key]; } } _this.req.headers['Property'] = JSON.stringify(_this.headPro); var req = { // 需要语音话的字符串 data: { "": contentData }, // data:contentData, // 放弃请求配置 cancelToken: new axios.CancelToken(function executor(c) { _this.abortMissionsArr.push(c); }) }; for (var key in _this.req) { req[key] = _this.req[key]; } // 发送请求 _this // .axios(req) .axios({ method: 'GET', url: "http://mp.ziread.cn/api/jdtts/test/1" }) .then((res) => { if (res.data.code == 10000 && res.data.result.status == 0) { // 存储数据 // 二维数组 if (!_this.base64ResultArr[progressIndex]) { _this.base64ResultArr[progressIndex] = []; } _this.base64ResultArr[progressIndex].push({ index: index, timeStamp: timeStampCurrentNow, audioSrc: res.data.result.audio }); // 如果是整章第一次加载, if (index == 0 && _this.startFlag) { _this.isLoadding = false; // 隐藏loadding效果 _this.startFlag = false; // 首次阅读 _this.base64ResultArr[0].forEach(function (item, index) { if (item.index == 0) { _this.audioSrc = item.audioSrc; _this.$refs.audio.src = "data:audio/mpeg;base64," + _this.audioSrc; _this.$refs.audio.play(); } }); } // 如果下载完成对应段落中音频内容数量和发起下载的段落内容数量相同, 则发起下章节的请求 if (_this.base64ResultArr[progressIndex].length == _this.progressArr[progressIndex].blogArr.length) { _this.linsteningProIndex += 1; } } else { alert("ERROR:CODE" + res.data.code); } }) .catch((err) => { alert("请求语音失败,请联系客服"); }); }, changeAudioSource(e) { var _this = this; var audioTag = e.target; var ProIndex = _this.lisProIndex; var innerIndex = _this.lisInnerIndex; // 下一个播放的真实索引 var nextAudioIndex = innerIndex + 1; // 当前段落读完了 if (_this.base64ResultArr[ProIndex] && (nextAudioIndex == _this.base64ResultArr[ProIndex].length)) { console.log("当前段落听书完毕,开启下一段落,索引:"); _this.lisProIndex += 1; console.log(_this.lisProIndex); // 如果所有段落听书结束,开启翻页 if (_this.lisProIndex == _this.base64ResultArr.length) { console.log("本章读完,开启下一章---TODO"); // 触发加载下一章事件 $('.read_main_other_box .read_nex_but').click(); return; } // 替换音频资源 _this.lisInnerIndex = 0; _this.audioSrc = _this.base64ResultArr[_this.lisProIndex][0].audioSrc; } else { // 有后续资源 // if (!_this.base64ResultArr[_this.lisProIndex]) return _this.base64ResultArr[_this.lisProIndex].forEach(function (item, index) { if (item.index == nextAudioIndex) { _this.lisInnerIndex = nextAudioIndex; _this.audioSrc = item.audioSrc; } }); } }, abortMission() { console.log("done"); if (this.abortMissionsArr.length == 0) return; this.abortMissionsArr.forEach(function (abFn) { abFn(); }); }, }, watch: { // 下载进度监听 linsteningProIndex: function () { var _this = this; console.log("开始下载" + _this.linsteningProIndex + "章节"); _this.initBlogContent(); }, }, mounted: function () { var _this = this; // 获取用户偏好设置 var hoby = window.localStorage.getItem('listenHoby') || '{"sp":"1.0","tim":"1"}'; window.localStorage.setItem('listenHoby', hoby); var timeout = window.localStorage.getItem('timeout'); if (hoby) { hoby = JSON.parse(hoby); _this.speed = hoby.sp ? hoby.sp - 0 : 1.0; _this.activeSoundCode = hoby.tim ? hoby.tim : '1'; // 当前使用的音色 // 用户修改音色,给最新音色赋值, 全局点击文章内容时校验 最新 最初值是否相同, 如果相同则不重新请求 _this.newSpeed = _this.speed; window.newSpeed = _this.speed; window.oldSpeed = _this.speed; _this.newVoiceCode = _this.activeSoundCode; window.newVoiceCode = _this.activeSoundCode;// 全局最新音色 window.oldVoiceCode = _this.activeSoundCode;// 全局最初音色 // 设置语速球位置 var percent = '50%'; if(_this.speed == 0.5){ percent = '0%'; }else if(_this.speed == 0.75){ percent = '23%'; }else if(_this.speed == 1.0){ percent = '48%'; }else if(_this.speed == 1.25){ percent = '73%'; }else if(_this.speed == 1.5){ percent = '96%'; } // var dot = _this.$refs.speed_dot var dot = $("#speed_bar_dot")[0]; dot.style.left = percent; } if (timeout) { _this.activeTime = timeout; } else { _this.activeTime = 0; } this.isIOS = !!(navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)); //ios终端 // 首次读书 _this.startListen(); // 网络检测 _this.scanNetConnect(); } }); }