@tencentcloud/roomkit-electron-vue3 2.7.0 → 2.7.1
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/es/components/AITools/AISubtitles.vue.mjs +1 -1
- package/es/components/AITools/AISubtitles.vue2.mjs +18 -19
- package/es/components/AITools/AITranscription.vue.mjs +1 -1
- package/es/components/AITools/AITranscription.vue2.mjs +65 -76
- package/es/components/ManageMember/MemberControl/index.vue.mjs +1 -1
- package/es/components/ManageMember/MemberControl/index.vue2.mjs +6 -4
- package/es/components/ManageMember/MemberItemCommon/MemberInfo.vue.mjs +1 -1
- package/es/components/RoomFooter/BasicBeauty.vue.mjs +1 -1
- package/es/components/RoomFooter/BasicBeauty.vue2.mjs +3 -1
- package/es/components/RoomFooter/ChatControl.vue.mjs +2 -0
- package/es/components/ScheduleConference/ScheduleConferencePanel/index.vue2.mjs +1 -1
- package/es/components/ScheduleConference/ScheduleRoomControl.vue2.mjs +1 -1
- package/es/components/ScheduleConference/ScheduleRoomList.vue2.mjs +1 -1
- package/es/index.mjs +118 -110
- package/es/services/function/aiTask.d.ts +13 -17
- package/es/services/function/aiTask.mjs +63 -100
- package/es/services/manager/dataReportManager.d.ts +4 -1
- package/es/services/manager/dataReportManager.mjs +3 -0
- package/es/utils/utils.d.ts +2 -0
- package/es/utils/utils.mjs +33 -0
- package/lib/components/AITools/AISubtitles.vue.js +1 -1
- package/lib/components/AITools/AISubtitles.vue2.js +17 -18
- package/lib/components/AITools/AITranscription.vue.js +1 -1
- package/lib/components/AITools/AITranscription.vue2.js +64 -75
- package/lib/components/ManageMember/MemberControl/index.vue.js +1 -1
- package/lib/components/ManageMember/MemberControl/index.vue2.js +5 -3
- package/lib/components/ManageMember/MemberItemCommon/MemberInfo.vue.js +1 -1
- package/lib/components/RoomFooter/BasicBeauty.vue.js +1 -1
- package/lib/components/RoomFooter/BasicBeauty.vue2.js +3 -1
- package/lib/components/RoomFooter/ChatControl.vue.js +2 -0
- package/lib/components/ScheduleConference/ScheduleConferencePanel/index.vue2.js +1 -1
- package/lib/components/ScheduleConference/ScheduleRoomControl.vue2.js +1 -1
- package/lib/components/ScheduleConference/ScheduleRoomList.vue2.js +1 -1
- package/lib/index.js +118 -110
- package/lib/services/function/aiTask.d.ts +13 -17
- package/lib/services/function/aiTask.js +63 -100
- package/lib/services/manager/dataReportManager.d.ts +4 -1
- package/lib/services/manager/dataReportManager.js +3 -0
- package/lib/utils/utils.d.ts +2 -0
- package/lib/utils/utils.js +33 -0
- package/package.json +2 -2
- package/src/TUIRoom/components/AITools/AISubtitles.vue +26 -23
- package/src/TUIRoom/components/AITools/AITranscription.vue +106 -101
- package/src/TUIRoom/components/ManageMember/MemberControl/index.vue +8 -3
- package/src/TUIRoom/components/ManageMember/MemberItemCommon/MemberInfo.vue +1 -1
- package/src/TUIRoom/components/RoomFooter/BasicBeauty.vue +2 -1
- package/src/TUIRoom/components/RoomFooter/ChatControl.vue +2 -1
- package/src/TUIRoom/services/function/aiTask.ts +79 -113
- package/src/TUIRoom/services/manager/dataReportManager.ts +3 -0
- package/src/TUIRoom/utils/utils.ts +47 -0
|
@@ -108,7 +108,7 @@ import IconButton from '../common/base/IconButton.vue';
|
|
|
108
108
|
import SvgIcon from '../common/base/SvgIcon.vue';
|
|
109
109
|
import BasicBeautyIcon from '../common/icons/BasicBeautyIcon.vue';
|
|
110
110
|
import { useI18n } from '../../locales';
|
|
111
|
-
import { roomService } from '../../services';
|
|
111
|
+
import { roomService, MetricsKey } from '../../services';
|
|
112
112
|
import Dialog from '../common/base/Dialog/index.vue';
|
|
113
113
|
import TuiButton from '../common/base/Button.vue';
|
|
114
114
|
import Slider from '../common/base/Slider.vue';
|
|
@@ -197,6 +197,7 @@ const openBeautySettingPanel = async () => {
|
|
|
197
197
|
view: 'test-preview',
|
|
198
198
|
});
|
|
199
199
|
isLoading.value = false;
|
|
200
|
+
roomService.dataReportManager.reportCount(MetricsKey.setBasicBeauty);
|
|
200
201
|
};
|
|
201
202
|
|
|
202
203
|
const closeBeautySettingPanel = async () => {
|
|
@@ -23,7 +23,7 @@ import { useChatStore } from '../../stores/chat';
|
|
|
23
23
|
import { storeToRefs } from 'pinia';
|
|
24
24
|
import { useI18n } from '../../locales';
|
|
25
25
|
import TuiBadge from '../common/base/Badge.vue';
|
|
26
|
-
import { roomService } from '../../services';
|
|
26
|
+
import { roomService, MetricsKey } from '../../services';
|
|
27
27
|
const { t } = useI18n();
|
|
28
28
|
const chatControlConfig = roomService.getComponentConfig('ChatControl');
|
|
29
29
|
const basicStore = useBasicStore();
|
|
@@ -39,5 +39,6 @@ async function toggleChatSidebar() {
|
|
|
39
39
|
basicStore.setSidebarOpenStatus(true);
|
|
40
40
|
basicStore.setSidebarName('chat');
|
|
41
41
|
chatStore.updateUnReadCount(0);
|
|
42
|
+
roomService.dataReportManager.reportCount(MetricsKey.openChat);
|
|
42
43
|
}
|
|
43
44
|
</script>
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { IRoomService } from '../';
|
|
2
2
|
import mitt from 'mitt';
|
|
3
3
|
import { isElectron, isMobile } from '../../utils/environment';
|
|
4
|
+
import { findLastIndex } from '../../utils/utils';
|
|
4
5
|
|
|
5
|
-
interface SubtitleMessage {
|
|
6
|
-
|
|
6
|
+
export interface SubtitleMessage {
|
|
7
|
+
sender: string;
|
|
7
8
|
text: string;
|
|
8
|
-
|
|
9
|
+
translationText: string;
|
|
10
|
+
end?: boolean;
|
|
11
|
+
startMsTs: number;
|
|
9
12
|
}
|
|
13
|
+
|
|
10
14
|
interface DataPayload {
|
|
11
15
|
end: boolean;
|
|
12
16
|
text: string;
|
|
@@ -34,22 +38,23 @@ export enum AI_TASK {
|
|
|
34
38
|
|
|
35
39
|
export interface AITaskEvent {
|
|
36
40
|
[AI_TASK.TRANSCRIPTION_TASK]: {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
transcriptionText: { value: string };
|
|
41
|
+
subtitleMessages: { [key: string]: SubtitleMessage };
|
|
42
|
+
transcribedMessageList: SubtitleMessage[];
|
|
40
43
|
};
|
|
41
44
|
[key: string]: unknown;
|
|
42
45
|
[key: symbol]: unknown;
|
|
43
46
|
}
|
|
44
47
|
|
|
48
|
+
const ASR_EVENT_CODE = 10000;
|
|
49
|
+
|
|
45
50
|
export class AITask {
|
|
46
51
|
private emitter = mitt<AITaskEvent>();
|
|
47
|
-
|
|
48
52
|
private trtc: any;
|
|
49
53
|
private service: IRoomService;
|
|
50
|
-
public
|
|
51
|
-
public
|
|
52
|
-
|
|
54
|
+
public subtitleMessages: { [key: string]: SubtitleMessage } = {};
|
|
55
|
+
public transcribedMessageList: SubtitleMessage[] = [];
|
|
56
|
+
private subtitleTimeout: { [key: string]: ReturnType<typeof setTimeout> } =
|
|
57
|
+
{};
|
|
53
58
|
|
|
54
59
|
constructor(service: IRoomService) {
|
|
55
60
|
this.service = service;
|
|
@@ -95,14 +100,13 @@ export class AITask {
|
|
|
95
100
|
) {
|
|
96
101
|
return;
|
|
97
102
|
}
|
|
98
|
-
|
|
99
|
-
this.trtc
|
|
100
|
-
trtc.on('custom-message', this.handleAIMessage);
|
|
103
|
+
this.trtc = this.service.roomEngine.instance?.getTRTCCloud()._trtc;
|
|
104
|
+
this.trtc.on('custom-message', this.handleAIMessage);
|
|
101
105
|
}
|
|
106
|
+
|
|
102
107
|
private handleUnmount() {
|
|
103
|
-
this.
|
|
104
|
-
this.
|
|
105
|
-
this.transcriptionText.value = '';
|
|
108
|
+
this.subtitleMessages = {};
|
|
109
|
+
this.transcribedMessageList = [];
|
|
106
110
|
this.trtc?.off('custom-message', this.handleAIMessage);
|
|
107
111
|
}
|
|
108
112
|
|
|
@@ -111,122 +115,84 @@ export class AITask {
|
|
|
111
115
|
this.service.lifeCycleManager.on('unmount', this.handleUnmount);
|
|
112
116
|
}
|
|
113
117
|
|
|
114
|
-
|
|
118
|
+
private resetSubtitleTimeout(id: string, fn: () => void) {
|
|
119
|
+
if (this.subtitleTimeout[id]) {
|
|
120
|
+
clearTimeout(this.subtitleTimeout[id]);
|
|
121
|
+
}
|
|
122
|
+
this.subtitleTimeout[id] = setTimeout(fn, 3000);
|
|
123
|
+
}
|
|
124
|
+
|
|
115
125
|
private handleAIMessage(event: any) {
|
|
116
126
|
if (event.cmdId !== 1) return;
|
|
117
127
|
const data = new TextDecoder().decode(event.data);
|
|
118
128
|
const jsonData = JSON.parse(data);
|
|
119
129
|
this.handleMessage(jsonData);
|
|
120
130
|
this.emit(AI_TASK.TRANSCRIPTION_TASK, {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
subtitleMsg: this.subtitleMsg,
|
|
131
|
+
subtitleMessages: this.subtitleMessages,
|
|
132
|
+
transcribedMessageList: this.transcribedMessageList,
|
|
124
133
|
});
|
|
125
134
|
}
|
|
126
135
|
|
|
127
136
|
private handleMessage(data: MessageData): void {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
if (data.type !== ASR_EVENT_CODE) return;
|
|
138
|
+
const { sender, payload } = data;
|
|
139
|
+
const { end } = payload;
|
|
140
|
+
|
|
141
|
+
const createSubtitleMsg = () => {
|
|
142
|
+
return {
|
|
143
|
+
sender,
|
|
144
|
+
text: payload.text,
|
|
145
|
+
translationText: payload.translation_text,
|
|
146
|
+
startMsTs: data.start_ms_ts,
|
|
147
|
+
end,
|
|
148
|
+
};
|
|
137
149
|
};
|
|
138
150
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
this.subtitleMsg[i].text = data.payload.text;
|
|
145
|
-
this.subtitleMsg[i].translation_text = data.payload.translation_text;
|
|
146
|
-
exist = true;
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (!exist) {
|
|
151
|
-
this.subtitleMsg.push({
|
|
152
|
-
userid: data.sender,
|
|
153
|
-
text: data.payload.text,
|
|
154
|
-
translation_text: data.payload.translation_text,
|
|
155
|
-
});
|
|
156
|
-
}
|
|
151
|
+
const updateMsg = (msg: SubtitleMessage) => {
|
|
152
|
+
msg.text = payload.text;
|
|
153
|
+
msg.translationText = payload.translation_text;
|
|
154
|
+
msg.end = end;
|
|
155
|
+
};
|
|
157
156
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
157
|
+
const appendMsg = <T extends SubtitleMessage>(
|
|
158
|
+
msg: T,
|
|
159
|
+
target: T[] | Record<string, T>
|
|
160
|
+
) => {
|
|
161
|
+
if (Array.isArray(target)) {
|
|
162
|
+
target.push(msg);
|
|
163
|
+
} else if (typeof target === 'object') {
|
|
164
|
+
const recordTarget = target as Record<string, T>;
|
|
165
|
+
recordTarget[msg.sender] = msg;
|
|
166
|
+
} else {
|
|
167
|
+
throw new Error('Invalid target type');
|
|
169
168
|
}
|
|
170
|
-
|
|
171
|
-
// todo start_ms_ts end_ms_ts
|
|
169
|
+
};
|
|
172
170
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
this.
|
|
171
|
+
const existingSubtitle = this.subtitleMessages[sender];
|
|
172
|
+
if (existingSubtitle) {
|
|
173
|
+
updateMsg(existingSubtitle);
|
|
174
|
+
} else {
|
|
175
|
+
appendMsg(createSubtitleMsg(), this.subtitleMessages);
|
|
178
176
|
}
|
|
179
177
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (data.userid === this.subtitleMsg[i].userid) {
|
|
185
|
-
this.subtitleMsg[i].text = data.text;
|
|
186
|
-
this.subtitleMsg[i].translation_text = data.translation_text;
|
|
187
|
-
exist = true;
|
|
188
|
-
break;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
if (!exist) {
|
|
192
|
-
this.subtitleMsg.push({
|
|
193
|
-
userid: data.userid,
|
|
194
|
-
text: data.text,
|
|
195
|
-
translation_text: data.translation_text,
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
refreshSubtitle();
|
|
200
|
-
} else if (data.type === 'transcription') {
|
|
201
|
-
let index = 0;
|
|
202
|
-
for (let i = 0; i < this.subtitleMsg.length; i++) {
|
|
203
|
-
if (data.userid === this.subtitleMsg[i].userid) {
|
|
204
|
-
this.subtitleMsg[i].text = data.text;
|
|
205
|
-
this.subtitleMsg[i].translation_text = data.translation_text;
|
|
206
|
-
index = i;
|
|
207
|
-
break;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
refreshSubtitle();
|
|
178
|
+
const transcriptionIndex = findLastIndex(
|
|
179
|
+
this.transcribedMessageList,
|
|
180
|
+
msg => msg.sender === sender && !msg.end
|
|
181
|
+
);
|
|
211
182
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
this.transcriptionText.value += content;
|
|
183
|
+
if (transcriptionIndex !== -1) {
|
|
184
|
+
updateMsg(this.transcribedMessageList[transcriptionIndex]);
|
|
185
|
+
} else {
|
|
186
|
+
appendMsg(createSubtitleMsg(), this.transcribedMessageList);
|
|
217
187
|
}
|
|
218
|
-
}
|
|
219
188
|
|
|
220
|
-
|
|
221
|
-
|
|
189
|
+
this.resetSubtitleTimeout(sender, () => {
|
|
190
|
+
if (!end) return;
|
|
191
|
+
delete this.subtitleMessages[sender];
|
|
192
|
+
this.emit(AI_TASK.TRANSCRIPTION_TASK, {
|
|
193
|
+
subtitleMessages: this.subtitleMessages,
|
|
194
|
+
transcribedMessageList: this.transcribedMessageList,
|
|
195
|
+
});
|
|
196
|
+
});
|
|
222
197
|
}
|
|
223
198
|
}
|
|
224
|
-
|
|
225
|
-
// utils
|
|
226
|
-
function formatTimestampToTime(timestamp: number): string {
|
|
227
|
-
const date = new Date(timestamp);
|
|
228
|
-
const hours = date.getHours().toString().padStart(2, '0');
|
|
229
|
-
const minutes = date.getMinutes().toString().padStart(2, '0');
|
|
230
|
-
const seconds = date.getSeconds().toString().padStart(2, '0');
|
|
231
|
-
return `${hours}:${minutes}:${seconds}`;
|
|
232
|
-
}
|
|
@@ -221,3 +221,50 @@ export function getNanoId(size = 21) {
|
|
|
221
221
|
}
|
|
222
222
|
return id;
|
|
223
223
|
}
|
|
224
|
+
|
|
225
|
+
export function findLastIndex<T>(
|
|
226
|
+
array: T[],
|
|
227
|
+
predicate: (value: T, index: number, obj: T[]) => boolean,
|
|
228
|
+
thisArg?: any
|
|
229
|
+
): number {
|
|
230
|
+
const len = array.length >>> 0;
|
|
231
|
+
|
|
232
|
+
let k = len - 1;
|
|
233
|
+
while (k >= 0) {
|
|
234
|
+
const kValue = array[k];
|
|
235
|
+
if (predicate.call(thisArg, kValue, k, array)) {
|
|
236
|
+
return k;
|
|
237
|
+
}
|
|
238
|
+
k = k - 1;
|
|
239
|
+
}
|
|
240
|
+
return -1;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function formatTimestampToTime(
|
|
244
|
+
timestamp: number,
|
|
245
|
+
format = 'MM-DD HH:mm'
|
|
246
|
+
): string {
|
|
247
|
+
const date = new Date(timestamp);
|
|
248
|
+
const padStart = (value: number, length = 2) =>
|
|
249
|
+
value.toString().padStart(length, '0');
|
|
250
|
+
|
|
251
|
+
const replacements: { [key: string]: string } = {
|
|
252
|
+
YYYY: date.getFullYear().toString(),
|
|
253
|
+
YY: (date.getFullYear() % 100).toString().padStart(2, '0'),
|
|
254
|
+
MM: padStart(date.getMonth() + 1),
|
|
255
|
+
DD: padStart(date.getDate()),
|
|
256
|
+
HH: padStart(date.getHours()),
|
|
257
|
+
hh: padStart(date.getHours() % 12),
|
|
258
|
+
mm: padStart(date.getMinutes()),
|
|
259
|
+
ss: padStart(date.getSeconds()),
|
|
260
|
+
A: date.getHours() >= 12 ? 'PM' : 'AM',
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// console.log(formatTimestampToTime(Date.now())); // "10-24 16:20"
|
|
264
|
+
// console.log(formatTimestampToTime(Date.now(), 'YYYY-MM-DD HH:mm:ss')); // "2024-10-24 16:20:30"
|
|
265
|
+
// console.log(formatTimestampToTime(Date.now(), 'MM-DD hh:mm A')); // "10-24 04:20 PM"
|
|
266
|
+
return format.replace(
|
|
267
|
+
/YYYY|YY|MM|DD|HH|hh|mm|ss|A/g,
|
|
268
|
+
match => replacements[match]
|
|
269
|
+
);
|
|
270
|
+
}
|