@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/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', withModule = true) {
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}${withModule ? '/api' : ''}`
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 withModule 是否包含模块路径
1104
+ * @param withApiModule 是否包含模块路径
1104
1105
  * @returns string API基础URL
1105
1106
  * @description 根据当前环境配置获取API基础URL
1106
1107
  */
1107
- getApiBaseUrl(withModule = true) {
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', withModule)) === null || _d === void 0 ? void 0 : _d.apiBaseUrl) || '';
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.activeController = null;
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.AUDIO,
1633
+ * type: BroadcastType.TEXT,
1610
1634
  * humanCode: 'human001',
1611
- * audioUrl: 'https://example.com/audio.mp3',
1635
+ * text: '这是第二段内容',
1636
+ * voiceCode: 'voice001',
1612
1637
  * volume: 0.8,
1613
- * isSubtitle: false
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}`, { humanCode: params.humanCode });
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
- yield this.stopBroadcast();
1625
- // 创建新的请求控制器
1626
- this.activeController = new AbortController();
1627
- // 监听中断信号
1628
- this.activeController.signal.addEventListener('abort', () => {
1629
- var _a, _b;
1630
- console.warn('abort');
1631
- // 如果正在生成音频,触发中断回调
1632
- if (this.isGeneratingAudio) {
1633
- (_b = (_a = this.callbacks).onAbort) === null || _b === void 0 ? void 0 : _b.call(_a);
1634
- }
1635
- // 重置状态
1636
- this.isGeneratingAudio = false;
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
- if (this.activeController) {
1794
- this.activeController.abort();
1795
- this.activeController = null;
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.activeController !== null,
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.activeController) {
1837
- this.activeController.abort();
1838
- this.activeController = null;
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
  /**