纳米tts组合

autobcb_admin (12020)6小时前

12 627.92kb 8

修改自晴天tts
网络导入
二维码导入(APP尚未完成该功能)
数据列表
名称 地址
纳米(DeepSeek) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "DeepSeek"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
纳米(豆包) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "doubao"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
纳米(通义) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "tongyi"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
纳米(混元) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "hunyuan"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
纳米(文心) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "wenxin"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
纳米(Max) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "MiniMax"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
纳米(智谱) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "zhipu"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
纳米(商汤) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "shangtang"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
纳米(小应) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "baixiaoying"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
纳米(星火) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "xunfei"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
纳米(星辰) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "stepspark"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
纳米(Kimi) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>默认tts</title> </head> <body> <script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"702014e4293d4dedac01462951f7029c","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script> </body> <!-- 没用到jq请去掉--> <script src="https://vc.jd.com/web/js/jquery-3.1.1.min.js"></script> <script> var isCookieJar=true;// 不需要CookieJar请修改此处 class FlutterJSBridge { constructor() { this.init(); //前台webview 里必须删除这行 } init() { if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); } else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; console.log('JSBridge初始化完成'); this.CookieJar(); }); } } //通知原生页面初始化完成,仅在书源和tts生效,webview请勿使用,只有通知加载成功后才允许运行,否则会一直等待加载成功 async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (error) { console.error('汇报完成准备失败:', error); } } //获取应用编译版本 async getbuildNumber() { try { return await window.flutter_inappwebview.callHandler('buildNumber'); } catch (error) { return 0; } } //获取应用版本 async getversion() { try { return await window.flutter_inappwebview.callHandler('version'); } catch (error) { return "0.0.0"; } } //获取设备唯一id async getDeviceid() { try { return await window.flutter_inappwebview.callHandler('id'); } catch (error) { return ""; } } //获取设备平台 此处返回 windows、macos、ios、ohos、android async getDevice() { try { return await window.flutter_inappwebview.callHandler('device'); } catch (error) { return ""; } } //输出日志,前台webview请勿使用 //str 为 String async log(str) { try { return await window.flutter_inappwebview.callHandler('log',str); } catch (error) { return false; } } //书源调试时可输出 html 代码到前台 //type 0 搜索源码 , 1详情源码 ,2目录源码 ,3正文源码 //str 为 String //type 为int async text(type,str) { try { return await window.flutter_inappwebview.callHandler('text',type,str); } catch (error) { return false; } } //toast弹窗 //str 为 String async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast',str); } catch (error) { return false; } } //获取默认ua async getWebViewUA() { try { return await window.flutter_inappwebview.callHandler('getWebViewUA'); } catch (error) { return ""; } } //通过url打开外部应用 //url 为 String async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl',url,""); } catch (error) { return false; } } //通过url打开外部应用并附带mimeType //url 为 String //mimeType 为 String async openurlwithMimeType(url,mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl',url,mimeType); } catch (error) { return false; } } /** * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url * @param url html内如果有相对路径的资源不传入url访问不了 * @param js 用来取返回值的js语句, 没有就返回整个源代码 * @param body 当参数不为空的时候,会以post请求,此时请务必在 header 中带上content-type * @param header 请求的header头,此参数必须是json字符串 * @return 返回js获取的内容 */ async webview(url,js,html,body,header) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",""); } catch (error) { return ""; } } /** * overrideUrlRegex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetOverrideUrl(url,js,html,body,header,overrideUrlRegex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,overrideUrlRegex,""); } catch (error) { return ""; } } /** * 使用webView获取资源url * urlregex 为正则表达式 * 使用方法和上面的一样 * 但返回的内容为正则到的内容,如果无法正则到则返回 js 获取的内容,如果 js 为空则返回页面 html */ async webViewGetSource(url,js,html,body,header,urlregex) { try { return await window.flutter_inappwebview.callHandler('webview',url,js,html,body,header,"",urlregex); } catch (error) { return ""; } } /** * 启动前台 webview 访问链接并获取结束时的 html,可用于手工过盾 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 * @return 返回网页的内容 */ async startBrowser(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowser',url,title,header); } catch (error) { return ""; } } /** * 启动前台 webview 并对每次打开的 url 进行拦截 * @param url 网址 * @param title 标题 * @param header 请求的header头,此参数必须是json字符串 */ async startBrowserWithShouldOverrideUrlLoading(url,title,header) { try { return await window.flutter_inappwebview.callHandler('startBrowserWithShouldOverrideUrlLoading',url,title,header); } catch (error) { return ""; } } //专门为段评设置的半屏显示,不返回任何东西 async startBrowserDp(url,title) { try { return await window.flutter_inappwebview.callHandler('startBrowserDp',url,title); } catch (error) { return ""; } } //仅前台webview可以使用,返回按钮,返回上一个页面 async back() { try { return await window.flutter_inappwebview.callHandler('back'); } catch (error) { return false; } } //将 utf8字符串转到 gbk 并 url 编码 async utf8ToGbkUrlEncoded(str) { try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded',str); } catch (error) { return ""; } } /* * @param str为图片链接 * @param header 请求的header头,此参数必须是json字符串 * 此函数是让用户输入图片中的验证码,当链接为空则直接让用户输入验证码 */ async getVerificationCode(str,header) { try { return await window.flutter_inappwebview.callHandler('getVerificationCode',str,header); } catch (error) { return ""; } } //提交内容书本信息 json 后的字符串 async addbook(book) { try { return await window.flutter_inappwebview.callHandler('addbook',book); } catch (error) { return ""; } } //utf8 字符串转base64 async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode',str); } catch (error) { return ""; } } //base64 转utf8字符串 async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode',str); } catch (error) { return ""; } } } //webview请勿使用 //以下提交的url,headers,body 都必须为字符串,headers必须为json字符串 //当followRedirects 为 false 时不处理重定向,当为 true 时会自动处理重定向 ,如不明白用途直接用 true 最佳 // 以下所有参数除当followRedirects外均为 String // 如果需要使用http2协议 请在url 前添加 http2:// ,例如 http2://baidu.com // 如果https一直被盾拦截 ,可以使用https2协议 class Http { constructor() {} /* * 通用返回字段 * method post get 或者 head * body 请求返回后的字节的 base64 * headers map<String,List<String>> 可通过headers[""]来或者 * statusCode 状态码 * statusMessage * data 返回后的字节 格式化后的内容 */ async Get(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"get",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Head(url,headers,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"head",url,"",JSON.stringify(headers),followRedirects,""); } catch (error) { return null; } } async Post(url,headers,body,contenttype,followRedirects) { try { return await window.flutter_inappwebview.callHandler('http',"post",url,body,JSON.stringify(headers),followRedirects,contenttype); } catch (error) { return null; } } } class Cache { constructor() {} async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get',key); } catch (error) { return null; } } async set(key,value) { try { return await window.flutter_inappwebview.callHandler('cache.set',key,value); } catch (error) { return null; } } async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove',key); } catch (error) { return null; } } //如果登录为弹窗格式的,里面输入框输入的内容可以通过这个函数获取,默认返回的json格式或者为空,需要自行转换 async getLoginInfo(){ return await this.get("LoginInfo") } //将修改后的弹窗输入内容报错 ,必须 JSON.stringify,不然会出错 async putLoginInfo(info){ return await this.set("LoginInfo",info) } //获取书本变量 async getbookVariable(bookurl){ return await this.get(bookurl) } //写入书本变量 async setbookVariable(bookurl,value){ return await this.set(bookurl,value) } } class Cookie { constructor() {} //通过url获取当前url的所有cookie async get(url) { try { return await window.flutter_inappwebview.callHandler('cookie.get',url); } catch (error) { return null; } } //通过url删除当前url的所有cookie async remove(url) { try { return await window.flutter_inappwebview.callHandler('cookie.remove',url); } catch (error) { return null; } } //通过url保存当前url的所有cookie async set(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.set',url,value); } catch (error) { return null; } } //设置单独一个cookie async setCookie(url,key,value) { try { return await window.flutter_inappwebview.callHandler('cookie.setcookie',url,key,value); } catch (error) { return null; } } //通过 url 获取单个 cookie 的值 async getCookie(url,value) { try { return await window.flutter_inappwebview.callHandler('cookie.getCookie',url,value); } catch (error) { return null; } } } //安全的创建一个 div 解析 html function parseHTMLSafely(htmlStr) { try { // 在函数作用域内创建独立的临时容器 // 每个调用创建新的jQuery对象,互不影响 var tempDiv = document.createElement('div'); tempDiv.innerHTML = htmlStr; return $(tempDiv); } catch (e) { flutterBridge.log("HTML解析错误:"+e.message); return $('<div>'); } } //parseHTMLSafely 创建的用完后必须删除 function removeHTMLSafely(tempContainer) { try { tempContainer.innerHTML = ''; if (tempContainer.parentNode) { tempContainer.parentNode.removeChild(tempContainer); } } catch (e) { flutterBridge.log("HTML移除失败:"+e.message); } } //移除 css js,创建parseHTMLSafely前如果用不上 cssjs 建议移除 function removeHTMLTags(htmlString) { // 移除script标签 let result = htmlString.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // 移除style标签 result = result.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, ''); return result; } </script> <script> const flutterBridge = new FlutterJSBridge(); const cache = new Cache(); const http = new Http(); const cookie = new Cookie(); // ========== 完整的TTS引擎数据 ========== const ttsData = { "microsoft": { name: "微软 Azure", icon: "microsoft", iconClass: "fab fa-microsoft", engines: [ {id: "ms-xiaoxiao", name: "晓晓", desc: "女声·温暖亲切", voice: "zh-CN-XiaoxiaoNeural"}, {id: "ms-xiaoyi", name: "晓亦", desc: "女声·活泼可爱", voice: "zh-CN-XiaoyiNeural"}, {id: "ms-xiaochen", name: "晓辰", desc: "女声·清新自然", voice: "zh-CN-XiaochenNeural"}, {id: "ms-xiaohan", name: "晓涵", desc: "女声·知性优雅", voice: "zh-CN-XiaohanNeural"}, {id: "ms-xiaomeng", name: "晓梦", desc: "女声·甜美可人", voice: "zh-CN-XiaomengNeural"}, {id: "ms-xiaomo", name: "晓墨", desc: "女声·温柔细腻", voice: "zh-CN-XiaomoNeural"}, {id: "ms-xiaoqiu", name: "晓秋", desc: "女声·成熟稳重", voice: "zh-CN-XiaoqiuNeural"}, {id: "ms-xiaorou", name: "晓柔", desc: "女声·柔和舒适", voice: "zh-CN-XiaorouNeural"}, {id: "ms-xiaorui", name: "晓翠", desc: "女声·清脆明亮", voice: "zh-CN-XiaoruiNeural"}, {id: "ms-xiaoshuang", name: "晓双", desc: "童声·活泼可爱", voice: "zh-CN-XiaoshuangNeural"}, {id: "ms-xiaoyan", name: "晓颜", desc: "女声·端庄大方", voice: "zh-CN-XiaoyanNeural"}, {id: "ms-xiaoyou", name: "晓悠", desc: "童声·天真烂漫", voice: "zh-CN-XiaoyouNeural"}, {id: "ms-xiaozhen", name: "晓甄", desc: "女声·大气专业", voice: "zh-CN-XiaozhenNeural"}, {id: "ms-yunxi", name: "云溪", desc: "男声·青年活力", voice: "zh-CN-YunxiNeural"}, {id: "ms-yunjian", name: "云间", desc: "男声·沉稳大气", voice: "zh-CN-YunjianNeural"}, {id: "ms-yunyang", name: "云扬", desc: "男声·新闻播报", voice: "zh-CN-YunyangNeural"}, {id: "ms-yunfeng", name: "云枫", desc: "男声·浑厚磁性", voice: "zh-CN-YunfengNeural"}, {id: "ms-yunhao", name: "云皓", desc: "男声·阳光温暖", voice: "zh-CN-YunhaoNeural"}, {id: "ms-yunjie", name: "云杰", desc: "男声·成熟稳重", voice: "zh-CN-YunjieNeural"}, {id: "ms-yunxia", name: "云夏", desc: "男声·少年清澈", voice: "zh-CN-YunxiaNeural"}, {id: "ms-yunye", name: "云野", desc: "男声·沧桑故事", voice: "zh-CN-YunyeNeural"}, {id: "ms-yunze", name: "云泽", desc: "男声·浑厚有力", voice: "zh-CN-YunzeNeural"}, {id: "ms-xiaoxiao-dia", name: "晓晓DIA", desc: "女声·方言版", voice: "zh-CN-XiaoxiaoDialectsNeural"}, {id: "ms-xiaoxiao-mt", name: "晓晓MT", desc: "女声·多语言", voice: "zh-CN-XiaoxiaoMultilingualNeural"}, {id: "ms-xiaoyu-mt", name: "晓宇MT", desc: "女声·多语言", voice: "zh-CN-XiaoyuMultilingualNeural"}, {id: "ms-yunxiao-mt", name: "云晓MT", desc: "男声·多语言", voice: "zh-CN-YunxiaoMultilingualNeural"}, {id: "ms-yunyi-mt", name: "云逸MT", desc: "男声·多语言", voice: "zh-CN-YunyiMultilingualNeural"}, {id: "ms-yunfan-mt", name: "云帆MT", desc: "男声·多语言", voice: "zh-CN-YunfanMultilingualNeural"}, { id: "ms-xiaochen-hd", name: "晓辰HD", desc: "女声·高清版", voice: "zh-CN-Xiaochen:DragonHDLatestNeural" }, {id: "ms-yunfan-hd", name: "云帆HD", desc: "男声·高清版", voice: "zh-CN-Yunfan:DragonHDLatestNeural"}, { id: "ms-xiaochen-fhd", name: "晓辰FHD", desc: "女声·超高清", voice: "zh-CN-Xiaochen:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao-fhd", name: "晓晓FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao:DragonHDFlashLatestNeural" }, { id: "ms-xiaoxiao2-fhd", name: "潇潇FHD", desc: "女声·超高清", voice: "zh-CN-Xiaoxiao2:DragonHDFlashLatestNeural" }, { id: "ms-yunxiao-fhd", name: "云觉FHD", desc: "男声·超高清", voice: "zh-CN-Yunxiao:DragonHDFlashLatestNeural" }, { id: "ms-yunye-fhd", name: "云野FHD", desc: "男声·超高清", voice: "zh-CN-Yunye:DragonHDFlashLatestNeural" }, { id: "ms-yunyi-fhd", name: "云逸FHD", desc: "男声·超高清", voice: "zh-CN-Yunyi:DragonHDFlashLatestNeural" }, {id: "ms-hsiao-chen", name: "晓宸(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoChenNeural"}, {id: "ms-hsiao-yu", name: "晓语(繁)", desc: "女声·台湾繁体", voice: "zh-TW-HsiaoYuNeural"}, {id: "ms-yun-jhe", name: "云喆(繁)", desc: "男声·台湾繁体", voice: "zh-TW-YunJheNeural"} ] }, "nano": { name: "纳米 AI", icon: "nano", iconClass: "fas fa-robot", engines: [ {id: "nano-deepseek", name: "DeepSeek", desc: "AI·深度求索", voice: "DeepSeek"}, {id: "nano-doubao", name: "豆包", desc: "AI·字节跳动", voice: "doubao"}, {id: "nano-zhinao", name: "智脑", desc: "AI·360智脑", voice: "zhinao"}, {id: "nano-tongyi", name: "通义", desc: "AI·阿里巴巴", voice: "tongyi"}, {id: "nano-hunyuan", name: "混元", desc: "AI·腾讯", voice: "hunyuan"}, {id: "nano-wenxin", name: "文心", desc: "AI·百度", voice: "wenxin"}, {id: "nano-minimax", name: "MiniMax", desc: "AI·MiniMax", voice: "MiniMax"}, {id: "nano-zhipu", name: "智谱", desc: "AI·智谱清言", voice: "zhipu"}, {id: "nano-shangtang", name: "商汤", desc: "AI·商汤科技", voice: "shangtang"}, {id: "nano-lingyi", name: "零一", desc: "AI·零一万物", voice: "lingyi"}, {id: "nano-baixiaoying", name: "百小应", desc: "AI·百度", voice: "baixiaoying"}, {id: "nano-xunfei", name: "星火", desc: "AI·讯飞", voice: "xunfei"}, {id: "nano-stepspark", name: "星辰", desc: "AI·Step", voice: "stepspark"}, {id: "nano-kimi", name: "Kimi", desc: "AI·月之暗面", voice: "Kimi"} ] }, "sibiachi": { name: "思必驰", icon: "sibiachi", iconClass: "fas fa-brain", engines: [ // 男声 - 精品系列 {id: "sbc-yukaimp", name: "俞师", desc: "男声·精品", voiceId: "yukaimp"}, {id: "sbc-jlshimp", name: "季师", desc: "男声·精品", voiceId: "jlshimp"}, {id: "sbc-tzruimp", name: "小睿", desc: "男声·精品", voiceId: "tzruimp"}, {id: "sbc-wjianm", name: "小江", desc: "男声·精品", voiceId: "wjianm_xsheng"}, // 男声 - 标准/其他风格 {id: "sbc-xijunm", name: "小军", desc: "男声·严肃", voiceId: "xijunm"}, {id: "sbc-xijunma", name: "小军温和", desc: "男声·温和", voiceId: "xijunma"}, {id: "sbc-gdgm", name: "纲叔", desc: "男声·沉稳", voiceId: "gdgm"}, {id: "sbc-yukaim", name: "老师", desc: "男声·磁性", voiceId: "yukaim_all"}, {id: "sbc-kaolam", name: "考拉", desc: "男声·电台", voiceId: "kaolam_diantai"}, {id: "sbc-geyoump", name: "葛爷", desc: "男声·淡定", voiceId: "geyoump"}, {id: "sbc-geyou", name: "葛爷风趣", desc: "男声·风趣", voiceId: "geyou"}, {id: "sbc-zxcm", name: "星哥", desc: "男声·幽默", voiceId: "zxcm"}, {id: "sbc-zxcmp", name: "星哥风趣", desc: "男声·风趣", voiceId: "zxcmp"}, {id: "sbc-qiumum", name: "秋木", desc: "男声·故事", voiceId: "qiumum_0gushi"}, // 童声 {id: "sbc-tangtang", name: "堂堂", desc: "童音·男", voiceId: "tangtang_boyfp"}, {id: "sbc-gdfanf-boy", name: "方方", desc: "童音·男", voiceId: "gdfanf_boy"}, // 女声 - 精品系列 {id: "sbc-cyangfp", name: "初阳", desc: "女声·精品", voiceId: "cyangfp"}, {id: "sbc-aningfp", name: "安宁", desc: "女声·精品", voiceId: "aningfp"}, {id: "sbc-xizhefp", name: "行者", desc: "女声·精品", voiceId: "xizhefp"}, {id: "sbc-feyinfp", name: "风吟", desc: "女声·精品", voiceId: "feyinfp"}, // 女声 - 甜美/温柔 {id: "sbc-zhilingfp", name: "小玲", desc: "女声·甜美", voiceId: "zhilingfp"}, {id: "sbc-xjingfp", name: "小静", desc: "女声·甜美", voiceId: "xjingfp"}, {id: "sbc-xmguof", name: "婷婷", desc: "女声·甜美", voiceId: "xmguof"}, {id: "sbc-xmamif", name: "小咪", desc: "女声·甜美", voiceId: "xmamif"}, {id: "sbc-gqlanfp", name: "小兰", desc: "女声·温柔", voiceId: "gqlanfp"}, {id: "sbc-madoufp-wenrou", name: "麻豆", desc: "女声·温柔", voiceId: "madoufp_wenrou"}, // 女声 - 客服/标准 {id: "sbc-xijiufp", name: "小九", desc: "女声·客服", voiceId: "xijiufp"}, {id: "sbc-juan1f", name: "小美", desc: "女声·客服", voiceId: "juan1f"}, {id: "sbc-gdfanfp", name: "芳芳", desc: "女声·客服", voiceId: "gdfanfp"}, {id: "sbc-cyangf", name: "初阳", desc: "女声·标准", voiceId: "cyangf"}, {id: "sbc-lucyfa", name: "小浩", desc: "女声·标准", voiceId: "lucyfa"}, {id: "sbc-luyaof", name: "瑶瑶", desc: "女声·标准", voiceId: "luyaof"}, {id: "sbc-yaayif", name: "阿姨", desc: "女声·标准", voiceId: "yaayif"}, {id: "sbc-gdfanf", name: "方方", desc: "女声·标准", voiceId: "gdfanf_natong"}, // 女声 - 其他特色 {id: "sbc-anonyf", name: "小佚", desc: "女声·平和", voiceId: "anonyf"}, {id: "sbc-smjief", name: "小洁", desc: "女声·清亮", voiceId: "smjief"}, {id: "sbc-xjingf", name: "小静", desc: "女声·飘逸", voiceId: "xjingf"}, {id: "sbc-jjingfp", name: "晶晶", desc: "女声·知性", voiceId: "jjingfp"}, {id: "sbc-hyanif", name: "小妮", desc: "女声·邻家", voiceId: "hyanif"}, {id: "sbc-kaolaf", name: "考拉", desc: "女声·清纯", voiceId: "kaolaf"}, {id: "sbc-xiyaof", name: "小妖", desc: "女声·传统", voiceId: "xiyaof"}, {id: "sbc-xiyaof-qx", name: "小妖", desc: "女声·清新", voiceId: "xiyaof_qingxin"}, {id: "sbc-zzherf", name: "株儿", desc: "女声·传统", voiceId: "zzherf"}, {id: "sbc-lanyuf", name: "蓝雨", desc: "女声·传统", voiceId: "lanyuf"}, {id: "sbc-xbekef", name: "贝壳", desc: "女声·传统", voiceId: "xbekef"}, {id: "sbc-feyinf", name: "风吟", desc: "女声·传统", voiceId: "feyinf"}, {id: "sbc-qianranf", name: "然然", desc: "女声·可爱", voiceId: "qianranf"}, {id: "sbc-lzliafp", name: "连连", desc: "女声·可爱", voiceId: "lzliafp"}, {id: "sbc-zhiling-hk", name: "小玲", desc: "女声·欢快", voiceId: "zhilingfp_huankuai"}, {id: "sbc-linbafp", name: "零八", desc: "女声·清新", voiceId: "linbafp_qingxin"}, // 女声 - 商务/电台/故事 {id: "sbc-lili1f-sw", name: "璃璃", desc: "女声·商务", voiceId: "lili1f_shangwu"}, {id: "sbc-lili1f-yb", name: "璃璃", desc: "女声·娱报", voiceId: "lili1f_yubo"}, {id: "sbc-lili1f-dt", name: "璃璃", desc: "女声·电台", voiceId: "lili1f_diantai"}, {id: "sbc-zzhuaf", name: "砖砖", desc: "女声·故事", voiceId: "zzhuaf"}, {id: "sbc-juyinf", name: "绝音", desc: "女声·恐怖", voiceId: "juyinf_guigushi"}, // 方言 - 粤语 {id: "sbc-hchunf", name: "何春", desc: "方言·粤语", voiceId: "hchunf_ctn"}, {id: "sbc-lunaif", name: "晓健", desc: "方言·粤语", voiceId: "lunaif_ctn"}, // 方言 - 其他 {id: "sbc-yezi1f", name: "叶子", desc: "方言·上海", voiceId: "yezi1f_csh"}, {id: "sbc-dayaof", name: "大瑶", desc: "方言·山东", voiceId: "dayaof_csd"}, {id: "sbc-wqingf", name: "文卿", desc: "方言·四川", voiceId: "wqingf_csn"}, {id: "sbc-ppangf", name: "胖胖", desc: "方言·四川", voiceId: "ppangf_csn"}, {id: "sbc-xizhuf", name: "木兰", desc: "方言·河南", voiceId: "xizhuf_cyu"}, {id: "sbc-xjingf-db", name: "翠花", desc: "方言·东北", voiceId: "xjingf_cdb"}, {id: "sbc-qfyanf", name: "风颜", desc: "方言·闽南", voiceId: "qfyanf_cmn"}, // 英文 {id: "sbc-brettmp", name: "BRETT", desc: "英文·男声", voiceId: "brettmp"} ] }, // "baidu-ai": { // name: "百度AI(推荐)", // icon: "baidu-ai", // iconClass: "fas fa-fire", // engines: [ // {id: "bdai-xiaoyao", name: "情感杜逍遥", desc: "男声·推荐", per: "3", type: "ai"}, // {id: "bdai-yaya", name: "情感度丫丫", desc: "女声·情感", per: "4", type: "ai"}, // {id: "bdai-4114", name: "AI评书", desc: "男声·推荐", per: "4114", type: "ai"}, // {id: "bdai-4117", name: "情感温柔女声", desc: "女声·推荐", per: "4117", type: "ai"} // ] // }, "baidu": { name: "百度语音", icon: "baidu", iconClass: "fas fa-cloud", engines: [ {id: "bd-dubowen", name: "度博文", desc: "男声·推荐", per: "106", pdt: "301", host: "tts"}, {id: "bd-duxiaoyao", name: "度逍遥", desc: "男声·推荐", per: "3", pdt: "505", host: "tts"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-5118", name: "PER5118优美女声", desc: "女声·推荐", per: "5118", pdt: "220", host: "tsn"}, // {id: "bd-4126", name: "PER4126温柔淑女", desc: "女声·温柔", per: "4126", pdt: "232", host: "tts"}, // {id: "bd-0", name: "PER0000度小美", desc: "女声·标准", per: "0", pdt: "160", host: "tts"}, // {id: "bd-2", name: "PER0002度小宇", desc: "男声·标准", per: "2", pdt: "301", host: "tts"}, // {id: "bd-3", name: "PER0003度逍遥②", desc: "男声·情感", per: "3", pdt: "160", host: "tts"}, // {id: "bd-4", name: "PER0004度丫丫", desc: "女声·可爱", per: "4", pdt: "301", host: "tts"}, // {id: "bd-5", name: "PER0005度小娇", desc: "女声·娇俏", per: "5", pdt: "301", host: "tts"}, // {id: "bd-100", name: "PER0100标准女声", desc: "女声·标准", per: "100", pdt: "160", host: "tts"}, // {id: "bd-103", name: "PER0103度米朵", desc: "女声·甜美", per: "103", pdt: "301", host: "tts"}, // {id: "bd-106", name: "PER0106度博文", desc: "男声·稳重", per: "106", pdt: "301", host: "tts"}, // {id: "bd-110", name: "PER0110度小童", desc: "童声", per: "110", pdt: "232", host: "tsn"}, // {id: "bd-111", name: "PER0111度小萌", desc: "童声·萌", per: "111", pdt: "220", host: "tsn"}, // {id: "bd-1100", name: "PER1100度小乔", desc: "女声·古风", per: "1100", pdt: "160", host: "tts"}, // {id: "bd-1200", name: "PER1200普通女声", desc: "女声·普通", per: "1200", pdt: "160", host: "tts"}, // {id: "bd-4003", name: "PER4003度逍遥①", desc: "男声·情感", per: "4003", pdt: "232", host: "tsn"}, // {id: "bd-4007", name: "PER4007台湾女声", desc: "女声·台湾", per: "4007", pdt: "232", host: "tts"}, // {id: "bd-4100", name: "PER4100温暖女声", desc: "女声·温暖", per: "4100", pdt: "220", host: "tts"}, // {id: "bd-4103", name: "PER4103萝莉女声", desc: "女声·萝莉", per: "4103", pdt: "232", host: "tsn"}, // {id: "bd-4105", name: "PER4105情感女声", desc: "女声·情感", per: "4105", pdt: "220", host: "tts"}, // {id: "bd-4106", name: "PER4106激情男声", desc: "男声·激情", per: "4106", pdt: "12", host: "tts"}, // {id: "bd-4114", name: "PER4114百度评书", desc: "男声·评书", per: "4114", pdt: "220", host: "tsn"}, // {id: "bd-4115", name: "PER4115情感男声", desc: "男声·情感", per: "4115", pdt: "220", host: "tsn"}, // {id: "bd-4117", name: "PER4117甜美女声", desc: "女声·甜美", per: "4117", pdt: "220", host: "tts"}, // {id: "bd-4118", name: "PER4118度小鹿", desc: "女声·知性", per: "4118", pdt: "232", host: "tts"}, // {id: "bd-4119", name: "PER4119度小鹿②", desc: "女声·知性", per: "4119", pdt: "220", host: "tsn"}, // {id: "bd-4121", name: "PER4121青年男声", desc: "男声·青年", per: "4121", pdt: "232", host: "tsn"}, // {id: "bd-4123", name: "PER4123百度解说", desc: "男声·解说", per: "4123", pdt: "12", host: "tts"}, // {id: "bd-4125", name: "PER4125沙雕女声", desc: "女声·搞笑", per: "4125", pdt: "220", host: "tts"}, // {id: "bd-4127", name: "PER4127儒雅男声", desc: "男声·儒雅", per: "4127", pdt: "12", host: "tts"}, // {id: "bd-4128", name: "PER4128醇厚男声", desc: "男声·醇厚", per: "4128", pdt: "12", host: "tts"}, // {id: "bd-4129", name: "PER4129少年男声", desc: "男声·少年", per: "4129", pdt: "12", host: "tts"}, // {id: "bd-5003", name: "PER5003说书人", desc: "男声·评书", per: "5003", pdt: "220", host: "tsn"}, // {id: "bd-5117", name: "PER5117百度女声", desc: "女声·标准", per: "5117", pdt: "232", host: "tts"} ] }, "sogou": { name: "搜狗语音", icon: "sogou", iconClass: "fas fa-comment-dots", engines: [ {id: "sg-xiyue", name: "夕月", desc: "女声·御姐(推荐)", speaker: "xiyue-pro"}, {id: "sg-wanqing", name: "婉清", desc: "女声·婉约", speaker: "wanqing-pro"}, {id: "sg-kangge", name: "康哥", desc: "男声·稳重", speaker: "kangge-pro"}, {id: "sg-ruoxi", name: "若曦", desc: "女声·温婉", speaker: "xf5-pro"}, {id: "sg-ahua", name: "阿华", desc: "男声·亲切", speaker: "ahua-pro"}, {id: "sg-axing", name: "阿星", desc: "男声·活泼", speaker: "axing-pro"}, {id: "sg-yani", name: "雅妮", desc: "女声·优雅", speaker: "yani-pro"}, {id: "sg-qingfeng", name: "青峰", desc: "男声·清朗", speaker: "qingfeng-pro"} ] }, "google": { name: "谷歌语音", icon: "google", iconClass: "fab fa-google", engines: [ {id: "gg-zh", name: "中文女声", desc: "女声·普通话", lang: "zh-ch"}, {id: "gg-tw", name: "台湾女声", desc: "女声·台湾", lang: "zh-tw"}, {id: "gg-hk", name: "粤语女声", desc: "女声·粤语", lang: "zh-HK"} ] }, "xunfei": { name: "讯飞语音", icon: "xunfei", iconClass: "fas fa-volume-up", engines: [ {id: "xf-xiaoyan", name: "小燕", desc: "女声·标准", voice: "iflytek"}, {id: "xf-xiaolin", name: "小琳", desc: "女声·台普", voice: "iflytekXiaolin"}, {id: "xf-xiaomei", name: "小美", desc: "女声·粤语", voice: "iflytekXiaomei"} ] }, "other": { name: "其他语音", icon: "other", iconClass: "fas fa-ellipsis-h", engines: [ {id: "ot-xiaoai", name: "小爱同学", desc: "小米·智能助手", type: "xiaoai"}, {id: "ot-xiaona", name: "微软小娜", desc: "微软·Cortana", type: "cortana"}, {id: "ot-guichu", name: "鬼畜女声", desc: "特效·搞笑", type: "mandarin"} ] } }; // ========== 微软TTS API列表 ========== const msApis = [ {url: "https://skybook.qzz.io/tts", fhd: true, key: "skybook"}, // {url: "http://171.113.113.119:8085/tts", fhd: true}, {url: "http://5.45.99.149:8075/tts", fhd: true}, {url: "http://104.214.168.83:8080/tts", fhd: true}, // {url: "http://74.48.40.244:8010/tts", fhd: true}, {url: "http://47.119.125.172:8080/tts", fhd: true}, {url: "http://64.112.42.45:9080/tts", fhd: true}, {url: "http://36.248.181.23:22335/tts", fhd: true}, // {url: "http://180.114.35.250:1080/tts", fhd: true}, {url: "http://124.71.164.73:8085/tts", fhd: true}, {url: "http://190.92.218.92:8080/tts", fhd: true} ]; // ========== MD5算法实现 ========== function md5(string) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i <= s.length; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return hex(md51(string)); } // ========== 生成音频URL或请求配置 ========== async function generateAudio(text,speed) { let selectedId = "Kimi"; let getTime = (o) => new Date(Date.now()+o*36e5).toISOString().replace('Z',`+${o.toString().padStart(2,'0')}:00`); let time = getTime(8) const encoded = encodeURIComponent(text); let webViewUA = navigator.userAgent; let _e = [ "Web", time, "1.2", "21329384620368073434705174017567", md5(webViewUA) ] let headers = { "User-Agent": webViewUA, "device-platform": _e[0], "timestamp": _e[1], "zm-ver": _e[2], "access-token": _e[3], "zm-token": "", "zm-ua": _e[4], "Content-Type": "application/x-www-form-urlencoded" } _e[3] || _e.splice(3,1) headers["zm-token"] = md5(_e.join("")) return { method: 'post', url: `https://bot.n.cn/api/tts/v1?roleid=${selectedId}`, headers, body: `text=${encoded}&set_speed=${speed/10}&audio_type=mp3&format=stream` }; } // ========== 工具函数 ========== function findEngine(id) { for (const p of Object.values(ttsData)) { const e = p.engines.find(x => x.id === id); if (e) return e; } return null; } function findPlatform(id) { for (const [k, p] of Object.entries(ttsData)) { if (p.engines.some(e => e.id === id)) return k; } return null; } // tts链接返回方式 ,不可缺少参数 async function getttsurl(speakText,speechRate){ let op = await generateAudio(speakText,speechRate); return JSON.stringify(op); } //返回http开头的则任务登录链接会跳webview,其他的会按照json解析显示弹窗 async function getloginurl(){ //return 'https://qysg.gyks.cf/qysgttslogin.html?t=11'; var login=[ { "name": "▱▱▱▱显示当前接口▱▱▱▱", "type": "button", "action": "gettts()" }, { "name": "DeepSeek", "type": "button", "action": "settts('DeepSeek')", "style": { "layout_wrapBefore": true, "layout_flexBasisPercent": 0.2 } }, { "name": "豆包", "type": "button", "action": "settts('doubao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智脑", "type": "button", "action": "settts('zhinao')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "通义", "type": "button", "action": "settts('tongyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "混元", "type": "button", "action": "settts('hunyuan')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "文心", "type": "button", "action": "settts('wenxin')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Max", "type": "button", "action": "settts('MiniMax')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "智谱", "type": "button", "action": "settts('zhipu')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "商汤", "type": "button", "action": "settts('shangtang')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "零一", "type": "button", "action": "settts('lingyi')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "小应", "type": "button", "action": "settts('baixiaoying')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星火", "type": "button", "action": "settts('xunfei')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "星辰", "type": "button", "action": "settts('stepspark')", "style": { "layout_flexBasisPercent": 0.2 } }, { "name": "Kimi", "type": "button", "action": "settts('Kimi')", "style": { "layout_flexBasisPercent": 0.2 } } ]; return JSON.stringify(login) } async function settts(v){ await cache.set("tts",v); flutterBridge.showToast("成功切换:"+v) } async function gettts(){ var get = await cache.get("tts"); flutterBridge.showToast("当前接口:"+get) } //如果登录 url 为非 http 开头的弹窗界面,每次修改完弹窗就会执行此函数 async function login(){ } </script> </html>
广告