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.
188 lines
6.0 KiB
188 lines
6.0 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 private methods |
|
///@{ |
|
function createURL(data) { |
|
var urlCreator = window.URL || window.webkitURL; |
|
return urlCreator ? urlCreator.createObjectURL(data) : data; |
|
} |
|
///@} |
|
|
|
/// @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 Data URL prepared to be used in a HTML @c src |
|
attribute within a @c audio or @c video tag. */ |
|
this.preview = function() { |
|
return createURL(stream); |
|
} |
|
|
|
/// Get Stream to the Recording |
|
/** @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'})); |
|
} |
|
|
|
/// 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; |
|
}); |
|
///@} |
|
}
|
|
|