diff --git a/.gitignore b/.gitignore index ade14b9..6d0dce1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .DS_Store npm-debug.log node_modules +lib/recordings diff --git a/lib/d4179581-bdc7-1ea3-f040-c3ed3feec22b.wav b/lib/d4179581-bdc7-1ea3-f040-c3ed3feec22b.wav deleted file mode 100644 index 864a515..0000000 Binary files a/lib/d4179581-bdc7-1ea3-f040-c3ed3feec22b.wav and /dev/null differ diff --git a/lib/vendor/recorder b/lib/vendor/recorder deleted file mode 160000 index ac0eb8a..0000000 --- a/lib/vendor/recorder +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ac0eb8a7c2601fc4ec1cbd1b1ee49f45a6c79580 diff --git a/lib/voice-assist.js b/lib/voice-assist.js index 8fa90c0..794dd8c 100644 --- a/lib/voice-assist.js +++ b/lib/voice-assist.js @@ -37,14 +37,20 @@ recorder.serialize = function() { return {}; }; -var voiceRecorder = require('./voiceRecorder'); +var voiceRecorder = require('./voiceRecorder'), + audioPromises + recorder.on('start', function() { - var transcriptPromise = voiceRecorder.start(); - transcriptPromise.then(function(transcript) { - console.log(transcript); - }); + voiceRecorder.start(); }).on('stop', function() { - voiceRecorder.stop(); + var promises = voiceRecorder.stop(), + wavPromise = promises.wav, + transcriptPromise = promises.transcript; + Promise.all([wavPromise, transcriptPromise]).then(function(info) { + var wavFilename = info.wavFilename, + transcript = info.transcript; + console.log(wavFilename, transcript); + }); }).on('cancel', function() { voiceRecorder.cancel(); }) diff --git a/lib/voiceRecorder.js b/lib/voiceRecorder.js index 444892d..8d08e8e 100644 --- a/lib/voiceRecorder.js +++ b/lib/voiceRecorder.js @@ -1,13 +1,25 @@ var _ = require('./vendor/underscore'), - wav = require('wav'); -require('./vendor/recorder/recorder') + RecordRTC = require('recordrtc'), + fs = require('fs'), + mkdirpLib = require('mkdirp'); +var RECORDING_STORAGE_DIRECTORY = __dirname + '/recordings/'; var recognitionEngine = new webkitSpeechRecognition(); -recognitionEngine.continuous = false; +recognitionEngine.continue = false; recognitionEngine.interimResults = false; recognitionEngine.maxResults = 1; +function guid() { + function s4() { + return Math .floor((1 + Math.random()) * 0x10000) + .toString(16) + .substring(1); + } + return s4() + s4() + '-' + s4() + '-' + s4() + '-' + + s4() + '-' + s4() + s4() + s4(); +} + function getUserMedia() { return new Promise(function(resolve, reject) { try { @@ -23,116 +35,85 @@ function getUserMedia() { } }); } -var audioStream, wavWriter; -/* -function convertFloat32ToInt16(buffer) { - var l = buffer.length, - buf = new Int16Array(l); - while (l--) { - buf[l] = Math.min(1, buffer[l])*0x7FFF; - } - return buf.buffer; -} -*/ -var audioStreamPromise; -var recording = false; -var recorder; - -function startRecording() { - recording = true; - var transcriptPromise = new Promise(function(resolve, reject) { - recognitionEngine.start(); - recognitionEngine.onresult = function(event) { - var results = event.results, - mostLikelyResult = results[0][0].transcript; - resolve(mostLikelyResult); - }; - recognitionEngine.onend = function() { - _.delay(function() { - resolve(""); - }, 3000); - } - }); - var wavName = __dirname+'/' + guid()+".wav"; - audioStreamPromise = getUserMedia().then(function(audioStream) { - var audio_context = new AudioContext(); - var input = audio_context.createMediaStreamSource(audioStream); - recorder = new Recorder(input); - recorder.record(); - return audioStream; - }); - /* - - wavWriter = new wav.FileWriter(wavName, { - channels: 1, - sampleRate: 44100, - bitDepth: 16 - }); - //stream.pipe(fileWriter); - - audioStreamPromise = getUserMedia().then(function(audioStream) { - var context = new AudioContext(), - audioInput = context.createMediaStreamSource(audioStream), - bufferSize = 2048, - recorderProcessor = context.createScriptProcessor(bufferSize, 1, 1); // create a javascript node - - // specify the processing function - recorderProcessor.onaudioprocess = function(e) { - if(recording) { - var left = e.inputBuffer.getChannelData(0); - var convertedVal = convertFloat32ToInt16(left); - console.log(left); - wavWriter.write(convertedVal.toString()); +function mkdirp(path) { + return new Promise(function(resolve, reject) { + mkdirpLib(path, function(err) { + if(err) { + reject(err); + } else { + resolve(path); } - }; - - // connect stream to our recorder - audioInput.connect(recorderProcessor); - - // connect our recorder to the previous destination - recorderProcessor.connect(context.destination); - - return audioStream; - }); - */ - - return transcriptPromise; -} - -function stopRecording() { - recording = false; - //wavWriter.end(); - - recognitionEngine.stop(); - audioStreamPromise.then(function(audioStream) { - recorder.stop(); - audioStream.stop(); - recorder.exportWAV(function(blob) { - var reader = new FileReader(); - reader.addEventListener("loadend", function() { - console.log(reader.result); - }); - reader.readAsArrayBuffer(blob); }); }); } -function cancelRecording() { - recognitionEngine.abort(); -} +var transcriptPromise, audioStreamPromise, recorder; module.exports = { - start: startRecording, - stop: stopRecording, - cancel: cancelRecording -} - -function guid() { - function s4() { - return Math .floor((1 + Math.random()) * 0x10000) - .toString(16) - .substring(1); + start: function () { + transcriptPromise = new Promise(function(resolve, reject) { + recognitionEngine.start(); + recognitionEngine.onresult = function(event) { + var results = event.results, + mostLikelyResult = results[0][0].transcript; + resolve(mostLikelyResult); + }; + recognitionEngine.onend = function() { + _.delay(function() { + resolve(""); + }, 3000); + } + }); + audioStreamPromise = getUserMedia().then(function(audioStream) { + recorder = RecordRTC(audioStream); + recorder.startRecording(); + return audioStream; + }); + }, + stop: function() { + recognitionEngine.stop(); + var wavPromise = audioStreamPromise.then(function(audioStream) { + return new Promise(function(resolve, reject) { + recorder.stopRecording(function() { + resolve(recorder.getBlob()); + }); + audioStream.stop(); + }); + }).then(function(blob) { + return new Promise(function(resolve, reject) { + var fr = new FileReader(); + fr.addEventListener("loadend", function() { + resolve(fr.result); + + }) + fr.readAsBinaryString(blob); + }); + }).then(function(binaryContent) { + var filename = guid() + ".wav", + fullFilename = RECORDING_STORAGE_DIRECTORY + filename; + + return mkdirp(RECORDING_STORAGE_DIRECTORY).then(function() { + return new Promise(function(resolve, reject) { + fs.writeFile(fullFilename, binaryContent, "binary", function(err) { + if(err) { + reject(err); + } else { + resolve(fullFilename); + } + }); + }); + }); + }); + + return { + transcript: transcriptPromise, + wav: wavPromise + }; + }, + cancel: function() { + recognitionEngine.abort(); + wavPromise.then(function(audioStream) { + audioStream.stop(); + }); } - return s4() + s4() + '-' + s4() + '-' + s4() + '-' + - s4() + '-' + s4() + s4() + s4(); } diff --git a/package.json b/package.json index 9800d80..a5fa552 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "atom": ">=1.0.0 <2.0.0" }, "dependencies": { - "wav": "latest" + "recordrtc": "latest", + "mkdirp": "latest", + "lame": "latest" } }