UNPKG

xunfei-tts

Version:

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

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