Skip to content

Commit

Permalink
Fix oppia#5627 : Stop recording should stop microphone and angular-re…
Browse files Browse the repository at this point in the history
…corder should be replaced. (oppia#6708)
  • Loading branch information
mzaman07 authored and DubeySandeep committed Jun 1, 2019
1 parent 081c002 commit 5fad146
Show file tree
Hide file tree
Showing 13 changed files with 319 additions and 138 deletions.
7 changes: 0 additions & 7 deletions core/templates/dev/head/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,6 @@ oppia.config(['toastrConfig', function(toastrConfig) {
});
}]);

oppia.config(['recorderServiceProvider', function(recorderServiceProvider) {
recorderServiceProvider.forceSwf(false);
recorderServiceProvider.withMp3Conversion(true, {
bitRate: 128
});
}]);

// Overwrite the built-in exceptionHandler service to log errors to the backend
// (so that they can be fixed).
oppia.factory('$exceptionHandler', ['$log', function($log) {
Expand Down
8 changes: 4 additions & 4 deletions core/templates/dev/head/AppInit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@

var oppia = angular.module(
'oppia', [
'angularAudioRecorder', 'dndLists', 'headroom', 'infinite-scroll',
'ngAnimate', 'ngAudio', 'ngCookies', 'ngImgCrop', 'ngJoyRide', 'ngMaterial',
'ngResource', 'ngSanitize', 'ngTouch', 'pascalprecht.translate', 'toastr',
'ui.bootstrap', 'ui.sortable', 'ui.tree', 'ui.validate'
'dndLists', 'headroom', 'infinite-scroll', 'ngAnimate',
'ngAudio', 'ngCookies', 'ngImgCrop', 'ngJoyRide', 'ngMaterial',
'ngResource', 'ngSanitize', 'ngTouch', 'pascalprecht.translate',
'toastr', 'ui.bootstrap', 'ui.sortable', 'ui.tree', 'ui.validate'
].concat(
window.GLOBALS ? (window.GLOBALS.ADDITIONAL_ANGULAR_MODULES || []) : []));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ require(
require(
'pages/exploration_editor/translation_tab/' +
'TranslationTabActiveContentIdService.ts');
require(
'pages/exploration_editor/translation_tab/VoiceoverRecordingService.ts');
require('pages/state_editor/state_properties/StateEditorService.ts');
require('pages/state_editor/state_properties/StatePropertyService.ts');
require(
Expand All @@ -45,7 +47,7 @@ oppia.directive('audioTranslationBar', [
isTranslationTabBusy: '='
},
link: function(scope: ICustomScope, elm) {
scope.getRecorderController();
scope.getVoiceoverRecorder();

$('.oppia-translation-tab').on('dragover', function(evt) {
evt.preventDefault();
Expand Down Expand Up @@ -81,25 +83,24 @@ oppia.directive('audioTranslationBar', [
'/pages/exploration_editor/translation_tab/' +
'audio_translation_bar_directive.html'),
controller: [
'$filter', '$rootScope', '$scope', '$timeout', '$uibModal',
'$filter', '$interval', '$rootScope', '$scope', '$uibModal', '$window',
'AlertsService', 'AssetsBackendApiService', 'AudioPlayerService',
'ContextService', 'EditabilityService', 'ExplorationStatesService',
'IdGenerationService', 'SiteAnalyticsService',
'StateEditorService', 'StateRecordedVoiceoversService',
'TranslationLanguageService', 'recorderService',
'TranslationTabActiveContentIdService', 'RECORDING_TIME_LIMIT',
'TranslationLanguageService', 'TranslationTabActiveContentIdService',
'RECORDING_TIME_LIMIT', 'VoiceoverRecordingService',
function(
$filter, $rootScope, $scope, $timeout, $uibModal,
$filter, $interval, $rootScope, $scope, $uibModal, $window,
AlertsService, AssetsBackendApiService, AudioPlayerService,
ContextService, EditabilityService, ExplorationStatesService,
IdGenerationService, SiteAnalyticsService,
StateEditorService, StateRecordedVoiceoversService,
TranslationLanguageService, recorderService,
TranslationTabActiveContentIdService, RECORDING_TIME_LIMIT) {
$scope.RECORDER_ID = 'recorderId';
TranslationLanguageService, TranslationTabActiveContentIdService,
RECORDING_TIME_LIMIT, VoiceoverRecordingService) {
$scope.recordingTimeLimit = RECORDING_TIME_LIMIT;
$scope.audioBlob = null;
$scope.recorder = null;
$scope.voiceoverRecorder = null;
$scope.unsupportedBrowser = false;
$scope.selectedRecording = false;
$scope.isAudioAvailable = false;
Expand All @@ -113,6 +114,10 @@ oppia.directive('audioTranslationBar', [
$scope.checkingMicrophonePermission = false;
$scope.audioTimerIsShown = true;
$scope.audioIsCurrentlyBeingSaved = false;
$scope.elapsedTime = 0;
$scope.timerInterval = null;
$scope.unsavedAudioIsPlaying = false;
$scope.waveSurfer = null;
document.body.onkeyup = function(e) {
if (e.keyCode === 82 && !$scope.isAudioAvailable) {
// 82 belongs to the keycode for 'R'
Expand All @@ -136,30 +141,23 @@ oppia.directive('audioTranslationBar', [
}
};

var cancelTimer = function() {
if ($scope.timerInterval) {
$interval.cancel($scope.timerInterval);
}
};

var generateNewFilename = function() {
return $scope.contentId + '-' +
$scope.languageCode + '-' +
IdGenerationService.generateNewId() + '.mp3';
};

$scope.onRecordStart = function() {
$scope.showRecorderWarning = true;
$scope.isTranslationTabBusy = true;
};

$scope.onConversionComplete = function() {
$rootScope.loadingMessage = '';
};

var getTranslationTabBusyMessage = function() {
var message = '';
if ($scope.recorder.status.isRecording) {
if ($scope.isRecording) {
message = 'You haven\'t finished recording. Please stop ' +
'recording and either save or cancel the recording.';
} else if ($scope.recorder.status.isConverting) {
message = 'It seems like recorded audio is still getting ' +
'converted into mp3. Please wait until the audio has finished' +
' processing.';
} else if ($scope.showRecorderWarning) {
message = 'You haven\'t saved your recording. Please save or ' +
'cancel the recording.';
Expand All @@ -168,29 +166,38 @@ oppia.directive('audioTranslationBar', [
};
var showPermissionAndStartRecording = function() {
$scope.checkingMicrophonePermission = true;
recorderService.showPermission({
onDenied: function() {
$scope.recordingPermissionDenied = true;
$scope.cannotRecord = true;
$scope.checkingMicrophonePermission = false;
},
onAllowed: function() {
$scope.recordingPermissionDenied = false;
$scope.cannotRecord = false;
$scope.recorder.startRecord();
$scope.selectedRecording = true;
$scope.checkingMicrophonePermission = false;
},
onClosed: function() {
$scope.recordingPermissionDenied = true;
$scope.cannotRecord = true;
$scope.checkingMicrophonePermission = false;
},
$scope.voiceoverRecorder.startRecording().then(function() {
// When the user accepts the microphone access.
$scope.showRecorderWarning = true;
$scope.isTranslationTabBusy = true;

$scope.recordingPermissionDenied = false;
$scope.cannotRecord = false;
$scope.selectedRecording = true;
$scope.checkingMicrophonePermission = false;

$scope.elapsedTime = 0;
$scope.timerInterval = $interval(function() {
$scope.elapsedTime++;
// $scope.recordingTimeLimit is decremented to
// compensate for the audio recording timing inconsistency,
// so it allows the server to accept the recording.
if ($scope.elapsedTime === $scope.recordingTimeLimit - 1) {
$scope.stopRecording();
}
}, 1000);
}, function() {
// When the user denies microphone access.
$scope.recordingPermissionDenied = true;
$scope.cannotRecord = true;
$scope.checkingMicrophonePermission = false;
$scope.$apply();
});
};

$scope.checkAndStartRecording = function() {
if (!$scope.recorder.isAvailable) {
$scope.voiceoverRecorder.initRecorder();
if (!$scope.voiceoverRecorder.status().isAvailable) {
$scope.unsupportedBrowser = true;
$scope.cannotRecord = true;
} else {
Expand All @@ -207,14 +214,15 @@ oppia.directive('audioTranslationBar', [
$scope.audioNeedsUpdate = !$scope.audioNeedsUpdate;
};

$scope.getRecorderController = function() {
$scope.recorder = recorderService.controller($scope.RECORDER_ID);

$scope.getVoiceoverRecorder = function() {
$scope.voiceoverRecorder = VoiceoverRecordingService;
};

$scope.reRecord = function() {
$scope.initAudioBar();
$scope.selectedRecording = false;
showPermissionAndStartRecording();
$scope.checkAndStartRecording();
};

$scope.cancelRecording = function() {
Expand All @@ -225,13 +233,49 @@ oppia.directive('audioTranslationBar', [
$scope.showRecorderWarning = false;
};

$scope.stopRecording = function() {
$scope.voiceoverRecorder.stopRecord();
$scope.recordingComplete = true;
cancelTimer();
$scope.voiceoverRecorder.getMp3Data().then(function(audio) {
var fileType = 'audio/mp3';
$scope.audioBlob = new Blob(audio, {type: fileType});
// Free the browser from web worker.
$scope.voiceoverRecorder.closeRecorder();
// Create audio play and pause for unsaved recording.
var url = $window.URL.createObjectURL($scope.audioBlob);
// Create visualizer for playing unsaved audio.
$scope.waveSurfer = $window.WaveSurfer.create({
container: '#visualized',
waveColor: '#009688',
progressColor: '#cccccc',
height: 38
});
$scope.waveSurfer.load(url);
});
};

// Play and pause for unsaved recording.
$scope.playAndPauseUnsavedAudio = function() {
$scope.unsavedAudioIsPlaying = !$scope.unsavedAudioIsPlaying;
if ($scope.unsavedAudioIsPlaying) {
$scope.waveSurfer.play();
$scope.waveSurfer.on('finish', function() {
$scope.unsavedAudioIsPlaying = false;
$scope.$apply();
});
} else {
$scope.waveSurfer.pause();
}
};

$scope.updateAudio = function() {
AudioPlayerService.stop();
AudioPlayerService.clear();
$scope.audioBlob = null;
$scope.audioIsUpdating = true;
$scope.selectedRecording = false;
showPermissionAndStartRecording();
$scope.checkAndStartRecording();
};

$scope.saveRecordedAudio = function() {
Expand Down Expand Up @@ -270,19 +314,17 @@ oppia.directive('audioTranslationBar', [
return;
}

if (!$scope.recorder.status.isRecording && !$scope.audioBlob) {
if (!$scope.isRecording && !$scope.audioBlob) {
$scope.checkAndStartRecording();
} else {
$scope.recorder.stopRecord();
$scope.stopRecording();
}
};

$scope.$on('externalSave', function() {
if ($scope.recorder && $scope.recorder.status.isPlaying) {
$scope.recorder.playbackPause();
}
if (recorderService.getHandler()) {
recorderService.getHandler().clear();
if ($scope.voiceoverRecorder.status().isRecording) {
$scope.voiceoverRecorder.stopRecord();
$scope.voiceoverRecorder.closeRecorder();
}
AudioPlayerService.stop();
AudioPlayerService.clear();
Expand Down Expand Up @@ -375,28 +417,23 @@ oppia.directive('audioTranslationBar', [
};

$scope.initAudioBar = function() {
// This stops angular-recorder when user navigate while recording.
if ($scope.recorder) {
if ($scope.recorder.status.isPlaying) {
$scope.recorder.playbackPause();
}
if ($scope.recorder.status.isRecording &&
// This stops the voiceoverRecorder when user navigates
// while recording.
if ($scope.voiceoverRecorder) {
if ($scope.voiceoverRecorder.status().isRecording &&
$scope.showRecorderWarning) {
$scope.recorder.stopRecord();
$rootScope.loadingMessage = 'loading';
}
if ($scope.recorder.status.isConverting) {
$rootScope.loadingMessage = 'loading';
}
if (recorderService && recorderService.getHandler()) {
recorderService.getHandler().stop();
recorderService.getHandler().clear();
$scope.voiceoverRecorder.stopRecord();
cancelTimer();
$scope.voiceoverRecorder.closeRecorder();
}
}
$scope.isTranslationTabBusy = false;
AudioPlayerService.stop();
AudioPlayerService.clear();
$scope.showRecorderWarning = false;
// re-initialize for unsaved recording
$scope.unsavedAudioIsPlaying = false;
$scope.waveSurfer = null;
$scope.languageCode = TranslationLanguageService
.getActiveLanguageCode();
$scope.canTranslate = EditabilityService.isTranslatable();
Expand Down
Loading

0 comments on commit 5fad146

Please sign in to comment.