0

I'm building a web app, where you can record audio from the browser and then upload it to the server so that other users can listen to it, give you an evaluation, corrections - language learning.

I have parts of the code but I cannot figure out how to combine them together:

JS (script for recording audio - works fine, skipped the part for record and stop button):

navigator.mediaDevices.getUserMedia({audio:true})
.then(stream => {handlerFunction(stream)})

function handlerFunction(stream) {
    rec = new MediaRecorder(stream);
    rec.ondataavailable = e => {
        audioChunks.push(e.data);
        if(rec.state == "inactive") {

            let blob = new Blob(audioChunks, {type:'audio/mpeg-3'});
            recordedAudio.src = URL.createObjectURL(blob);
            recordedAudio.controls = true;

            var url = recordedAudio.src;
            var link = document.getElementById("download");
            link.href = url;
            link.download = 'audio.wav';
        }
    }
}

HTML part to create the controls: record, stop, then download the recorded audio:

<button id="record">Record</button>
<button id="stopRecord">Stop</button>
<p> <audio id="recordedAudio"></audio></p>
<div id="recordings"><a id="download"> Download</a></div>

Then I have a file chooser and an AngularJS directive to upload a file - after calling: doUploadFile() the file gets to the controller and is being uploaded to the server.

Uploading works fine with selecting the file, but I don't know how to combine the 2 pieces of code together.

<form>
    <input type="file" file-model="uploadedFile">
    <button type="submit" ng-click="doUploadFile()">Upload</button>
</form> 

File upload directive:

.directive('fileModel', ['$parse', function($parse) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var model = $parse(attrs.fileModel);
            var modelSetter = model.assign;

            element.bind('change', function() {
                scope.$apply(function() {
                    modelSetter(scope, element[0].files[0]);
                });
            });
        }
    };
}]);

What I want to achieve here:

  1. After finishing recording a button/link pops up

  2. This link is associated with the recorded audio file

  3. Clicking this button calls the doUploadFile() method

How to modify the code and put the 2 pieces together so we can upload straight after recording is finished?

I'm still new to AngularJS, would be very happy for your help!

szark
  • 77
  • 10
  • found this post, will try out the modification: https://stackoverflow.com/questions/13333378/how-can-javascript-upload-a-blob – szark Sep 21 '18 at 17:34

1 Answers1

0

EDIT

Managed to get it working: Erased the form for file upload. The directive is also not needed anymore. I put the code for the recording and uploading together. I added a FormData object inside of the controller and appended the blob. Works fine now.

var data = new FormData();


$scope.doUploadFile = function() {
    var url = "/uploadfile";

    var config = {
            transformRequest: angular.identity,
            transformResponse: angular.identity,
            headers : { 'Content-Type': undefined }
    }

    $http.post(url, data, config)
    .then(function(response) {
        $scope.uploadResult = response.data;
        data = new FormData();
    });
};

navigator.mediaDevices.getUserMedia({audio:true})
.then(stream => {handlerFunction(stream)})

function handlerFunction(stream) {
    rec = new MediaRecorder(stream);
    rec.ondataavailable = e => {
        audioChunks.push(e.data);
        if(rec.state == "inactive") {

            let blob = new Blob(audioChunks, {type:'audio/mpeg-3'});
            recordedAudio.src = URL.createObjectURL(blob);
            recordedAudio.controls = true;
            recordedAudio.autoplay = false;

            var url = recordedAudio.src;

            data.append('uploadfile', blob, "recording.wav");
        }
    }
}
szark
  • 77
  • 10