-
Notifications
You must be signed in to change notification settings - Fork 1
/
recorder.js
executable file
·273 lines (230 loc) · 7.28 KB
/
recorder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
var Wami = window.Wami || {};
// Returns a (very likely) unique string with of random letters and numbers
Wami.createID = function() {
return "wid" + ("" + 1e10).replace(/[018]/g, function(a) {
return (a ^ Math.random() * 16 >> a / 4).toString(16)
});
}
// Creates a named callback in WAMI and returns the name as a string.
Wami.nameCallback = function(cb, cleanup) {
Wami._callbacks = Wami._callbacks || {};
var id = Wami.createID();
Wami._callbacks[id] = function() {
if (cleanup) {
Wami._callbacks[id] = null;
}
cb.apply(null, arguments);
};
var named = "Wami._callbacks['" + id + "']";
return named;
}
// This method ensures that a WAMI recorder is operational, and that
// the following API is available in the Wami namespace. All functions
// must be named (i.e. cannot be anonymous).
//
// Wami.startPlaying(url, startfn = null, finishedfn = null, failedfn = null);
// Wami.stopPlaying()
//
// Wami.startRecording(url, startfn = null, finishedfn = null, failedfn = null);
// Wami.stopRecording()
//
// Wami.getRecordingLevel() // Returns a number between 0 and 100
// Wami.getPlayingLevel() // Returns a number between 0 and 100
//
// Wami.hide()
// Wami.show()
//
// Manipulate the WAMI recorder's settings. In Flash
// we need to check if the microphone permission has been granted.
// We might also set/return sample rate here, etc.
//
// Wami.getSettings();
// Wami.setSettings(options);
//
// Optional way to set up browser so that it's constantly listening
// This is to prepend audio in case the user starts talking before
// they click-to-talk.
//
// Wami.startListening()
//
Wami.setup = function(options) {
if (Wami.startRecording) {
// Wami's already defined.
if (options.onReady) {
options.onReady();
}
return;
}
// Assumes that swfobject.js is included if Wami.swfobject isn't
// already defined.
Wami.swfobject = Wami.swfobject || swfobject;
if (!Wami.swfobject) {
alert("Unable to find swfobject to help embed the SWF.");
}
var _options;
setOptions(options);
embedWamiSWF(_options.id, Wami.nameCallback(delegateWamiAPI));
function supportsTransparency() {
// Detecting the OS is a big no-no in Javascript programming, but
// I can't think of a better way to know if wmode is supported or
// not... since NOT supporting it (like Flash on Ubuntu) is a bug.
return (navigator.platform.indexOf("Linux") == -1);
}
function setOptions(options) {
// Start with default options
_options = {
swfUrl : "Wami.swf",
onReady : function() {
Wami.hide();
},
onSecurity : checkSecurity,
onError : function(error) {
alert(error);
}
};
if (typeof options == 'undefined') {
alert('Need at least an element ID to place the Flash object.');
}
if (typeof options == 'string') {
_options.id = options;
} else {
_options.id = options.id;
}
if (options.swfUrl) {
_options.swfUrl = options.swfUrl;
}
if (options.onReady) {
_options.onReady = options.onReady;
}
if (options.onLoaded) {
_options.onLoaded = options.onLoaded;
}
if (options.onSecurity) {
_options.onSecurity = options.onSecurity;
}
if (options.onError) {
_options.onError = options.onError;
}
// Create a DIV for the SWF under _options.id
var container = document.createElement('div');
container.style.position = 'absolute';
_options.cid = Wami.createID();
container.setAttribute('id', _options.cid);
var swfdiv = document.createElement('div');
var id = Wami.createID();
swfdiv.setAttribute('id', id);
container.appendChild(swfdiv);
document.getElementById(_options.id).appendChild(container);
_options.id = id;
}
function checkSecurity() {
var settings = Wami.getSettings();
if (settings.microphone.granted) {
_options.onReady();
} else {
// Show any Flash settings panel you want:
// http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/SecurityPanel.html
Wami.showSecurity("privacy", "Wami.show", Wami
.nameCallback(_options.onSecurity), Wami
.nameCallback(_options.onError));
}
}
// Embed the WAMI SWF and call the named callback function when loaded.
function embedWamiSWF(id, initfn) {
var flashVars = {
visible : false,
loadedCallback : initfn
}
var params = {
allowScriptAccess : "always"
}
if (supportsTransparency()) {
params.wmode = "transparent";
}
if (typeof console !== 'undefined') {
flashVars.console = true;
}
var version = '10.0.0';
document.getElementById(id).innerHTML = "WAMI requires Flash "
+ version
+ " or greater<br />https://get.adobe.com/flashplayer/";
// This is the minimum size due to the microphone security panel
Wami.swfobject.embedSWF(_options.swfUrl, id, 214, 137, version, null,
flashVars, params);
// Without this line, Firefox has a dotted outline of the flash
Wami.swfobject.createCSS("#" + id, "outline:none");
}
// To check if the microphone settings were 'remembered', we
// must actually embed an entirely new Wami client and check
// whether its microphone is granted. If it is, it was remembered.
function checkRemembered(finishedfn) {
var id = Wami.createID();
var div = document.createElement('div');
div.style.top = '-999px';
div.style.left = '-999px';
div.setAttribute('id', id);
var body = document.getElementsByTagName('body').item(0);
body.appendChild(div);
var fn = Wami.nameCallback(function() {
var swf = document.getElementById(id);
Wami._remembered = swf.getSettings().microphone.granted;
Wami.swfobject.removeSWF(id);
eval(finishedfn + "()");
});
embedWamiSWF(id, fn);
}
// Attach all the audio methods to the Wami namespace in the callback.
function delegateWamiAPI() {
var recorder = document.getElementById(_options.id);
function delegate(name) {
Wami[name] = function() {
return recorder[name].apply(recorder, arguments);
}
}
delegate('startPlaying');
delegate('stopPlaying');
delegate('startRecording');
delegate('stopRecording');
delegate('startListening');
delegate('stopListening');
delegate('getRecordingLevel');
delegate('getPlayingLevel');
delegate('setSettings');
// Append extra information about whether mic settings are sticky
Wami.getSettings = function() {
var settings = recorder.getSettings();
settings.microphone.remembered = Wami._remembered;
return settings;
}
Wami.showSecurity = function(panel, startfn, finishedfn, failfn) {
// Flash must be on top for this.
var container = document.getElementById(_options.cid);
var augmentedfn = Wami.nameCallback(function() {
checkRemembered(finishedfn);
container.style.cssText = "position: absolute;";
});
container.style.cssText = "position: absolute; z-index: 99999";
recorder.showSecurity(panel, startfn, augmentedfn, failfn);
}
Wami.show = function() {
if (!supportsTransparency()) {
recorder.style.visibility = "visible";
}
}
Wami.hide = function() {
// Hiding flash in all the browsers is tricky. Please read:
// https://code.google.com/p/wami-recorder/wiki/HidingFlash
if (!supportsTransparency()) {
recorder.style.visibility = "hidden";
}
}
// If we already have permissions, they were previously 'remembered'
Wami._remembered = recorder.getSettings().microphone.granted;
if (_options.onLoaded) {
_options.onLoaded();
}
if (!_options.noSecurityCheck) {
checkSecurity();
}
}
}