From b284f25fdef51bfd749a672159679fece389a659 Mon Sep 17 00:00:00 2001 From: Radium Zheng Date: Sat, 4 Aug 2018 02:06:11 +1000 Subject: [PATCH] Refactor how download works. Cleaner filenames. --- .../controller/RecordingController.js | 17 +++++++++++-- .../local-recording/recording/OggAdapter.js | 22 +++++++++++----- .../recording/RecordingAdapter.js | 6 ++--- .../local-recording/recording/Utils.js | 25 +++++-------------- .../local-recording/recording/WavAdapter.js | 14 ++++++----- .../recording/flac/FlacAdapter.js | 14 ++++++----- .../local-recording/recording/index.js | 5 ++-- 7 files changed, 59 insertions(+), 44 deletions(-) diff --git a/react/features/local-recording/controller/RecordingController.js b/react/features/local-recording/controller/RecordingController.js index 3b328bdae..cd2d80d53 100644 --- a/react/features/local-recording/controller/RecordingController.js +++ b/react/features/local-recording/controller/RecordingController.js @@ -5,7 +5,8 @@ import { i18next } from '../../base/i18n'; import { FlacAdapter, OggAdapter, - WavAdapter + WavAdapter, + downloadBlob } from '../recording'; import { sessionManager } from '../session'; @@ -320,7 +321,19 @@ class RecordingController { */ downloadRecordedData(sessionToken: number) { if (this._adapters[sessionToken]) { - this._adapters[sessionToken].download(); + this._adapters[sessionToken].exportRecordedData() + .then(args => { + const { data, format } = args; + + const filename = `session_${sessionToken}` + + `_${this._conference.myUserId()}.${format}`; + + downloadBlob(data, filename); + }) + .catch(error => { + logger.error('Failed to download audio for' + + ` session ${sessionToken}. Error: ${error}`); + }); } else { logger.error(`Invalid session token for download ${sessionToken}`); } diff --git a/react/features/local-recording/recording/OggAdapter.js b/react/features/local-recording/recording/OggAdapter.js index 722a1ca30..fdb03e8c6 100644 --- a/react/features/local-recording/recording/OggAdapter.js +++ b/react/features/local-recording/recording/OggAdapter.js @@ -1,5 +1,4 @@ import { RecordingAdapter } from './RecordingAdapter'; -import { downloadBlob, timestampString } from './Utils'; const logger = require('jitsi-meet-logger').getLogger(__filename); @@ -11,14 +10,22 @@ export class OggAdapter extends RecordingAdapter { /** * Instance of MediaRecorder. + * @private */ _mediaRecorder = null; /** * Initialization promise. + * @private */ _initPromise = null; + /** + * The recorded audio file. + * @private + */ + _recordedData = null; + /** * Implements {@link RecordingAdapter#start()}. * @@ -52,16 +59,19 @@ export class OggAdapter extends RecordingAdapter { } /** - * Implements {@link RecordingAdapter#download()}. + * Implements {@link RecordingAdapter#exportRecordedData()}. * * @inheritdoc */ - download() { + exportRecordedData() { if (this._recordedData !== null) { - const audioURL = window.URL.createObjectURL(this._recordedData); - - downloadBlob(audioURL, `recording${timestampString()}.ogg`); + return Promise.resolve({ + data: this._recordedData, + format: 'ogg' + }); } + + return Promise.reject('No audio data recorded.'); } /** diff --git a/react/features/local-recording/recording/RecordingAdapter.js b/react/features/local-recording/recording/RecordingAdapter.js index bbfc355ad..514c9ddc1 100644 --- a/react/features/local-recording/recording/RecordingAdapter.js +++ b/react/features/local-recording/recording/RecordingAdapter.js @@ -26,11 +26,11 @@ export class RecordingAdapter { } /** - * Initiates download of the recorded and encoded audio file. + * Export the recorded and encoded audio file. * - * @returns {void} + * @returns {Promise} */ - download() { + exportRecordedData() { throw new Error('Not implemented'); } diff --git a/react/features/local-recording/recording/Utils.js b/react/features/local-recording/recording/Utils.js index 59f1af469..322b5e6a4 100644 --- a/react/features/local-recording/recording/Utils.js +++ b/react/features/local-recording/recording/Utils.js @@ -1,33 +1,20 @@ /** * Force download of Blob in browser by faking an tag. * - * @param {string} blob - Base64 URL. + * @param {Blob} blob - Base64 URL. * @param {string} fileName - The filename to appear in the download dialog. * @returns {void} */ export function downloadBlob(blob, fileName = 'recording.ogg') { + const base64Url = window.URL.createObjectURL(blob); + // fake a anchor tag const a = document.createElement('a'); - document.body.appendChild(a); a.style = 'display: none'; - a.href = blob; + a.href = base64Url; a.download = fileName; + document.body.appendChild(a); a.click(); -} - -/** - * Obtains a timestamp of now. Used in filenames. - * - * @returns {string} - */ -export function timestampString() { - const timeStampInMs = window.performance - && window.performance.now - && window.performance.timing - && window.performance.timing.navigationStart - ? window.performance.now() + window.performance.timing.navigationStart - : Date.now(); - - return timeStampInMs.toString(); + document.body.removeChild(a); } diff --git a/react/features/local-recording/recording/WavAdapter.js b/react/features/local-recording/recording/WavAdapter.js index fad888450..dc6b16162 100644 --- a/react/features/local-recording/recording/WavAdapter.js +++ b/react/features/local-recording/recording/WavAdapter.js @@ -1,5 +1,4 @@ import { RecordingAdapter } from './RecordingAdapter'; -import { downloadBlob, timestampString } from './Utils'; const logger = require('jitsi-meet-logger').getLogger(__filename); @@ -98,16 +97,19 @@ export class WavAdapter extends RecordingAdapter { } /** - * Implements {@link RecordingAdapter#download()}. + * Implements {@link RecordingAdapter#exportRecordedData()}. * * @inheritdoc */ - download() { + exportRecordedData() { if (this._data !== null) { - const audioURL = window.URL.createObjectURL(this._data); - - downloadBlob(audioURL, `recording${timestampString()}.wav`); + return Promise.resolve({ + data: this._data, + format: 'wav' + }); } + + return Promise.reject('No audio data recorded.'); } /** diff --git a/react/features/local-recording/recording/flac/FlacAdapter.js b/react/features/local-recording/recording/flac/FlacAdapter.js index c8de2ee3c..bd6f07928 100644 --- a/react/features/local-recording/recording/flac/FlacAdapter.js +++ b/react/features/local-recording/recording/flac/FlacAdapter.js @@ -1,5 +1,4 @@ import { RecordingAdapter } from '../RecordingAdapter'; -import { downloadBlob, timestampString } from '../Utils'; import { DEBUG, MAIN_THREAD_FINISH, @@ -93,16 +92,19 @@ export class FlacAdapter extends RecordingAdapter { } /** - * Implements {@link RecordingAdapter#download()}. + * Implements {@link RecordingAdapter#exportRecordedData()}. * * @inheritdoc */ - download() { + exportRecordedData() { if (this._data !== null) { - const audioURL = window.URL.createObjectURL(this._data); - - downloadBlob(audioURL, `recording${timestampString()}.flac`); + return Promise.resolve({ + data: this._data, + format: 'flac' + }); } + + return Promise.reject('No audio data recorded.'); } /** diff --git a/react/features/local-recording/recording/index.js b/react/features/local-recording/recording/index.js index 1353495f7..7764a6109 100644 --- a/react/features/local-recording/recording/index.js +++ b/react/features/local-recording/recording/index.js @@ -1,4 +1,5 @@ -export * from './RecordingAdapter'; -export * from './flac'; export * from './OggAdapter'; +export * from './RecordingAdapter'; +export * from './Utils'; export * from './WavAdapter'; +export * from './flac';