ソースを参照

refactor: use createLocalTracks instead of gUM; fix some docs;

master
Radium Zheng 7年前
コミット
e125861b29

+ 1
- 1
react/features/local-recording/controller/RecordingController.js ファイルの表示

258
         this._format = newFormat;
258
         this._format = newFormat;
259
         logger.log(`Recording format switched to ${newFormat}`);
259
         logger.log(`Recording format switched to ${newFormat}`);
260
 
260
 
261
-        // will be used next time
261
+        // the new format will be used in the next recording session
262
     }
262
     }
263
 
263
 
264
     /**
264
     /**

+ 3
- 1
react/features/local-recording/middleware.js ファイルの表示

14
 
14
 
15
     switch (action.type) {
15
     switch (action.type) {
16
     case CONFERENCE_JOINED: {
16
     case CONFERENCE_JOINED: {
17
-        // the Conference object is ready
18
         const { conference } = getState()['features/base/conference'];
17
         const { conference } = getState()['features/base/conference'];
19
 
18
 
20
         recordingController.registerEvents(conference);
19
         recordingController.registerEvents(conference);
48
         break;
47
         break;
49
     }
48
     }
50
 
49
 
50
+    // @todo: detect change in features/base/settings micDeviceID
51
+    // @todo: SET_AUDIO_MUTED, when audio is muted
52
+
51
     return result;
53
     return result;
52
 });
54
 });

+ 14
- 23
react/features/local-recording/recording/OggAdapter.js ファイルの表示

9
  */
9
  */
10
 export class OggAdapter extends RecordingAdapter {
10
 export class OggAdapter extends RecordingAdapter {
11
 
11
 
12
+    /**
13
+     * Instance of MediaRecorder.
14
+     */
12
     _mediaRecorder = null;
15
     _mediaRecorder = null;
13
 
16
 
14
     /**
17
     /**
21
 
24
 
22
         if (this._mediaRecorder === null) {
25
         if (this._mediaRecorder === null) {
23
             p = new Promise((resolve, error) => {
26
             p = new Promise((resolve, error) => {
24
-                navigator.getUserMedia(
25
-
26
-                    // constraints, only audio needed
27
-                    {
28
-                        audioBitsPerSecond: 44100, // 44 kbps
29
-                        audio: true,
30
-                        mimeType: 'application/ogg'
31
-                    },
32
-
33
-                    // success callback
34
-                    stream => {
35
-                        this._mediaRecorder = new MediaRecorder(stream);
36
-                        this._mediaRecorder.ondataavailable
37
-                            = e => this._saveMediaData(e.data);
38
-                        resolve();
39
-                    },
40
-
41
-                    // Error callback
42
-                    err => {
43
-                        logger.error(`Error calling getUserMedia(): ${err}`);
44
-                        error();
45
-                    }
46
-                );
27
+                this._getAudioStream(0)
28
+                .then(stream => {
29
+                    this._mediaRecorder = new MediaRecorder(stream);
30
+                    this._mediaRecorder.ondataavailable
31
+                        = e => this._saveMediaData(e.data);
32
+                    resolve();
33
+                })
34
+                .catch(err => {
35
+                    logger.error(`Error calling getUserMedia(): ${err}`);
36
+                    error();
37
+                });
47
             });
38
             });
48
         } else {
39
         } else {
49
             p = new Promise(resolve => {
40
             p = new Promise(resolve => {

+ 30
- 1
react/features/local-recording/recording/RecordingAdapter.js ファイルの表示

1
+import JitsiMeetJS from '../../base/lib-jitsi-meet';
2
+
1
 /**
3
 /**
2
- * Common interface for recording mechanisms
4
+ * Base class for recording backends.
3
  */
5
  */
4
 export class RecordingAdapter {
6
 export class RecordingAdapter {
5
 
7
 
38
     download() {
40
     download() {
39
         throw new Error('Not implemented');
41
         throw new Error('Not implemented');
40
     }
42
     }
43
+
44
+    /**
45
+     * Helper method for getting an audio MediaStream. Use this instead of
46
+     * calling browser APIs directly.
47
+     *
48
+     * @protected
49
+     * @param {number} micDeviceId - The ID of the current audio device.
50
+     * @returns {Promise}
51
+     */
52
+    _getAudioStream(micDeviceId) {
53
+        return JitsiMeetJS.createLocalTracks({
54
+            devices: [ 'audio' ],
55
+            micDeviceId
56
+        }).then(result => {
57
+            if (result.length !== 1) {
58
+                throw new Error('Unexpected number of streams '
59
+                    + 'from createLocalTracks.');
60
+            }
61
+            const mediaStream = result[0].stream;
62
+
63
+            if (mediaStream === undefined) {
64
+                throw new Error('Failed to get MediaStream.');
65
+            }
66
+
67
+            return mediaStream;
68
+        });
69
+    }
41
 }
70
 }

+ 22
- 34
react/features/local-recording/recording/WavAdapter.js ファイルの表示

40
         }
40
         }
41
 
41
 
42
         const p = new Promise((resolve, reject) => {
42
         const p = new Promise((resolve, reject) => {
43
-            navigator.getUserMedia(
44
-
45
-                // constraints - only audio needed for this app
46
-                {
47
-                    audioBitsPerSecond: WAV_SAMPLE_RATE * WAV_BITS_PER_SAMPLE,
48
-                    audio: true,
49
-                    mimeType: 'application/ogg' // useless?
50
-                },
51
-
52
-                // Success callback
53
-                stream => {
54
-                    this._audioContext = new AudioContext();
55
-                    this._audioSource
56
-                     = this._audioContext.createMediaStreamSource(stream);
57
-                    this._audioProcessingNode
58
-                      = this._audioContext.createScriptProcessor(4096, 1, 1);
59
-                    this._audioProcessingNode.onaudioprocess = e => {
60
-                        const channelLeft = e.inputBuffer.getChannelData(0);
61
-
62
-                        // https://developer.mozilla.org/en-US/docs/
63
-                        // Web/API/AudioBuffer/getChannelData
64
-                        // the returned value is an Float32Array
65
-                        this._saveWavPCM(channelLeft);
66
-                    };
67
-                    this._isInitialized = true;
68
-                    resolve();
69
-                },
70
-
71
-                // Error callback
72
-                err => {
73
-                    logger.error(`Error calling getUserMedia(): ${err}`);
74
-                    reject();
75
-                }
76
-            );
43
+            this._getAudioStream(0)
44
+            .then(stream => {
45
+                this._audioContext = new AudioContext();
46
+                this._audioSource
47
+                    = this._audioContext.createMediaStreamSource(stream);
48
+                this._audioProcessingNode
49
+                    = this._audioContext.createScriptProcessor(4096, 1, 1);
50
+                this._audioProcessingNode.onaudioprocess = e => {
51
+                    const channelLeft = e.inputBuffer.getChannelData(0);
52
+
53
+                    // https://developer.mozilla.org/en-US/docs/
54
+                    // Web/API/AudioBuffer/getChannelData
55
+                    // the returned value is an Float32Array
56
+                    this._saveWavPCM(channelLeft);
57
+                };
58
+                this._isInitialized = true;
59
+                resolve();
60
+            })
61
+            .catch(err => {
62
+                logger.error(`Error calling getUserMedia(): ${err}`);
63
+                reject();
64
+            });
77
         });
65
         });
78
 
66
 
79
         return p;
67
         return p;

+ 25
- 37
react/features/local-recording/recording/flac/FlacAdapter.js ファイルの表示

12
 const logger = require('jitsi-meet-logger').getLogger(__filename);
12
 const logger = require('jitsi-meet-logger').getLogger(__filename);
13
 
13
 
14
 /**
14
 /**
15
- * Recording adapter that uses libflac in the background
15
+ * Recording adapter that uses libflac.js in the background.
16
  */
16
  */
17
 export class FlacAdapter extends RecordingAdapter {
17
 export class FlacAdapter extends RecordingAdapter {
18
 
18
 
43
                 // try load the minified version first
43
                 // try load the minified version first
44
                 this._encoder = new Worker('/libs/flacEncodeWorker.min.js');
44
                 this._encoder = new Worker('/libs/flacEncodeWorker.min.js');
45
             } catch (exception1) {
45
             } catch (exception1) {
46
-                // if failed, try un minified version
46
+                // if failed, try unminified version
47
                 try {
47
                 try {
48
                     this._encoder = new Worker('/libs/flacEncodeWorker.js');
48
                     this._encoder = new Worker('/libs/flacEncodeWorker.js');
49
                 } catch (exception2) {
49
                 } catch (exception2) {
83
         });
83
         });
84
 
84
 
85
         const callbackInitAudioContext = (resolve, reject) => {
85
         const callbackInitAudioContext = (resolve, reject) => {
86
-            navigator.getUserMedia(
87
-
88
-                // constraints - only audio needed for this app
89
-                {
90
-                    audioBitsPerSecond: 44100, // 44 kbps
91
-                    audio: true,
92
-                    mimeType: 'application/ogg' // useless?
93
-                },
94
-
95
-                // Success callback
96
-                stream => {
97
-                    this._audioContext = new AudioContext();
98
-                    this._audioSource
99
-                     = this._audioContext.createMediaStreamSource(stream);
100
-                    this._audioProcessingNode
101
-                      = this._audioContext.createScriptProcessor(4096, 1, 1);
102
-                    this._audioProcessingNode.onaudioprocess = e => {
103
-                        // delegate to the WebWorker to do the encoding
104
-                        const channelLeft = e.inputBuffer.getChannelData(0);
105
-
106
-                        this._encoder.postMessage({
107
-                            command: MAIN_THREAD_NEW_DATA_ARRIVED,
108
-                            buf: channelLeft
109
-                        });
110
-                    };
111
-                    logger.debug('AudioContext is set up.');
112
-                    resolve();
113
-                },
114
-
115
-                // Error callback
116
-                err => {
117
-                    logger.error(`Error calling getUserMedia(): ${err}`);
118
-                    reject();
119
-                }
120
-            );
86
+            this._getAudioStream(0)
87
+            .then(stream => {
88
+                this._audioContext = new AudioContext();
89
+                this._audioSource
90
+                    = this._audioContext.createMediaStreamSource(stream);
91
+                this._audioProcessingNode
92
+                    = this._audioContext.createScriptProcessor(4096, 1, 1);
93
+                this._audioProcessingNode.onaudioprocess = e => {
94
+                    // delegate to the WebWorker to do the encoding
95
+                    const channelLeft = e.inputBuffer.getChannelData(0);
96
+
97
+                    this._encoder.postMessage({
98
+                        command: MAIN_THREAD_NEW_DATA_ARRIVED,
99
+                        buf: channelLeft
100
+                    });
101
+                };
102
+                logger.debug('AudioContext is set up.');
103
+                resolve();
104
+            })
105
+            .catch(err => {
106
+                logger.error(`Error calling getUserMedia(): ${err}`);
107
+                reject();
108
+            });
121
         };
109
         };
122
 
110
 
123
         // FIXME: because Promise constructor immediately executes the executor
111
         // FIXME: because Promise constructor immediately executes the executor

+ 11
- 17
react/features/local-recording/recording/flac/flacEncodeWorker.js ファイルの表示

26
 declare var Flac: Object;
26
 declare var Flac: Object;
27
 
27
 
28
 const FLAC_ERRORS = {
28
 const FLAC_ERRORS = {
29
-    // The encoder is in the normal OK state and
30
-    // samples can be processed.
29
+    // The encoder is in the normal OK state and samples can be processed.
31
     0: 'FLAC__STREAM_ENCODER_OK',
30
     0: 'FLAC__STREAM_ENCODER_OK',
32
 
31
 
33
-    // The encoder is in the
34
-    // uninitialized state one of the FLAC__stream_encoder_init_*() functions
35
-    // must be called before samples can be processed.
32
+    // The encoder is in the uninitialized state one of the
33
+    // FLAC__stream_encoder_init_*() functions must be called before samples can
34
+    // be processed.
36
     1: 'FLAC__STREAM_ENCODER_UNINITIALIZED',
35
     1: 'FLAC__STREAM_ENCODER_UNINITIALIZED',
37
 
36
 
38
     // An error occurred in the underlying Ogg layer.
37
     // An error occurred in the underlying Ogg layer.
39
     2: 'FLAC__STREAM_ENCODER_OGG_ERROR',
38
     2: 'FLAC__STREAM_ENCODER_OGG_ERROR',
40
 
39
 
41
-    // An error occurred in the
42
-    // underlying verify stream decoder; check
40
+    // An error occurred in the underlying verify stream decoder; check
43
     // FLAC__stream_encoder_get_verify_decoder_state().
41
     // FLAC__stream_encoder_get_verify_decoder_state().
44
     3: 'FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR',
42
     3: 'FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR',
45
 
43
 
46
-    // The verify decoder detected a mismatch between the
47
-    // original audio signal and the decoded audio signal.
48
-
44
+    // The verify decoder detected a mismatch between the original audio signal
45
+    // and the decoded audio signal.
49
     4: 'FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA',
46
     4: 'FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA',
50
 
47
 
51
-    // One of the callbacks returned
52
-    // a fatal error.
48
+    // One of the callbacks returned a fatal error.
53
     5: 'FLAC__STREAM_ENCODER_CLIENT_ERROR',
49
     5: 'FLAC__STREAM_ENCODER_CLIENT_ERROR',
54
 
50
 
55
-    // An I/O error occurred while
56
-    // opening/reading/writing a file. Check errno.
57
-
51
+    // An I/O error occurred while opening/reading/writing a file. Check errno.
58
     6: 'FLAC__STREAM_ENCODER_IO_ERROR',
52
     6: 'FLAC__STREAM_ENCODER_IO_ERROR',
59
 
53
 
60
-    // An error occurred while writing
61
-    // the stream; usually, the write_callback returned an error.
54
+    // An error occurred while writing the stream; usually, the write_callback
55
+    // returned an error.
62
     7: 'FLAC__STREAM_ENCODER_FRAMING_ERROR',
56
     7: 'FLAC__STREAM_ENCODER_FRAMING_ERROR',
63
 
57
 
64
     // Memory allocation failed.
58
     // Memory allocation failed.

+ 0
- 4
react/features/local-recording/reducer.js ファイルの表示

9
 } from './actionTypes';
9
 } from './actionTypes';
10
 import { recordingController } from './controller';
10
 import { recordingController } from './controller';
11
 
11
 
12
-const logger = require('jitsi-meet-logger').getLogger(__filename);
13
-
14
 ReducerRegistry.register('features/local-recording', (state = {}, action) => {
12
 ReducerRegistry.register('features/local-recording', (state = {}, action) => {
15
-    logger.debug(`Redux state (features/local-recording):\n ${
16
-        JSON.stringify(state)}`);
17
     switch (action.type) {
13
     switch (action.type) {
18
     case LOCAL_RECORDING_ENGAGED: {
14
     case LOCAL_RECORDING_ENGAGED: {
19
         return {
15
         return {

読み込み中…
キャンセル
保存