xunfei-tts
Version:
借助“讯飞在线语音合成API”实现浏览器端“文本转语音
734 lines (733 loc) • 25.8 kB
JavaScript
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
};