Search code examples
javascriptazureazure-cognitive-servicesvoice-recognitionrecorder.js

recorder.js to node to azure speaker recognition


I have a browser app which records the user's voice through their microphone and exports to a WAV file using recorder.js. I think convert that to a data url and post it to node. I then try to send the audio to the Microsoft Azure Speaker Recognition API but I always get "Invalid Audio Format: Not a WAVE file - no RIFF header" back.

Is there a way to add a RIFF header or is there something about recorder.js or converting to and from base64 which removes these headers? Is there a way to add them back in?

The code: INDEX.HTML

rec.exportWAV(function (blob) {
    var reader = new window.FileReader();
    reader.readAsDataURL(blob);
    reader.onloadend = function () {
        base64 = reader.result;
        console.log(base64)
        $.ajax({
            type: "POST",
            url: '/addVoiceToProfile',
            data: { userId: '', voiceId: "XXX-XXX", voice: base64, sampleRate: audioContext.sampleRate / 1000 },
            success: function (results) {
                console.log(results)
            }
        })
    }
})

NODE ROUTE:

app.post('/addVoiceToProfile', function(req, res){
    var voicedata = req.body.voice;
    var base64Data = voicedata.replace(/^data:([A-Za-z-+/]+);base64,/, '');
    addVoicesToProfile(base64Data, req.body.voiceId).then(function(results){
        res.send(results)
    })
})

addVoicesToProfile:

function addVoicesToProfile(voice, id, user){
    return new Promise(function (resolve, reject) {
        var url = AzureParameters.endPoint+"/spid/v1.0/verificationProfiles/"+id+"/enroll";
        request({
            url:url,
            headers:{'Content-Type':'audio/wave', 'Ocp-Apim-Subscription-Key':AzureParameters.key},
            body: Buffer.from(voice, 'base64').toString('binary'),
            method: "POST",
            json: true
        }, function(err, response, body){
            if(err) return reject(err);
            return resolve(body)
        })
    })
}

Solution

  • It seems like the problem was actually the way the file was being sent. I don't know why it works if it is sent as a wav in the body of the post, not as data in the post, but here is my working code if it is helpful for anyone in the future:

    html:

    I used this answer for the html. it includes the encoding for the wav. The only change I made was, as the answer suggests, I post to my server, not directly to the MS Azure service.

    node route:

    This took me a while as I couldn't get node to see the file I was sending. Also I am using bodyParser so the raw body of post requests is fiddled with before I see it. This is my route for the post request:

      app.post('/uploadAudio', function (req, res, next) {
        var data = new Buffer('');
        req.on('data', function (chunk) {
            data = Buffer.concat([data, chunk]);
        });
        req.on('end', function () {
            req.rawBody = data;
            next();
        });
      }, function (req, res) {
        addVoicesToProfile(req.rawBody)
      })
    

    I hope this helps someone because both parts of this took me way too long to work out!