Files
safechat/nodejs/public/javascripts/mediarecorder.js

189 lines
6.0 KiB
JavaScript
Raw Normal View History

2016-01-13 14:41:46 +00:00
/// @class MediaRecorder
/** Provides a recorder to record fotos, audio and video from a web
browser client using the JavaScript getUserMedia feature.
@param constraints The constraints as JSON data:
@code
{
video: true, // true if you want to record video
audio: true // true if you want to record audio
}
@endcode
You can record video or audio only or both together.
if not specified, defaults to @ref defaultconstraints.
@note Special thanks to the following projects:
- For the basics regarding getUserMedia:
http://www.html5rocks.com/en/tutorials/getusermedia/intro/
- For a simple example of a media recorder:
https://github.com/samdutton/simpl/blob/gh-pages/mediarecorder
@note Supported browsers are:
- Firefox 29 or later
- Chrome 47 or later, with @c "Enable experimental Web Platform
features" enabled from @c "chrome://flags"
@note This class must be used from within a secure context. A
secure context is an encrypted SSL connection through HTTPS, or
the special address @c localhost.
@todo Why are mediaSource and sourceBuffer needed? They are not
further referenced.
*/
function MediaStreamRecorder(constraints) {
/// @name private variables
///@{
var events = [];
var mediaSource = new MediaSource();
var stream;
var mediaRecorder;
var recordedBlobs = [];
var sourceBuffer;
var defaultconstraints = {
audio: true,
video: true
};
///@}
2016-01-13 15:54:50 +00:00
/// @name private methods
///@{
function createURL(data) {
var urlCreator = window.URL || window.webkitURL;
return urlCreator ? urlCreator.createObjectURL(data) : data;
}
///@}
2016-01-13 14:41:46 +00:00
/// @name internal event handlers
///@{
/// Create Source Buffer on Event Source Open
function handleSourceOpen(event) {
sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp8"');
}
/// Store Data in local Binary Large Object
function handleDataAvailable(event) {
if (event.data && event.data.size > 0) {
recordedBlobs.push(event.data);
}
}
/// Propagate @c ready Event to Registered Handler
function handleReady() {
if (events['ready']) events['ready']();
}
/// Propagate @c start Event to Registered Handler
function handleStart() {
if (events['stop']) events['start']();
}
/// Propagate @c stop Event to Registered Handler
function handleStop(event) {
if (events['stop']) events['stop'](event);
}
///@}
/// @name public methods
///@{
/// Register Eventhandler
/** @param eventname The following events are available:
- @c ready Video preview stream is ready for use
- @c stop Recording has stopped, parameter: @event
- @c start Recording has started
@param eventhandler callback function to be called when the
event occurs.
*/
this.on = function(eventname, eventhandler) {
events[eventname] = eventhandler;
}
/// Get Stream to the Preview
2016-01-13 15:54:50 +00:00
/** @return Data URL prepared to be used in a HTML @c src
attribute within a @c audio or @c video tag. */
2016-01-13 14:41:46 +00:00
this.preview = function() {
2016-01-13 15:54:50 +00:00
return createURL(stream);
2016-01-13 14:41:46 +00:00
}
/// Get Stream to the Recording
2016-01-13 15:54:50 +00:00
/** @param callback Callback function that will be called with a
data url to be used in a HTML @c src attribute within a
@c audio or @c video tag, or to be used in a HTML @c
href attribute in a @c a tag for downloading the
recording. */
this.recording = function(callback) {
var reader = new FileReader();
reader.onload = function(e) {
callback(e.target.result);
}
reader.readAsDataURL(new Blob(recordedBlobs, {type: 'video/webm'}));
2016-01-13 14:41:46 +00:00
}
/// Start Stream Recording
/** @throws Exception if browser is not supported */
this.start = function() {
// The nested try blocks will be simplified when Chrome 47 moves to Stable
var options = {mimeType: 'video/webm'};
recordedBlobs = [];
try {
mediaRecorder = new MediaRecorder(stream, options);
} catch (e0) {
try {
options = {mimeType: 'video/webm,codecs=vp9'};
mediaRecorder = new MediaRecorder(stream, options);
} catch (e1) {
try {
options = 'video/vp8'; // Chrome 47
mediaRecorder = new MediaRecorder(stream, options);
} catch (e2) {
throw {
text: 'MediaRecorder is not supported by browser',
e0: e0,
e1: e1,
e2: e2
};
}
}
}
mediaRecorder.onstop = handleStop;
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start(10); // collect 10ms of data
handleStart();
}
/// Stop Stream Recording
/** Use recording() to get access to the result. */
this.stop = function () {
if (mediaRecorder) mediaRecorder.stop();
delete mediaRecorder; mediaRecorder = null;
}
/// Close Preview Stream
/** Closes the stream and releases the camera. This should always
be called to cleanup, when the camera is no more needed. */
this.release = function() {
stop();
stream.getTracks().forEach(function(track) {track.stop()});
delete stream; stream = null;
}
///@}
/// @name initialization
///@{
mediaSource.addEventListener('sourceopen', handleSourceOpen, false);
if (!constraints) constraints = defaultconstraints;
navigator.mediaDevices.getUserMedia(constraints)
.then(function(s) {
stream = s;
handleReady();
}).catch(function(error) {
throw error;
});
///@}
}