video attachments from camera
This commit is contained in:
		
							
								
								
									
										176
									
								
								nodejs/public/javascripts/mediarecorder.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								nodejs/public/javascripts/mediarecorder.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,176 @@
 | 
			
		||||
/// @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;
 | 
			
		||||
        });
 | 
			
		||||
    ///@}
 | 
			
		||||
}
 | 
			
		||||
@@ -343,67 +343,72 @@ function guessfilename(mimetype, user, date) {
 | 
			
		||||
function attachments(files, id, from, date) {
 | 
			
		||||
    if (files) files.forEach(function(file) {
 | 
			
		||||
        if (!file.name) file.name = guessfilename(file.type, from, date);
 | 
			
		||||
        var img = document.createElement('img');
 | 
			
		||||
        img.title = file.name;
 | 
			
		||||
        if (file.type.match('^image/')) {
 | 
			
		||||
            img.src = file.content;
 | 
			
		||||
        } else {
 | 
			
		||||
            img.src = "images/Document_sans_PICOL-PIctorial-COmmunication-Language.svg";
 | 
			
		||||
        }
 | 
			
		||||
        var a = document.createElement('a');
 | 
			
		||||
        a.href = file.content;
 | 
			
		||||
        a.download = file.name;
 | 
			
		||||
        a.target = '_blank';
 | 
			
		||||
        a.appendChild(img);
 | 
			
		||||
        if (file.type.match('^image/')) {
 | 
			
		||||
            var img = document.createElement('img');
 | 
			
		||||
            img.title = file.name;
 | 
			
		||||
            img.src = file.content;
 | 
			
		||||
            a.appendChild(img);
 | 
			
		||||
        } else if (file.type.match('^video/')) {
 | 
			
		||||
            var video = document.createElement('video');
 | 
			
		||||
            video.controls = true;
 | 
			
		||||
            video.title = file.name;
 | 
			
		||||
            video.src = file.content;
 | 
			
		||||
            a.appendChild(video);
 | 
			
		||||
        } else {
 | 
			
		||||
            var img = document.createElement('img');
 | 
			
		||||
            img.title = file.name;
 | 
			
		||||
            img.src = "images/Document_sans_PICOL-PIctorial-COmmunication-Language.svg";
 | 
			
		||||
            a.appendChild(img);
 | 
			
		||||
        }
 | 
			
		||||
        $(id).append(a);            
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// function getUserMedia() {
 | 
			
		||||
//     return navigator.mediaDevices.getUserMedia || navigator.getUserMedia
 | 
			
		||||
//         || navigator.webkitGetUserMedia || navigator.mozGetUserMedia
 | 
			
		||||
//         || navigator.msGetUserMedia;
 | 
			
		||||
// }
 | 
			
		||||
var recorder;
 | 
			
		||||
 | 
			
		||||
var mediarecorder = null;
 | 
			
		||||
var mediastream = null;
 | 
			
		||||
function record() {
 | 
			
		||||
    mediarecorder = mediastream.record();
 | 
			
		||||
}
 | 
			
		||||
function done() {
 | 
			
		||||
    mediarecorder.getRecordedData(function(videoblob) {
 | 
			
		||||
        previewfile(videoblob, "video/webm");
 | 
			
		||||
    });
 | 
			
		||||
    mediarecorder = null;
 | 
			
		||||
    if (recorder) {
 | 
			
		||||
        recorder.stop();
 | 
			
		||||
        previewfile(recorder.recording(), "video/webm");
 | 
			
		||||
        abort();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function abort() {
 | 
			
		||||
    mediarecorder = null;
 | 
			
		||||
    mediastream.getTracks().forEach(function(track) {track.stop()});
 | 
			
		||||
    mediastream = null;
 | 
			
		||||
    if (recorder) {
 | 
			
		||||
        $("#videorecorder").hide();
 | 
			
		||||
        recorder.release();
 | 
			
		||||
        delete recorder; recorder = null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Record Video from builtin camera
 | 
			
		||||
function recordvideo() {
 | 
			
		||||
    $("#videorecorder").show();
 | 
			
		||||
    if (mediastream) {
 | 
			
		||||
        mediarecorder = mediastream.record();
 | 
			
		||||
    }
 | 
			
		||||
    try {
 | 
			
		||||
        navigator.mediaDevices.getUserMedia({audio: true, video: true})
 | 
			
		||||
            .then(function(stream) {
 | 
			
		||||
                console.log(stream);
 | 
			
		||||
                mediastream = stream;
 | 
			
		||||
                var video = $("#videorecorder video");
 | 
			
		||||
                video.attr("src", window.URL.createObjectURL(mediastream));
 | 
			
		||||
            }).catch(function() {
 | 
			
		||||
                error("capture video failed", false);
 | 
			
		||||
            });
 | 
			
		||||
        abort();
 | 
			
		||||
        $("#videorecorder").show();
 | 
			
		||||
        recorder = new MediaStreamRecorder({
 | 
			
		||||
            video: {
 | 
			
		||||
                mandatory: {
 | 
			
		||||
                    maxWidth: 400,
 | 
			
		||||
                    maxHeight: 400
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            audio: true
 | 
			
		||||
        });
 | 
			
		||||
        recorder.on("ready", function() {
 | 
			
		||||
            $("#videorecorder video").attr("src", recorder.preview());
 | 
			
		||||
            recorder.start();
 | 
			
		||||
        });
 | 
			
		||||
        recorder.on('')
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        console.log(e);
 | 
			
		||||
        error("cannot access camera", true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function previewfile(content, type, name) {
 | 
			
		||||
@@ -440,6 +445,7 @@ function previewfile(content, type, name) {
 | 
			
		||||
        filecontent.push({name: name, type: type, content: content});
 | 
			
		||||
        var video = document.createElement("video");
 | 
			
		||||
        video.setAttribute("controls", "controls");
 | 
			
		||||
        video.setAttribute("loop", "loop");
 | 
			
		||||
        video.setAttribute("src", content);
 | 
			
		||||
        video.setAttribute("title", name);
 | 
			
		||||
        $("#preview").append(video);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user