|
@@ -8,16 +8,21 @@ import {
|
8
|
8
|
sendAnalytics
|
9
|
9
|
} from '../../react/features/analytics';
|
10
|
10
|
import {
|
|
11
|
+ getCurrentConference,
|
11
|
12
|
sendTones,
|
12
|
13
|
setPassword,
|
13
|
14
|
setSubject
|
14
|
15
|
} from '../../react/features/base/conference';
|
15
|
16
|
import { parseJWTFromURLParams } from '../../react/features/base/jwt';
|
|
17
|
+import { JitsiRecordingConstants } from '../../react/features/base/lib-jitsi-meet';
|
16
|
18
|
import {
|
17
|
19
|
processExternalDeviceRequest
|
18
|
20
|
} from '../../react/features/device-selection/functions';
|
|
21
|
+import { isEnabled as isDropboxEnabled } from '../../react/features/dropbox';
|
19
|
22
|
import { setE2EEKey } from '../../react/features/e2ee';
|
20
|
23
|
import { invite } from '../../react/features/invite';
|
|
24
|
+import { RECORDING_TYPES } from '../../react/features/recording/constants';
|
|
25
|
+import { getActiveSession } from '../../react/features/recording/functions';
|
21
|
26
|
import { muteAllParticipants } from '../../react/features/remote-video-menu/actions';
|
22
|
27
|
import { toggleTileView } from '../../react/features/video-layout';
|
23
|
28
|
import { setVideoQuality } from '../../react/features/video-quality';
|
|
@@ -190,6 +195,114 @@ function initCommands() {
|
190
|
195
|
logger.debug('Set video quality command received');
|
191
|
196
|
sendAnalytics(createApiEvent('set.video.quality'));
|
192
|
197
|
APP.store.dispatch(setVideoQuality(frameHeight));
|
|
198
|
+ },
|
|
199
|
+
|
|
200
|
+ /**
|
|
201
|
+ * Starts a file recording or streaming depending on the passed on params.
|
|
202
|
+ * For youtube streams, `youtubeStreamKey` must be passed on. `youtubeBroadcastID` is optional.
|
|
203
|
+ * For dropbox recording, recording `mode` should be `file` and a dropbox oauth2 token must be provided.
|
|
204
|
+ * For file recording, recording `mode` should be `file` and optionally `shouldShare` could be passed on.
|
|
205
|
+ * No other params should be passed.
|
|
206
|
+ *
|
|
207
|
+ * @param { string } arg.mode - Recording mode, either `file` or `stream`.
|
|
208
|
+ * @param { string } arg.dropboxToken - Dropbox oauth2 token.
|
|
209
|
+ * @param { boolean } arg.shouldShare - Whether the recording should be shared with the participants or not.
|
|
210
|
+ * Only applies to certain jitsi meet deploys.
|
|
211
|
+ * @param { string } arg.youtubeStreamKey - The youtube stream key.
|
|
212
|
+ * @param { string } arg.youtubeBroadcastID - The youtube broacast ID.
|
|
213
|
+ * @returns {void}
|
|
214
|
+ */
|
|
215
|
+ 'start-recording': ({ mode, dropboxToken, shouldShare, youtubeStreamKey, youtubeBroadcastID }) => {
|
|
216
|
+ const state = APP.store.getState();
|
|
217
|
+ const conference = getCurrentConference(state);
|
|
218
|
+
|
|
219
|
+ if (!conference) {
|
|
220
|
+ logger.error('Conference is not defined');
|
|
221
|
+
|
|
222
|
+ return;
|
|
223
|
+ }
|
|
224
|
+
|
|
225
|
+ if (dropboxToken && !isDropboxEnabled(state)) {
|
|
226
|
+ logger.error('Failed starting recording: dropbox is not enabled on this deployment');
|
|
227
|
+
|
|
228
|
+ return;
|
|
229
|
+ }
|
|
230
|
+
|
|
231
|
+ if (mode === JitsiRecordingConstants.mode.STREAM && !youtubeStreamKey) {
|
|
232
|
+ logger.error('Failed starting recording: missing youtube stream key');
|
|
233
|
+
|
|
234
|
+ return;
|
|
235
|
+ }
|
|
236
|
+
|
|
237
|
+ let recordingConfig;
|
|
238
|
+
|
|
239
|
+ if (mode === JitsiRecordingConstants.mode.FILE) {
|
|
240
|
+ if (dropboxToken) {
|
|
241
|
+ recordingConfig = {
|
|
242
|
+ mode: JitsiRecordingConstants.mode.FILE,
|
|
243
|
+ appData: JSON.stringify({
|
|
244
|
+ 'file_recording_metadata': {
|
|
245
|
+ 'upload_credentials': {
|
|
246
|
+ 'service_name': RECORDING_TYPES.DROPBOX,
|
|
247
|
+ 'token': dropboxToken
|
|
248
|
+ }
|
|
249
|
+ }
|
|
250
|
+ })
|
|
251
|
+ };
|
|
252
|
+ } else {
|
|
253
|
+ recordingConfig = {
|
|
254
|
+ mode: JitsiRecordingConstants.mode.FILE,
|
|
255
|
+ appData: JSON.stringify({
|
|
256
|
+ 'file_recording_metadata': {
|
|
257
|
+ 'share': shouldShare
|
|
258
|
+ }
|
|
259
|
+ })
|
|
260
|
+ };
|
|
261
|
+ }
|
|
262
|
+ } else if (mode === JitsiRecordingConstants.mode.STREAM) {
|
|
263
|
+ recordingConfig = {
|
|
264
|
+ broadcastId: youtubeBroadcastID,
|
|
265
|
+ mode: JitsiRecordingConstants.mode.STREAM,
|
|
266
|
+ streamId: youtubeStreamKey
|
|
267
|
+ };
|
|
268
|
+ } else {
|
|
269
|
+ logger.error('Invalid recording mode provided');
|
|
270
|
+
|
|
271
|
+ return;
|
|
272
|
+ }
|
|
273
|
+
|
|
274
|
+ conference.startRecording(recordingConfig);
|
|
275
|
+ },
|
|
276
|
+
|
|
277
|
+ /**
|
|
278
|
+ * Stops a recording or streaming in progress.
|
|
279
|
+ *
|
|
280
|
+ * @param {string} mode - `file` or `stream`.
|
|
281
|
+ * @returns {void}
|
|
282
|
+ */
|
|
283
|
+ 'stop-recording': mode => {
|
|
284
|
+ const state = APP.store.getState();
|
|
285
|
+ const conference = getCurrentConference(state);
|
|
286
|
+
|
|
287
|
+ if (!conference) {
|
|
288
|
+ logger.error('Conference is not defined');
|
|
289
|
+
|
|
290
|
+ return;
|
|
291
|
+ }
|
|
292
|
+
|
|
293
|
+ if (![ JitsiRecordingConstants.mode.FILE, JitsiRecordingConstants.mode.STREAM ].includes(mode)) {
|
|
294
|
+ logger.error('Invalid recording mode provided!');
|
|
295
|
+
|
|
296
|
+ return;
|
|
297
|
+ }
|
|
298
|
+
|
|
299
|
+ const activeSession = getActiveSession(state, mode);
|
|
300
|
+
|
|
301
|
+ if (activeSession && activeSession.id) {
|
|
302
|
+ conference.stopRecording(activeSession.id);
|
|
303
|
+ } else {
|
|
304
|
+ logger.error('No recording or streaming session found');
|
|
305
|
+ }
|
193
|
306
|
}
|
194
|
307
|
};
|
195
|
308
|
transport.on('event', ({ data, name }) => {
|
|
@@ -514,7 +627,8 @@ class API {
|
514
|
627
|
notifyDeviceListChanged(devices: Object) {
|
515
|
628
|
this._sendEvent({
|
516
|
629
|
name: 'device-list-changed',
|
517
|
|
- devices });
|
|
630
|
+ devices
|
|
631
|
+ });
|
518
|
632
|
}
|
519
|
633
|
|
520
|
634
|
/**
|