Skip to content

Commit 99d4bcf

Browse files
author
Mikhail Baranov
committed
add widget for record audio answer
1 parent 1235911 commit 99d4bcf

File tree

4 files changed

+172
-2
lines changed

4 files changed

+172
-2
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"live-server": "^1.2.0",
2424
"nouislider": "^10.1.0",
2525
"pretty-checkbox": "^3.0.3",
26+
"recordrtc": "^5.4.6",
2627
"select2": "^4.0.4",
2728
"signature_pad": "^2.3.2",
2829
"sortablejs": "^1.6.1",

src/microphone.js

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import RecordRTC from "recordrtc";
2+
3+
function init(Survey) {
4+
var widget = {
5+
6+
name: "microphone",
7+
title: "Microphone",
8+
iconName: "icon-microphone",
9+
widgetIsLoaded: function() {
10+
return typeof RecordRTC != "undefined";
11+
},
12+
isFit: function(question) {
13+
return question.getType() === "microphone";
14+
},
15+
htmlTemplate:
16+
"<div><button type='button' title='Record'><i class='fa fa-microphone' aria-hidden='true'></i></button> <button type='button' title='Save'><i class='fa fa-cloud' aria-hidden='true'></i></button></div>",
17+
activatedByChanged: function(activatedBy) {
18+
Survey.JsonObject.metaData.addClass("microphone", [], null, "empty");
19+
},
20+
21+
afterRender: function(question, el) {
22+
var rootWidget = this;
23+
var buttonStartEl = el.getElementsByTagName("button")[0];
24+
var buttonStopEl = el.getElementsByTagName("button")[1];
25+
26+
////////// RecordRTC logic
27+
28+
var successCallback = function(stream) {
29+
var options={
30+
type: 'audio',
31+
mimeType: 'audio/webm',
32+
audioBitsPerSecond: 44100,
33+
sampleRate: 44100,
34+
bufferSize: 32768,
35+
numberOfAudioChannels: 1
36+
};
37+
console.log("successCallback");
38+
question.survey.mystream = stream;
39+
question.survey.recordRTC = RecordRTC(question.survey.mystream, options);
40+
if(typeof question.survey.recordRTC != "undefined"){
41+
console.log("startRecording");
42+
question.survey.recordRTC.startRecording();
43+
}
44+
};
45+
46+
var errorCallback=function() {
47+
alert('No microphone');
48+
question.survey.recordRTC=undefined;
49+
question.survey.mystream=undefined;
50+
};
51+
52+
var processAudio= function(audioVideoWebMURL) {
53+
console.log("processAudio");
54+
var recordedBlob = question.survey.recordRTC.getBlob();
55+
console.log("Blob size:" + recordedBlob.size);
56+
57+
console.log("question.id : " + question.id);
58+
console.log("question.name : " + question.name);
59+
60+
61+
var fileReader = new FileReader();
62+
fileReader.onload = function(event){
63+
var dataUri = event.target.result;
64+
console.log("dataUri: " +dataUri);
65+
//question.value = (question.value || []).concat([fileReader.result])
66+
question.value = dataUri;
67+
};
68+
fileReader.readAsDataURL(recordedBlob);
69+
70+
console.log("cleaning");
71+
question.survey.recordRTC=undefined;
72+
question.survey.mystream=undefined;
73+
};
74+
75+
var startRecording=function() {
76+
77+
// erase previous data
78+
question.value=undefined;
79+
80+
// if recorder open on another question - try to stop recording
81+
if(typeof question.survey.recordRTC != "undefined"){
82+
question.survey.recordRTC.stopRecording(doNothingHandler);
83+
if(typeof question.survey.mystream != "undefined"){
84+
question.survey.mystream.getAudioTracks().forEach(function(track) {
85+
track.stop();
86+
}
87+
);
88+
}
89+
}
90+
91+
var mediaConstraints = {
92+
video: false,
93+
audio: true
94+
};
95+
96+
navigator.mediaDevices
97+
.getUserMedia(mediaConstraints)
98+
.then(successCallback.bind(this), errorCallback.bind(this));
99+
};
100+
101+
var stopRecording=function() {
102+
console.log("stopRecording");
103+
if(typeof question.survey.recordRTC != "undefined"){
104+
question.survey.recordRTC.stopRecording(processAudio.bind(this));
105+
if(typeof question.survey.mystream != "undefined"){
106+
question.survey.mystream.getAudioTracks().forEach(function(track) {
107+
track.stop();
108+
}
109+
);
110+
}
111+
112+
113+
}
114+
};
115+
116+
////////////// end RTC logic //////////////////
117+
118+
if (!question.isReadOnly) {
119+
buttonStartEl.onclick = startRecording;
120+
} else {
121+
buttonStartEl.parentNode.removeChild(buttonStartEl);
122+
}
123+
124+
if (!question.isReadOnly) {
125+
buttonStopEl.onclick = stopRecording;
126+
} else {
127+
buttonStopEl.parentNode.removeChild(buttonStartEl);
128+
}
129+
130+
var updateValueHandler = function() {
131+
132+
};
133+
134+
var doNothingHandler = function() {
135+
136+
};
137+
138+
question.valueChangedCallback = updateValueHandler;
139+
updateValueHandler();
140+
141+
142+
},
143+
willUnmount: function(question, el) {
144+
console.log("unmount microphone no record ");
145+
if(typeof question.survey.recordRTC != "undefined"){
146+
question.survey.recordRTC.stopRecording(doNothingHandler);
147+
if(typeof question.survey.mystream != "undefined"){
148+
question.survey.mystream.getAudioTracks().forEach(function(track) {
149+
track.stop();
150+
});
151+
}
152+
question.value=undefined;
153+
question.survey.recordRTC=undefined;
154+
question.survey.mystream=undefined;
155+
}
156+
}
157+
};
158+
159+
Survey.CustomWidgetCollection.Instance.addCustomWidget(widget, "customtype");
160+
}
161+
162+
if (typeof Survey !== "undefined") {
163+
init(Survey);
164+
}
165+
166+
export default init;

src/surveyjs-widgets.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export { default as ckeditor } from "./ck-editor.js";
1212
export { default as autocomplete } from "./easy-autocomplete.js";
1313
export { default as prettycheckbox } from "./pretty-checkbox.js";
1414
export { default as bootstrapslider } from "./bootstrap-slider.js";
15+
export { default as microphone } from "./microphone.js";

webpack.config.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ var widgets = [
3434
"ck-editor",
3535
"easy-autocomplete",
3636
"pretty-checkbox",
37-
"bootstrap-slider"
37+
"bootstrap-slider",
38+
"microphone"
3839
];
3940

4041
var dependencies = {
@@ -49,7 +50,8 @@ var dependencies = {
4950
"jquery-bar-rating": "^1.2.2",
5051
"easy-autocomplete": "^1.3.5",
5152
"pretty-checkbox": "^3.0.3",
52-
"bootstrap-slider": "^10.0.0"
53+
"bootstrap-slider": "^10.0.0",
54+
"recordrtc": "^5.4.6"
5355
};
5456

5557
var entry = {};

0 commit comments

Comments
 (0)