@lls/lls-audio 0.0.59 → 0.0.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +27 -25
- package/player/Play.js +13 -7
- package/player/styles/styles.js +31 -14
- package/recorder/AudioWorker.js +134 -0
- package/recorder/Visualizer.js +33 -0
- package/recorder/index.js +202 -15
- package/stories/index.js +12 -6
- package/{recorder/AsyncLoader.js → stories/visualizer.js} +43 -50
- package/stories/wordDetector.js +97 -0
- package/utils/audio.js +26 -141
- package/utils/mediaDevices.js +33 -0
- package/wordDetector/index.js +139 -0
- package/recorder/DesktopAudioRecorder.js +0 -190
- package/recorder/DesktopRecorder.js +0 -143
- package/stories/recorder.js +0 -30
|
@@ -10,75 +10,68 @@ var _react = require('react');
|
|
|
10
10
|
|
|
11
11
|
var _react2 = _interopRequireDefault(_react);
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
var _player = require('../player');
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
var _player2 = _interopRequireDefault(_player);
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
var _recorder = require('../recorder');
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
var _recorder2 = _interopRequireDefault(_recorder);
|
|
20
|
+
|
|
21
|
+
var _Visualizer = require('../recorder/Visualizer');
|
|
20
22
|
|
|
21
|
-
var
|
|
23
|
+
var _Visualizer2 = _interopRequireDefault(_Visualizer);
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
var href = _ref.href;
|
|
25
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
link.rel = 'stylesheet';
|
|
28
|
-
link.type = 'text/css';
|
|
29
|
-
link.href = href;
|
|
30
|
-
link.media = 'all';
|
|
31
|
-
return link;
|
|
32
|
-
};
|
|
27
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
33
28
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
onError = _ref2.onError;
|
|
29
|
+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
|
30
|
+
|
|
31
|
+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
|
38
32
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
script.src = src;
|
|
42
|
-
script.async = false;
|
|
43
|
-
script.onload = onload;
|
|
44
|
-
script.onerror = onError;
|
|
45
|
-
return script;
|
|
46
|
-
};
|
|
33
|
+
var VisualizerExample = function (_Component) {
|
|
34
|
+
_inherits(VisualizerExample, _Component);
|
|
47
35
|
|
|
48
|
-
|
|
49
|
-
|
|
36
|
+
function VisualizerExample(props) {
|
|
37
|
+
_classCallCheck(this, VisualizerExample);
|
|
50
38
|
|
|
51
|
-
|
|
52
|
-
_classCallCheck(this, AsyncLoader);
|
|
39
|
+
var _this = _possibleConstructorReturn(this, (VisualizerExample.__proto__ || Object.getPrototypeOf(VisualizerExample)).call(this, props));
|
|
53
40
|
|
|
54
|
-
|
|
41
|
+
_this.state = {
|
|
42
|
+
volume: 0
|
|
43
|
+
};
|
|
44
|
+
_this.setVolume = _this.setVolume.bind(_this);
|
|
45
|
+
return _this;
|
|
55
46
|
}
|
|
56
47
|
|
|
57
|
-
_createClass(
|
|
58
|
-
key: '
|
|
59
|
-
value: function
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
_props$onLoad = _props.onLoad,
|
|
64
|
-
onLoad = _props$onLoad === undefined ? function () {} : _props$onLoad,
|
|
65
|
-
_props$onError = _props.onError,
|
|
66
|
-
onError = _props$onError === undefined ? function () {} : _props$onError;
|
|
67
|
-
|
|
68
|
-
if (src && !loadedScripts.includes(href || src)) {
|
|
69
|
-
var el = href ? getCssEl({ href: href }) : getScriptEl({ src: src, onLoad: onLoad, onError: onError });
|
|
70
|
-
document.body.appendChild(el);
|
|
71
|
-
loadedScripts.push(href || src);
|
|
72
|
-
}
|
|
48
|
+
_createClass(VisualizerExample, [{
|
|
49
|
+
key: 'setVolume',
|
|
50
|
+
value: function setVolume(volume) {
|
|
51
|
+
this.setState({
|
|
52
|
+
volume: volume
|
|
53
|
+
});
|
|
73
54
|
}
|
|
74
55
|
}, {
|
|
75
56
|
key: 'render',
|
|
76
57
|
value: function render() {
|
|
77
|
-
|
|
58
|
+
var volume = this.state.volume;
|
|
59
|
+
|
|
60
|
+
return _react2.default.createElement(
|
|
61
|
+
'div',
|
|
62
|
+
null,
|
|
63
|
+
_react2.default.createElement(_recorder2.default, {
|
|
64
|
+
onVolumeChange: this.setVolume,
|
|
65
|
+
onError: function onError(err) {
|
|
66
|
+
return console.log('error', err);
|
|
67
|
+
}
|
|
68
|
+
}),
|
|
69
|
+
_react2.default.createElement(_Visualizer2.default, { volume: volume })
|
|
70
|
+
);
|
|
78
71
|
}
|
|
79
72
|
}]);
|
|
80
73
|
|
|
81
|
-
return
|
|
74
|
+
return VisualizerExample;
|
|
82
75
|
}(_react.Component);
|
|
83
76
|
|
|
84
|
-
exports.default =
|
|
77
|
+
exports.default = VisualizerExample;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
8
|
+
|
|
9
|
+
var _react = require('react');
|
|
10
|
+
|
|
11
|
+
var _react2 = _interopRequireDefault(_react);
|
|
12
|
+
|
|
13
|
+
var _player = require('../player');
|
|
14
|
+
|
|
15
|
+
var _player2 = _interopRequireDefault(_player);
|
|
16
|
+
|
|
17
|
+
var _wordDetector = require('../wordDetector');
|
|
18
|
+
|
|
19
|
+
var _wordDetector2 = _interopRequireDefault(_wordDetector);
|
|
20
|
+
|
|
21
|
+
var _Visualizer = require('../recorder/Visualizer');
|
|
22
|
+
|
|
23
|
+
var _Visualizer2 = _interopRequireDefault(_Visualizer);
|
|
24
|
+
|
|
25
|
+
var _recorder = require('../recorder');
|
|
26
|
+
|
|
27
|
+
var _recorder2 = _interopRequireDefault(_recorder);
|
|
28
|
+
|
|
29
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
30
|
+
|
|
31
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
32
|
+
|
|
33
|
+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
|
34
|
+
|
|
35
|
+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
|
36
|
+
|
|
37
|
+
var onError = function onError(e) {
|
|
38
|
+
return console.log("onError", e);
|
|
39
|
+
};
|
|
40
|
+
var onSuccess = function onSuccess(res, attempts) {
|
|
41
|
+
return console.log({ res: res, attempts: attempts });
|
|
42
|
+
};
|
|
43
|
+
var onFailure = function onFailure(res, attempts) {
|
|
44
|
+
return console.log({ res: res, attempts: attempts });
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
var WordDetectorExample = function (_Component) {
|
|
48
|
+
_inherits(WordDetectorExample, _Component);
|
|
49
|
+
|
|
50
|
+
function WordDetectorExample(props) {
|
|
51
|
+
_classCallCheck(this, WordDetectorExample);
|
|
52
|
+
|
|
53
|
+
var _this = _possibleConstructorReturn(this, (WordDetectorExample.__proto__ || Object.getPrototypeOf(WordDetectorExample)).call(this, props));
|
|
54
|
+
|
|
55
|
+
_this.state = {
|
|
56
|
+
volume: 0
|
|
57
|
+
};
|
|
58
|
+
_this.setVolume = _this.setVolume.bind(_this);
|
|
59
|
+
return _this;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
_createClass(WordDetectorExample, [{
|
|
63
|
+
key: 'setVolume',
|
|
64
|
+
value: function setVolume(volume) {
|
|
65
|
+
this.setState({
|
|
66
|
+
volume: volume
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}, {
|
|
70
|
+
key: 'render',
|
|
71
|
+
value: function render() {
|
|
72
|
+
var volume = this.state.volume;
|
|
73
|
+
|
|
74
|
+
return _react2.default.createElement(
|
|
75
|
+
'div',
|
|
76
|
+
null,
|
|
77
|
+
_react2.default.createElement(
|
|
78
|
+
'div',
|
|
79
|
+
null,
|
|
80
|
+
'Say "Hello"'
|
|
81
|
+
),
|
|
82
|
+
_react2.default.createElement(_wordDetector2.default, {
|
|
83
|
+
word: 'hello',
|
|
84
|
+
onVolumeChange: this.setVolume,
|
|
85
|
+
onError: onError,
|
|
86
|
+
onSuccess: onSuccess,
|
|
87
|
+
onFailure: onFailure
|
|
88
|
+
}),
|
|
89
|
+
_react2.default.createElement(_Visualizer2.default, { volume: volume })
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}]);
|
|
93
|
+
|
|
94
|
+
return WordDetectorExample;
|
|
95
|
+
}(_react.Component);
|
|
96
|
+
|
|
97
|
+
exports.default = WordDetectorExample;
|
package/utils/audio.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.getWaveform = undefined;
|
|
7
7
|
|
|
8
8
|
var _audioContext = require('./audioContext');
|
|
9
9
|
|
|
@@ -47,166 +47,51 @@ var getWaveform = exports.getWaveform = function getWaveform(url) {
|
|
|
47
47
|
});
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
/*
|
|
51
|
+
export const convertAudioBufferToWaveform = (audioBuffer) => {
|
|
51
52
|
// All this code (except the last line) is stolen/inspired from https://github.com/bbc/waveform-data.js/blob/master/lib/builders/audiodecoder.js
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
dataObject.setInt32(
|
|
65
|
-
dataObject.
|
|
66
|
-
dataObject.setInt32(8, audioBuffer.sampleRate, true); //sample rate
|
|
67
|
-
dataObject.setInt32(12, scale, true); //scale
|
|
68
|
-
dataObject.setInt32(16, dataLength, true); //length
|
|
53
|
+
const scale = 512
|
|
54
|
+
const scaleAdjuster = 127
|
|
55
|
+
const dataLength = Math.floor(audioBuffer.length / scale)
|
|
56
|
+
let offset = 20
|
|
57
|
+
const dataObject = new DataView(new ArrayBuffer(offset + dataLength * 2))
|
|
58
|
+
let leftChannel, rightChannel
|
|
59
|
+
let minValue = Infinity, max_value = -Infinity, scale_counter = scale;
|
|
60
|
+
const bufferLength = audioBuffer.length
|
|
61
|
+
|
|
62
|
+
dataObject.setInt32(0, 1, true); //version
|
|
63
|
+
dataObject.setUint32(4, 1, true); //is 8 bit
|
|
64
|
+
dataObject.setInt32(8, audioBuffer.sampleRate, true); //sample rate
|
|
65
|
+
dataObject.setInt32(12, scale, true); //scale
|
|
66
|
+
dataObject.setInt32(16, dataLength, true); //length
|
|
69
67
|
|
|
70
68
|
leftChannel = audioBuffer.getChannelData(0);
|
|
71
69
|
rightChannel = audioBuffer.getChannelData(1);
|
|
72
70
|
|
|
73
|
-
for (
|
|
74
|
-
|
|
71
|
+
for (let i = 0; i < bufferLength; i++){
|
|
72
|
+
const sample = (leftChannel[i] + rightChannel[i]) / 2 * scaleAdjuster;
|
|
75
73
|
|
|
76
|
-
if (sample < minValue)
|
|
74
|
+
if (sample < minValue){
|
|
77
75
|
minValue = sample;
|
|
78
76
|
if (minValue < -128) {
|
|
79
77
|
minValue = -128;
|
|
80
78
|
}
|
|
81
79
|
}
|
|
82
80
|
|
|
83
|
-
if (sample > max_value)
|
|
81
|
+
if (sample > max_value){
|
|
84
82
|
max_value = sample;
|
|
85
83
|
if (max_value > 127) {
|
|
86
84
|
max_value = 127;
|
|
87
85
|
}
|
|
88
86
|
}
|
|
89
87
|
|
|
90
|
-
if (--scale_counter === 0)
|
|
88
|
+
if (--scale_counter === 0){
|
|
91
89
|
dataObject.setInt8(offset++, Math.floor(minValue));
|
|
92
90
|
dataObject.setInt8(offset++, Math.floor(max_value));
|
|
93
|
-
minValue = Infinity;max_value = -Infinity;scale_counter = scale;
|
|
91
|
+
minValue = Infinity; max_value = -Infinity; scale_counter = scale;
|
|
94
92
|
}
|
|
95
93
|
}
|
|
96
94
|
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
var appendBuffer = exports.appendBuffer = function appendBuffer(buffer1, buffer2) {
|
|
101
|
-
if (!buffer1) return buffer2;
|
|
102
|
-
if (!buffer2) return buffer1;
|
|
103
|
-
var numberOfChannels = Math.min(buffer1.numberOfChannels, buffer2.numberOfChannels);
|
|
104
|
-
var tmp = audioContext.createBuffer(numberOfChannels, buffer1.length + buffer2.length, buffer1.sampleRate);
|
|
105
|
-
for (var i = 0; i < numberOfChannels; i++) {
|
|
106
|
-
var channel = tmp.getChannelData(i);
|
|
107
|
-
channel.set(buffer1.getChannelData(i), 0);
|
|
108
|
-
channel.set(buffer2.getChannelData(i), buffer1.length);
|
|
109
|
-
}
|
|
110
|
-
return tmp;
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
var convertBlobToaudioBuffer = exports.convertBlobToaudioBuffer = function convertBlobToaudioBuffer(blob, cb) {
|
|
114
|
-
var fileReader = new FileReader();
|
|
115
|
-
fileReader.onload = function (_ref) {
|
|
116
|
-
var result = _ref.target.result;
|
|
117
|
-
|
|
118
|
-
audioContext.decodeAudioData(result, function (buf) {
|
|
119
|
-
cb(buf);
|
|
120
|
-
});
|
|
121
|
-
};
|
|
122
|
-
fileReader.readAsArrayBuffer(blob);
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
var audioBufferToWav = exports.audioBufferToWav = function audioBufferToWav(buffer, opt) {
|
|
126
|
-
opt = opt || {};
|
|
127
|
-
|
|
128
|
-
var numChannels = buffer.numberOfChannels;
|
|
129
|
-
var sampleRate = buffer.sampleRate;
|
|
130
|
-
var format = opt.float32 ? 3 : 1;
|
|
131
|
-
var bitDepth = format === 3 ? 32 : 16;
|
|
132
|
-
|
|
133
|
-
var result = numChannels === 2 ? interleave(buffer.getChannelData(0), buffer.getChannelData(1)) : buffer.getChannelData(0);
|
|
134
|
-
|
|
135
|
-
return encodeWAV(result, format, sampleRate, numChannels, bitDepth);
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
var encodeWAV = function encodeWAV(samples, format, sampleRate, numChannels, bitDepth) {
|
|
139
|
-
var bytesPerSample = bitDepth / 8;
|
|
140
|
-
var blockAlign = numChannels * bytesPerSample;
|
|
141
|
-
|
|
142
|
-
var buffer = new ArrayBuffer(44 + samples.length * bytesPerSample);
|
|
143
|
-
var view = new DataView(buffer);
|
|
144
|
-
|
|
145
|
-
/* RIFF identifier */
|
|
146
|
-
writeString(view, 0, 'RIFF');
|
|
147
|
-
/* RIFF chunk length */
|
|
148
|
-
view.setUint32(4, 36 + samples.length * bytesPerSample, true);
|
|
149
|
-
/* RIFF type */
|
|
150
|
-
writeString(view, 8, 'WAVE');
|
|
151
|
-
/* format chunk identifier */
|
|
152
|
-
writeString(view, 12, 'fmt ');
|
|
153
|
-
/* format chunk length */
|
|
154
|
-
view.setUint32(16, 16, true);
|
|
155
|
-
/* sample format (raw) */
|
|
156
|
-
view.setUint16(20, format, true);
|
|
157
|
-
/* channel count */
|
|
158
|
-
view.setUint16(22, numChannels, true);
|
|
159
|
-
/* sample rate */
|
|
160
|
-
view.setUint32(24, sampleRate, true);
|
|
161
|
-
/* byte rate (sample rate * block align) */
|
|
162
|
-
view.setUint32(28, sampleRate * blockAlign, true);
|
|
163
|
-
/* block align (channel count * bytes per sample) */
|
|
164
|
-
view.setUint16(32, blockAlign, true);
|
|
165
|
-
/* bits per sample */
|
|
166
|
-
view.setUint16(34, bitDepth, true);
|
|
167
|
-
/* data chunk identifier */
|
|
168
|
-
writeString(view, 36, 'data');
|
|
169
|
-
/* data chunk length */
|
|
170
|
-
view.setUint32(40, samples.length * bytesPerSample, true);
|
|
171
|
-
if (format === 1) {
|
|
172
|
-
// Raw PCM
|
|
173
|
-
floatTo16BitPCM(view, 44, samples);
|
|
174
|
-
} else {
|
|
175
|
-
writeFloat32(view, 44, samples);
|
|
176
|
-
}
|
|
177
|
-
return buffer;
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
var interleave = function interleave(inputL, inputR) {
|
|
181
|
-
var length = inputL.length + inputR.length;
|
|
182
|
-
var result = new Float32Array(length);
|
|
183
|
-
|
|
184
|
-
var index = 0;
|
|
185
|
-
var inputIndex = 0;
|
|
186
|
-
|
|
187
|
-
while (index < length) {
|
|
188
|
-
result[index++] = inputL[inputIndex];
|
|
189
|
-
result[index++] = inputR[inputIndex];
|
|
190
|
-
inputIndex++;
|
|
191
|
-
}
|
|
192
|
-
return result;
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
var writeFloat32 = function writeFloat32(output, offset, input) {
|
|
196
|
-
for (var i = 0; i < input.length; i++, offset += 4) {
|
|
197
|
-
output.setFloat32(offset, input[i], true);
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
var floatTo16BitPCM = function floatTo16BitPCM(output, offset, input) {
|
|
202
|
-
for (var i = 0; i < input.length; i++, offset += 2) {
|
|
203
|
-
var s = Math.max(-1, Math.min(1, input[i]));
|
|
204
|
-
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
var writeString = function writeString(view, offset, string) {
|
|
209
|
-
for (var i = 0; i < string.length; i++) {
|
|
210
|
-
view.setUint8(offset + i, string.charCodeAt(i));
|
|
211
|
-
}
|
|
212
|
-
};
|
|
95
|
+
return WaveformData.create(dataObject.buffer)
|
|
96
|
+
}
|
|
97
|
+
*/
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var shimMediaDevices = exports.shimMediaDevices = function shimMediaDevices() {
|
|
7
|
+
// Older browsers might not implement mediaDevices at all, so we set an empty object first
|
|
8
|
+
if (window.navigator.mediaDevices === undefined) {
|
|
9
|
+
window.navigator.mediaDevices = {};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Some browsers partially implement mediaDevices. We can't just assign an object
|
|
13
|
+
// with getUserMedia as it would overwrite existing properties.
|
|
14
|
+
// Here, we will just add the getUserMedia property if it's missing.
|
|
15
|
+
if (window.navigator.mediaDevices.getUserMedia === undefined) {
|
|
16
|
+
window.navigator.mediaDevices.getUserMedia = function (constraints) {
|
|
17
|
+
|
|
18
|
+
// First get ahold of the legacy getUserMedia, if present
|
|
19
|
+
var getUserMedia = window.navigator.webkitGetUserMedia || window.navigator.mozGetUserMedia;
|
|
20
|
+
|
|
21
|
+
// Some browsers just don't implement it - return a rejected promise with an error
|
|
22
|
+
// to keep a consistent interface
|
|
23
|
+
if (!getUserMedia) {
|
|
24
|
+
return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
|
|
28
|
+
return new Promise(function (resolve, reject) {
|
|
29
|
+
getUserMedia.call(navigator, constraints, resolve, reject);
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
8
|
+
|
|
9
|
+
var _react = require('react');
|
|
10
|
+
|
|
11
|
+
var _react2 = _interopRequireDefault(_react);
|
|
12
|
+
|
|
13
|
+
var _recorder = require('../recorder');
|
|
14
|
+
|
|
15
|
+
var _recorder2 = _interopRequireDefault(_recorder);
|
|
16
|
+
|
|
17
|
+
var _similarity = require('similarity');
|
|
18
|
+
|
|
19
|
+
var _similarity2 = _interopRequireDefault(_similarity);
|
|
20
|
+
|
|
21
|
+
var _fileSaver = require('file-saver');
|
|
22
|
+
|
|
23
|
+
var _fileSaver2 = _interopRequireDefault(_fileSaver);
|
|
24
|
+
|
|
25
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
26
|
+
|
|
27
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
28
|
+
|
|
29
|
+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
|
30
|
+
|
|
31
|
+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
|
32
|
+
|
|
33
|
+
var API_URL = 'http://localhost:3004/speechtotext';
|
|
34
|
+
var SIMILARITY_THRESHOLD = 0.8;
|
|
35
|
+
|
|
36
|
+
var debug = function debug(wav) {
|
|
37
|
+
_fileSaver2.default.saveAs(wav, 'test.wav');
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
var sendFileToSpeechToTextApi = function sendFileToSpeechToTextApi(wav) {
|
|
41
|
+
return new Promise(function (resolve, reject) {
|
|
42
|
+
var xhr = new XMLHttpRequest();
|
|
43
|
+
xhr.open('POST', API_URL, true);
|
|
44
|
+
|
|
45
|
+
xhr.onreadystatechange = function () {
|
|
46
|
+
if (xhr.readyState == 4 && xhr.status == 200) {
|
|
47
|
+
console.log('Speech to text: ', xhr.responseText);
|
|
48
|
+
resolve(xhr.responseText);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
xhr.onerror = function () {
|
|
52
|
+
reject();
|
|
53
|
+
};
|
|
54
|
+
xhr.setRequestHeader('Content-Type', 'audio/wav');
|
|
55
|
+
xhr.send(wav);
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
var defaultCompare = function defaultCompare() {
|
|
60
|
+
var a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
|
61
|
+
var b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
|
|
62
|
+
return (0, _similarity2.default)(a.toLowerCase().trim(), b.toLowerCase().trim()) > SIMILARITY_THRESHOLD;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
var WordDetector = function (_Component) {
|
|
66
|
+
_inherits(WordDetector, _Component);
|
|
67
|
+
|
|
68
|
+
function WordDetector(props) {
|
|
69
|
+
_classCallCheck(this, WordDetector);
|
|
70
|
+
|
|
71
|
+
var _this = _possibleConstructorReturn(this, (WordDetector.__proto__ || Object.getPrototypeOf(WordDetector)).call(this, props));
|
|
72
|
+
|
|
73
|
+
_this.state = {
|
|
74
|
+
attempts: 0
|
|
75
|
+
};
|
|
76
|
+
_this.onError = _this.onError.bind(_this);
|
|
77
|
+
_this.onResult = _this.onResult.bind(_this);
|
|
78
|
+
_this.onRecordComplete = _this.onRecordComplete.bind(_this);
|
|
79
|
+
return _this;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
_createClass(WordDetector, [{
|
|
83
|
+
key: 'onRecordComplete',
|
|
84
|
+
value: function onRecordComplete(wav) {
|
|
85
|
+
var _this2 = this;
|
|
86
|
+
|
|
87
|
+
//debug(wav)
|
|
88
|
+
|
|
89
|
+
sendFileToSpeechToTextApi(wav).then(function (res) {
|
|
90
|
+
_this2.onResult(res);
|
|
91
|
+
}).catch(function (e) {
|
|
92
|
+
_this2.onError(e);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}, {
|
|
96
|
+
key: 'onError',
|
|
97
|
+
value: function onError(e) {
|
|
98
|
+
var _props$onError = this.props.onError,
|
|
99
|
+
onError = _props$onError === undefined ? function () {} : _props$onError;
|
|
100
|
+
|
|
101
|
+
onError(e);
|
|
102
|
+
}
|
|
103
|
+
}, {
|
|
104
|
+
key: 'onResult',
|
|
105
|
+
value: function onResult() {
|
|
106
|
+
var res = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
|
107
|
+
var attempts = this.state.attempts;
|
|
108
|
+
var _props = this.props,
|
|
109
|
+
word = _props.word,
|
|
110
|
+
_props$onSuccess = _props.onSuccess,
|
|
111
|
+
onSuccess = _props$onSuccess === undefined ? function () {} : _props$onSuccess,
|
|
112
|
+
_props$onFailure = _props.onFailure,
|
|
113
|
+
onFailure = _props$onFailure === undefined ? function () {} : _props$onFailure,
|
|
114
|
+
_props$compare = _props.compare,
|
|
115
|
+
compare = _props$compare === undefined ? defaultCompare : _props$compare;
|
|
116
|
+
|
|
117
|
+
var incrementedAttempts = attempts + 1;
|
|
118
|
+
var success = compare(word, res);
|
|
119
|
+
this.setState({
|
|
120
|
+
attempts: success ? 0 : incrementedAttempts
|
|
121
|
+
}, function () {
|
|
122
|
+
var cb = success ? onSuccess : onFailure;
|
|
123
|
+
cb(res, incrementedAttempts);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}, {
|
|
127
|
+
key: 'render',
|
|
128
|
+
value: function render() {
|
|
129
|
+
var _props$onVolumeChange = this.props.onVolumeChange,
|
|
130
|
+
onVolumeChange = _props$onVolumeChange === undefined ? function () {} : _props$onVolumeChange;
|
|
131
|
+
|
|
132
|
+
return _react2.default.createElement(_recorder2.default, { onError: this.onError, onVolumeChange: onVolumeChange, onRecordComplete: this.onRecordComplete });
|
|
133
|
+
}
|
|
134
|
+
}]);
|
|
135
|
+
|
|
136
|
+
return WordDetector;
|
|
137
|
+
}(_react.Component);
|
|
138
|
+
|
|
139
|
+
exports.default = WordDetector;
|