Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
eab3df7
Update pushSpeechTranscript.js
hiroshisuga May 28, 2023
ca55fc2
Update startDictation.js
hiroshisuga May 28, 2023
c29c304
Update stopDictation.js
hiroshisuga May 28, 2023
9965c43
Update createCaptions.js
hiroshisuga May 28, 2023
03d06f7
Update updateCaptionsOwner.js
hiroshisuga May 28, 2023
cc82223
Update component.jsx
hiroshisuga May 28, 2023
9f4e84f
Update container.jsx
hiroshisuga May 28, 2023
d6fd312
Update component.jsx
hiroshisuga May 28, 2023
4711513
Update container.jsx
hiroshisuga May 28, 2023
f421853
Update component.jsx
hiroshisuga May 28, 2023
9dc5f71
Update container.jsx
hiroshisuga May 28, 2023
c0bbd9b
Update service.js
hiroshisuga May 28, 2023
b46fd12
Update component.jsx
hiroshisuga May 28, 2023
2b57a61
Update service.js
hiroshisuga May 28, 2023
a9f6805
Update styles.js
hiroshisuga May 28, 2023
715b145
Update container.jsx
hiroshisuga May 28, 2023
b5084f0
Update component.jsx
hiroshisuga May 28, 2023
e88a063
Update component.jsx
hiroshisuga May 28, 2023
29077de
Update component.jsx
hiroshisuga May 28, 2023
2af5ba2
Update container.jsx
hiroshisuga May 28, 2023
1eb7f78
Update settings.yml
hiroshisuga May 28, 2023
7fbbffe
Update en.json
hiroshisuga May 28, 2023
a61021d
Update methods.js
hiroshisuga May 28, 2023
06b15ac
Create enableAutoTranslation.js
hiroshisuga May 28, 2023
073f0fe
Create disableAutoTranslation.js
hiroshisuga May 28, 2023
485199f
Update disableAutoTranslation.js
hiroshisuga May 28, 2023
f5133f1
Update enableAutoTranslation.js
hiroshisuga May 28, 2023
6ee3414
Create setAutoTranslation.js
hiroshisuga May 28, 2023
1d692e9
Update disableAutoTranslation.js
hiroshisuga May 28, 2023
0c1dad1
Update enableAutoTranslation.js
hiroshisuga May 28, 2023
7e75ff1
Update component.jsx
hiroshisuga May 28, 2023
75cfb51
Update component.jsx
hiroshisuga May 28, 2023
bd69628
Update service.js
hiroshisuga May 28, 2023
4502f61
Update pushSpeechTranscript.js
hiroshisuga May 28, 2023
97b3444
Update component.jsx
hiroshisuga May 28, 2023
80a8a61
Update component.jsx
hiroshisuga May 28, 2023
5c60ea7
Update component.jsx
hiroshisuga May 28, 2023
0790250
Update package.json
hiroshisuga May 28, 2023
c7d62a4
Update service.js
hiroshisuga May 28, 2023
41e77f6
Update component.jsx
hiroshisuga May 28, 2023
4cf3c8a
Update service.js
hiroshisuga May 28, 2023
ee77ad6
Update component.jsx
hiroshisuga May 28, 2023
1398989
bug for optional array
hiroshisuga May 29, 2023
8a6f6b2
remove enableAutoTranslation
hiroshisuga May 29, 2023
7695daa
Update disableAutoTranslation.js
hiroshisuga May 29, 2023
30be0ec
Update enableAutoTranslation.js
hiroshisuga May 29, 2023
2c78725
Update setAutoTranslation.js
hiroshisuga May 29, 2023
ed0b492
add react-select in package-lock.json
hiroshisuga May 29, 2023
f619ccd
some bug fixed
hiroshisuga May 30, 2023
45a2cce
modify comment but not sure
hiroshisuga May 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions bigbluebutton-html5/imports/api/captions/server/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import updateCaptionsOwner from '/imports/api/captions/server/methods/updateCapt
import startDictation from '/imports/api/captions/server/methods/startDictation';
import stopDictation from '/imports/api/captions/server/methods/stopDictation';
import pushSpeechTranscript from '/imports/api/captions/server/methods/pushSpeechTranscript';
import enableAutoTranslation from '/imports/api/captions/server/methods/enableAutoTranslation';
import disableAutoTranslation from '/imports/api/captions/server/methods/disableAutoTranslation';

Meteor.methods({
updateCaptionsOwner,
startDictation,
stopDictation,
pushSpeechTranscript,
enableAutoTranslation,
disableAutoTranslation,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//Do we need this? It just modifies an entry of Captions -> seems yes
import { check } from 'meteor/check';
import { extractCredentials } from '/imports/api/common/server/helpers';
import Logger from '/imports/startup/server/logger';
import setAutoTranslation from '/imports/api/captions/server/modifiers/setAutoTranslation';

export default function disableAutoTranslation(locale) {
try {
const { meetingId, requesterUserId } = extractCredentials(this.userId);

check(locale, String);
check(meetingId, String);
check(requesterUserId, String);

//const caption = Captions.findOne({ meetingId, locale }, { fields: { translating:1 } });
setAutoTranslation(meetingId, locale, false);
} catch (err) {
Logger.error(`Exception while invoking method disbleAutoTranslation ${err.stack}`);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//Do we need this? It just modifies an entry of Captions -> seems yes
import { check } from 'meteor/check';
import { extractCredentials } from '/imports/api/common/server/helpers';
import Logger from '/imports/startup/server/logger';
import setAutoTranslation from '/imports/api/captions/server/modifiers/setAutoTranslation';

export default function enableAutoTranslation(locale) {
try {
const { meetingId, requesterUserId } = extractCredentials(this.userId);

check(locale, String);
check(meetingId, String);
check(requesterUserId, String);

//const caption = Captions.findOne({ meetingId, locale }, { fields: { translating:1 } });
setAutoTranslation(meetingId, locale, true);
} catch (err) {
Logger.error(`Exception while invoking method enableAutoTranslation ${err.stack}`);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,67 @@
import { check } from 'meteor/check';
import Captions from '/imports/api/captions';
import Users from '/imports/api/users';
import { extractCredentials } from '/imports/api/common/server/helpers';
import Logger from '/imports/startup/server/logger';
import setTranscript from '/imports/api/captions/server/modifiers/setTranscript';
import updatePad from '/imports/api/pads/server/methods/updatePad';
import axios from 'axios';

export default function pushSpeechTranscript(locale, transcript, type) {
const CAPTIONS_CONFIG = Meteor.settings.public.captions;

function sendTranscript(meetingId, requesterUserId, type, dst, text) {
const user = Users.findOne({meetingId, userId: requesterUserId}, { fields: {name: 1}});
//console.log("sendTranscript", text);
const textWithName = `${user.name}: ${text}`;
if (type === 'final') {
const textLf = `\n${textWithName}`;
updatePad(meetingId, requesterUserId, dst, textLf);
}
setTranscript(meetingId, dst, textWithName);
}

function translateText(meetingId, requesterUserId, textOri, type, src, dst) {
if ( !CAPTIONS_CONFIG.enableAutomaticTranslation || textOri === "" || !dst || dst === "" || dst === src || dst.replace(/-..$/,'') === src || dst === src.replace(/-..$/,'') ) {
sendTranscript(meetingId, requesterUserId, type, dst, textOri);
} else {
let url = '';
if (CAPTIONS_CONFIG.googleTranslateUrl) {
url = CAPTIONS_CONFIG.googleTranslateUrl + '/exec?' +
'text=' + encodeURIComponent(textOri) + '&source=' + src + '&target=' + dst;
} else if (CAPTIONS_CONFIG.deeplTranslateUrl) {
url = CAPTIONS_CONFIG.deeplTranslateUrl +
'&text=' + encodeURIComponent(textOri) + '&source_lang=' + src.replace(/-..$/,'').toUpperCase() +
'&target_lang=' + dst.toUpperCase();
} else {
Logger.error('Could not get a translation service.');
return;
}

axios({
method: 'get',
url,
responseType: 'json',
}).then((response) => {
if (CAPTIONS_CONFIG.googleTranslateUrl) {
const { code, text } = response.data;
if (code === 200) {
sendTranscript(meetingId, requesterUserId, type, dst, text);
} else {
Logger.error(`Failed to get Google translation for ${textOri}`);
}
} else if (CAPTIONS_CONFIG.deeplTranslateUrl) {
const { translations } = response.data;
if (translations.length > 0 && translations[0].text) {
sendTranscript(meetingId, requesterUserId, type, dst, translations[0].text);
} else {
Logger.error(`Failed to get DeepL translation for ${textOri}`);
}
}
}).catch((error) => Logger.error(`Could not get translation for ${textOri.trim()} on the locale ${dst}: ${error}`));
}
}

export default function pushSpeechTranscript(locale, transcript, type, locales) {
try {
const { meetingId, requesterUserId } = extractCredentials(this.userId);

Expand All @@ -14,22 +70,20 @@ export default function pushSpeechTranscript(locale, transcript, type) {
check(locale, String);
check(transcript, String);
check(type, String);
check(locales, Array);

const captions = Captions.findOne({
meetingId,
ownerId: requesterUserId,
locale,
dictating: true,
});
locales.forEach(function(dstLocale, index) {
const caption = Captions.findOne({
meetingId,
locale: dstLocale,
});

if (captions) {
if (type === 'final') {
const text = `\n${transcript}`;
updatePad(meetingId, requesterUserId, locale, text);
if (!caption) {
Logger.error(`Could not find the caption's pad for meetingId=${meetingId} locale=${locale}`);
} else {
translateText(meetingId, requesterUserId, transcript, type, locale, dstLocale);
}

setTranscript(meetingId, locale, transcript);
}
});
} catch (err) {
Logger.error(`Exception while invoking method pushSpeechTranscript ${err.stack}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export default function startDictation(locale) {

const captions = Captions.findOne({
meetingId,
ownerId: requesterUserId,
locale,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export default function stopDictation(locale) {

const captions = Captions.findOne({
meetingId,
ownerId: requesterUserId,
locale,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export default function createCaptions(meetingId, locale, name) {
ownerId: '',
dictating: false,
transcript: '',
translating: false,
translationDoner: {},
speechDoner: {},
};

const numberAffected = Captions.upsert(selector, modifier);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//Do we need this? It just sets "translating" -> seems yes
import Captions from '/imports/api/captions';
import Logger from '/imports/startup/server/logger';
import { check } from 'meteor/check';

export default function setAutoTranslation(meetingId, locale, translating) {
check(meetingId, String);
check(locale, String);
check(translating, Boolean);

const selector = {
meetingId,
locale,
};

const modifier = {
$set: {
translating,
}
};

try {
const numberAffected = Captions.update(selector, modifier);

if (numberAffected) {
Logger.verbose('Captions: updated pad autoTranslation', { locale });
}
} catch (err) {
Logger.error(`Updating captions pad autoTranslation: ${err}`);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export default function updateCaptionsOwner(meetingId, locale, ownerId) {
const modifier = {
$set: {
ownerId,
dictating: false, // Refresh dictation mode
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ import React from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
import Styled from './styles';
import ButtonEmoji from '/imports/ui/components/common/button/button-emoji/ButtonEmoji';
import _ from 'lodash';
import Dropdown from '/imports/ui/components/dropdown/component';
import DropdownTrigger from '/imports/ui/components/dropdown/trigger/component';
import DropdownContent from '/imports/ui/components/dropdown/content/component';
import DropdownList from '/imports/ui/components/dropdown/list/component';
import DropdownListItem from '/imports/ui/components/dropdown/list/item/component';
import Service from '/imports/ui/components/captions/service';

const propTypes = {
intl: PropTypes.shape({
Expand All @@ -20,20 +28,61 @@ const intlMessages = defineMessages({
id: 'app.actionsBar.captions.stop',
description: 'Stop closed captions option',
},
changeCaption: {
id: 'app.actionsBar.changeCaption',
description: 'Open change caption label',
},
});

const CaptionsButton = ({ intl, isActive, handleOnClick }) => (
<Styled.CaptionsButton
icon="closed_caption"
label={intl.formatMessage(isActive ? intlMessages.stop : intlMessages.start)}
color={isActive ? 'primary' : 'default'}
ghost={!isActive}
hideLabel
circle
size="lg"
onClick={handleOnClick}
id={isActive ? 'stop-captions-button' : 'start-captions-button'}
/>
const handleClickCaption = (locale, selectedLocale) => {
if (selectedLocale != locale) {
Service.setCaptionsActive(locale);
}
}

const getAvailableCaptions = (captions, selected) => {
return(
captions.map(locale => (
<DropdownListItem
label={locale.name}
key={_.uniqueId('locale-selector')}
onClick={() => handleClickCaption(locale.locale, selected)}
iconRight={selected == locale.locale ? 'check' : null}
/>
))
);
};

const CaptionsButton = ({ intl, isActive, handleOnClick, translatedLocales, selectedLocale }) => (
<div>
<Styled.CaptionsButton
icon="closed_caption"
label={intl.formatMessage(isActive ? intlMessages.stop : intlMessages.start)}
color={isActive ? 'primary' : 'default'}
ghost={!isActive}
hideLabel
circle
size="lg"
onClick={handleOnClick}
id={isActive ? 'stop-captions-button' : 'start-captions-button'}
/>
{isActive &&
<Dropdown>
<DropdownTrigger tabIndex={0}>
<ButtonEmoji
emoji="device_list_selector"
hideLabel
label={intl.formatMessage(intlMessages.changeCaption)}
/>
</DropdownTrigger>
<DropdownContent placement="top left">
<DropdownList>
{getAvailableCaptions(translatedLocales, selectedLocale)}
</DropdownList>
</DropdownContent>
</Dropdown>
}
</div>
);

CaptionsButton.propTypes = propTypes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ export default withModalMounter(withTracker(({ mountModal }) => ({
handleOnClick: () => (Service.isCaptionsActive()
? Service.deactivateCaptions()
: mountModal(<CaptionsReaderMenuContainer />)),
translatedLocales: Service.getLocalesAutoTranslated(),
selectedLocale: Service.getCaptionsActive(),
}))(Container));
Loading