@coze/realtime-api 1.2.0 → 1.2.1-beta.11

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/umd/index.js CHANGED
@@ -96,6 +96,7 @@
96
96
  checkDevicePermission: ()=>checkDevicePermission,
97
97
  checkPermission: ()=>checkPermission,
98
98
  getAudioDevices: ()=>getAudioDevices,
99
+ isMobileVideoDevice: ()=>isMobileVideoDevice,
99
100
  isScreenShareDevice: ()=>isScreenShareDevice,
100
101
  isScreenShareSupported: ()=>isScreenShareSupported,
101
102
  sleep: ()=>sleep
@@ -173,6 +174,11 @@
173
174
  };
174
175
  const isScreenShareDevice = (deviceId)=>'screenShare' === deviceId;
175
176
  /**
177
+ * 判断是否前后置摄像头
178
+ * @param deviceId
179
+ * @returns
180
+ */ const isMobileVideoDevice = (deviceId)=>'user' === deviceId || 'environment' === deviceId;
181
+ /**
176
182
  * Check if browser supports screen sharing
177
183
  * 检查浏览器是否支持屏幕共享
178
184
  */ function isScreenShareSupported() {
@@ -193,6 +199,10 @@
193
199
  * zh: 所有服务端事件
194
200
  */ EventNames["ALL_SERVER"] = "server.*";
195
201
  /**
202
+ * en: Room info
203
+ * zh: 房间信息
204
+ */ EventNames["ROOM_INFO"] = "client.room.info";
205
+ /**
196
206
  * en: Client connected
197
207
  * zh: 客户端连接
198
208
  */ EventNames["CONNECTED"] = "client.connected";
@@ -225,6 +235,10 @@
225
235
  * zh: 客户端视频关闭
226
236
  */ EventNames["VIDEO_OFF"] = "client.video.off";
227
237
  /**
238
+ * en: Client video error
239
+ * zh: 客户端视频(或屏幕共享)错误
240
+ */ EventNames["VIDEO_ERROR"] = "client.video.error";
241
+ /**
228
242
  * en: Client video event
229
243
  * zh: 客户端视频事件
230
244
  */ EventNames["PLAYER_EVENT"] = "client.video.event";
@@ -291,7 +305,51 @@
291
305
  /**
292
306
  * en: Session updated
293
307
  * zh: 会话更新
294
- */ EventNames["SESSION_UPDATE"] = "server.session.update";
308
+ */ EventNames["SESSION_UPDATED"] = "server.session.updated";
309
+ /**
310
+ * en: Conversation created
311
+ * zh: 会话创建
312
+ */ EventNames["CONVERSATION_CREATED"] = "server.conversation.created";
313
+ /**
314
+ * en: Conversation chat created
315
+ * zh: 会话对话创建
316
+ */ EventNames["CONVERSATION_CHAT_CREATED"] = "server.conversation.chat.created";
317
+ /**
318
+ * en: Conversation chat in progress
319
+ * zh: 对话正在处理中
320
+ */ EventNames["CONVERSATION_CHAT_IN_PROGRESS"] = "server.conversation.chat.in_progress";
321
+ /**
322
+ * en: Conversation message delta received
323
+ * zh: 文本消息增量返回
324
+ */ EventNames["CONVERSATION_MESSAGE_DELTA"] = "server.conversation.message.delta";
325
+ /**
326
+ * en: Conversation message completed
327
+ * zh: 文本消息完成
328
+ */ EventNames["CONVERSATION_MESSAGE_COMPLETED"] = "server.conversation.message.completed";
329
+ /**
330
+ * en: Conversation chat completed
331
+ * zh: 对话完成
332
+ */ EventNames["CONVERSATION_CHAT_COMPLETED"] = "server.conversation.chat.completed";
333
+ /**
334
+ * en: Conversation chat requires action
335
+ * zh: 对话需要插件
336
+ */ EventNames["CONVERSATION_CHAT_REQUIRES_ACTION"] = "server.conversation.chat.requires_action";
337
+ /**
338
+ * en: Conversation chat failed
339
+ * zh: 对话失败
340
+ */ EventNames["CONVERSATION_CHAT_FAILED"] = "server.conversation.chat.failed";
341
+ /**
342
+ * en: Session pre answer updated
343
+ * zh: 安抚配置更新成功
344
+ */ EventNames["SESSION_PRE_ANSWER_UPDATED"] = "server.session.pre_answer.updated";
345
+ /**
346
+ * en: Conversation audio transcript delta
347
+ * zh: 用户语音识别字幕
348
+ */ EventNames["CONVERSATION_AUDIO_TRANSCRIPT_DELTA"] = "server.conversation.audio_transcript.delta";
349
+ /**
350
+ * en: Mode updated
351
+ * zh: 更新房间模式成功
352
+ */ EventNames["MODE_UPDATED"] = "server.mode.updated";
295
353
  return EventNames;
296
354
  }(event_names_EventNames || {});
297
355
  /* ESM default export */ const event_names = event_names_EventNames;
@@ -382,6 +440,7 @@
382
440
  this.engine.on(rtc_default().events.onUserLeave, this.handleUserLeave);
383
441
  this.engine.on(rtc_default().events.onError, this.handleEventError);
384
442
  this.engine.on(rtc_default().events.onNetworkQuality, this.handleNetworkQuality);
443
+ this.engine.on(rtc_default().events.onTrackEnded, this.handleTrackEnded);
385
444
  if (this._isSupportVideo) this.engine.on(rtc_default().events.onPlayerEvent, this.handlePlayerEvent);
386
445
  if (this._debug) {
387
446
  this.engine.on(rtc_default().events.onLocalAudioPropertiesReport, this.handleLocalAudioPropertiesReport);
@@ -394,6 +453,7 @@
394
453
  this.engine.off(rtc_default().events.onUserLeave, this.handleUserLeave);
395
454
  this.engine.off(rtc_default().events.onError, this.handleEventError);
396
455
  this.engine.off(rtc_default().events.onNetworkQuality, this.handleNetworkQuality);
456
+ this.engine.off(rtc_default().events.onTrackEnded, this.handleTrackEnded);
397
457
  if (this._isSupportVideo) this.engine.off(rtc_default().events.onPlayerEvent, this.handlePlayerEvent);
398
458
  if (this._debug) {
399
459
  this.engine.off(rtc_default().events.onLocalAudioPropertiesReport, this.handleLocalAudioPropertiesReport);
@@ -444,6 +504,10 @@
444
504
  downlinkNetworkQuality
445
505
  });
446
506
  }
507
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
508
+ handleTrackEnded(event) {
509
+ if ((null == event ? void 0 : event.kind) === 'video') this.dispatch(event_names.VIDEO_OFF, event);
510
+ }
447
511
  async joinRoom(options) {
448
512
  const { token, roomId, uid, audioMutedDefault, videoOnDefault, isAutoSubscribeAudio } = options;
449
513
  try {
@@ -477,7 +541,11 @@
477
541
  const devices = await getAudioDevices({
478
542
  video: true
479
543
  });
480
- if (-1 === devices.videoInputs.findIndex((i)=>i.deviceId === deviceId)) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, `Video input device not found: ${deviceId}`);
544
+ if (!isMobileVideoDevice(deviceId) && -1 === devices.videoInputs.findIndex((i)=>i.deviceId === deviceId)) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, `Video input device not found: ${deviceId}`);
545
+ this.engine.setLocalVideoPlayer(isScreenShareDevice(deviceId) ? rtc_.StreamIndex.STREAM_INDEX_SCREEN : rtc_.StreamIndex.STREAM_INDEX_MAIN, {
546
+ renderDom: (null === (_this__videoConfig = this._videoConfig) || void 0 === _this__videoConfig ? void 0 : _this__videoConfig.renderDom) || 'local-player',
547
+ userId: this._roomUserId
548
+ });
481
549
  await this.changeVideoState(false);
482
550
  if (isScreenShareDevice(deviceId)) {
483
551
  if (this._streamIndex === rtc_.StreamIndex.STREAM_INDEX_MAIN) this.engine.setLocalVideoPlayer(rtc_.StreamIndex.STREAM_INDEX_MAIN);
@@ -493,10 +561,6 @@
493
561
  if (isAutoCapture) await this.engine.startVideoCapture(deviceId);
494
562
  this._streamIndex = rtc_.StreamIndex.STREAM_INDEX_MAIN;
495
563
  }
496
- this.engine.setLocalVideoPlayer(this._streamIndex, {
497
- renderDom: (null === (_this__videoConfig = this._videoConfig) || void 0 === _this__videoConfig ? void 0 : _this__videoConfig.renderDom) || 'local-player',
498
- userId: this._roomUserId
499
- });
500
564
  }
501
565
  async createLocalStream(userId, videoConfig) {
502
566
  this._roomUserId = userId;
@@ -506,7 +570,12 @@
506
570
  if (!devices.audioInputs.length) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, 'Failed to get audio devices');
507
571
  if (this._isSupportVideo && !devices.videoInputs.length) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, 'Failed to get video devices');
508
572
  await this.engine.startAudioCapture(devices.audioInputs[0].deviceId);
509
- if (this._isSupportVideo) this.setVideoInputDevice((null == videoConfig ? void 0 : videoConfig.videoInputDeviceId) || devices.videoInputs[0].deviceId, null == videoConfig ? void 0 : videoConfig.videoOnDefault);
573
+ if (this._isSupportVideo) try {
574
+ await this.setVideoInputDevice((null == videoConfig ? void 0 : videoConfig.videoInputDeviceId) || devices.videoInputs[0].deviceId, null == videoConfig ? void 0 : videoConfig.videoOnDefault);
575
+ this.dispatch((null == videoConfig ? void 0 : videoConfig.videoOnDefault) ? event_names.VIDEO_ON : event_names.VIDEO_OFF, {});
576
+ } catch (e) {
577
+ this.dispatch(event_names.VIDEO_ERROR, e);
578
+ }
510
579
  }
511
580
  async disconnect() {
512
581
  try {
@@ -529,23 +598,18 @@
529
598
  }
530
599
  }
531
600
  async changeVideoState(isVideoOn) {
532
- try {
533
- if (isVideoOn) {
534
- if (this._streamIndex === rtc_.StreamIndex.STREAM_INDEX_MAIN) await this.engine.startVideoCapture();
535
- else {
536
- var _this__videoConfig;
537
- this.engine.setVideoSourceType(rtc_.StreamIndex.STREAM_INDEX_SCREEN, rtc_.VideoSourceType.VIDEO_SOURCE_TYPE_INTERNAL);
538
- await this.engine.startScreenCapture(null === (_this__videoConfig = this._videoConfig) || void 0 === _this__videoConfig ? void 0 : _this__videoConfig.screenConfig);
539
- await this.engine.publishScreen(rtc_.MediaType.VIDEO);
540
- }
541
- } else if (this._streamIndex === rtc_.StreamIndex.STREAM_INDEX_MAIN) await this.engine.stopVideoCapture();
601
+ if (isVideoOn) {
602
+ if (this._streamIndex === rtc_.StreamIndex.STREAM_INDEX_MAIN) await this.engine.startVideoCapture();
542
603
  else {
543
- await this.engine.stopScreenCapture();
544
- await this.engine.unpublishScreen(rtc_.MediaType.VIDEO);
604
+ var _this__videoConfig;
605
+ this.engine.setVideoSourceType(rtc_.StreamIndex.STREAM_INDEX_SCREEN, rtc_.VideoSourceType.VIDEO_SOURCE_TYPE_INTERNAL);
606
+ await this.engine.startScreenCapture(null === (_this__videoConfig = this._videoConfig) || void 0 === _this__videoConfig ? void 0 : _this__videoConfig.screenConfig);
607
+ await this.engine.publishScreen(rtc_.MediaType.VIDEO);
545
608
  }
546
- } catch (e) {
547
- this.dispatch(event_names.ERROR, e);
548
- throw e;
609
+ } else if (this._streamIndex === rtc_.StreamIndex.STREAM_INDEX_MAIN) await this.engine.stopVideoCapture();
610
+ else {
611
+ await this.engine.stopScreenCapture();
612
+ await this.engine.unpublishScreen(rtc_.MediaType.VIDEO);
549
613
  }
550
614
  }
551
615
  async stop() {
@@ -635,6 +699,7 @@
635
699
  this.handleEventError = this.handleEventError.bind(this);
636
700
  this.handlePlayerEvent = this.handlePlayerEvent.bind(this);
637
701
  this.handleNetworkQuality = this.handleNetworkQuality.bind(this);
702
+ this.handleTrackEnded = this.handleTrackEnded.bind(this);
638
703
  // Debug only
639
704
  this.handleLocalAudioPropertiesReport = this.handleLocalAudioPropertiesReport.bind(this);
640
705
  this.handleRemoteAudioPropertiesReport = this.handleRemoteAudioPropertiesReport.bind(this);
@@ -658,16 +723,17 @@
658
723
  // Step1 get token
659
724
  if (getRoomInfo) roomInfo = await getRoomInfo();
660
725
  else {
661
- let config;
662
- if (this._config.videoConfig) config = isScreenShareDevice(this._config.videoConfig.videoInputDeviceId) ? {
663
- video_config: {
726
+ const config = {};
727
+ if (this._config.prologueContent) config.prologue_content = this._config.prologueContent;
728
+ if (void 0 !== this._config.roomMode && null !== this._config.roomMode) config.room_mode = this._config.roomMode;
729
+ if (this._config.videoConfig) {
730
+ if (isScreenShareDevice(this._config.videoConfig.videoInputDeviceId)) config.video_config = {
664
731
  stream_video_type: 'screen'
665
- }
666
- } : {
667
- video_config: {
732
+ };
733
+ else config.video_config = {
668
734
  stream_video_type: 'main'
669
- }
670
- };
735
+ };
736
+ }
671
737
  roomInfo = await this._api.audio.rooms.create({
672
738
  bot_id: botId,
673
739
  conversation_id: conversationId || void 0,
@@ -682,6 +748,12 @@
682
748
  this.dispatch(event_names.ERROR, error);
683
749
  throw new RealtimeAPIError(error_RealtimeError.CREATE_ROOM_ERROR, error instanceof Error ? error.message : 'Unknown error', error);
684
750
  }
751
+ this.dispatch(event_names.ROOM_INFO, {
752
+ roomId: roomInfo.room_id,
753
+ uid: roomInfo.uid,
754
+ token: roomInfo.token,
755
+ appId: roomInfo.app_id
756
+ });
685
757
  this._isTestEnv = TEST_APP_ID === roomInfo.app_id;
686
758
  // Step2 create engine
687
759
  this._client = new EngineClient(roomInfo.app_id, this._config.debug, this._isTestEnv, this._isSupportVideo, this._config.videoConfig);
@@ -763,10 +835,14 @@
763
835
  else this.dispatch(event_names.AUDIO_MUTED, {});
764
836
  }
765
837
  async setVideoEnable(isEnable) {
766
- var _this__client;
767
- await (null === (_this__client = this._client) || void 0 === _this__client ? void 0 : _this__client.changeVideoState(isEnable));
768
- if (isEnable) this.dispatch(event_names.VIDEO_ON, {});
769
- else this.dispatch(event_names.VIDEO_OFF, {});
838
+ try {
839
+ var _this__client;
840
+ await (null === (_this__client = this._client) || void 0 === _this__client ? void 0 : _this__client.changeVideoState(isEnable));
841
+ this.dispatch(isEnable ? event_names.VIDEO_ON : event_names.VIDEO_OFF, {});
842
+ } catch (e) {
843
+ this.dispatch(event_names.VIDEO_ERROR, e);
844
+ throw e;
845
+ }
770
846
  }
771
847
  /**
772
848
  * en: Enable audio properties reporting (debug mode only)
@@ -823,9 +899,19 @@
823
899
  deviceId
824
900
  });
825
901
  }
826
- async setVideoInputDevice(deviceId) {
827
- var _this__client;
828
- await (null === (_this__client = this._client) || void 0 === _this__client ? void 0 : _this__client.setVideoInputDevice(deviceId));
902
+ /**
903
+ * en: Set the video input device
904
+ *
905
+ * zh: 设置视频输入设备
906
+ */ async setVideoInputDevice(deviceId) {
907
+ try {
908
+ var _this__client;
909
+ await (null === (_this__client = this._client) || void 0 === _this__client ? void 0 : _this__client.setVideoInputDevice(deviceId));
910
+ this.dispatch(event_names.VIDEO_ON, {});
911
+ } catch (e) {
912
+ this.dispatch(event_names.VIDEO_ERROR, e);
913
+ throw e;
914
+ }
829
915
  this.dispatch(event_names.VIDEO_INPUT_DEVICE_CHANGED, {
830
916
  deviceId
831
917
  });
@@ -880,6 +966,8 @@
880
966
  * 可选,视频输入设备的设备 ID。
881
967
  * @param config.videoConfig.screenConfig - Optional, Screen share configuration if videoInputDeviceId is 'screenShare' see https://www.volcengine.com/docs/6348/104481#screenconfig for more details. |
882
968
  * 可选,屏幕共享配置,如果 videoInputDeviceId 是 'screenShare',请参考 https://www.volcengine.com/docs/6348/104481#screenconfig 了解更多详情。
969
+ * @param config.prologueContent - Optional, Prologue content. | 可选,开场白内容。
970
+ * @param config.roomMode - Optional, Room mode. | 可选,房间模式。
883
971
  */ constructor(config){
884
972
  super(config.debug), this._client = null, this.isConnected = false, this._isTestEnv = false, this._isSupportVideo = false;
885
973
  this._config = config;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coze/realtime-api",
3
- "version": "1.2.0",
3
+ "version": "1.2.1-beta.11",
4
4
  "description": "A powerful real-time communication SDK for voice interactions with Coze AI bots | 扣子官方实时通信 SDK,用于与 Coze AI bots 进行语音交互",
5
5
  "keywords": [
6
6
  "coze",
@@ -54,8 +54,8 @@
54
54
  "test:cov": "vitest --coverage --run"
55
55
  },
56
56
  "dependencies": {
57
- "@coze/api": "1.2.0",
58
- "@volcengine/rtc": "^4.62.1"
57
+ "@coze/api": "1.2.1-beta.23",
58
+ "@volcengine/rtc": "~4.62.11"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@coze-infra/eslint-config": "workspace:*",
@@ -66,10 +66,10 @@
66
66
  "@types/node": "^20",
67
67
  "@types/uuid": "^9.0.1",
68
68
  "@types/whatwg-fetch": "^0.0.33",
69
- "@vitest/coverage-v8": "~2.1.4",
69
+ "@vitest/coverage-v8": "~2.1.9",
70
70
  "axios": "^1.7.7",
71
71
  "typescript": "^5.5.3",
72
- "vitest": "~2.1.4"
72
+ "vitest": "~2.1.9"
73
73
  },
74
74
  "cozePublishConfig": {
75
75
  "exports": {