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

This commit is contained in:
Radium Zheng 2018-07-10 03:49:55 +10:00
parent 3241c7a929
commit e125861b29
8 changed files with 104 additions and 116 deletions

View File

@ -258,7 +258,7 @@ class RecordingController {
this._format = newFormat; this._format = newFormat;
logger.log(`Recording format switched to ${newFormat}`); logger.log(`Recording format switched to ${newFormat}`);
// will be used next time // the new format will be used in the next recording session
} }
/** /**

View File

@ -14,7 +14,6 @@ MiddlewareRegistry.register(({ getState, dispatch }) => next => action => {
switch (action.type) { switch (action.type) {
case CONFERENCE_JOINED: { case CONFERENCE_JOINED: {
// the Conference object is ready
const { conference } = getState()['features/base/conference']; const { conference } = getState()['features/base/conference'];
recordingController.registerEvents(conference); recordingController.registerEvents(conference);
@ -48,5 +47,8 @@ MiddlewareRegistry.register(({ getState, dispatch }) => next => action => {
break; break;
} }
// @todo: detect change in features/base/settings micDeviceID
// @todo: SET_AUDIO_MUTED, when audio is muted
return result; return result;
}); });

View File

@ -9,6 +9,9 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
*/ */
export class OggAdapter extends RecordingAdapter { export class OggAdapter extends RecordingAdapter {
/**
* Instance of MediaRecorder.
*/
_mediaRecorder = null; _mediaRecorder = null;
/** /**
@ -21,29 +24,17 @@ export class OggAdapter extends RecordingAdapter {
if (this._mediaRecorder === null) { if (this._mediaRecorder === null) {
p = new Promise((resolve, error) => { p = new Promise((resolve, error) => {
navigator.getUserMedia( this._getAudioStream(0)
.then(stream => {
// constraints, only audio needed
{
audioBitsPerSecond: 44100, // 44 kbps
audio: true,
mimeType: 'application/ogg'
},
// success callback
stream => {
this._mediaRecorder = new MediaRecorder(stream); this._mediaRecorder = new MediaRecorder(stream);
this._mediaRecorder.ondataavailable this._mediaRecorder.ondataavailable
= e => this._saveMediaData(e.data); = e => this._saveMediaData(e.data);
resolve(); resolve();
}, })
.catch(err => {
// Error callback
err => {
logger.error(`Error calling getUserMedia(): ${err}`); logger.error(`Error calling getUserMedia(): ${err}`);
error(); error();
} });
);
}); });
} else { } else {
p = new Promise(resolve => { p = new Promise(resolve => {

View File

@ -1,5 +1,7 @@
import JitsiMeetJS from '../../base/lib-jitsi-meet';
/** /**
* Common interface for recording mechanisms * Base class for recording backends.
*/ */
export class RecordingAdapter { export class RecordingAdapter {
@ -38,4 +40,31 @@ export class RecordingAdapter {
download() { download() {
throw new Error('Not implemented'); throw new Error('Not implemented');
} }
/**
* Helper method for getting an audio MediaStream. Use this instead of
* calling browser APIs directly.
*
* @protected
* @param {number} micDeviceId - The ID of the current audio device.
* @returns {Promise}
*/
_getAudioStream(micDeviceId) {
return JitsiMeetJS.createLocalTracks({
devices: [ 'audio' ],
micDeviceId
}).then(result => {
if (result.length !== 1) {
throw new Error('Unexpected number of streams '
+ 'from createLocalTracks.');
}
const mediaStream = result[0].stream;
if (mediaStream === undefined) {
throw new Error('Failed to get MediaStream.');
}
return mediaStream;
});
}
} }

View File

@ -40,17 +40,8 @@ export class WavAdapter extends RecordingAdapter {
} }
const p = new Promise((resolve, reject) => { const p = new Promise((resolve, reject) => {
navigator.getUserMedia( this._getAudioStream(0)
.then(stream => {
// constraints - only audio needed for this app
{
audioBitsPerSecond: WAV_SAMPLE_RATE * WAV_BITS_PER_SAMPLE,
audio: true,
mimeType: 'application/ogg' // useless?
},
// Success callback
stream => {
this._audioContext = new AudioContext(); this._audioContext = new AudioContext();
this._audioSource this._audioSource
= this._audioContext.createMediaStreamSource(stream); = this._audioContext.createMediaStreamSource(stream);
@ -66,14 +57,11 @@ export class WavAdapter extends RecordingAdapter {
}; };
this._isInitialized = true; this._isInitialized = true;
resolve(); resolve();
}, })
.catch(err => {
// Error callback
err => {
logger.error(`Error calling getUserMedia(): ${err}`); logger.error(`Error calling getUserMedia(): ${err}`);
reject(); reject();
} });
);
}); });
return p; return p;

View File

@ -12,7 +12,7 @@ import {
const logger = require('jitsi-meet-logger').getLogger(__filename); const logger = require('jitsi-meet-logger').getLogger(__filename);
/** /**
* Recording adapter that uses libflac in the background * Recording adapter that uses libflac.js in the background.
*/ */
export class FlacAdapter extends RecordingAdapter { export class FlacAdapter extends RecordingAdapter {
@ -43,7 +43,7 @@ export class FlacAdapter extends RecordingAdapter {
// try load the minified version first // try load the minified version first
this._encoder = new Worker('/libs/flacEncodeWorker.min.js'); this._encoder = new Worker('/libs/flacEncodeWorker.min.js');
} catch (exception1) { } catch (exception1) {
// if failed, try un minified version // if failed, try unminified version
try { try {
this._encoder = new Worker('/libs/flacEncodeWorker.js'); this._encoder = new Worker('/libs/flacEncodeWorker.js');
} catch (exception2) { } catch (exception2) {
@ -83,17 +83,8 @@ export class FlacAdapter extends RecordingAdapter {
}); });
const callbackInitAudioContext = (resolve, reject) => { const callbackInitAudioContext = (resolve, reject) => {
navigator.getUserMedia( this._getAudioStream(0)
.then(stream => {
// constraints - only audio needed for this app
{
audioBitsPerSecond: 44100, // 44 kbps
audio: true,
mimeType: 'application/ogg' // useless?
},
// Success callback
stream => {
this._audioContext = new AudioContext(); this._audioContext = new AudioContext();
this._audioSource this._audioSource
= this._audioContext.createMediaStreamSource(stream); = this._audioContext.createMediaStreamSource(stream);
@ -110,14 +101,11 @@ export class FlacAdapter extends RecordingAdapter {
}; };
logger.debug('AudioContext is set up.'); logger.debug('AudioContext is set up.');
resolve(); resolve();
}, })
.catch(err => {
// Error callback
err => {
logger.error(`Error calling getUserMedia(): ${err}`); logger.error(`Error calling getUserMedia(): ${err}`);
reject(); reject();
} });
);
}; };
// FIXME: because Promise constructor immediately executes the executor // FIXME: because Promise constructor immediately executes the executor

View File

@ -26,39 +26,33 @@ importScripts('/libs/libflac3-1.3.2.min.js');
declare var Flac: Object; declare var Flac: Object;
const FLAC_ERRORS = { const FLAC_ERRORS = {
// The encoder is in the normal OK state and // The encoder is in the normal OK state and samples can be processed.
// samples can be processed.
0: 'FLAC__STREAM_ENCODER_OK', 0: 'FLAC__STREAM_ENCODER_OK',
// The encoder is in the // The encoder is in the uninitialized state one of the
// uninitialized state one of the FLAC__stream_encoder_init_*() functions // FLAC__stream_encoder_init_*() functions must be called before samples can
// must be called before samples can be processed. // be processed.
1: 'FLAC__STREAM_ENCODER_UNINITIALIZED', 1: 'FLAC__STREAM_ENCODER_UNINITIALIZED',
// An error occurred in the underlying Ogg layer. // An error occurred in the underlying Ogg layer.
2: 'FLAC__STREAM_ENCODER_OGG_ERROR', 2: 'FLAC__STREAM_ENCODER_OGG_ERROR',
// An error occurred in the // An error occurred in the underlying verify stream decoder; check
// underlying verify stream decoder; check
// FLAC__stream_encoder_get_verify_decoder_state(). // FLAC__stream_encoder_get_verify_decoder_state().
3: 'FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR', 3: 'FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR',
// The verify decoder detected a mismatch between the // The verify decoder detected a mismatch between the original audio signal
// original audio signal and the decoded audio signal. // and the decoded audio signal.
4: 'FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA', 4: 'FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA',
// One of the callbacks returned // One of the callbacks returned a fatal error.
// a fatal error.
5: 'FLAC__STREAM_ENCODER_CLIENT_ERROR', 5: 'FLAC__STREAM_ENCODER_CLIENT_ERROR',
// An I/O error occurred while // An I/O error occurred while opening/reading/writing a file. Check errno.
// opening/reading/writing a file. Check errno.
6: 'FLAC__STREAM_ENCODER_IO_ERROR', 6: 'FLAC__STREAM_ENCODER_IO_ERROR',
// An error occurred while writing // An error occurred while writing the stream; usually, the write_callback
// the stream; usually, the write_callback returned an error. // returned an error.
7: 'FLAC__STREAM_ENCODER_FRAMING_ERROR', 7: 'FLAC__STREAM_ENCODER_FRAMING_ERROR',
// Memory allocation failed. // Memory allocation failed.

View File

@ -9,11 +9,7 @@ import {
} from './actionTypes'; } from './actionTypes';
import { recordingController } from './controller'; import { recordingController } from './controller';
const logger = require('jitsi-meet-logger').getLogger(__filename);
ReducerRegistry.register('features/local-recording', (state = {}, action) => { ReducerRegistry.register('features/local-recording', (state = {}, action) => {
logger.debug(`Redux state (features/local-recording):\n ${
JSON.stringify(state)}`);
switch (action.type) { switch (action.type) {
case LOCAL_RECORDING_ENGAGED: { case LOCAL_RECORDING_ENGAGED: {
return { return {