@zeewain/3d-avatar-sdk 1.2.2 → 1.2.4-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +213 -9
- package/dist/examples/test-vue2/package.json +1 -1
- package/dist/examples/test-vue3/index.html +1 -0
- package/dist/examples/test-vue3/package.json +3 -1
- package/dist/examples/test-vue3/plugins/html.ts +38 -0
- package/dist/examples/test-vue3/pnpm-lock.yaml +291 -90
- package/dist/examples/test-vue3/src/App.vue +4 -2
- package/dist/examples/test-vue3/src/components/BroadcastAPI.vue +38 -20
- package/dist/examples/test-vue3/tsconfig.node.json +2 -1
- package/dist/examples/test-vue3/vite.config.ts +4 -1
- package/dist/index.d.ts +108 -11
- package/dist/index.es5.js +400 -155
- package/dist/index.es5.umd.js +400 -155
- package/dist/index.esm.js +349 -137
- package/dist/index.umd.cjs +349 -137
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1019,6 +1019,7 @@ const ENV_MAP = {
|
|
|
1019
1019
|
/**
|
|
1020
1020
|
* 获取指定环境的配置
|
|
1021
1021
|
* @param env - 环境类型,默认为'dev'
|
|
1022
|
+
* @param withApiModule - 是否包含API模块路径
|
|
1022
1023
|
* @returns 返回对应环境的配置对象
|
|
1023
1024
|
* @example
|
|
1024
1025
|
* ```typescript
|
|
@@ -1026,11 +1027,11 @@ const ENV_MAP = {
|
|
|
1026
1027
|
* console.log(config.apiBaseUrl); // https://aiip.zeewain.com/api/dh-talker
|
|
1027
1028
|
* ```
|
|
1028
1029
|
*/
|
|
1029
|
-
function getEnvConfig(env = 'dev',
|
|
1030
|
+
function getEnvConfig(env = 'dev', withApiModule = true) {
|
|
1030
1031
|
const baseUrl = ENV_MAP[env];
|
|
1031
1032
|
if (baseUrl) {
|
|
1032
1033
|
return {
|
|
1033
|
-
apiBaseUrl: `${baseUrl.apiBaseUrl}${
|
|
1034
|
+
apiBaseUrl: `${baseUrl.apiBaseUrl}${withApiModule ? '/api' : ''}`
|
|
1034
1035
|
};
|
|
1035
1036
|
}
|
|
1036
1037
|
return null;
|
|
@@ -1100,17 +1101,17 @@ class ConfigManager {
|
|
|
1100
1101
|
}
|
|
1101
1102
|
/**
|
|
1102
1103
|
* 获取API基础URL
|
|
1103
|
-
* @param
|
|
1104
|
+
* @param withApiModule 是否包含模块路径
|
|
1104
1105
|
* @returns string API基础URL
|
|
1105
1106
|
* @description 根据当前环境配置获取API基础URL
|
|
1106
1107
|
*/
|
|
1107
|
-
getApiBaseUrl(
|
|
1108
|
+
getApiBaseUrl(withApiModule = true) {
|
|
1108
1109
|
var _a, _b, _c, _d;
|
|
1109
1110
|
if (((_a = this.config) === null || _a === void 0 ? void 0 : _a.env) === 'custom' && ((_b = this.config) === null || _b === void 0 ? void 0 : _b.apiUrl)) {
|
|
1110
1111
|
// 如果环境为自定义,则直接返回配置的API,无需添加模块路径
|
|
1111
|
-
return this.config.apiUrl
|
|
1112
|
+
return `${this.config.apiUrl}${withApiModule ? '/api' : ''}`;
|
|
1112
1113
|
}
|
|
1113
|
-
return ((_d = getEnvConfig(((_c = this.config) === null || _c === void 0 ? void 0 : _c.env) || 'prod',
|
|
1114
|
+
return ((_d = getEnvConfig(((_c = this.config) === null || _c === void 0 ? void 0 : _c.env) || 'prod', withApiModule)) === null || _d === void 0 ? void 0 : _d.apiBaseUrl) || '';
|
|
1114
1115
|
}
|
|
1115
1116
|
/**
|
|
1116
1117
|
* 获取自定义API URL
|
|
@@ -1506,6 +1507,20 @@ var BroadcastType;
|
|
|
1506
1507
|
* @fileoverview 流式播报服务重构实现模块
|
|
1507
1508
|
* @description 提供流式播报服务的重构实现,继承Unity基础服务,支持文本转语音和自定义音频播报
|
|
1508
1509
|
*/
|
|
1510
|
+
/**
|
|
1511
|
+
* 播报任务状态枚举
|
|
1512
|
+
*/
|
|
1513
|
+
var BroadcastTaskStatus;
|
|
1514
|
+
(function (BroadcastTaskStatus) {
|
|
1515
|
+
/** 请求中 */
|
|
1516
|
+
BroadcastTaskStatus["REQUESTING"] = "requesting";
|
|
1517
|
+
/** 已完成 */
|
|
1518
|
+
BroadcastTaskStatus["COMPLETED"] = "completed";
|
|
1519
|
+
/** 失败 */
|
|
1520
|
+
BroadcastTaskStatus["FAILED"] = "failed";
|
|
1521
|
+
/** 已取消 */
|
|
1522
|
+
BroadcastTaskStatus["CANCELLED"] = "cancelled";
|
|
1523
|
+
})(BroadcastTaskStatus || (BroadcastTaskStatus = {}));
|
|
1509
1524
|
/**
|
|
1510
1525
|
* 流式播报服务重构类
|
|
1511
1526
|
* @class BroadcastServiceRefactored
|
|
@@ -1535,12 +1550,20 @@ class BroadcastService extends UnityBaseService {
|
|
|
1535
1550
|
super(config);
|
|
1536
1551
|
/** 事件回调函数集合 */
|
|
1537
1552
|
this.callbacks = {};
|
|
1538
|
-
/**
|
|
1539
|
-
this.
|
|
1553
|
+
/** 播报任务队列 */
|
|
1554
|
+
this.taskQueue = [];
|
|
1555
|
+
/** 任务序号计数器 */
|
|
1556
|
+
this.taskSequence = 0;
|
|
1557
|
+
/** 当前发送任务的序号 */
|
|
1558
|
+
this.currentSendingSequence = 0;
|
|
1540
1559
|
/** 是否正在生成音频 */
|
|
1541
1560
|
this.isGeneratingAudio = false;
|
|
1542
1561
|
/** 是否已经收到音频 */
|
|
1543
1562
|
this.hasReceivedAudio = false;
|
|
1563
|
+
/** 队列处理定时器 */
|
|
1564
|
+
this.queueProcessTimer = null;
|
|
1565
|
+
/** 主请求控制器(兼容性保留) */
|
|
1566
|
+
this.activeController = null;
|
|
1544
1567
|
this.callbacks = config.callbacks || {};
|
|
1545
1568
|
this.logger.info('Broadcast service initialized', { config });
|
|
1546
1569
|
}
|
|
@@ -1589,8 +1612,9 @@ class BroadcastService extends UnityBaseService {
|
|
|
1589
1612
|
/**
|
|
1590
1613
|
* 开始播报
|
|
1591
1614
|
* @param params - 播报参数
|
|
1615
|
+
* @param isAppend - 是否追加播报
|
|
1592
1616
|
* @returns Promise<void> 播报操作的Promise
|
|
1593
|
-
* @description
|
|
1617
|
+
* @description 开始流式播报,支持文本转语音和自定义音频播报。使用队列机制确保音频按序播报
|
|
1594
1618
|
* @throws {SDKError} 当参数验证失败或播报失败时抛出错误
|
|
1595
1619
|
* @example
|
|
1596
1620
|
* ```typescript
|
|
@@ -1604,130 +1628,54 @@ class BroadcastService extends UnityBaseService {
|
|
|
1604
1628
|
* isSubtitle: true
|
|
1605
1629
|
* });
|
|
1606
1630
|
*
|
|
1607
|
-
* //
|
|
1631
|
+
* // 追加播报(会进入队列按序播报)
|
|
1608
1632
|
* await broadcastService.startBroadcast({
|
|
1609
|
-
* type: BroadcastType.
|
|
1633
|
+
* type: BroadcastType.TEXT,
|
|
1610
1634
|
* humanCode: 'human001',
|
|
1611
|
-
*
|
|
1635
|
+
* text: '这是第二段内容',
|
|
1636
|
+
* voiceCode: 'voice001',
|
|
1612
1637
|
* volume: 0.8,
|
|
1613
|
-
* isSubtitle:
|
|
1614
|
-
* });
|
|
1638
|
+
* isSubtitle: true
|
|
1639
|
+
* }, true);
|
|
1615
1640
|
* ```
|
|
1616
1641
|
*/
|
|
1617
|
-
startBroadcast(params) {
|
|
1642
|
+
startBroadcast(params, isAppend) {
|
|
1618
1643
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1619
1644
|
var _a, _b;
|
|
1620
|
-
this.logger.info(`Starting broadcast: ${params.type}`, {
|
|
1645
|
+
this.logger.info(`Starting broadcast: ${params.type}`, {
|
|
1646
|
+
humanCode: params.humanCode,
|
|
1647
|
+
isAppend,
|
|
1648
|
+
queueLength: this.taskQueue.length
|
|
1649
|
+
});
|
|
1621
1650
|
// 验证参数
|
|
1622
1651
|
this.validateBroadcastParams(params);
|
|
1623
|
-
//
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
this.hasReceivedAudio = false;
|
|
1638
|
-
this.activeController = null;
|
|
1639
|
-
});
|
|
1640
|
-
// 通知Unity开始新任务(清空队列)
|
|
1641
|
-
this.sendMessage('StartBroadcast', {
|
|
1642
|
-
callbackFun: this.uniqueCallbackName,
|
|
1643
|
-
operationType: BroadcastOperationType.START_BROADCAST,
|
|
1644
|
-
motionList: params.motionList,
|
|
1645
|
-
motionPlayMode: params.motionPlayMode
|
|
1646
|
-
});
|
|
1647
|
-
try {
|
|
1648
|
-
const apiUrl = `${ConfigManager.getInstance().getApiBaseUrl(true)}${this.getBroadcastApiPath(params.type)}`;
|
|
1649
|
-
const requestBody = {
|
|
1650
|
-
humanCode: params.humanCode,
|
|
1651
|
-
speed: params.speed,
|
|
1652
|
-
volume: params.volume >= 0 ? params.volume * 100 : undefined, // 转换为百分比
|
|
1653
|
-
isSubtitle: params.isSubtitle
|
|
1654
|
-
};
|
|
1655
|
-
// 根据播报类型设置特定参数
|
|
1656
|
-
if (params.type === BroadcastType.TEXT) {
|
|
1657
|
-
requestBody.text = params.text;
|
|
1658
|
-
requestBody.voiceCode = params.voiceCode;
|
|
1659
|
-
}
|
|
1660
|
-
else if (params.type === BroadcastType.AUDIO) {
|
|
1661
|
-
requestBody.text = params.text;
|
|
1662
|
-
requestBody.audioUrl = params.audioUrl;
|
|
1663
|
-
}
|
|
1664
|
-
this.logger.debug('Sending broadcast request', { apiUrl, requestBody });
|
|
1652
|
+
// 非追加模式下需要初始化播报
|
|
1653
|
+
if (!isAppend) {
|
|
1654
|
+
// 先停止当前播报并清空队列
|
|
1655
|
+
yield this.stopBroadcast();
|
|
1656
|
+
// 重置序号计数器
|
|
1657
|
+
this.taskSequence = 0;
|
|
1658
|
+
this.currentSendingSequence = 0;
|
|
1659
|
+
// 通知Unity开始新任务(清空队列)
|
|
1660
|
+
this.sendMessage('StartBroadcast', {
|
|
1661
|
+
callbackFun: this.uniqueCallbackName,
|
|
1662
|
+
operationType: BroadcastOperationType.START_BROADCAST,
|
|
1663
|
+
motionList: params.motionList,
|
|
1664
|
+
motionPlayMode: params.motionPlayMode
|
|
1665
|
+
});
|
|
1665
1666
|
// 触发开始回调
|
|
1666
1667
|
(_b = (_a = this.callbacks).onStart) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
1667
1668
|
this.isGeneratingAudio = true;
|
|
1668
|
-
// 发起流式播报请求
|
|
1669
|
-
yield fetchEventSource(apiUrl, {
|
|
1670
|
-
method: 'POST',
|
|
1671
|
-
headers: {
|
|
1672
|
-
'Content-Type': 'application/json',
|
|
1673
|
-
'x_auth_token': ConfigManager.getInstance().getToken()
|
|
1674
|
-
},
|
|
1675
|
-
body: JSON.stringify(requestBody),
|
|
1676
|
-
signal: this.activeController.signal,
|
|
1677
|
-
openWhenHidden: true,
|
|
1678
|
-
onmessage: (event) => {
|
|
1679
|
-
const response = JSON.parse(event.data);
|
|
1680
|
-
// 错误处理
|
|
1681
|
-
if (response.code !== 0) {
|
|
1682
|
-
this.handleBroadcastError(response.code);
|
|
1683
|
-
return;
|
|
1684
|
-
}
|
|
1685
|
-
// 流式播报
|
|
1686
|
-
if (response.data) {
|
|
1687
|
-
// 未完成播报时,更新任务ID
|
|
1688
|
-
if (!response.data.done) {
|
|
1689
|
-
this.hasReceivedAudio = true;
|
|
1690
|
-
}
|
|
1691
|
-
// 自定义音频播报时,如果服务器未返回音频URL,使用传入的audioUrl
|
|
1692
|
-
if (params.type === BroadcastType.AUDIO && params.audioUrl && !response.data.voiceUrl) {
|
|
1693
|
-
response.data.voiceUrl = params.audioUrl;
|
|
1694
|
-
}
|
|
1695
|
-
// 如果有音频URL,发送到Unity
|
|
1696
|
-
if (response.data.voiceUrl) {
|
|
1697
|
-
this.sendMessage('AppendBroadcast', {
|
|
1698
|
-
response,
|
|
1699
|
-
callbackFun: this.uniqueCallbackName,
|
|
1700
|
-
operationType: BroadcastOperationType.APPEND_BROADCAST
|
|
1701
|
-
});
|
|
1702
|
-
}
|
|
1703
|
-
if (response.data.done) {
|
|
1704
|
-
this.isGeneratingAudio = false;
|
|
1705
|
-
this.hasReceivedAudio = false;
|
|
1706
|
-
this.activeController = null;
|
|
1707
|
-
}
|
|
1708
|
-
}
|
|
1709
|
-
},
|
|
1710
|
-
onclose: () => {
|
|
1711
|
-
var _a;
|
|
1712
|
-
// 如果不是由abort触发的关闭,需要处理
|
|
1713
|
-
if (this.isGeneratingAudio) {
|
|
1714
|
-
(_a = this.activeController) === null || _a === void 0 ? void 0 : _a.abort();
|
|
1715
|
-
}
|
|
1716
|
-
// 流结束时调用完成回调
|
|
1717
|
-
this.logger.debug('Broadcast stream closed');
|
|
1718
|
-
},
|
|
1719
|
-
onerror: (error) => {
|
|
1720
|
-
this.logger.error('Broadcast stream error', error);
|
|
1721
|
-
const sdkError = new SDKError(OperationErrorCode.OPERATION_FAILED, '服务出错了', error);
|
|
1722
|
-
this.handleError(sdkError);
|
|
1723
|
-
// 必须抛出错误,否则会循环重试请求
|
|
1724
|
-
throw new Error(`服务出错了${sdkError.message}`);
|
|
1725
|
-
}
|
|
1726
|
-
});
|
|
1727
|
-
}
|
|
1728
|
-
catch (error) {
|
|
1729
|
-
this.handleError(error);
|
|
1730
1669
|
}
|
|
1670
|
+
// 创建新的播报任务
|
|
1671
|
+
const task = this.createBroadcastTask(params);
|
|
1672
|
+
// 添加任务到队列
|
|
1673
|
+
this.addTaskToQueue(task);
|
|
1674
|
+
this.logger.debug('Broadcast task created and queued', {
|
|
1675
|
+
taskId: task.id,
|
|
1676
|
+
sequence: task.sequence,
|
|
1677
|
+
isAppend
|
|
1678
|
+
});
|
|
1731
1679
|
});
|
|
1732
1680
|
}
|
|
1733
1681
|
/**
|
|
@@ -1788,12 +1736,12 @@ class BroadcastService extends UnityBaseService {
|
|
|
1788
1736
|
*/
|
|
1789
1737
|
stopBroadcast() {
|
|
1790
1738
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1791
|
-
this.logger.info('Stopping broadcast');
|
|
1792
|
-
//
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1739
|
+
this.logger.info('Stopping broadcast and clearing queue', { queueLength: this.taskQueue.length });
|
|
1740
|
+
// 取消所有队列中的任务
|
|
1741
|
+
this.cancelAllTasks();
|
|
1742
|
+
// 重置状态
|
|
1743
|
+
this.isGeneratingAudio = false;
|
|
1744
|
+
this.hasReceivedAudio = false;
|
|
1797
1745
|
try {
|
|
1798
1746
|
yield this.sendAsyncMessage('StopBroadcast', BroadcastOperationType.STOP_BROADCAST, {});
|
|
1799
1747
|
this.logger.info('Broadcast stopped successfully');
|
|
@@ -1816,15 +1764,23 @@ class BroadcastService extends UnityBaseService {
|
|
|
1816
1764
|
/**
|
|
1817
1765
|
* 获取播报状态
|
|
1818
1766
|
* @returns 播报状态信息
|
|
1819
|
-
* @description
|
|
1767
|
+
* @description 获取当前播报服务的状态信息,包括队列状态
|
|
1820
1768
|
*/
|
|
1821
1769
|
getStatus() {
|
|
1822
1770
|
return {
|
|
1823
|
-
isActive: this.
|
|
1771
|
+
isActive: this.taskQueue.length > 0 || this.isGeneratingAudio,
|
|
1824
1772
|
isGeneratingAudio: this.isGeneratingAudio,
|
|
1825
1773
|
hasReceivedAudio: this.hasReceivedAudio,
|
|
1826
1774
|
pendingCallbacks: this.getPendingCallbackCount(),
|
|
1827
|
-
hasController: this.activeController !== null
|
|
1775
|
+
hasController: this.activeController !== null,
|
|
1776
|
+
queueInfo: {
|
|
1777
|
+
totalTasks: this.taskQueue.length,
|
|
1778
|
+
requestingTasks: this.taskQueue.filter((t) => t.status === BroadcastTaskStatus.REQUESTING).length,
|
|
1779
|
+
completedTasks: this.taskQueue.filter((t) => t.status === BroadcastTaskStatus.COMPLETED).length,
|
|
1780
|
+
failedTasks: this.taskQueue.filter((t) => t.status === BroadcastTaskStatus.FAILED).length,
|
|
1781
|
+
totalPendingResponses: this.taskQueue.reduce((sum, t) => sum + t.pendingResponses.length, 0),
|
|
1782
|
+
currentSendingSequence: this.currentSendingSequence
|
|
1783
|
+
}
|
|
1828
1784
|
};
|
|
1829
1785
|
}
|
|
1830
1786
|
/**
|
|
@@ -1832,15 +1788,268 @@ class BroadcastService extends UnityBaseService {
|
|
|
1832
1788
|
* @description 清理所有资源和回调
|
|
1833
1789
|
*/
|
|
1834
1790
|
destroy() {
|
|
1835
|
-
//
|
|
1836
|
-
if (this.
|
|
1837
|
-
this.
|
|
1838
|
-
this.
|
|
1791
|
+
// 清理队列处理定时器
|
|
1792
|
+
if (this.queueProcessTimer) {
|
|
1793
|
+
clearInterval(this.queueProcessTimer);
|
|
1794
|
+
this.queueProcessTimer = null;
|
|
1839
1795
|
}
|
|
1796
|
+
// 取消所有任务
|
|
1797
|
+
this.cancelAllTasks();
|
|
1840
1798
|
// 调用基类销毁方法
|
|
1841
1799
|
super.destroy();
|
|
1842
1800
|
this.logger.info('Broadcast service destroyed');
|
|
1843
1801
|
}
|
|
1802
|
+
/**
|
|
1803
|
+
* 创建播报任务
|
|
1804
|
+
* @param params - 播报参数
|
|
1805
|
+
* @returns IBroadcastTask 播报任务对象
|
|
1806
|
+
* @description 创建新的播报任务并分配唯一ID和序号
|
|
1807
|
+
* @private
|
|
1808
|
+
*/
|
|
1809
|
+
createBroadcastTask(params) {
|
|
1810
|
+
const task = {
|
|
1811
|
+
id: `broadcast_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
|
|
1812
|
+
sequence: ++this.taskSequence,
|
|
1813
|
+
params,
|
|
1814
|
+
status: BroadcastTaskStatus.REQUESTING,
|
|
1815
|
+
controller: new AbortController(),
|
|
1816
|
+
pendingResponses: [],
|
|
1817
|
+
isGenerationComplete: false,
|
|
1818
|
+
createdAt: new Date()
|
|
1819
|
+
};
|
|
1820
|
+
this.logger.debug('Created broadcast task', { taskId: task.id, sequence: task.sequence });
|
|
1821
|
+
return task;
|
|
1822
|
+
}
|
|
1823
|
+
/**
|
|
1824
|
+
* 添加任务到队列
|
|
1825
|
+
* @param task - 播报任务
|
|
1826
|
+
* @description 将任务添加到队列并立即开始请求
|
|
1827
|
+
* @private
|
|
1828
|
+
*/
|
|
1829
|
+
addTaskToQueue(task) {
|
|
1830
|
+
this.taskQueue.push(task);
|
|
1831
|
+
this.logger.debug('Task added to queue', { taskId: task.id, queueLength: this.taskQueue.length });
|
|
1832
|
+
// 立即开始该任务的请求
|
|
1833
|
+
this.startTaskRequest(task);
|
|
1834
|
+
// 开始处理队列
|
|
1835
|
+
this.processQueue();
|
|
1836
|
+
}
|
|
1837
|
+
/**
|
|
1838
|
+
* 处理队列
|
|
1839
|
+
* @description 处理队列中的任务,发起请求生成音频
|
|
1840
|
+
* @private
|
|
1841
|
+
*/
|
|
1842
|
+
processQueue() {
|
|
1843
|
+
// 启动队列处理定时器(如果尚未启动)
|
|
1844
|
+
if (!this.queueProcessTimer) {
|
|
1845
|
+
this.queueProcessTimer = setInterval(() => {
|
|
1846
|
+
this.processQueueStep();
|
|
1847
|
+
}, 100); // 每100ms检查一次队列状态
|
|
1848
|
+
}
|
|
1849
|
+
// 立即处理一次
|
|
1850
|
+
this.processQueueStep();
|
|
1851
|
+
}
|
|
1852
|
+
/**
|
|
1853
|
+
* 队列处理步骤
|
|
1854
|
+
* @description 处理队列中的单个步骤,包括发起请求和发送音频
|
|
1855
|
+
* @private
|
|
1856
|
+
*/
|
|
1857
|
+
processQueueStep() {
|
|
1858
|
+
// 按序号找到下一个要处理的任务
|
|
1859
|
+
const nextTask = this.taskQueue.find((task) => task.sequence === this.currentSendingSequence + 1
|
|
1860
|
+
&& task.pendingResponses.length > 0);
|
|
1861
|
+
if (nextTask) {
|
|
1862
|
+
this.sendNextResponse(nextTask);
|
|
1863
|
+
}
|
|
1864
|
+
// 清理已完成的任务
|
|
1865
|
+
this.cleanupCompletedTasks();
|
|
1866
|
+
// 如果队列为空,停止定时器
|
|
1867
|
+
if (this.taskQueue.length === 0 && this.queueProcessTimer) {
|
|
1868
|
+
clearInterval(this.queueProcessTimer);
|
|
1869
|
+
this.queueProcessTimer = null;
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
/**
|
|
1873
|
+
* 开始任务请求
|
|
1874
|
+
* @param task - 播报任务
|
|
1875
|
+
* @description 为任务发起流式请求生成音频
|
|
1876
|
+
* @private
|
|
1877
|
+
*/
|
|
1878
|
+
startTaskRequest(task) {
|
|
1879
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1880
|
+
task.status = BroadcastTaskStatus.REQUESTING;
|
|
1881
|
+
this.logger.debug('Starting task request', { taskId: task.id });
|
|
1882
|
+
try {
|
|
1883
|
+
const apiUrl = `${ConfigManager.getInstance().getApiBaseUrl(true)}${this.getBroadcastApiPath(task.params.type)}`;
|
|
1884
|
+
const requestBody = {
|
|
1885
|
+
humanCode: task.params.humanCode,
|
|
1886
|
+
speed: task.params.speed,
|
|
1887
|
+
volume: task.params.volume >= 0 ? task.params.volume * 100 : undefined,
|
|
1888
|
+
isSubtitle: task.params.isSubtitle
|
|
1889
|
+
};
|
|
1890
|
+
// 根据播报类型设置特定参数
|
|
1891
|
+
if (task.params.type === BroadcastType.TEXT) {
|
|
1892
|
+
requestBody.text = task.params.text;
|
|
1893
|
+
requestBody.voiceCode = task.params.voiceCode;
|
|
1894
|
+
}
|
|
1895
|
+
else if (task.params.type === BroadcastType.AUDIO) {
|
|
1896
|
+
requestBody.text = task.params.text;
|
|
1897
|
+
requestBody.audioUrl = task.params.audioUrl;
|
|
1898
|
+
}
|
|
1899
|
+
// 发起流式请求
|
|
1900
|
+
fetchEventSource(apiUrl, {
|
|
1901
|
+
method: 'POST',
|
|
1902
|
+
headers: {
|
|
1903
|
+
'Content-Type': 'application/json',
|
|
1904
|
+
'x_auth_token': ConfigManager.getInstance().getToken()
|
|
1905
|
+
},
|
|
1906
|
+
body: JSON.stringify(requestBody),
|
|
1907
|
+
signal: task.controller.signal,
|
|
1908
|
+
openWhenHidden: true,
|
|
1909
|
+
onmessage: (event) => {
|
|
1910
|
+
this.handleTaskResponse(task, event.data);
|
|
1911
|
+
},
|
|
1912
|
+
onclose: () => {
|
|
1913
|
+
this.handleTaskClose(task);
|
|
1914
|
+
},
|
|
1915
|
+
onerror: (error) => {
|
|
1916
|
+
this.handleTaskError(task, error);
|
|
1917
|
+
throw new Error(`Task ${task.id} request failed: ${error}`);
|
|
1918
|
+
}
|
|
1919
|
+
});
|
|
1920
|
+
}
|
|
1921
|
+
catch (error) {
|
|
1922
|
+
this.handleTaskError(task, error);
|
|
1923
|
+
}
|
|
1924
|
+
});
|
|
1925
|
+
}
|
|
1926
|
+
/**
|
|
1927
|
+
* 处理任务响应
|
|
1928
|
+
* @param task - 播报任务
|
|
1929
|
+
* @param data - 响应数据
|
|
1930
|
+
* @description 处理任务的流式响应数据
|
|
1931
|
+
* @private
|
|
1932
|
+
*/
|
|
1933
|
+
handleTaskResponse(task, data) {
|
|
1934
|
+
try {
|
|
1935
|
+
const response = JSON.parse(data);
|
|
1936
|
+
// 错误处理
|
|
1937
|
+
if (response.code !== 0) {
|
|
1938
|
+
this.handleBroadcastError(response.code);
|
|
1939
|
+
return;
|
|
1940
|
+
}
|
|
1941
|
+
// 处理音频数据
|
|
1942
|
+
if (response.data && response.data.voiceUrl) {
|
|
1943
|
+
// 自定义音频播报时,如果服务器未返回音频URL,使用传入的audioUrl
|
|
1944
|
+
if (task.params.type === BroadcastType.AUDIO && task.params.audioUrl && !response.data.voiceUrl) {
|
|
1945
|
+
response.data.voiceUrl = task.params.audioUrl;
|
|
1946
|
+
}
|
|
1947
|
+
// 添加处理后的响应对象到待发送队列
|
|
1948
|
+
task.pendingResponses.push(response);
|
|
1949
|
+
this.logger.debug('Response added to task', { taskId: task.id, pendingCount: task.pendingResponses.length });
|
|
1950
|
+
}
|
|
1951
|
+
// 检查是否完成
|
|
1952
|
+
if (response.data && response.data.done) {
|
|
1953
|
+
task.isGenerationComplete = true;
|
|
1954
|
+
this.logger.debug('Task generation completed', { taskId: task.id, totalResponses: task.pendingResponses.length });
|
|
1955
|
+
// 任务完成生成,保持REQUESTING状态直到所有响应发送完毕
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
catch (error) {
|
|
1959
|
+
this.handleTaskError(task, error);
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
/**
|
|
1963
|
+
* 发送下一个响应
|
|
1964
|
+
* @param task - 播报任务
|
|
1965
|
+
* @description 发送任务中的第一个待发送响应到Unity,发送后立即删除
|
|
1966
|
+
* @private
|
|
1967
|
+
*/
|
|
1968
|
+
sendNextResponse(task) {
|
|
1969
|
+
var _a;
|
|
1970
|
+
if (task.pendingResponses.length === 0) {
|
|
1971
|
+
return;
|
|
1972
|
+
}
|
|
1973
|
+
// 取出第一个待发送的响应
|
|
1974
|
+
const response = task.pendingResponses.shift();
|
|
1975
|
+
this.logger.debug('Sending response to Unity', {
|
|
1976
|
+
taskId: task.id,
|
|
1977
|
+
remainingResponses: task.pendingResponses.length,
|
|
1978
|
+
voiceUrl: (_a = response.data) === null || _a === void 0 ? void 0 : _a.voiceUrl
|
|
1979
|
+
});
|
|
1980
|
+
// 发送响应到Unity
|
|
1981
|
+
this.sendMessage('AppendBroadcast', {
|
|
1982
|
+
response,
|
|
1983
|
+
callbackFun: this.uniqueCallbackName,
|
|
1984
|
+
operationType: BroadcastOperationType.APPEND_BROADCAST
|
|
1985
|
+
});
|
|
1986
|
+
// 如果任务已完成且没有更多待发送响应,标记任务完成并推进序号
|
|
1987
|
+
if (task.isGenerationComplete && task.pendingResponses.length === 0) {
|
|
1988
|
+
task.status = BroadcastTaskStatus.COMPLETED;
|
|
1989
|
+
this.currentSendingSequence = task.sequence;
|
|
1990
|
+
this.logger.debug('Task completed', { taskId: task.id });
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
/**
|
|
1994
|
+
* 处理任务关闭
|
|
1995
|
+
* @param task - 播报任务
|
|
1996
|
+
* @description 处理任务的流式连接关闭
|
|
1997
|
+
* @private
|
|
1998
|
+
*/
|
|
1999
|
+
handleTaskClose(task) {
|
|
2000
|
+
this.logger.debug('Task stream closed', { taskId: task.id });
|
|
2001
|
+
// 如果还没有标记为完成,则标记为完成
|
|
2002
|
+
if (!task.isGenerationComplete && task.status === BroadcastTaskStatus.REQUESTING) {
|
|
2003
|
+
task.isGenerationComplete = true;
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
/**
|
|
2007
|
+
* 处理任务错误
|
|
2008
|
+
* @param task - 播报任务
|
|
2009
|
+
* @param error - 错误对象
|
|
2010
|
+
* @description 处理任务执行过程中的错误
|
|
2011
|
+
* @private
|
|
2012
|
+
*/
|
|
2013
|
+
handleTaskError(task, error) {
|
|
2014
|
+
var _a, _b;
|
|
2015
|
+
task.status = BroadcastTaskStatus.FAILED;
|
|
2016
|
+
task.error = error;
|
|
2017
|
+
this.logger.error(`Task failed - ${task.id}`, error);
|
|
2018
|
+
// 触发错误回调
|
|
2019
|
+
(_b = (_a = this.callbacks).onError) === null || _b === void 0 ? void 0 : _b.call(_a, error);
|
|
2020
|
+
}
|
|
2021
|
+
/**
|
|
2022
|
+
* 清理已完成的任务
|
|
2023
|
+
* @description 从队列中移除已完成、失败或取消的任务
|
|
2024
|
+
* @private
|
|
2025
|
+
*/
|
|
2026
|
+
cleanupCompletedTasks() {
|
|
2027
|
+
const beforeLength = this.taskQueue.length;
|
|
2028
|
+
this.taskQueue = this.taskQueue.filter(task => task.status !== BroadcastTaskStatus.COMPLETED
|
|
2029
|
+
&& task.status !== BroadcastTaskStatus.FAILED
|
|
2030
|
+
&& task.status !== BroadcastTaskStatus.CANCELLED);
|
|
2031
|
+
const removedCount = beforeLength - this.taskQueue.length;
|
|
2032
|
+
if (removedCount > 0) {
|
|
2033
|
+
this.logger.debug('Cleaned up completed tasks', { removedCount, remainingTasks: this.taskQueue.length });
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
/**
|
|
2037
|
+
* 取消所有任务
|
|
2038
|
+
* @description 取消队列中的所有任务
|
|
2039
|
+
* @private
|
|
2040
|
+
*/
|
|
2041
|
+
cancelAllTasks() {
|
|
2042
|
+
for (const task of this.taskQueue) {
|
|
2043
|
+
if (task.status !== BroadcastTaskStatus.COMPLETED && task.status !== BroadcastTaskStatus.FAILED) {
|
|
2044
|
+
task.controller.abort();
|
|
2045
|
+
task.status = BroadcastTaskStatus.CANCELLED;
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
this.taskQueue = [];
|
|
2049
|
+
this.taskSequence = 0;
|
|
2050
|
+
this.currentSendingSequence = 0;
|
|
2051
|
+
this.logger.debug('All tasks cancelled and queue cleared');
|
|
2052
|
+
}
|
|
1844
2053
|
/** 全局回调函数名称 */
|
|
1845
2054
|
get callbackFunctionName() {
|
|
1846
2055
|
return 'uniBroadcastCallback';
|
|
@@ -2129,13 +2338,15 @@ class ZEEAvatarSDK {
|
|
|
2129
2338
|
// 4. 创建带有唯一标识符的Avatar服务
|
|
2130
2339
|
this.avatarService = new AvatarService({
|
|
2131
2340
|
unityInstance: this.unityInstance,
|
|
2132
|
-
instanceId: this.instanceId
|
|
2341
|
+
instanceId: this.instanceId,
|
|
2342
|
+
enableDebugLog: this.config.enableDebugLog
|
|
2133
2343
|
});
|
|
2134
2344
|
// 5. 创建带有唯一标识符的播报服务
|
|
2135
2345
|
this.broadcastService = new BroadcastService({
|
|
2136
2346
|
unityInstance: this.unityInstance,
|
|
2137
2347
|
instanceId: this.instanceId,
|
|
2138
|
-
callbacks: this.config.broadcastCallbacks
|
|
2348
|
+
callbacks: this.config.broadcastCallbacks,
|
|
2349
|
+
enableDebugLog: this.config.enableDebugLog
|
|
2139
2350
|
});
|
|
2140
2351
|
// 6. 初始化数字人
|
|
2141
2352
|
const result = yield this.avatarService.initializeAvatar(avatarCode, cameraType);
|
|
@@ -2223,12 +2434,13 @@ class ZEEAvatarSDK {
|
|
|
2223
2434
|
/**
|
|
2224
2435
|
* 开始播报
|
|
2225
2436
|
* @param params 播报参数
|
|
2437
|
+
* @param isAppend 是否追加播报
|
|
2226
2438
|
* @returns Promise<void> 播报操作的Promise
|
|
2227
2439
|
*/
|
|
2228
|
-
startBroadcast(params) {
|
|
2440
|
+
startBroadcast(params, isAppend) {
|
|
2229
2441
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2230
2442
|
this.ensureInitialized();
|
|
2231
|
-
return yield this.broadcastService.startBroadcast(params);
|
|
2443
|
+
return yield this.broadcastService.startBroadcast(params, isAppend);
|
|
2232
2444
|
});
|
|
2233
2445
|
}
|
|
2234
2446
|
/**
|