/* author:cyhu(viskey.hu@gmail.com) 2015.4.14 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of the authors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var auth_on = false; var uaps_url = 'https://aipingtai.iflysec.com/uap/'; var uaps_params = { // appid: '98765432', // token: '12345678', appid: 'CEVP6G9K', token: 'D2572A0D7', auth_id: 'ffffffff-eacb-3650-390c-5b1800000000_f1e610e1_4', ability: 'ab_tts', svc: 'tts', }; var get_url = ''; var get_uaps_url = function (uaps_uri, msg) { $.ajax({ async: false, type: 'post', url: uaps_uri, contentType: 'application/json-rpc', data: JSON.stringify(msg), dataType: 'text', Accept: 'application/json-rpc', success: function (data, textStatus, jqXHR) { // console.log(data); // console.log(textStatus); // console.log(jqXHR); // alert("--------return data : " + data); // alert("--------return json : " + utils.base64decode(data)); // alert("--------return result.url : " + JSON.parse(utils.base64decode(data)).result.url); var resp_data = utils.base64decode(data); if ( JSON.stringify(JSON.parse(resp_data).result) != null && JSON.stringify(JSON.parse(resp_data).result) != undefined ) { get_url = JSON.parse(utils.base64decode(data)).result.url; } if ( JSON.stringify(JSON.parse(resp_data).error) != null && JSON.stringify(JSON.parse(resp_data).error) != undefined ) { alert( 'tts_uaps_getUrl,error : ' + JSON.stringify(JSON.parse(resp_data).error) ); } }, error: function (xhr, textStatus) { console.log('错误'); console.log(xhr); console.log(textStatus); alert(JSON.parse(utils.base64decode(xhr.responseText))); }, complete: function (XHR, TS) { XHR = null; }, //回收资源 }); }; uaps_sse = function (uaps_uri, msg) { $.ajax({ async: true, type: 'post', url: uaps_uri, contentType: 'application/json-rpc', data: JSON.stringify(msg), dataType: 'text', Accept: 'application/json-rpc', success: function (data, textStatus, jqXHR) { // console.log(data); // console.log(textStatus); // console.log(jqXHR); //alert("---------uaps_sse : "+JSON.parse(utils.base64decode(data)).result.ret); var uaps_sse_ret = JSON.parse(utils.base64decode(data)).result.ret; if (uaps_sse_ret != 0) { alert('tts_uaps_sse ,error : ' + uaps_sse_ret); } }, error: function (xhr, textStatus) { console.log('错误'); console.log(xhr); console.log(textStatus); alert(JSON.parse(utils.base64decode(xhr.responseText))); }, complete: function (XHR, TS) { XHR = null; }, //回收资源 }); }; uaps_heart = function (uaps_uri, msg) { $.ajax({ async: true, type: 'post', url: uaps_uri, contentType: 'application/json-rpc', data: JSON.stringify(msg), dataType: 'text', Accept: 'application/json-rpc', success: function (data, textStatus, jqXHR) { // console.log(data); // console.log(textStatus); // console.log(jqXHR); //alert("---------uaps_heart : "+JSON.parse(utils.base64decode(data)).result.ret); var uaps_heart_ret = JSON.parse(utils.base64decode(data)).result.ret; if (uaps_heart_ret != 0) { alert('tts_uaps_heart ,error : ' + uaps_heart_ret); } }, error: function (xhr, textStatus) { console.log('错误'); console.log(xhr); console.log(textStatus); alert(JSON.parse(utils.base64decode(xhr.responseText))); }, complete: function (XHR, TS) { XHR = null; }, //回收资源 }); }; var _utf8_decode = function (utftext) { var string = ''; var i = 0; var c = (c1 = c2 = 0); while (i < utftext.length) { c = utftext.charCodeAt(i); if (c < 128) { string += String.fromCharCode(c); i++; } else if (c > 191 && c < 224) { c2 = utftext.charCodeAt(i + 1); string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); i += 2; } else { c2 = utftext.charCodeAt(i + 1); c3 = utftext.charCodeAt(i + 2); string += String.fromCharCode( ((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63) ); i += 3; } } return string; }; var brower_info = { sys: null, type: null, link: null, }; /* */ var print_log = true; //var websocket_url = ''; var websocket_url = ''; var reconnection = false; var reconnection_delay = 999999; var force_new_connection = true; var buffer_length = 0; var tts_params_obj = null; this.node = null; var tts_session_id = null; var tts_text_ready = null; var func_on_tts_process = null; var func_on_tts_result = null; var browser_id = null; /* new Fingerprint().get(); */ var is_re_request = false; var request_synid = null; var ua = navigator.userAgent.toLowerCase(); var utils = { log: function (message, level) { if (level > 0) { console.log(message); } }, base64encode: function (str) { var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; var out, i, len; var c1, c2, c3; len = str.length; i = 0; out = ''; while (i < len) { c1 = str.charCodeAt(i++) & 0xff; if (i == len) { out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt((c1 & 0x3) << 4); out += '=='; break; } c2 = str.charCodeAt(i++); if (i == len) { out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4)); out += base64EncodeChars.charAt((c2 & 0xf) << 2); out += '='; break; } c3 = str.charCodeAt(i++); out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4)); out += base64EncodeChars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6)); out += base64EncodeChars.charAt(c3 & 0x3f); } return out; }, base64decode: function (input) { var output = ''; var _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; var chr1, chr2, chr3; var enc1, enc2, enc3, enc4; var i = 0; if (input != null) { input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); while (i < input.length) { enc1 = _keyStr.indexOf(input.charAt(i++)); enc2 = _keyStr.indexOf(input.charAt(i++)); enc3 = _keyStr.indexOf(input.charAt(i++)); enc4 = _keyStr.indexOf(input.charAt(i++)); chr1 = (enc1 << 2) | (enc2 >> 4); chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); chr3 = ((enc3 & 3) << 6) | enc4; output = output + String.fromCharCode(chr1); if (enc3 != 64) { output = output + String.fromCharCode(chr2); } if (enc4 != 64) { output = output + String.fromCharCode(chr3); } } output = _utf8_decode(output); return output; } else { return null; } }, }; if ( (/msie/.test(ua) && !/opera/.test(ua)) || ((/msie/.test(ua) || /trident/.test(ua)) && !/opera/.test(ua)) ) brower_info.type = 'ie'; else if (ua.match(/firefox\/([\d.]+)/)) { brower_info.type = 'firefox'; } else if (ua.match(/chrome\/([\d.]+)/)) brower_info.type = 'chrome'; else if (ua.match(/opera.([\d.]+)/)) brower_info.type = 'opera'; else if (ua.match(/version\/([\d.]+).*safari/)) brower_info.type = 'safari'; else brower_info.type = 'other'; if (!!ua.match(/AppleWebKit.*Mobile.*/) || !!ua.match(/AppleWebKit/)) brower_info.sys = 'mobile'; else if (!!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)) brower_info.sys = 'ios'; else if (ua.indexOf('Android') > -1 || ua.indexOf('Linux') > -1) brower_info.sys = 'android'; else if (ua.indexOf('iPhone') > -1 || ua.indexOf('Mac') > -1) brower_info.sys = 'iPhone'; else if (ua.indexOf('iPad') > -1) brower_info.sys = 'iPad'; else if (navigator.userAgent.indexOf('MicroMessenger') > -1) brower_info.sys = 'Weixin'; else brower_info.sys = 'other'; //if(brower_info.type == 'ie' || ((brower_info.type == 'chrome' || brower_info.type == 'opera') && brower_info.sys != 'other')) //{ brower_info.link = 'mp3'; //}else if(brower_info.sys == 'Weixin'){ //brower_info.link = 'mp3'; //} function register_connection_listener() { window.socket.onopen = function () { console.log('connected to server ...'); //var json = {"ver" : "1.0", "sub" : "tts", "cmd" : "ssb", "synid" : tts_params_obj.synid , "msg" : "request", "appid": tts_params_obj.appid, "appkey":tts_params_obj.appkey, "data" : { "params" : tts_params_obj.params , "text" : tts_text_ready}}; var json = { jsonrpc: '2.0', method: 'deal_request', id: 1, params: { cmd: 'ssb', svc: 'tts', auf: '4', //"appid" : "pc20onli", type: '' + tts_params_obj.type, vid: '' + tts_params_obj.vcn, aue: 'raw', //固定为8k16bitwav格式 data: tts_text_ready, }, }; if (tts_params_obj.appid == null || tts_params_obj.appid == undefined) { json.params.appid = 'pc20onli'; } else { json.params.appid = tts_params_obj; } if (tts_params_obj.spd) { json.params.spd = tts_params_obj.spd; } //console.log(tts_params_obj.params); console.log(JSON.stringify(json)); window.socket.send(JSON.stringify(json)); }; window.socket.onclose = function (e) { console.log('client disconnect ...'); is_re_request = false; }; window.socket.onmessage = function (obj) { // console.log('on message'); // console.log(obj); var json = strToJson(obj.data); var cmd = json.result['cmd']; var data = json.result['audioKey']; //var ret = 0; // console.log('json : ' + JSON.stringify(json)); // console.log('cmd : ' + cmd); // console.log('data : ' + data); is_re_request = true; //------------------ if (auth_on) { var uaps_heart_param = { token: uaps_params.token, appid: uaps_params.appid, ability: uaps_params.ability, auth_id: uaps_params.auth_id, svc: uaps_params.svc, batchHeartBeat: '1', }; var msg = { jsonrpc: '2.0', method: 'deal_request', params: uaps_heart_param, }; uaps_heart(uaps_url, msg); } //------------------ ttsGetAudioStream(json.result); }; } function LOGCAT(str) { if (print_log) console.log('[' + getCurrentTime() + '] ' + str); } function getCurrentTime() { var now = new Date(); var year = now.getFullYear(); var month = now.getMonth() + 1; var day = now.getDate(); var hh = now.getHours(); var mm = now.getMinutes(); var clock = year + '-'; if (month < 10) clock += '0'; clock += month + '-'; if (day < 10) clock += '0'; clock += day + ' '; if (hh < 10) clock += '0'; clock += hh + ':'; if (mm < 10) clock += '0'; clock += mm; return clock; } sendRequestMessage = function () { console.log('connected to server ...'); var json = { jsonrpc: '2.0', method: 'deal_request', id: 1, params: { cmd: 'ssb', svc: 'tts', appid: 'pc20onli', type: '' + tts_params_obj.type, vid: '' + tts_params_obj.vcn, aue: 'raw', //固定为8k16bitwav格式 auf: '4', data: tts_text_ready, }, }; if (tts_params_obj.spd) { json.params.spd = tts_params_obj.spd; } // console.log(JSON.stringify(json)); window.socket.send(JSON.stringify(json)); }; function initTtsParams(cfg) { if (cfg.reconnection != undefined && cfg.reconnection != null) reconnection = cfg.reconnection; if (cfg.reconnection_delay != undefined && cfg.reconnection_delay != null) reconnection_delay = cfg.reconnectionDelay; if (cfg.serveUrl != undefined && cfg.serveUrl != null) websocket_url = cfg.serveUrl; } function IFlyTtsSession(cfg) { initTtsParams(cfg); /* * start a speech synthesize session, schedule: start->send text -> return audio url * ->on end -> next session * @params parameters for synthesize * @content content for synthesize * @funcOnResult on volume listener * @funcOnProcess on process */ this.start = function (params, content, funcOnResult, funcOnProcess) { iflytek_tts_start(params, content, funcOnResult, funcOnProcess); }; /* * stop synthsize session */ this.stop = function () {}; /* * cancel synthsize session */ this.cancel = function () { iflytek_tts_cancel(); }; } //合成ssb参数, 合成文本, 回调函数 function iflytek_tts_start(params, content, funcOnResult, funcOnProcess) { if (arguments.length < 3) { LOGCAT('INPUT PARAMETERS ERROR'); return -1; } if (funcOnProcess != undefined) func_on_tts_process = funcOnProcess; func_on_tts_result = funcOnResult; tts_params_obj = params; tts_text_ready = content; if ( window.socket == null || window.socket == undefined || window.socket.readyState != 1 ) { //var url = websocket_url; //------------------------ var url = ''; if (auth_on) { var uaps_ssb_param = { token: uaps_params.token, appid: uaps_params.appid, ability: uaps_params.ability, auth_id: uaps_params.auth_id, svc: uaps_params.svc, cmd: 'ssb', }; var msg = { jsonrpc: '2.0', method: 'deal_request', params: uaps_ssb_param, }; get_uaps_url(uaps_url, msg); url = 'wss://' + get_url; } else { url = websocket_url; } //------------------------------ //如果外部没有传入url,则采用默认的url /* if(tts_params_obj.url != null && tts_params_obj.url != undefined) { url = tts_params_obj.url; } */ // console.log(url); window.socket = new WebSocket(url); } register_connection_listener(); if (is_re_request) { sendRequestMessage(); } } function iflytek_tts_cancel() { is_re_request = true; LOGCAT('----------tts cancel----------'); } /* * request session end */ function ttsSessionEnd(wait_time) { is_re_request = true; LOGCAT('----------session end----------'); //------------------ if (auth_on) { var uaps_sse_param = { token: uaps_params.token, appid: uaps_params.appid, ability: uaps_params.ability, auth_id: uaps_params.auth_id, svc: uaps_params.svc, cmd: 'sse', }; var msg = { jsonrpc: '2.0', method: 'deal_request', params: uaps_sse_param, }; uaps_heart(uaps_url, msg); } //------------------------- } function strToJson(str) { var json = eval('(' + str + ')'); return json; } function ttsGetAudioStream(data) { if (data.audioKey != null && data.audioKey != '') { func_on_tts_result(0, { audio_url: data.audioKey, duration: data.duration, }); } else { // console.log('data.audioKey is null'); } ttsSessionEnd(0); }