将用计算机摄像头捕获的视频从网站发送到服务器
Sending video captured with the computer camera from a website to a server
我正在尝试让计算机或 android 设备从相机录制视频并将其发送到将存储它的服务器。该系统必须是基于网络的,并且需要不断地发送视频片段。
这是javascript中的代码:
var camera = (function() {
var options;
var video, canvas, context;
var renderTimer;
function initVideoStream() {
video = document.createElement("video");
video.setAttribute('width', options.width);
video.setAttribute('height', options.height);
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
if (navigator.getUserMedia) {
navigator.getUserMedia({
video: true
}, function(stream) {
options.onSuccess();
if (video.mozSrcObject !== undefined) { // hack for Firefox < 19
video.mozSrcObject = stream;
} else {
video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
}
initCanvas();
}, options.onError);
} else {
options.onNotSupported();
}
}
function initCanvas() {
canvas = document.getElementById("canvas");//options.targetCanvas || document.createElement("canvas");
canvas.setAttribute('width', options.width);
canvas.setAttribute('height', options.height);
context = canvas.getContext('2d');
// mirror video
if (options.mirror) {
context.translate(canvas.width, 0);
context.scale(-1, 1);
}
startCapture();
}
function startCapture() {
video.play();
renderTimer = setInterval(function() {
try {
context.drawImage(video, 0, 0, video.width, video.height);
options.onFrame(canvas);
} catch (e) {
// TODO
}
}, Math.round(1000 / options.fps));
}
function stopCapture() {
pauseCapture();
if (video.mozSrcObject !== undefined) {
video.mozSrcObject = null;
} else {
video.src = "";
}
}
function pauseCapture() {
if (renderTimer) clearInterval(renderTimer);
video.pause();
}
return {
init: function(captureOptions) {
var doNothing = function(){};
options = captureOptions || {};
options.fps = options.fps || 30;
options.width = options.width || 640;
options.height = options.height || 480;
options.mirror = options.mirror || false;
options.targetCanvas = options.targetCanvas || null; // TODO: is the element actually a <canvas> ?
initVideoStream();
},
start: startCapture,
pause: pauseCapture,
stop: stopCapture
};
})();
var imgSender = (function() {
function imgsFromCanvas(canvas, options) {
var context = canvas.getContext("2d");
var canvasWidth = canvas.width; //# pixels horizontally
var canvasHeight = canvas.height; //# pixels vertically
var imageData = context.getImageData(0, 0, canvasWidth, canvasHeight); //Vector of all pixels
options.callback(canvasWidth, canvasHeight, imageData.data);
}
return {
fromCanvas: function(canvas, options) {
options = options || {};
options.callback = options.callback || doNothing;
return imgsFromCanvas(canvas, options);
}
};
})();
var FPS = 30; //fps
var minVideoTime = 5; //Seconds that every video clip sent will take
var arrayImgs = []; //Array with all the images that will be sent to the server
var videoTime = 0; //Number of seconds of video stored in videoTime
(function() {
var capturing = false;
camera.init({
width: 160,
height: 120,
fps: FPS,
mirror: true,
onFrame: function(canvas) {
imgSender.fromCanvas(canvas, {
callback: function(w,h,image) {
arrayImgs.push(image);
videoTime += 1/FPS;
if (minVideoTime <= videoTime) {
sendToPhp(w,h,videoTime*FPS);
arrayImgs = [];
videoTime = 0;
function sendToPhp(width,height,numFrames) {
$.ajax({
type: "POST",
url: "sendToServer.php",
data: {
arrayImgs: arrayImgs,
width: w,
height: h,
nframes: numFrames
},
async: true, // If set to non-async, browser shows page as "Loading.."
cache: false,
timeout:500, // Timeout in ms (0.5s)
success: function(answer){
console.log("SUCCESS: ", answer);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
console.log("ERROR: ", textStatus, " , ", errorThrown); }
});
}
}
}
});
},
onSuccess: function() {
document.getElementById("info").style.display = "none";
capturing = true;
document.getElementById("pause").style.display = "block";
document.getElementById("pause").onclick = function() {
if (capturing) {
camera.pause();
} else {
camera.start();
}
capturing = !capturing;
};
},
onError: function(error) {
// TODO: log error
},
onNotSupported: function() {
document.getElementById("info").style.display = "none";
document.getElementById("notSupported").style.display = "block";
}
});
})();
如您所见,我正在使用 getUserMedia 获取视频,我正在对数组中的图像进行采样,直到我有 5 秒的视频,然后我将其发送到一个 php 文件,该文件将发送到服务器。
我的问题: 所有 ajax 请求都有很多延迟,我也有大小问题,ajax 请求没有不能同时接受这么多数据,所以我不得不降低帧率和发送视频的长度。
有没有更好的方法来做到这一点?到目前为止,我丢失了 超过 50% 的视频! 也许是通过 WebRTC?请帮忙
谢谢!
对于您的用例,您应该使用 MediaRecorder API。这将使您可以将视频以 WebM 的形式录制成块,您可以在后台上传到服务器。 WebM/VP8(或 mp4)在压缩视频方面比您现在使用的临时 MJPEG 做得更好。
另请参阅 RecordRTC,其中包括尚未实现此功能的浏览器的兼容层等。
我正在尝试让计算机或 android 设备从相机录制视频并将其发送到将存储它的服务器。该系统必须是基于网络的,并且需要不断地发送视频片段。
这是javascript中的代码:
var camera = (function() {
var options;
var video, canvas, context;
var renderTimer;
function initVideoStream() {
video = document.createElement("video");
video.setAttribute('width', options.width);
video.setAttribute('height', options.height);
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
if (navigator.getUserMedia) {
navigator.getUserMedia({
video: true
}, function(stream) {
options.onSuccess();
if (video.mozSrcObject !== undefined) { // hack for Firefox < 19
video.mozSrcObject = stream;
} else {
video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
}
initCanvas();
}, options.onError);
} else {
options.onNotSupported();
}
}
function initCanvas() {
canvas = document.getElementById("canvas");//options.targetCanvas || document.createElement("canvas");
canvas.setAttribute('width', options.width);
canvas.setAttribute('height', options.height);
context = canvas.getContext('2d');
// mirror video
if (options.mirror) {
context.translate(canvas.width, 0);
context.scale(-1, 1);
}
startCapture();
}
function startCapture() {
video.play();
renderTimer = setInterval(function() {
try {
context.drawImage(video, 0, 0, video.width, video.height);
options.onFrame(canvas);
} catch (e) {
// TODO
}
}, Math.round(1000 / options.fps));
}
function stopCapture() {
pauseCapture();
if (video.mozSrcObject !== undefined) {
video.mozSrcObject = null;
} else {
video.src = "";
}
}
function pauseCapture() {
if (renderTimer) clearInterval(renderTimer);
video.pause();
}
return {
init: function(captureOptions) {
var doNothing = function(){};
options = captureOptions || {};
options.fps = options.fps || 30;
options.width = options.width || 640;
options.height = options.height || 480;
options.mirror = options.mirror || false;
options.targetCanvas = options.targetCanvas || null; // TODO: is the element actually a <canvas> ?
initVideoStream();
},
start: startCapture,
pause: pauseCapture,
stop: stopCapture
};
})();
var imgSender = (function() {
function imgsFromCanvas(canvas, options) {
var context = canvas.getContext("2d");
var canvasWidth = canvas.width; //# pixels horizontally
var canvasHeight = canvas.height; //# pixels vertically
var imageData = context.getImageData(0, 0, canvasWidth, canvasHeight); //Vector of all pixels
options.callback(canvasWidth, canvasHeight, imageData.data);
}
return {
fromCanvas: function(canvas, options) {
options = options || {};
options.callback = options.callback || doNothing;
return imgsFromCanvas(canvas, options);
}
};
})();
var FPS = 30; //fps
var minVideoTime = 5; //Seconds that every video clip sent will take
var arrayImgs = []; //Array with all the images that will be sent to the server
var videoTime = 0; //Number of seconds of video stored in videoTime
(function() {
var capturing = false;
camera.init({
width: 160,
height: 120,
fps: FPS,
mirror: true,
onFrame: function(canvas) {
imgSender.fromCanvas(canvas, {
callback: function(w,h,image) {
arrayImgs.push(image);
videoTime += 1/FPS;
if (minVideoTime <= videoTime) {
sendToPhp(w,h,videoTime*FPS);
arrayImgs = [];
videoTime = 0;
function sendToPhp(width,height,numFrames) {
$.ajax({
type: "POST",
url: "sendToServer.php",
data: {
arrayImgs: arrayImgs,
width: w,
height: h,
nframes: numFrames
},
async: true, // If set to non-async, browser shows page as "Loading.."
cache: false,
timeout:500, // Timeout in ms (0.5s)
success: function(answer){
console.log("SUCCESS: ", answer);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
console.log("ERROR: ", textStatus, " , ", errorThrown); }
});
}
}
}
});
},
onSuccess: function() {
document.getElementById("info").style.display = "none";
capturing = true;
document.getElementById("pause").style.display = "block";
document.getElementById("pause").onclick = function() {
if (capturing) {
camera.pause();
} else {
camera.start();
}
capturing = !capturing;
};
},
onError: function(error) {
// TODO: log error
},
onNotSupported: function() {
document.getElementById("info").style.display = "none";
document.getElementById("notSupported").style.display = "block";
}
});
})();
如您所见,我正在使用 getUserMedia 获取视频,我正在对数组中的图像进行采样,直到我有 5 秒的视频,然后我将其发送到一个 php 文件,该文件将发送到服务器。
我的问题: 所有 ajax 请求都有很多延迟,我也有大小问题,ajax 请求没有不能同时接受这么多数据,所以我不得不降低帧率和发送视频的长度。
有没有更好的方法来做到这一点?到目前为止,我丢失了 超过 50% 的视频! 也许是通过 WebRTC?请帮忙
谢谢!
对于您的用例,您应该使用 MediaRecorder API。这将使您可以将视频以 WebM 的形式录制成块,您可以在后台上传到服务器。 WebM/VP8(或 mp4)在压缩视频方面比您现在使用的临时 MJPEG 做得更好。
另请参阅 RecordRTC,其中包括尚未实现此功能的浏览器的兼容层等。