Fully end to end encrypted anonymous chat program. Server only stores public key lookup for users and the encrypted messages. No credentials are transfered to the server, but kept in local browser storage. This allows 100% safe chatting. https://safechat.ch
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

176 lines
5.7 KiB

/// @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
};
///@}
/// @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
/** @return Stream prepared to be used in a HTML @c src attribute
within a @c audio or @c video tag. */
this.preview = function() {
return window.URL ? window.URL.createObjectURL(stream) : stream;
}
/// Get Stream to the Recording
/** @return Stream prepared 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() {
var buff = new Blob(recordedBlobs, {type: 'video/webm'});
return window.URL ? window.URL.createObjectURL(buff) : buff;
}
/// 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;
});
///@}
}