: N ( ) , base64. , base64. 2 :
( ). , .
index.html
<!DOCTYPE html>
<html>
<head>
<script src="record-test.js"></script>
</head>
<body>
<video id="video"></video>
<canvas id="canvas" style="display:none;"></canvas>
<input type="button" id="stopRecordBtn" value="Stop recording">
</body>
</html>
-test.js:
(function() {
'use strict';
var FRAME_INTERVAL_MS = 500;
var FRAME_WIDTH = 320;
var FRAME_HEIGHT = 240;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
window.URL = window.URL || window.webkitURL;
var video, canvas, ctx;
var mediaStream;
var videoRecordItv;
var base64Frames = [];
var init = function() {
video = document.getElementById('video');
canvas = document.getElementById('canvas');
canvas.width = FRAME_WIDTH;
canvas.height = FRAME_HEIGHT;
ctx = canvas.getContext('2d');
var stopBtn = document.getElementById('stopRecordBtn');
stopBtn.addEventListener('click', stopRecording);
navigator.getUserMedia({video: true}, onGotStream, function(e) {console.log(e);});
}
var onGotStream = function(stream) {
mediaStream = stream;
video.src = URL.createObjectURL(mediaStream);
video.play();
videoRecordItv = setInterval(function() {
var frame = getBase64FrameFromVideo();
base64Frames.push(frame);
}, FRAME_INTERVAL_MS);
}
var getBase64FrameFromVideo = function() {
ctx.drawImage(video, 0, 0, FRAME_WIDTH, FRAME_HEIGHT);
var base64PrefixLength = 'data:image/jpeg;base64,'.length;
return canvas.toDataURL('image/jpeg').slice(base64PrefixLength);
}
var stopRecording = function() {
mediaStream && mediaStream.stop && mediaStream.stop();
mediaStream = null;
clearInterval(videoRecordItv);
uploadFramesToServer();
}
var uploadFramesToServer = function() {
var sid = Math.random();
var curFrameIdx = 0;
(function postFrame() {
console.log('post frame #' + curFrameIdx);
var base64Frame = base64Frames[curFrameIdx];
var blobFrame = base64ToBlob(base64Frame, 'image/jpeg');
var formData = new FormData;
formData.append('frame', blobFrame, 'upload.jpg');
formData.append('sid', sid);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/postFrame', true);
xhr.onload = function(e) {
console.log(this.response);
if (base64Frames[++curFrameIdx]) {
postFrame();
} else {
console.log('finish post frames');
}
};
xhr.send(formData);
})();
}
var base64ToBlob = function(base64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(base64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
return new Blob(byteArrays, {type: contentType});
}
document.addEventListener('DOMContentLoaded', init);
})();
, , FFmpeg.
Chrome, Firefox.
, . !