UNPKG

xunfei-tts

Version:

借助“讯飞在线语音合成API”实现浏览器端“文本转语音

695 lines (694 loc) 24 kB
var v = Object.defineProperty; var L = (t, s, e) => s in t ? v(t, s, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[s] = e; var r = (t, s, e) => L(t, typeof s != "symbol" ? s + "" : s, e); import H from "crypto-js"; function _(t, s) { if (s === "UTF8") { const e = new TextEncoder().encode(t), n = []; for (let a = 0; a < e.length; a++) n.push(String.fromCharCode(e[a])); const i = n.join(""); return window.btoa(i); } return t; } class w { constructor() { r(this, "listeners", /* @__PURE__ */ new Map()); } on(s, e) { const n = this.listeners.get(s); n ? n.push(e) : this.listeners.set(s, [e]); } emit(s, e) { const n = this.listeners.get(s); n && n.forEach((i) => { i(e); }); } } let I = null; function E() { return I || (I = new w()), I; } function S() { const t = Date.now().toString(36), s = Math.floor(Math.random() * 2 ** 32).toString(36); return t + s; } function X() { const t = navigator.userAgent.toLowerCase(); return /iphone|ipad|ipod/.test(t); } class y { /** * 处理器被激活(首次激活触发) */ onActive() { } /** * 处理器首次执行任务之前 */ onBeforeFirstExecute() { } /** * 处理器执行任务完成 */ onCompleted() { } /** * 处理器执被销毁 */ onFinish() { } } class b extends y { constructor() { super(...arguments); r(this, "nextHandler", null); r(this, "prevHandler", null); r(this, "executeController", null); r(this, "isFirstExecute", !0); r(this, "isHandleDataAcceptedComplete", !1); } setExecuteController(e) { this.executeController = e; } linkHandler(e) { this.nextHandler && (this.nextHandler.prevHandler = null), this.nextHandler = e, e.prevHandler = this; } get isLastHandler() { return !this.nextHandler; } get isFirstHandler() { return !this.prevHandler; } forwardToHandler(e) { this.nextHandler && this.nextHandler.handle(e); } setHandlerStatus(e) { this.handlerStatus = e; } equalHandlerStatus(e) { return this.handlerStatus === e; } } var u = /* @__PURE__ */ ((t) => (t.OFFLINE = "offline", t.ACTIVE = "active", t.PENDING = "pending", t.EXECUTING = "executing", t.COMPLETED = "completed", t.FINISH = "finish", t))(u || {}), c = /* @__PURE__ */ ((t) => (t.OFFLINE = "offline", t.ACTIVE = "active", t.PENDING = "pending", t.EXECUTING = "executing", t.COMPLETED = "completed", t.FINISH = "finish", t))(c || {}), g = /* @__PURE__ */ ((t) => (t.PENDING = "pending", t.EXECUTING = "executing", t.COMPLETED = "completed", t))(g || {}), T = /* @__PURE__ */ ((t) => (t.PENDING = "pending", t.EXECUTING = "executing", t.COMPLETED = "completed", t))(T || {}); const U = E(); class D extends b { constructor() { super(); /** * 获取待处理任务数量 */ r(this, "taskQueue", []); /** * 当前处理器状态 */ r(this, "handlerStatus", c.OFFLINE); } /** * 待处理任务队列 */ get taskQueueLength() { return this.taskQueue.length; } /** * 检查任务执行条件 * 子类可重写此方法,实现自定义的任务执行前置条件检查 * * @returns {boolean} - 当满足执行条件时返回 true,否则返回 false */ executePreCheck() { return !0; } /** * 触发处理器激活行为(空闲状态 => 激活状态) */ triggerHandlerActive() { this.setHandlerStatus(c.ACTIVE), this.onActive(), this.triggerHandlerPending(); } /** * 触发处理器待机行为(激活状态 => 待执行状态) */ triggerHandlerPending() { this.setHandlerStatus(c.PENDING); } /** * 触发处理器执行行为(激活状态 => 执行状态) */ async triggerHandlerExecute() { this.setHandlerStatus(c.EXECUTING), Promise.resolve().then(() => { this.taskQueue.filter(({ status: e }) => e === g.PENDING).forEach((e) => { e.status = g.EXECUTING; const n = this.isFirstExecute; n && (this.isFirstExecute = !1, this.onBeforeFirstExecute()); let i = !1; this.isHandleDataAcceptedComplete && this.taskQueue.every(({ status: o }) => o !== g.PENDING) && (i = !0); const a = { taskItem: e, isFirstExecute: n, isLastExecute: i }; this.execute(a); }); }); } handle(e) { if (this.taskQueue.push({ uuid: S(), original: e, status: g.PENDING }), !this.executePreCheck()) { this.setHandlerStatus(c.PENDING); return; } this.triggerHandlerExecute(); } /** * 处理队列 */ taskCompletedCallback(e) { const n = this.taskQueue.findIndex((i) => i.uuid === e); n !== -1 && (this.taskQueue[n].status = g.COMPLETED, this.taskQueue.splice(n, 1)), this.isHandleDataAcceptedComplete && this.taskQueue.length === 0 && (this.triggerHandlerCompleted(), this.isLastHandler && this.triggerAppFinish()); } /** * 触发处理器成功行为(执行状态 => 成功状态) */ triggerHandlerCompleted() { this.setHandlerStatus(c.COMPLETED), this.nextHandler && (this.nextHandler.handle(null), this.nextHandler.isHandleDataAcceptedComplete = !0), this.onCompleted(); } /** * 触发处理器销毁行为(待机状态 => 销毁状态) */ triggerHandlerFinish() { this.taskQueue = [], this.isFirstExecute = !0, this.isHandleDataAcceptedComplete = !1, this.setHandlerStatus(c.FINISH), this.onFinish(); } /** * 触发应用被销毁行为 */ triggerAppFinish() { U.emit("_appFinish"); } } const O = E(); class m extends b { constructor() { super(); /** * 待处理任务队列 */ r(this, "taskQueue", []); /** * 当前处理器状态 */ r(this, "handlerStatus", u.OFFLINE); } /** * 获取待处理任务数量 */ get taskQueueLength() { return this.taskQueue.length; } /** * 检查任务执行条件 * 子类可重写此方法,实现自定义的任务执行前置条件检查 * * @returns {boolean} - 当满足执行条件时返回 true,否则返回 false */ executePreCheck() { return !0; } /** * 触发处理器激活行为(空闲状态 => 激活状态) */ triggerHandlerActive() { this.setHandlerStatus(u.ACTIVE), this.onActive(), this.triggerHandlerPending(); } /** * 触发处理器待机行为(激活状态 => 待执行状态 执行状态 => 待执行状态) */ triggerHandlerPending() { this.setHandlerStatus(u.PENDING); } /** * 触发处理器执行行为(激活状态 => 执行状态) */ triggerHandlerExecute() { this.setHandlerStatus(u.EXECUTING); const e = this.taskQueue.shift(); Promise.resolve().then(() => { const { isFirstExecute: n } = this; n && (this.isFirstExecute = !1, this.onBeforeFirstExecute()); let i = !1; this.isHandleDataAcceptedComplete && !this.taskQueueLength && (i = !0); const a = { taskItem: e, isFirstExecute: n, isLastExecute: i }; this.execute(a); }); } /** * 触发处理器成功行为(执行状态 => 成功状态) */ triggerHandlerCompleted() { this.setHandlerStatus(u.COMPLETED), this.nextHandler && (this.nextHandler.handle(null), this.nextHandler.isHandleDataAcceptedComplete = !0), this.onCompleted(); } /** * 触发处理器销毁行为(待机状态 => 销毁状态) */ triggerHandlerFinish() { this.taskQueue = [], this.isFirstExecute = !0, this.isHandleDataAcceptedComplete = !1, this.setHandlerStatus(u.FINISH), this.onFinish(); } /** * 触发应用被销毁行为 */ triggerAppFinish() { O.emit("_appFinish"); } /** * 任务完成后的回调函数。 */ taskCompletedCallback() { this.taskQueueLength ? this.triggerHandlerExecute() : this.isHandleDataAcceptedComplete ? (this.triggerHandlerCompleted(), this.isLastHandler && this.triggerAppFinish()) : this.triggerHandlerPending(); } handle(e) { if (this.taskQueue.push({ uuid: S(), original: e, status: T.PENDING }), !this.executePreCheck()) { this.triggerHandlerPending(); return; } this.equalHandlerStatus(u.PENDING) && this.triggerHandlerExecute(); } } const N = E(); class W extends m { constructor() { super(...arguments); r(this, "audioContext", new AudioContext()); r(this, "bufferSource", null); r(this, "gainNode", null); r(this, "volume", 1); } execute(e) { if (e.isLastExecute) { this.taskCompletedCallback(); return; } const n = this.audioContext.createBuffer(1, e.taskItem.original.length, 22050); n.copyToChannel && n.copyToChannel(new Float32Array(e.taskItem.original), 0, 0), this.bufferSource = this.audioContext.createBufferSource(), this.bufferSource.buffer = n, this.gainNode = this.audioContext.createGain(), this.bufferSource.connect(this.gainNode), this.gainNode.connect(this.audioContext.destination), this.gainNode.gain.setValueAtTime(this.volume, this.audioContext.currentTime), this.bufferSource.start(), this.bufferSource.addEventListener("ended", () => { this.taskCompletedCallback(); }); } onFinish() { this.bufferSource && (this.bufferSource.stop(), this.bufferSource = null), this.gainNode && (this.gainNode.disconnect(), this.gainNode = null), this.audioContext && (this.audioContext.suspend(), this.audioContext = new AudioContext()), N.emit("_audioActuatorFinish"); } onBeforeFirstExecute() { N.emit("_audioActuatorBeforeFirstExecute"); } setVolume(e) { this.gainNode && this.gainNode.gain.setValueAtTime(e, this.audioContext.currentTime), this.volume = e; } } const k = "KGZ1bmN0aW9uKCl7InVzZSBzdHJpY3QiO2Z1bmN0aW9uIGkodCl7dD1hdG9iKHQpO2NvbnN0IG89bmV3IFVpbnQ4QXJyYXkodC5sZW5ndGgpO2ZvcihsZXQgbj0wO248dC5sZW5ndGg7bis9MSlvW25dPXQuY2hhckNvZGVBdChuKTtyZXR1cm4gbmV3IEludDE2QXJyYXkobmV3IERhdGFWaWV3KG8uYnVmZmVyKS5idWZmZXIpfWZ1bmN0aW9uIGwodCl7Y29uc3Qgbz1bXTtmb3IobGV0IG49MDtuPHQubGVuZ3RoO24rPTEpe2NvbnN0IGU9dFtuXTwwP3Rbbl0vMzI3Njg6dFtuXS8zMjc2NztvLnB1c2goZSl9cmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkobyl9ZnVuY3Rpb24gZih0LG89NDQxMDAsbj0xNmUzKXtjb25zdCBlPU1hdGgucm91bmQodC5sZW5ndGgqKG4vbykpLHI9bmV3IEZsb2F0MzJBcnJheShlKSxzPSh0Lmxlbmd0aC0xKS8oZS0xKTtyWzBdPXRbMF07Zm9yKGxldCBhPTE7YTxlLTE7YSs9MSl7Y29uc3QgYz1hKnMsdT1NYXRoLmZsb29yKGMpLnRvRml4ZWQoKSx5PU1hdGguY2VpbChjKS50b0ZpeGVkKCkscD1jLU51bWJlcih1KTtyW2FdPXRbdV0rKHRbeV0tdFt1XSkqcH1yZXR1cm4gcltlLTFdPXRbdC5sZW5ndGgtMV0scn1mdW5jdGlvbiBoKHQsbz0xNmUzLG49MjI1MDUpe2NvbnN0IGU9dC5vcmlnaW5hbCxyPWkoZSk7bGV0IHM9bChyKTtzPWYocyxvLG4pLHM9QXJyYXkuZnJvbShzKSxnbG9iYWxUaGlzLnBvc3RNZXNzYWdlKHt0eXBlOiJzdWNjZXNzIixkYXRhOnthdWRpb0RhdGE6cyxyYXdBdWRpb0RhdGE6QXJyYXkuZnJvbShyKSx1dWlkOnQudXVpZH19KX1mdW5jdGlvbiBnKHQpe2godCl9Z2xvYmFsVGhpcy5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIix0PT57Y29uc3R7dHlwZTpvLGRhdGE6bn09dC5kYXRhO289PT0ic2VuZCImJmcobil9KX0pKCk7Cg==", Q = (t) => Uint8Array.from(atob(t), (s) => s.charCodeAt(0)), x = typeof self < "u" && self.Blob && new Blob([Q(k)], { type: "text/javascript;charset=utf-8" }); function Z(t) { let s; try { if (s = x && (self.URL || self.webkitURL).createObjectURL(x), !s) throw ""; const e = new Worker(s, { name: t == null ? void 0 : t.name }); return e.addEventListener("error", () => { (self.URL || self.webkitURL).revokeObjectURL(s); }), e; } catch { return new Worker( "data:text/javascript;base64," + k, { name: t == null ? void 0 : t.name } ); } finally { s && (self.URL || self.webkitURL).revokeObjectURL(s); } } const K = E(); class V extends D { constructor() { super(...arguments); r(this, "transcodeWorkerInstance", null); } onActive() { var e; this.transcodeWorkerInstance = new Z(), (e = this.transcodeWorkerInstance) == null || e.addEventListener("message", (n) => { const { type: i, data: a } = n.data; if (i === "success") { const { audioData: o } = a; this.forwardToHandler(o); } this.taskCompletedCallback(a.uuid); }); } execute(e) { var n; if (e.isLastExecute) { this.taskCompletedCallback(e.taskItem.uuid); return; } (n = this.transcodeWorkerInstance) == null || n.postMessage({ type: "send", data: e.taskItem }); } onFinish() { K.emit("_responseTranscodeFinish"), this.transcodeWorkerInstance && this.transcodeWorkerInstance.terminate(); } } var d = /* @__PURE__ */ ((t) => (t.SPACE_CHAR = "spaceChar", t.CHINESE_CHAR = "chineseChar", t.CHINESE_PUNCTUATION = "chinesePunctuation", t.ENGLISH_WORD = "englishWord", t.ENGLISH_PUNCTUATION = "englishPunctuation", t.UNKNOWN_CHAR = "unknownChar", t))(d || {}); class z { constructor() { // 中文字符 r(this, "CHINESE_CHAR_REGEX", /[\u4E00-\u9FA5]/); // 中文标点符号 r(this, "CHINESE_PUNCTUATION_REGEX", /[。?!,;:“”‘’()—…、·]/); // // 中文段落结束符号(句末标点) r(this, "CHINESE_PARAGRAPH_END_REGEX", /[。?!;]/); // 英文单词起始字符 r(this, "ENGLISH_WORD_START_REGEX", /[a-z]/i); // 英文单词延续字符(含缩写和连字符) r(this, "ENGLISH_WORD_CONTINUE_REGEX", /[a-z'’-]/i); // 英文标点符号 r(this, "ENGLISH_PUNCTUATION_REGEX", /[.,!?;:'"()-]/); // 英文段落结束符号(句末标点) r(this, "ENGLISH_PARAGRAPH_END_REGEX", /[.!?;]/); // 空白字符(统一转为单个空格) r(this, "SPACE_CHAR_REGEX", /\s/); // 最小段落长度 r(this, "MIN_PARAGRAPH_LENGTH", 10); // 待处理的剩余文本标记 r(this, "pendingTokens", []); } /** * 将输入文本转换为标记流。 * @param text 原始文本内容。 * @returns 标记化后的文本标记数组。 */ tokenizeText(s) { const e = []; let n = 0; for (; n < s.length; ) { const i = s[n]; if (this.CHINESE_CHAR_REGEX.test(i)) e.push({ type: d.CHINESE_CHAR, value: i }); else if (this.ENGLISH_WORD_START_REGEX.test(i)) { const a = n; let o = n + 1; for (; o < s.length && this.ENGLISH_WORD_CONTINUE_REGEX.test(s[o]); ) o++; const h = s.substring(a, o); e.push({ type: d.ENGLISH_WORD, value: h }), n += h.length - 1; } else this.CHINESE_PUNCTUATION_REGEX.test(i) ? e.push({ type: d.CHINESE_PUNCTUATION, value: i }) : this.ENGLISH_PUNCTUATION_REGEX.test(i) ? e.push({ type: d.ENGLISH_PUNCTUATION, value: i }) : this.SPACE_CHAR_REGEX.test(i) ? e.push({ type: d.SPACE_CHAR, value: i }) : e.push({ type: d.UNKNOWN_CHAR, value: i }); n++; } return e; } /** * 文本净化预处理 - 去除无效字符和格式。 * @param text 原始文本。 * @returns 净化后的文本。 */ sanitizeText(s) { return s.replace(/\s+/g, " ").replace(/(\d+)\s+/g, "$1").replace(/\*+/g, "").replace(/[\u{1F000}-\u{1FAFF}]/gu, ""); } /** * 段落输出之前的整理逻辑。 * @param paragraphs 段落数组。 * @returns 整理后的段落数组。 */ sanitizeParagraphs(s) { return s.map((e) => e.trim()).filter((e) => e.length > 0); } /** * 判断标记是否为段落结束符号。 * @param token 文本标记。 * @returns 是否为段落结束符号。 */ isParagraphEndToken(s) { return this.CHINESE_PARAGRAPH_END_REGEX.test(s.value) || this.ENGLISH_PARAGRAPH_END_REGEX.test(s.value); } /** * 将标记数组转换回文本。 * @param tokens 文本标记数组。 * @returns 组合后的文本。 */ tokensToString(s) { return s.map((e) => e.value).join(""); } /** * 将标记流分割成多个段落。 * @param tokens 文本标记数组。 * @returns 分段后的标记数组集合。 */ splitToParagraphs(s) { const e = []; let n = []; for (const i of s) n.push(i), n.length >= this.MIN_PARAGRAPH_LENGTH && this.isParagraphEndToken(i) && (e.push(n), n = []); return n.length > 0 && e.push(n), e; } /** * 合并因小数点导致的错误分段。 * @param paragraphs 分段后的标记数组集合。 * @returns 合并后的标记数组集合。 */ mergeDecimalParagraphs(s) { return s.reduce((e, n) => { if (e.length === 0) e.push(n); else { const i = e[e.length - 1], a = this.tokensToString(i), o = this.tokensToString(n); /\d+\.$/.test(a) && /^\d+/.test(o) ? e[e.length - 1] = [...i, ...n] : e.push(n); } return e; }, []); } /** * 处理输入文本,返回分段后的文本数组。 * @param text 输入文本内容。 * @param includeRemaining 是否包含未完成的段落。 * @returns 分段后的文本数组。 */ processText(s, e = !1) { const n = this.tokenizeText(this.sanitizeText(s)), i = [...this.pendingTokens, ...n], a = this.mergeDecimalParagraphs(this.splitToParagraphs(i)); if (a.length > 0) { const o = a[a.length - 1], h = o[o.length - 1]; e ? this.pendingTokens = [] : this.isParagraphEndToken(h) ? /\d+\.$/.test(this.tokensToString(o)) ? this.pendingTokens = a.pop() : this.pendingTokens = [] : this.pendingTokens = a.pop(); } return this.sanitizeParagraphs(a.map((o) => this.tokensToString(o))); } } const B = E(); class M extends m { constructor() { super(...arguments); r(this, "textStreamSlicer", new z()); } execute(e) { e.isLastExecute ? this.textStreamSlicer.processText("", !0).forEach((n) => { this.forwardToHandler(n); }) : this.textStreamSlicer.processText(e.taskItem.original).forEach((n) => { this.forwardToHandler(n); }), this.taskCompletedCallback(); } onFinish() { B.emit("_textSplitFinish"); } } const Y = E(), $ = { aue: "raw", sfl: 1, auf: "audio/L16;rate=16000", vcn: "xiaoyan", speed: 50, volume: 50, pitch: 50, bgs: 0, tte: "UTF8", reg: "2", rdn: "0" }; class q extends m { constructor() { super(...arguments); r(this, "systemConfig"); r(this, "businessParams"); r(this, "webSockeSet", /* @__PURE__ */ new Set()); } initProperty(e, n) { this.systemConfig = e, this.businessParams = { ...$, ...n }; } execute(e) { if (e.isLastExecute) { this.taskCompletedCallback(); return; } const n = new WebSocket(this.generateRequestUrl()); this.webSockeSet.add(n), n.addEventListener("open", async () => { n.send(JSON.stringify(this.generateRequestParams(e.taskItem.original))), n.addEventListener("message", (i) => { const { code: a, data: o } = JSON.parse(i.data), { audio: h, status: C } = o; a === 0 && h && this.forwardToHandler(h), C === 2 && (this.webSockeSet.delete(n), n.close(), this.taskCompletedCallback()); }); }); } generateRequestParams(e) { return { common: { app_id: this.systemConfig.APPID }, business: { ...this.businessParams }, data: { status: 2, text: _(e, this.businessParams.tte) } }; } generateRequestUrl() { const e = this.systemConfig.API_KEY, n = this.systemConfig.API_SECRET; let i = "wss://tts-api.xfyun.cn/v2/tts"; const { host: a } = window.location, o = (/* @__PURE__ */ new Date()).toGMTString(), h = "hmac-sha256", C = "host date request-line", A = `host: ${a} date: ${o} GET /v2/tts HTTP/1.1`, G = H.HmacSHA256(A, n), R = H.enc.Base64.stringify(G), P = `api_key="${e}", algorithm="${h}", headers="${C}", signature="${R}"`, F = btoa(P); return i = `${i}?authorization=${F}&date=${o}&host=${a}`, i; } onFinish() { Y.emit("_ttsRequestFinish"), this.webSockeSet && this.webSockeSet.size && (this.webSockeSet.forEach((e) => e.close()), this.webSockeSet.clear()), this.webSockeSet = /* @__PURE__ */ new Set(); } } var l = /* @__PURE__ */ ((t) => (t.OFFLINE = "offline", t.EXECUTE = "execute", t))(l || {}); const p = E(); class J { constructor(s, e = {}) { r(this, "textSplitInstance", new M()); r(this, "responseTranscodeInstance", new V()); r(this, "audioActuatorInstance", new W()); r(this, "ttsRequestInstance", new q()); r(this, "systemStatus", l.OFFLINE); this.ttsRequestInstance.initProperty(s, e), this.textSplitInstance.setExecuteController(this), this.responseTranscodeInstance.setExecuteController(this), this.audioActuatorInstance.setExecuteController(this), this.ttsRequestInstance.setExecuteController(this), this.textSplitInstance.linkHandler(this.ttsRequestInstance), this.ttsRequestInstance.linkHandler(this.responseTranscodeInstance), this.responseTranscodeInstance.linkHandler(this.audioActuatorInstance), this.bindEvent(); } bindEvent() { p.on("_audioActuatorBeforeFirstExecute", () => { this.emit("audioFirstStart"); }), p.on("_appError", (s) => { this.finish(), this.emit("appError", s); }), p.on("_appFinish", () => { this.finish(); }); } /** * 进入待机状态,等待传入文本数据 */ start() { return this.systemStatus === l.EXECUTE ? this : (this.textSplitInstance.triggerHandlerActive(), this.ttsRequestInstance.triggerHandlerActive(), this.responseTranscodeInstance.triggerHandlerActive(), this.audioActuatorInstance.triggerHandlerActive(), this.systemStatus = l.EXECUTE, this); } /** * 传入文本数据 * * @param text 待转换的文本 */ send(s) { return this.systemStatus !== l.EXECUTE ? this : (this.textSplitInstance.handle(s), this); } /** * 应用停止处理传入的文本,但是并不会停止音频播放 */ end() { return this.systemStatus !== l.EXECUTE ? this : (this.textSplitInstance.handle(null), this.textSplitInstance.isHandleDataAcceptedComplete = !0, this); } /** * 停止所有处理器,并且重置状态,触发 appFinish 事件 */ finish() { this.systemStatus !== l.OFFLINE && (this.textSplitInstance.triggerHandlerFinish(), this.responseTranscodeInstance.triggerHandlerFinish(), this.audioActuatorInstance.triggerHandlerFinish(), this.ttsRequestInstance.triggerHandlerFinish(), this.systemStatus = l.OFFLINE, this.emit("appFinish")); } emit(s, e) { p.emit(s, e); } on(s, e) { return p.on(s, e), this; } /** * 设置音量 * * @param volume 音量 0-1 */ setVolume(s) { return this.audioActuatorInstance.setVolume(s), this; } } let f; function j() { return new Promise((t, s) => { navigator.mediaDevices.getUserMedia({ audio: !0 }).then((e) => { t(e); }).catch((e) => { e.name === "NotAllowedError" ? s(new Error("用户拒绝了音频权限请求")) : e.name === "NotFoundError" ? s(new Error("设备上没有可用的音频输入设备")) : s(new Error(`音频权限请求失败: ${e.message}`)); }); }); } const se = { /** * 配置系统参数。 * @param {SystemConfig} _systemConfig - 系统配置参数。 * @returns {object} 返回当前对象,支持链式调用。 */ config(t) { return f = t, X() && j().catch((s) => { throw new Error(s.message); }), this; }, /** * 创建文本转语音控制器实例。 * @param {Partial<BusinessParams>} [businessParams] - 业务参数,默认为空对象。 * @returns {TtsController} 返回TtsController实例。 * @throws {Error} 如果系统配置未设置或API_KEY、API_SECRET、APPID为空,则抛出错误。 */ create(t = {}) { const { API_KEY: s, API_SECRET: e, APPID: n } = f; if (!f) throw new Error("请先调用config方法进行配置"); if (!e) throw new Error("API_SECRET不能为空"); if (!n) throw new Error("APPID不能为空"); if (!s) throw new Error("API_KEY不能为空"); return new J(f, t); } }; export { se as default };