@coze/realtime-api 1.3.1 → 1.3.2-alpha.f7fe14

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.
@@ -1,103 +1,97 @@
1
- "use strict";
2
- // The require scope
3
- var __webpack_require__ = {};
4
- /************************************************************************/ // webpack/runtime/define_property_getters
5
- (()=>{
6
- __webpack_require__.d = function(exports1, definition) {
7
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
8
- enumerable: true,
9
- get: definition[key]
10
- });
11
- };
12
- })();
13
- // webpack/runtime/has_own_property
14
- (()=>{
15
- __webpack_require__.o = function(obj, prop) {
16
- return Object.prototype.hasOwnProperty.call(obj, prop);
17
- };
18
- })();
19
- // webpack/runtime/make_namespace_object
20
- (()=>{
21
- // define __esModule on exports
22
- __webpack_require__.r = function(exports1) {
23
- if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
24
- value: 'Module'
25
- });
26
- Object.defineProperty(exports1, '__esModule', {
27
- value: true
28
- });
29
- };
30
- })();
31
- /************************************************************************/ var __webpack_exports__ = {};
32
- // ESM COMPAT FLAG
33
- __webpack_require__.r(__webpack_exports__);
34
- // EXPORTS
35
- __webpack_require__.d(__webpack_exports__, {
36
- WebLiveClient: ()=>/* binding */ WebLiveClient,
37
- ResourceStatus: ()=>/* binding */ live_ResourceStatus
38
- });
39
- const api_namespaceObject = require("@coze/api");
1
+ 'use strict';
2
+
3
+ var api = require('@coze/api');
4
+
40
5
  // WTN服务基础URL
41
6
  const WTN_BASE_URL = 'https://wtn.volcvideo.com';
42
7
  /**
43
8
  * WebRTC资源状态
44
- */ var live_ResourceStatus = /*#__PURE__*/ function(ResourceStatus) {
9
+ */
10
+ exports.ResourceStatus = void 0;
11
+ (function (ResourceStatus) {
45
12
  ResourceStatus["IDLE"] = "idle";
46
13
  ResourceStatus["CONNECTING"] = "connecting";
47
14
  ResourceStatus["CONNECTED"] = "connected";
48
15
  ResourceStatus["FAILED"] = "failed";
49
16
  ResourceStatus["CLOSING"] = "closing";
50
17
  ResourceStatus["CLOSED"] = "closed";
51
- return ResourceStatus;
52
- }({});
18
+ })(exports.ResourceStatus || (exports.ResourceStatus = {}));
53
19
  /**
54
20
  * 同声传译客户端
55
- */ class WebLiveClient {
21
+ */
22
+ class WebLiveClient {
23
+ constructor(liveId) {
24
+ this.peerConnection = null;
25
+ this.resourceUrl = '';
26
+ this.status = exports.ResourceStatus.IDLE;
27
+ this.statusListeners = [];
28
+ /**
29
+ * 获取直播信息
30
+ */
31
+ this.getLiveData = async () => {
32
+ const api$1 = new api.CozeAPI({
33
+ baseURL: api.COZE_CN_BASE_URL,
34
+ token: '', // 免登录
35
+ });
36
+ return await api$1.audio.live.retrieve(this.liveId);
37
+ };
38
+ this.setupPeerConnectionListeners();
39
+ this.player = document.createElement('audio');
40
+ this.liveId = liveId;
41
+ }
56
42
  /**
57
- * 获取当前连接状态
58
- */ getStatus() {
43
+ * 获取当前连接状态
44
+ */
45
+ getStatus() {
59
46
  return this.status;
60
47
  }
61
48
  /**
62
- * 添加状态变化监听器
63
- * @param callback 状态变化回调函数
64
- */ onStatusChange(callback) {
49
+ * 添加状态变化监听器
50
+ * @param callback 状态变化回调函数
51
+ */
52
+ onStatusChange(callback) {
65
53
  this.statusListeners.push(callback);
66
54
  }
67
55
  /**
68
- * 移除状态变化监听器
69
- * @param callback 要移除的回调函数
70
- */ offStatusChange(callback) {
56
+ * 移除状态变化监听器
57
+ * @param callback 要移除的回调函数
58
+ */
59
+ offStatusChange(callback) {
71
60
  this.removeStatusListener(callback);
72
61
  }
73
62
  /**
74
- * 移除状态变化监听器
75
- * @param callback 要移除的回调函数
76
- */ removeStatusListener(callback) {
63
+ * 移除状态变化监听器
64
+ * @param callback 要移除的回调函数
65
+ */
66
+ removeStatusListener(callback) {
77
67
  const index = this.statusListeners.indexOf(callback);
78
- if (-1 !== index) this.statusListeners.splice(index, 1);
68
+ if (index !== -1) {
69
+ this.statusListeners.splice(index, 1);
70
+ }
79
71
  }
80
72
  /**
81
- * 订阅音频资源
82
- * @param appId 应用ID
83
- * @param streamId 流ID
84
- * @param clientId 客户端ID
85
- */ async subscribe(appId, streamId) {
86
- let clientId = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : '';
73
+ * 订阅音频资源
74
+ * @param appId 应用ID
75
+ * @param streamId 流ID
76
+ * @param clientId 客户端ID
77
+ */
78
+ async subscribe(appId, streamId, clientId = '') {
79
+ var _a;
87
80
  try {
88
- var _pc_localDescription;
89
81
  // 先清理现有连接
90
82
  if (this.peerConnection) {
91
83
  this.peerConnection.close();
92
84
  this.peerConnection = null;
93
85
  }
94
- this.setStatus("connecting");
86
+ this.setStatus(exports.ResourceStatus.CONNECTING);
95
87
  // 1. 创建RTCPeerConnection
96
- const rtcConfig = {};
88
+ const rtcConfig = {
89
+ // iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
90
+ };
97
91
  const pc = new RTCPeerConnection(rtcConfig);
98
- pc.ontrack = (event)=>{
92
+ pc.ontrack = (event) => {
99
93
  // 音频流
100
- this.player.onloadeddata = ()=>{
94
+ this.player.onloadeddata = () => {
101
95
  this.player.play();
102
96
  };
103
97
  this.player.srcObject = event.streams[0];
@@ -105,7 +99,7 @@ const WTN_BASE_URL = 'https://wtn.volcvideo.com';
105
99
  this.peerConnection = pc;
106
100
  this.setupPeerConnectionListeners();
107
101
  pc.addTransceiver('audio', {
108
- direction: 'recvonly'
102
+ direction: 'recvonly',
109
103
  });
110
104
  // 2. 创建Offer (SDP)
111
105
  const offer = await pc.createOffer();
@@ -113,18 +107,24 @@ const WTN_BASE_URL = 'https://wtn.volcvideo.com';
113
107
  await pc.setLocalDescription(offer);
114
108
  // 等待ICE收集完成再继续
115
109
  await this.waitForIceGathering(pc);
116
- if (!(null === (_pc_localDescription = pc.localDescription) || void 0 === _pc_localDescription ? void 0 : _pc_localDescription.sdp)) throw new Error('Failed to create SDP offer');
110
+ if (!((_a = pc.localDescription) === null || _a === void 0 ? void 0 : _a.sdp)) {
111
+ throw new Error('Failed to create SDP offer');
112
+ }
117
113
  // 3. 发送Offer到WTN服务订阅资源
118
114
  let subscribeUrl = `${WTN_BASE_URL}/sub/${appId}/${streamId}?MuteVideo=true`;
119
- if (clientId) subscribeUrl += `&clientid=${clientId}`;
115
+ if (clientId) {
116
+ subscribeUrl += `&clientid=${clientId}`;
117
+ }
120
118
  const response = await fetch(subscribeUrl, {
121
119
  method: 'POST',
122
120
  headers: {
123
- 'Content-Type': 'application/sdp'
121
+ 'Content-Type': 'application/sdp',
124
122
  },
125
- body: offer.sdp
123
+ body: offer.sdp,
126
124
  });
127
- if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
125
+ if (!response.ok) {
126
+ throw new Error(`HTTP error! status: ${response.status}`);
127
+ }
128
128
  // 4. 保存资源URL (用于销毁资源)
129
129
  this.resourceUrl = response.headers.get('location') || '';
130
130
  // 5. 设置远程SDP (Answer)
@@ -132,54 +132,63 @@ const WTN_BASE_URL = 'https://wtn.volcvideo.com';
132
132
  const answerSdp = await response.text();
133
133
  const answer = new RTCSessionDescription({
134
134
  type: 'answer',
135
- sdp: answerSdp
135
+ sdp: answerSdp,
136
136
  });
137
137
  await this.peerConnection.setRemoteDescription(answer);
138
138
  // 7. 返回结果
139
139
  return {
140
140
  status: this.status,
141
- peerConnection: this.peerConnection
141
+ peerConnection: this.peerConnection, // 返回连接对象,以便客户端可以监听媒体事件
142
142
  };
143
- } catch (error) {
144
- this.status = "failed";
143
+ }
144
+ catch (error) {
145
+ this.status = exports.ResourceStatus.FAILED;
145
146
  console.error('Failed to subscribe WebRTC stream:', error);
146
147
  return Promise.reject(error);
147
148
  }
148
149
  }
149
150
  /**
150
- * 销毁订阅资源
151
- */ async unsubscribe() {
151
+ * 销毁订阅资源
152
+ */
153
+ async unsubscribe() {
152
154
  try {
153
155
  // 销毁订阅资源
154
- if (!this.resourceUrl) throw new Error('No valid subscription resource URL to unsubscribe');
155
- this.setStatus("closing");
156
+ if (!this.resourceUrl) {
157
+ throw new Error('No valid subscription resource URL to unsubscribe');
158
+ }
159
+ this.setStatus(exports.ResourceStatus.CLOSING);
156
160
  const response = await fetch(this.resourceUrl, {
157
- method: 'DELETE'
161
+ method: 'DELETE',
158
162
  });
159
- if (!response.ok) throw new Error(`Failed to unsubscribe: ${response.status} ${response.statusText}`);
163
+ if (!response.ok) {
164
+ throw new Error(`Failed to unsubscribe: ${response.status} ${response.statusText}`);
165
+ }
160
166
  // 关闭RTC连接
161
167
  if (this.peerConnection) {
162
168
  this.peerConnection.close();
163
169
  this.peerConnection = null;
164
170
  }
165
171
  this.resourceUrl = '';
166
- this.status = "closed";
172
+ this.status = exports.ResourceStatus.CLOSED;
167
173
  return true;
168
- } catch (error) {
174
+ }
175
+ catch (error) {
169
176
  console.error('Error unsubscribing resource:', error);
170
- this.status = "failed";
177
+ this.status = exports.ResourceStatus.FAILED;
171
178
  return Promise.reject(error);
172
179
  }
173
180
  }
174
181
  /**
175
- * 静音/取消静音
176
- * @param muted 是否静音
177
- */ setMuted(muted) {
182
+ * 静音/取消静音
183
+ * @param muted 是否静音
184
+ */
185
+ setMuted(muted) {
178
186
  this.player.muted = muted;
179
187
  }
180
188
  /**
181
- * 关闭并清理资源
182
- */ close() {
189
+ * 关闭并清理资源
190
+ */
191
+ close() {
183
192
  // 关闭PeerConnection
184
193
  this.closePeerConnection();
185
194
  // Clean up audio element
@@ -190,21 +199,22 @@ const WTN_BASE_URL = 'https://wtn.volcvideo.com';
190
199
  }
191
200
  // 重置状态
192
201
  this.resourceUrl = '';
193
- this.setStatus("idle");
202
+ this.setStatus(exports.ResourceStatus.IDLE);
194
203
  }
195
204
  /**
196
- * 等待ICE收集完成
197
- * @param pc RTCPeerConnection实例
198
- */ waitForIceGathering(pc) {
199
- return new Promise((resolve)=>{
205
+ * 等待ICE收集完成
206
+ * @param pc RTCPeerConnection实例
207
+ */
208
+ waitForIceGathering(pc) {
209
+ return new Promise(resolve => {
200
210
  // 如果已经收集完成,直接返回
201
- if ('complete' === pc.iceGatheringState) {
211
+ if (pc.iceGatheringState === 'complete') {
202
212
  resolve();
203
213
  return;
204
214
  }
205
215
  // 设置收集完成时的回调
206
- const checkState = ()=>{
207
- if ('complete' === pc.iceGatheringState) {
216
+ const checkState = () => {
217
+ if (pc.iceGatheringState === 'complete') {
208
218
  pc.removeEventListener('icegatheringstatechange', checkState);
209
219
  resolve();
210
220
  }
@@ -212,81 +222,68 @@ const WTN_BASE_URL = 'https://wtn.volcvideo.com';
212
222
  // 监听收集状态变化
213
223
  pc.addEventListener('icegatheringstatechange', checkState);
214
224
  // 添加超时处理,防止永远等待
215
- setTimeout(()=>resolve(), 5000);
225
+ setTimeout(() => resolve(), 5000);
216
226
  });
217
227
  }
218
228
  setupPeerConnectionListeners() {
219
- if (!this.peerConnection) return;
220
- this.peerConnection.oniceconnectionstatechange = ()=>{
221
- var _this_peerConnection, _this_peerConnection1;
222
- console.log('ICE connection state changed:', null === (_this_peerConnection = this.peerConnection) || void 0 === _this_peerConnection ? void 0 : _this_peerConnection.iceConnectionState);
223
- switch(null === (_this_peerConnection1 = this.peerConnection) || void 0 === _this_peerConnection1 ? void 0 : _this_peerConnection1.iceConnectionState){
229
+ if (!this.peerConnection) {
230
+ return;
231
+ }
232
+ this.peerConnection.oniceconnectionstatechange = () => {
233
+ var _a, _b, _c;
234
+ console.log('ICE connection state changed:', (_a = this.peerConnection) === null || _a === void 0 ? void 0 : _a.iceConnectionState);
235
+ switch ((_b = this.peerConnection) === null || _b === void 0 ? void 0 : _b.iceConnectionState) {
224
236
  case 'connected':
225
237
  case 'completed':
226
- this.setStatus("connected");
238
+ this.setStatus(exports.ResourceStatus.CONNECTED);
227
239
  break;
228
240
  case 'failed':
229
241
  case 'disconnected':
230
- this.setStatus("failed");
242
+ this.setStatus(exports.ResourceStatus.FAILED);
231
243
  break;
232
244
  case 'closed':
233
- this.setStatus("closed");
245
+ this.setStatus(exports.ResourceStatus.CLOSED);
234
246
  break;
235
247
  default:
236
- var _this_peerConnection2;
237
- console.log('ICE connection state changed:', null === (_this_peerConnection2 = this.peerConnection) || void 0 === _this_peerConnection2 ? void 0 : _this_peerConnection2.iceConnectionState);
248
+ console.log('ICE connection state changed:', (_c = this.peerConnection) === null || _c === void 0 ? void 0 : _c.iceConnectionState);
238
249
  break;
239
250
  }
240
251
  };
241
- this.peerConnection.onicecandidate = (event)=>{
242
- if (event.candidate) console.log('New ICE candidate:', event.candidate);
252
+ this.peerConnection.onicecandidate = event => {
253
+ if (event.candidate) {
254
+ console.log('New ICE candidate:', event.candidate);
255
+ }
243
256
  };
244
257
  }
245
258
  /**
246
- * 关闭PeerConnection
247
- */ closePeerConnection() {
259
+ * 关闭PeerConnection
260
+ */
261
+ closePeerConnection() {
248
262
  if (this.peerConnection) {
249
263
  this.peerConnection.close();
250
264
  this.peerConnection = null;
251
265
  }
252
266
  }
253
267
  /**
254
- * 设置状态并触发监听回调
255
- * @param newStatus 新状态
256
- * @private 私有方法,仅内部使用
257
- */ setStatus(newStatus) {
268
+ * 设置状态并触发监听回调
269
+ * @param newStatus 新状态
270
+ * @private 私有方法,仅内部使用
271
+ */
272
+ setStatus(newStatus) {
258
273
  const oldStatus = this.status;
259
274
  if (oldStatus !== newStatus) {
260
275
  this.status = newStatus;
261
276
  // 触发所有监听器
262
- for (const listener of this.statusListeners)try {
263
- listener(newStatus);
264
- } catch (error) {
265
- console.error('Error in status listener:', error);
277
+ for (const listener of this.statusListeners) {
278
+ try {
279
+ listener(newStatus);
280
+ }
281
+ catch (error) {
282
+ console.error('Error in status listener:', error);
283
+ }
266
284
  }
267
285
  }
268
286
  }
269
- constructor(liveId){
270
- this.peerConnection = null;
271
- this.resourceUrl = '';
272
- this.status = "idle";
273
- this.statusListeners = [];
274
- /**
275
- * 获取直播信息
276
- */ this.getLiveData = async ()=>{
277
- const api = new api_namespaceObject.CozeAPI({
278
- baseURL: api_namespaceObject.COZE_CN_BASE_URL,
279
- token: ''
280
- });
281
- return await api.audio.live.retrieve(this.liveId);
282
- };
283
- this.setupPeerConnectionListeners();
284
- this.player = document.createElement('audio');
285
- this.liveId = liveId;
286
- }
287
287
  }
288
- var __webpack_export_target__ = exports;
289
- for(var i in __webpack_exports__)__webpack_export_target__[i] = __webpack_exports__[i];
290
- if (__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, '__esModule', {
291
- value: true
292
- });
288
+
289
+ exports.WebLiveClient = WebLiveClient;