Skip to content

Commit 953ee44

Browse files
committed
Add the video-recorder service
1 parent b540597 commit 953ee44

21 files changed

+977
-10
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@
1515
/libpeerconnection.log
1616
npm-debug.log
1717
testem.log
18+
19+
exp-player/public/VideoRecorder.swf
+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import Ember from 'ember';
2+
3+
let {$, RSVP} = Ember;
4+
5+
const HOOKS = ['onRecordingStarted', 'onCamAccess', 'onFlashReady', 'onUploadDone'];
6+
7+
const ATTRIBUTES = {
8+
align: 'middle',
9+
id: 'VideoRecorder',
10+
name: 'VideoRecorder',
11+
};
12+
13+
const FLASHVARS = {
14+
authenticity_token: '',
15+
lstext : 'Loading...',
16+
mrt: '120',
17+
qualityurl: 'audio_video_quality_profiles/320x240x30x90.xml',
18+
recorderId: '123',
19+
sscode: 'php',
20+
userId : 'XXY',
21+
};
22+
23+
const PARAMS = {
24+
quality: 'high',
25+
bgcolor: '#dfdfdf',
26+
play: 'true',
27+
loop: 'false',
28+
allowscriptaccess: 'sameDomain',
29+
wmode: 'transparent'
30+
}
31+
32+
export default Ember.Service.extend({
33+
height: 'auto',
34+
width: '100%',
35+
params: PARAMS,
36+
flashVars: FLASHVARS,
37+
attributes: ATTRIBUTES,
38+
39+
divId: Ember.computed.alias('attributes.id'),
40+
sscode: Ember.computed.alias('flashVars.sscode'),
41+
videoId: Ember.computed.alias('flashVars.userId'),
42+
43+
started: Ember.computed.alias('_started').readOnly(),
44+
camAccess: Ember.computed.alias('_camAccess').readOnly(),
45+
recording: Ember.computed.alias('_recording').readOnly(),
46+
47+
debug: false,
48+
_started: false,
49+
_camAccess: false,
50+
_recording: false,
51+
52+
_recordPromise: null,
53+
54+
//Initial setup, installs flash hooks into the page
55+
init() {
56+
let self = this;
57+
HOOKS.forEach(hookName => {
58+
window[hookName] = function() {
59+
if (self.get('debug')) console.log(hookName, arguments);
60+
if (self['_' + hookName]) self['_' + hookName].apply(self, arguments);
61+
if (self[hookName]) self[hookName].apply(self, arguments);
62+
}
63+
});
64+
},
65+
66+
//Insert the recorder and start recording
67+
//Returns a promise that resolve to true or false to indicate
68+
//whether or not recording has started.
69+
//IE a user might not have granted access to their webcam
70+
start(videoId, element, {config: config, hidden: hidden, record: record}={config: false, hidden: false, record: true}) {
71+
if (this.get('started')) throw new Error('Video recorder already started');
72+
if (typeof(videoId) !== 'string') throw new Error('videoId must be a string');
73+
74+
this.set('_started', true);
75+
this.set('videoId', videoId);
76+
this.set('sscode', config ? 'asp' : 'php');
77+
78+
$(element).append(`<div id="${this.get('divId')}-container"></div`);
79+
$(`#${this.get('divId')}-container`).append(`<div id="${this.get('divId')}"></div`);
80+
81+
if (hidden) this.hide();
82+
83+
return new RSVP.Promise((resolve, reject) => {
84+
swfobject.embedSWF('VideoRecorder.swf', $(`#${this.get('divId')}`)[0], this.get('width'), this.get('height'), '10.3.0', '', this.get('flashVars'), this.get('params'), this.get('attributes'), vr => {
85+
if (!vr.success) reject(new Error('Install failed'));
86+
87+
$('#' + vr.id).css('height', '80vh');
88+
this.set('recorder', $('#' + vr.id)[0]);
89+
90+
if (record) return this.record();
91+
return resolve(false);
92+
});
93+
});
94+
},
95+
96+
// Pause the recorder
97+
pause() {
98+
if (this.get('recording')) throw new Error('Never started recording');
99+
this.get('recorder').pause();
100+
return true;
101+
},
102+
103+
// Stop recording and save the video to the server
104+
// By default destroys the flash element
105+
stop({destroy: destroy}={destroy:false}) {
106+
if (this.get('recording')) this.get('recorder').stopVideo();
107+
if (!this.get('started')) return;
108+
this.set('_started', false);
109+
if (destroy) this.destroy();
110+
},
111+
112+
record() {
113+
if (!this.get('started')) throw new Error('Must call start before record');
114+
if (this.get('recording')) throw new Error('Already recording');
115+
this.get('recorder').record();
116+
return new Ember.RSVP.Promise((resolve, reject) => this.set('_recordPromise', {resolve, reject}));
117+
},
118+
119+
// Uninstall the video recorder
120+
destroy() {
121+
// Seems that removing the swf object causes it to clean itself up
122+
// this.get('recorder').disconnectAndRemove();
123+
//TODO fix the flash error when destroying. Seems harmless for now...
124+
$(`#${this.get('divId')}-container`).remove();
125+
this.set('recorder', null);
126+
this.set('_recording', false);
127+
return true;
128+
},
129+
130+
show() {
131+
$(`#${this.get('divId')}-container`).removeAttr('style');
132+
return true;
133+
},
134+
135+
hide() {
136+
$(`#${this.get('divId')}-container`).css({
137+
'top': '0%',
138+
'left': '0%',
139+
'z-index': -1,
140+
'position': 'absolute',
141+
});
142+
return true;
143+
},
144+
145+
on(eName, func) {
146+
if (HOOKS.indexOf(eName) === -1) throw `Invalid event ${eName}`;
147+
this.set(eName, func);
148+
},
149+
150+
// Begin Flash hooks
151+
152+
_onRecordingStarted(recorderId) {
153+
this.set('_recording', true);
154+
if (this.get('_recordingPromise')) this.get('_recordPromise').resolve(true);
155+
},
156+
157+
_onUploadDone() {
158+
this.set('_recording', false);
159+
},
160+
161+
_onCamAccess(allowed,recorderId) {
162+
this.set('_camAccess', allowed);
163+
}
164+
165+
// End Flash hooks
166+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from 'exp-player/services/video-recorder';

exp-player/bower.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"alpaca": "1.5.14",
1212
"handlebars": "3.0.3",
1313
"bootstrap": "3.3.2",
14-
"lodash": "~3.10.1"
14+
"lodash": "~3.10.1",
15+
"swfobject": "*"
1516
},
1617
"resolutions": {
1718
"ember": "2.2.0"

0 commit comments

Comments
 (0)