Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transcription improvements #14221

Merged
merged 6 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions lang/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -1360,6 +1360,7 @@
"failedToStart": "Transcribing failed to start",
"labelToolTip": "The meeting is being transcribed",
"off": "Transcribing stopped",
"on": "Transcribing started",
"pending": "Preparing to transcribe the meeting...",
"sourceLanguageDesc": "Currently the meeting language is set to <b>{{sourceLanguage}}</b>. <br/> You can change it from ",
"sourceLanguageHere": "here",
Expand Down
13 changes: 13 additions & 0 deletions modules/API/API.js
Original file line number Diff line number Diff line change
Expand Up @@ -1975,6 +1975,19 @@ class API {
});
}

/**
* Notify external application (if API is enabled) that transcribing has started or stopped.
*
* @param {boolean} on - True if transcribing is on, false otherwise.
* @returns {void}
*/
notifyTranscribingStatusChanged(on) {
this._sendEvent({
name: 'transcribing-status-changed',
on
});
}

/**
* Notify external application (if API is enabled) that the user received
* a transcription chunk.
Expand Down
1 change: 1 addition & 0 deletions modules/API/external/external_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ const events = {
'suspend-detected': 'suspendDetected',
'tile-view-changed': 'tileViewChanged',
'toolbar-button-clicked': 'toolbarButtonClicked',
'transcribing-status-changed': 'transcribingStatusChanged',
'transcription-chunk-received': 'transcriptionChunkReceived',
'whiteboard-status-changed': 'whiteboardStatusChanged'
};
Expand Down
7 changes: 7 additions & 0 deletions react/features/notifications/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,10 @@ export const SILENT_JOIN_THRESHOLD = 30;
* Amount of participants beyond which no left notification will be emitted.
*/
export const SILENT_LEFT_THRESHOLD = 30;

/**
* The identifier for the transcriber notifications.
*
* @type {string}
*/
export const TRANSCRIBING_NOTIFICATION_ID = 'TRANSCRIBING_NOTIFICATION';
14 changes: 0 additions & 14 deletions react/features/transcribing/actionTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,3 @@ export const _TRANSCRIBER_LEFT = 'TRANSCRIBER_LEFT';
*/
export const _POTENTIAL_TRANSCRIBER_JOINED
= 'POTENTIAL_TRANSCRIBER_JOINED';

/**
* The type of Redux action which sets the pending transcribing notification UID
* to use it for when hiding the notification is necessary, or unsets it when
* undefined (or no param) is passed.
*
* {
* type: SET_PENDING_TRANSCRIBING_NOTIFICATION_UID,
* uid: ?number
* }
* @public
*/
export const SET_PENDING_TRANSCRIBING_NOTIFICATION_UID
= 'SET_PENDING_TRANSCRIBING_NOTIFICATION_UID';
69 changes: 23 additions & 46 deletions react/features/transcribing/actions.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { IStore } from '../app/types';
import { hideNotification, showErrorNotification, showNotification } from '../notifications/actions';
import { NOTIFICATION_TIMEOUT_TYPE } from '../notifications/constants';
import { showErrorNotification, showNotification } from '../notifications/actions';
import {
NOTIFICATION_TIMEOUT_TYPE,
TRANSCRIBING_NOTIFICATION_ID
} from '../notifications/constants';

import {
SET_PENDING_TRANSCRIBING_NOTIFICATION_UID,
_POTENTIAL_TRANSCRIBER_JOINED,
_TRANSCRIBER_JOINED,
_TRANSCRIBER_LEFT
Expand Down Expand Up @@ -61,54 +62,28 @@ export function potentialTranscriberJoined(participantId: string) {
* Signals that the pending transcribing notification should be shown on the
* screen.
*
* @returns {Function}
* @returns {showNotification}
*/
export function showPendingTranscribingNotification() {
return async (dispatch: IStore['dispatch']) => {
const notification = await dispatch(showNotification({
descriptionKey: 'transcribing.pending',
titleKey: 'dialog.transcribing'
}, NOTIFICATION_TIMEOUT_TYPE.LONG));

if (notification) {
dispatch(setPendingTranscribingNotificationUid(notification.uid));
}
};
}

/**
* Sets UID of the the pending transcribing notification to use it when hiding
* the notification is necessary, or unsets it when undefined (or no param) is
* passed.
*
* @param {?number} uid - The UID of the notification.
* @returns {{
* type: SET_PENDING_TRANSCRIBING_NOTIFICATION_UID,
* uid: number
* }}
*/
export function setPendingTranscribingNotificationUid(uid?: string) {
return {
type: SET_PENDING_TRANSCRIBING_NOTIFICATION_UID,
uid
};
return showNotification({
descriptionKey: 'transcribing.pending',
titleKey: 'dialog.transcribing',
uid: TRANSCRIBING_NOTIFICATION_ID
}, NOTIFICATION_TIMEOUT_TYPE.LONG);
}

/**
* Signals that the pending transcribing notification should be removed from the
* Signals that the started transcribing notification should be shown on the
* screen.
*
* @returns {Function}
* @returns {showNotification}
*/
export function hidePendingTranscribingNotification() {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
const { pendingNotificationUid } = getState()['features/transcribing'];

if (pendingNotificationUid) {
dispatch(hideNotification(pendingNotificationUid));
dispatch(setPendingTranscribingNotificationUid());
}
};
export function showStartedTranscribingNotification() {
return showNotification({
descriptionKey: 'transcribing.on',
titleKey: 'dialog.transcribing',
uid: TRANSCRIBING_NOTIFICATION_ID
}, NOTIFICATION_TIMEOUT_TYPE.SHORT);
}

/**
Expand All @@ -120,7 +95,8 @@ export function hidePendingTranscribingNotification() {
export function showStoppedTranscribingNotification() {
return showNotification({
descriptionKey: 'transcribing.off',
titleKey: 'dialog.transcribing'
titleKey: 'dialog.transcribing',
uid: TRANSCRIBING_NOTIFICATION_ID
}, NOTIFICATION_TIMEOUT_TYPE.SHORT);
}

Expand All @@ -133,6 +109,7 @@ export function showStoppedTranscribingNotification() {
export function showTranscribingError() {
return showErrorNotification({
descriptionKey: 'transcribing.error',
titleKey: 'transcribing.failedToStart'
titleKey: 'transcribing.failedToStart',
uid: TRANSCRIBING_NOTIFICATION_ID
}, NOTIFICATION_TIMEOUT_TYPE.LONG);
}
74 changes: 47 additions & 27 deletions react/features/transcribing/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { batch } from 'react-redux';

import {
HIDDEN_PARTICIPANT_JOINED,
HIDDEN_PARTICIPANT_LEFT,
PARTICIPANT_UPDATED
} from '../base/participants/actionTypes';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import { SET_REQUESTING_SUBTITLES } from '../subtitles/actionTypes';
import { toggleRequestingSubtitles } from '../subtitles/actions.any';

import {
_TRANSCRIBER_JOINED,
_TRANSCRIBER_LEFT
} from './actionTypes';
import {
hidePendingTranscribingNotification,
potentialTranscriberJoined,
showPendingTranscribingNotification,
showStartedTranscribingNotification,
showStoppedTranscribingNotification,
transcriberJoined,
transcriberLeft
Expand All @@ -29,62 +29,82 @@ const TRANSCRIBER_DISPLAY_NAME = 'Transcriber';
* @returns {Function}
*/
// eslint-disable-next-line no-unused-vars
MiddlewareRegistry.register(store => next => action => {
MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
const {
isTranscribing,
transcriberJID,
potentialTranscriberJIDs
} = store.getState()['features/transcribing'];
} = getState()['features/transcribing'];

switch (action.type) {
case _TRANSCRIBER_JOINED: {
notifyTranscribingStatusChanged(true);
dispatch(showStartedTranscribingNotification());

const state = getState();
const { transcription } = state['features/base/config'];
const { _requestingSubtitles } = state['features/subtitles'];

if (!_requestingSubtitles && !transcription?.disableStartForAll) {
dispatch(toggleRequestingSubtitles());
}
break;
}
case _TRANSCRIBER_LEFT: {
store.dispatch(showStoppedTranscribingNotification());
const state = store.getState();
notifyTranscribingStatusChanged(false);
dispatch(showStoppedTranscribingNotification());

const state = getState();
const { transcription } = state['features/base/config'];
const { _requestingSubtitles } = state['features/subtitles'];

if (_requestingSubtitles && !transcription?.disableStartForAll) {
store.dispatch(toggleRequestingSubtitles());
dispatch(toggleRequestingSubtitles());
}
break;
}
case HIDDEN_PARTICIPANT_JOINED:
if (action.displayName
&& action.displayName === TRANSCRIBER_DISPLAY_NAME) {
store.dispatch(transcriberJoined(action.id));
if (action.displayName === TRANSCRIBER_DISPLAY_NAME) {
dispatch(transcriberJoined(action.id));
} else {
store.dispatch(potentialTranscriberJoined(action.id));
dispatch(potentialTranscriberJoined(action.id));
}

break;
case HIDDEN_PARTICIPANT_LEFT:
if (action.id === transcriberJID) {
store.dispatch(transcriberLeft(action.id));
dispatch(transcriberLeft(action.id));
}
break;
case PARTICIPANT_UPDATED: {
const { participant } = action;

if (potentialTranscriberJIDs.includes(participant.id)
&& participant.name === TRANSCRIBER_DISPLAY_NAME) {
batch(() => {
store.dispatch(transcriberJoined(participant.id));
store.dispatch(hidePendingTranscribingNotification());
});
if (potentialTranscriberJIDs.includes(participant.id) && participant.name === TRANSCRIBER_DISPLAY_NAME) {
dispatch(transcriberJoined(participant.id));
}

break;
}
case _TRANSCRIBER_JOINED: {
const state = store.getState();
const { transcription } = state['features/base/config'];
const { _requestingSubtitles } = state['features/subtitles'];

if (!_requestingSubtitles && !transcription?.disableStartForAll) {
store.dispatch(toggleRequestingSubtitles());
case SET_REQUESTING_SUBTITLES:
if (action.enabled && !isTranscribing) {
dispatch(showPendingTranscribingNotification());
}

break;
}

}

return next(action);
});

/**
* Notify external application (if API is enabled) that transcribing has started or stopped.
*
* @param {boolean} on - True if transcribing is on, false otherwise.
* @returns {void}
*/
function notifyTranscribingStatusChanged(on: boolean) {
if (typeof APP !== 'undefined') {
APP.API.notifyTranscribingStatusChanged(on);
}
}
30 changes: 1 addition & 29 deletions react/features/transcribing/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import ReducerRegistry from '../base/redux/ReducerRegistry';

import {
SET_PENDING_TRANSCRIBING_NOTIFICATION_UID,
_POTENTIAL_TRANSCRIBER_JOINED,
_TRANSCRIBER_JOINED,
_TRANSCRIBER_LEFT
Expand All @@ -12,7 +11,6 @@ import {
*
* @returns {{
* isTranscribing: boolean,
* isDialing: boolean,
* transcriberJID: null,
* potentialTranscriberJIDs: Array
* }}
Expand All @@ -28,20 +26,6 @@ function _getInitialState() {
*/
isTranscribing: false,

/**
* Indicates whether the transcriber has been dialed into the room and
* we're currently awaiting successful joining or failure of joining.
*
* @type {boolean}
*/
isDialing: false,

/**
* Indicates whether the transcribing feature is in the process of
* terminating; the transcriber has been told to leave.
*/
isTerminating: false,

/**
* The JID of the active transcriber.
*
Expand All @@ -59,10 +43,7 @@ function _getInitialState() {
}

export interface ITranscribingState {
isDialing: boolean;
isTerminating: boolean;
isTranscribing: boolean;
pendingNotificationUid?: string;
potentialTranscriberJIDs: string[];
transcriberJID?: string | null;
}
Expand All @@ -77,28 +58,19 @@ ReducerRegistry.register<ITranscribingState>('features/transcribing',
return {
...state,
isTranscribing: true,
isDialing: false,
transcriberJID: action.transcriberJID
};
case _TRANSCRIBER_LEFT:
return {
...state,
isTerminating: false,
isTranscribing: false,
transcriberJID: undefined,
potentialTranscriberJIDs: []
};
case _POTENTIAL_TRANSCRIBER_JOINED:
return {
...state,
potentialTranscriberJIDs:
[ action.transcriberJID ]
.concat(state.potentialTranscriberJIDs)
};
case SET_PENDING_TRANSCRIBING_NOTIFICATION_UID:
return {
...state,
pendingNotificationUid: action.uid
potentialTranscriberJIDs: [ action.transcriberJID, ...state.potentialTranscriberJIDs ]
};
default:
return state;
Expand Down