agora-appbuilder-core 4.1.12 → 4.1.13-beta.2
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/package.json +1 -1
- package/template/defaultConfig.js +2 -2
- package/template/src/assets/font-styles.css +4 -0
- package/template/src/assets/fonts/icomoon.ttf +0 -0
- package/template/src/assets/selection.json +1 -1
- package/template/src/atoms/ActionMenu.tsx +1 -1
- package/template/src/atoms/CustomIcon.tsx +1 -0
- package/template/src/atoms/Popup.tsx +1 -1
- package/template/src/components/Controls.tsx +21 -32
- package/template/src/language/default-labels/videoCallScreenLabels.ts +9 -9
- package/template/src/pages/VideoCall.tsx +2 -1
- package/template/src/pages/video-call/ActionSheetContent.tsx +0 -7
- package/template/src/pages/video-call/SidePanelHeader.tsx +80 -63
- package/template/src/rtm-events/constants.ts +9 -0
- package/template/src/subComponents/caption/Caption.tsx +4 -20
- package/template/src/subComponents/caption/CaptionContainer.tsx +262 -250
- package/template/src/subComponents/caption/CaptionIcon.tsx +6 -4
- package/template/src/subComponents/caption/CaptionText.tsx +26 -20
- package/template/src/subComponents/caption/LanguageSelectorPopup.tsx +30 -142
- package/template/src/subComponents/caption/Transcript.tsx +77 -32
- package/template/src/subComponents/caption/TranscriptIcon.tsx +7 -6
- package/template/src/subComponents/caption/TranslateActionMenu.tsx +128 -0
- package/template/src/subComponents/caption/useCaption.tsx +629 -482
- package/template/src/subComponents/caption/useSTTAPI.tsx +25 -4
- package/template/src/subComponents/caption/useStreamMessageUtils.native.ts +1 -1
- package/template/src/subComponents/caption/useStreamMessageUtils.ts +1 -1
- package/template/src/subComponents/caption/utils.ts +48 -40
|
@@ -36,6 +36,26 @@ const useSTTAPI = (): IuseSTTAPI => {
|
|
|
36
36
|
const STT_API_URL = `${$config.BACKEND_ENDPOINT}/v1/stt`;
|
|
37
37
|
const localUid = useLocalUid();
|
|
38
38
|
|
|
39
|
+
const roomIdRef = React.useRef(roomId);
|
|
40
|
+
React.useEffect(() => {
|
|
41
|
+
roomIdRef.current = roomId;
|
|
42
|
+
}, [roomId]);
|
|
43
|
+
|
|
44
|
+
const localUidRef = React.useRef(localUid);
|
|
45
|
+
React.useEffect(() => {
|
|
46
|
+
localUidRef.current = localUid;
|
|
47
|
+
}, [localUid]);
|
|
48
|
+
|
|
49
|
+
const tokenRef = React.useRef(store.token);
|
|
50
|
+
React.useEffect(() => {
|
|
51
|
+
tokenRef.current = store.token;
|
|
52
|
+
}, [store.token]);
|
|
53
|
+
|
|
54
|
+
const rtcPropsRef = React.useRef(rtcProps);
|
|
55
|
+
React.useEffect(() => {
|
|
56
|
+
rtcPropsRef.current = rtcProps;
|
|
57
|
+
}, [rtcProps]);
|
|
58
|
+
|
|
39
59
|
const apiCall = async (
|
|
40
60
|
method: 'startv7' | 'update' | 'stopv7',
|
|
41
61
|
botUid: number,
|
|
@@ -49,10 +69,11 @@ const useSTTAPI = (): IuseSTTAPI => {
|
|
|
49
69
|
const ownerUid = botUid - 900000000;
|
|
50
70
|
|
|
51
71
|
let requestBody: any = {
|
|
52
|
-
passphrase:
|
|
72
|
+
passphrase:
|
|
73
|
+
roomIdRef?.current?.host || roomIdRef?.current?.attendee || '',
|
|
53
74
|
dataStream_uid: botUid,
|
|
54
75
|
encryption_mode: $config.ENCRYPTION_ENABLED
|
|
55
|
-
?
|
|
76
|
+
? rtcPropsRef?.current.encryption.mode
|
|
56
77
|
: null,
|
|
57
78
|
};
|
|
58
79
|
|
|
@@ -89,14 +110,14 @@ const useSTTAPI = (): IuseSTTAPI => {
|
|
|
89
110
|
// If method is update and no targets are passed
|
|
90
111
|
requestBody.translate = false;
|
|
91
112
|
}
|
|
92
|
-
requestBody.subscribeAudioUids = [`${
|
|
113
|
+
requestBody.subscribeAudioUids = [`${localUidRef.current}`];
|
|
93
114
|
}
|
|
94
115
|
|
|
95
116
|
const response = await fetch(`${STT_API_URL}/${method}`, {
|
|
96
117
|
method: 'POST',
|
|
97
118
|
headers: {
|
|
98
119
|
'Content-Type': 'application/json',
|
|
99
|
-
authorization:
|
|
120
|
+
authorization: tokenRef?.current ? `Bearer ${tokenRef?.current}` : '',
|
|
100
121
|
'X-Request-Id': requestId,
|
|
101
122
|
'X-Session-Id': logger.getSessionId(),
|
|
102
123
|
},
|
|
@@ -50,7 +50,7 @@ const useStreamMessageUtils = (): {
|
|
|
50
50
|
.lookupType('agora.audio2text.Text')
|
|
51
51
|
.decode(payload as Uint8Array) as any;
|
|
52
52
|
|
|
53
|
-
console.log('[
|
|
53
|
+
console.log('[STT_GLOBAL] stt v7 textstream', botUid, textstream);
|
|
54
54
|
// console.log('STT - Parsed Textstream : ', textstream);
|
|
55
55
|
|
|
56
56
|
// Identifing Current & Prev Speakers for the Captions
|
|
@@ -52,7 +52,7 @@ const useStreamMessageUtils = (): {
|
|
|
52
52
|
.lookupType('agora.audio2text.Text')
|
|
53
53
|
.decode(payload as Uint8Array) as any;
|
|
54
54
|
|
|
55
|
-
console.log('[
|
|
55
|
+
console.log('[STT_GLOBAL] stt v7 textstream', botUid, textstream);
|
|
56
56
|
//console.log('STT - Parsed Textstream : ', textstream);
|
|
57
57
|
// console.log(
|
|
58
58
|
// `STT-callback(${++counter}): %c${textstream.uid} %c${textstream.words
|
|
@@ -110,7 +110,7 @@ export function getLanguageLabel(
|
|
|
110
110
|
languageCode: LanguageType[],
|
|
111
111
|
): string | undefined {
|
|
112
112
|
const langLabels = languageCode.map(langCode => {
|
|
113
|
-
return langData.find(data => data.value === langCode)
|
|
113
|
+
return langData.find(data => data.value === langCode)?.label;
|
|
114
114
|
});
|
|
115
115
|
return langLabels ? langLabels.join(', ') : undefined;
|
|
116
116
|
}
|
|
@@ -163,31 +163,32 @@ export const formatTranscriptContent = (
|
|
|
163
163
|
const formattedContent = meetingTranscript
|
|
164
164
|
.map(item => {
|
|
165
165
|
if (
|
|
166
|
-
item.uid.toString().
|
|
167
|
-
item.uid.toString().
|
|
166
|
+
item.uid.toString().includes('langUpdate') ||
|
|
167
|
+
item.uid.toString().includes('translationUpdate')
|
|
168
168
|
) {
|
|
169
|
-
return `${defaultContent[item?.uid?.split('-')[1]]?.name} ${item.text}`;
|
|
169
|
+
// return `${defaultContent[item?.uid?.split('-')[1]]?.name} ${item.text}`;
|
|
170
|
+
return item.text;
|
|
170
171
|
}
|
|
171
172
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
.
|
|
186
|
-
|
|
187
|
-
|
|
173
|
+
const speakerName = defaultContent[item.uid]?.name || 'Speaker';
|
|
174
|
+
|
|
175
|
+
// Original
|
|
176
|
+
let entry = `${speakerName}:\n${item.text}`;
|
|
177
|
+
|
|
178
|
+
// Selected Translation
|
|
179
|
+
const storedLang = item.selectedTranslationLanguage;
|
|
180
|
+
const selectedTranslation = storedLang
|
|
181
|
+
? item.translations?.find(t => t.lang === storedLang) || null
|
|
182
|
+
: null;
|
|
183
|
+
if (selectedTranslation) {
|
|
184
|
+
const langLabel =
|
|
185
|
+
langData.find(l => l.value === selectedTranslation.lang)?.label ||
|
|
186
|
+
selectedTranslation.lang;
|
|
187
|
+
|
|
188
|
+
entry += `\n→ (${langLabel}) ${selectedTranslation.text}`;
|
|
188
189
|
}
|
|
189
190
|
|
|
190
|
-
return
|
|
191
|
+
return entry;
|
|
191
192
|
})
|
|
192
193
|
.join('\n\n');
|
|
193
194
|
|
|
@@ -196,13 +197,20 @@ export const formatTranscriptContent = (
|
|
|
196
197
|
);
|
|
197
198
|
|
|
198
199
|
const attendees = Object.entries(defaultContent)
|
|
199
|
-
.filter(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
200
|
+
.filter(([uid, user]) => {
|
|
201
|
+
const uidNum = Number(uid);
|
|
202
|
+
|
|
203
|
+
const isBot =
|
|
204
|
+
uidNum === 111111 || // STT bot (web)
|
|
205
|
+
uidNum > 900000000 || // STT bots (native)
|
|
206
|
+
uidNum === 100000 || // Recording bot (web user)
|
|
207
|
+
uidNum === 100001; // Recording bot (web screen)
|
|
208
|
+
|
|
209
|
+
const isWaitingRoom = user?.isInWaitingRoom === true;
|
|
210
|
+
|
|
211
|
+
return user.type === 'rtc' && !isBot && !isWaitingRoom;
|
|
212
|
+
})
|
|
213
|
+
.map(([_, user]) => user.name)
|
|
206
214
|
.join(',');
|
|
207
215
|
|
|
208
216
|
const info =
|
|
@@ -232,19 +240,18 @@ export const formatTranscriptContent = (
|
|
|
232
240
|
* @param captionText - The original caption text
|
|
233
241
|
* @param translations - Array of available translations
|
|
234
242
|
* @param viewerSourceLanguage - The user's source (spoken) language
|
|
235
|
-
* @param speakerUid - The UID of the person speaking
|
|
236
|
-
* @param currentUserUid - The UID of the current user
|
|
237
243
|
* @returns The appropriate caption text to display
|
|
238
244
|
*/
|
|
239
245
|
export const getUserTranslatedText = (
|
|
240
246
|
captionText: string,
|
|
241
247
|
translations: Array<{lang: string; text: string; isFinal: boolean}> = [],
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
248
|
+
sourceLanguage: LanguageType,
|
|
249
|
+
selectedTranslationLanguage: LanguageType,
|
|
250
|
+
// speakerUid: string | number,
|
|
251
|
+
// currentUserUid: string | number,
|
|
245
252
|
): {
|
|
246
253
|
value: string;
|
|
247
|
-
|
|
254
|
+
langLabel: string;
|
|
248
255
|
} => {
|
|
249
256
|
// console.log(
|
|
250
257
|
// 'getUserTranslatedText input params',
|
|
@@ -256,16 +263,17 @@ export const getUserTranslatedText = (
|
|
|
256
263
|
// );
|
|
257
264
|
|
|
258
265
|
// 1. If the speaker is the local user, always show their own source text
|
|
259
|
-
if (
|
|
266
|
+
if (!selectedTranslationLanguage) {
|
|
260
267
|
return {
|
|
261
268
|
value: captionText,
|
|
262
|
-
|
|
269
|
+
langLabel: getLanguageLabel([sourceLanguage]) || '',
|
|
263
270
|
};
|
|
264
271
|
}
|
|
272
|
+
|
|
265
273
|
// For other users' captions, try to find translation matching viewer's source language
|
|
266
|
-
if (
|
|
274
|
+
if (selectedTranslationLanguage && translations && translations.length > 0) {
|
|
267
275
|
const matchingTranslation = translations.find(
|
|
268
|
-
t => t.lang ===
|
|
276
|
+
t => t.lang === selectedTranslationLanguage,
|
|
269
277
|
);
|
|
270
278
|
if (matchingTranslation) {
|
|
271
279
|
// Translation exists (even if empty)
|
|
@@ -274,7 +282,7 @@ export const getUserTranslatedText = (
|
|
|
274
282
|
const translatedText = matchingTranslation.text?.trim() || '';
|
|
275
283
|
return {
|
|
276
284
|
value: translatedText,
|
|
277
|
-
|
|
285
|
+
langLabel: getLanguageLabel([selectedTranslationLanguage]) || '',
|
|
278
286
|
};
|
|
279
287
|
}
|
|
280
288
|
}
|
|
@@ -282,7 +290,7 @@ export const getUserTranslatedText = (
|
|
|
282
290
|
// Fallback to original text if no translation found
|
|
283
291
|
return {
|
|
284
292
|
value: captionText,
|
|
285
|
-
|
|
293
|
+
langLabel: 'Original',
|
|
286
294
|
};
|
|
287
295
|
};
|
|
288
296
|
|