I have a page which uses the HTML5 getUserMedia functionality to capture an image from the user's webcam. I am having serious inconsistencies in the scaling of the captured image when it is rendered to the canvas. Only the top corner of the image is actually rendered, as if rather than capturing the video element, it is slicing a piece from the underlying stream. Oddly enough, when I go to most other sites using this technology, I do not have this problem. I am running Chrome 29.0.1547.76 m on Windows 7, running on a 2011 MacBook Pro.
<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript">
var openCameraButton;
var takePictureButton;
var mediaStream;
var video;
var canvas;
var context;
navigator.getMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
function onLoad(){
video = document.querySelector('video');
canvas = document.querySelector('canvas');
context = canvas.getContext('2d');
context.imageSmoothingEnabled = true;
context.webkitImageSmoothingEnabled = true;
context.mozImageSmoothingEnabled = true;
};
function openCamera(){
navigator.getMedia(
{ video:true, audio: false },
function(localMediaStream){
mediaStream = localMediaStream;
video.src=window.URL.createObjectURL(localMediaStream);
},
function(err){
alert('Unable to support live capture.');
}
);
}
function takePicture(){
var w = video.videoWidth;
var h = video.videoHeight;
context.drawImage(video,0,0,w,h);
canvas.style.display='block';
video.style.display='none';
}
</script>
</head>
<body onload="onLoad();">
<div>
<video autoplay style="width:640px; height:480px;"></video>
<canvas style="width:640px; height:480px; display:none;"></canvas>
</div>
<div>
<button id="openCameraButton" type="button" onclick="openCamera();" >Open Camera</button>
<button id="takePictureButton" type="button" onclick="takePicture();" >Take Picture</button>
</div>
</body>
</html>
Any ideas?
please try this:
function takePicture(){
var w = video.videoWidth;
var h = video.videoHeight;
canvas.width = w;
canvas.height = h;
context.drawImage(video,0,0,w,h);
canvas.style.display='block';
video.style.display='none';
}
Related
I am trying to capture image from webcam into a canvas and I would like to store this image data as an pixel array. How can I store it, please?
this is how I am drawing the picture from webcam to a context:
context = canvas.getcontext('2d');
captureButton.addEventListerner('click', ()=> {
context.drawImage(player, 0, 0, canvas.width. canvas.height);}
player is defined in html as <video id='player' controls autoplay></video>
best regards
This is something I've already done in my library jsia, so I'll expand it out for you here:
This doesn't work on Stack Exchange because of security restrictions, but you can see it working at https://mellen.github.io/jsiaExamples/barcodeReader
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var vid = document.getElementById('vid');
function setupVideoCallback(videoElement, callbackCapture, callbackError, timeBetweenFrames)
{
var localMediaStream = null;
navigator.getUserMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia );
var um = navigator.mediaDevices.getUserMedia({video: true}).then(handleVid).catch(vidErr);
if(!um)
{
um = navigator.getUserMedia({video: true}, handleVid, vidErr);
}
function handleVid(stream)
{
videoElement.srcObject = stream;
localMediaStream = stream;
}
function vidErr(e)
{
callbackError(e)
}
function capture()
{
if(localMediaStream)
{
callbackCapture();
}
}
setInterval(capture, timeBetweenFrames);
}
function drawVideoOnCanvas()
{
canvas.width = vid.clientWidth;
canvas.height = vid.clientHeight;
ctx.drawImage(vid, 0, 0);
}
setupVideoCallback(vid, drawVideoOnCanvas, e => console.log(e), 10);
<canvas id="canvas"></canvas>
<video autoplay style="visibility:hidden" id="vid"></video>
Hi I'm dealing with a problem in my project.
The code extracts an image from a video and creates a canvas with the image extracted on it, this works fine but when trying to upload the base64 data image which is created from the video. It generates a 0 byte image on the server.
Anyone knows why??
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
<script type="text/javascript" src="https://www.dudoby.com/js/jquery.min.js"></script>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div class="booth">
<video id="video" width="400" height="300" autoplay></video>
</div>
<iframe style="visibility: hidden;" name="u-n"></iframe>
<button id="capture">Capture</button>
<form id="submitphoto" action="../success/upload_video" method="POST" enctype="multipart/form-data">
<div id="output">
</div>
</form>
<script type="text/javascript" src="js/video.js"></script>
</body>
</html>
JS File:
(function() {
var video = document.getElementById('video'),
vendorUrl = window.URL || window.webkitURL;
navigator.getMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
//Capture video
navigator.getMedia({
video: true,
audio: false
}, function(stream){
video.src = vendorUrl.createObjectURL(stream);
blob = video.src;
video.play();
}, function(error) {
//An error ocurred
//error.code
});
//Get image
var video, $output;
var scale = 0.25;
var initialize = function() {
$output = $("#output");
video = $("#video").get(0);
$("#capture").click(captureImage);
};
var captureImage = function() {
var canvas = document.createElement("canvas");
canvas.width = video.videoWidth * scale;
canvas.height = video.videoHeight * scale;
canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
var img = document.createElement("img");
img.src = canvas.toDataURL();
$output.prepend(img);
var input = document.createElement("input");
input.setAttribute("type", "hidden");
input.setAttribute("name", "data");
input.value = canvas.toDataURL();
$output.prepend(input);
$("#submitphoto").submit();
};
$(initialize);
})();
PHP FiLE:
<?php
session_start();
ob_start();
$logged_user = $_SESSION['valid_user'];
include("../adb/thisdb.php");
error_reporting(0);
$file = $_POST['data'];
$img = str_replace('data:image/png;base64,', '', $file);
file_put_contents('../video_streaming/testimg.png', base64_decode($img));
ob_flush();
?>
EDIT>FIXED: After trying lots of things, I've finally fixed the error by changing the form url to a direct full address.
PREVIOUS:
<form target="u-n" id="submitphoto" action="../success/upload_video" method="POST" enctype="multipart/form-data">
WORKING ONE:
<form target="u-n" id="submitphoto" action="https://www.dudoby.com/success/upload_video" method="POST" enctype="multipart/form-data">
I'm trying to create a streaming video for a project, I am creating in node.js including html, and I can not finish by this error
Uncaught TypeError: Can not read property 'getContext' of null
then I need to fix that problem, but I can not because I sought solutions and this type of error, but none works for me up to work only issue
I had to comment on these lines:
var context = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 600;
context.width = canvas.width;
context.height = canvas.height
Here the codes of my proyect:
Emitir Video
<canvas style = "display:none;" id "preview" width='1280' height='720'></canvas>
<div id = "logger"></div>
<script type="text/javascript">
var canvas = document.getElementById("preview");
var context = canvas.getContext("2d"); // This is the line that generates the error
canvas.width = 800;
canvas.height = 600;
context.width = canvas.width;
context.height = canvas.height;
var video = document.getElementById("video");
var socket = io();
function logger(msg)
{
$("#logger").text(msg);
}
function loadCam(stream)
{
video.src = window.URL.createObjectURL(stream);
logger('Camara cargada correctamente [OK]');
}
function loadFail()
{
logger('Camara no conectada, Favor Conectela');
}
function viewVideo(video,context)
{
context.drawImage(video,0,0,context.width,context.height);
socket.emit('stream',canvas.toDataURL('image/webp'));
}
$(function(){
navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msgGetUserMedia);
if (navigator.getUserMedia)
{
navigator.getUserMedia({video: true}, loadCam, loadFail);
}
//1000 = 1 Seg.
setInterval(function(){
viewVideo(video,context);
},70);
});
</script>
</body>
</html>
Thanks i will apreciate helps.
You need to change id "preview" to id="preview", then you can move on to whatever the next error will be :)
I have created a live video feed on a webpage with HTML 5, it works find but i am wondering is it possible to get video from many different sources.
How it works is it uses the built in webcam, grabs the video feed from that and adds it to the HTML of the page.
Is there any way I can duplicate this but grab video sources from another webcam? (i.e Have multiple live video feeds on the one page)
index.html
<!Doctype html>
<head>
<title>LiveStream</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div class="booth">
<video id="video" width="400" height="300" autoplay controls></video>
<canvas id="canvas" width="400" width="300">
<script src="video.js"></script>
</div>
</body>
video.js
(function(){
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
video = document.getElementById('video'),
vendorUrl = window.URL || window.webkitURL;
navigator.getMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
navigator.getMedia({
video: true,
audio: true
}, function(stream){
video.src = vendorUrl.createObjectURL(stream);
video.play();
}, function(error){
//Error occured!
});
})();
I have tried the following with MediaDevices.enumerateDevices but it isn't working!
(function(){
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
video = document.getElementById('video'),
vendorUrl = window.URL || window.webkitURL;
navigator.getMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia ||
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
devices.forEach(function(device) {
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
video = document.getElementById('video'),
vendorUrl = window.URL || window.webkitURL;
});
})
navigator.getMedia({
video: true,
audio: true
}, function(stream){
video.src = vendorUrl.createObjectURL(stream);
video.play();
}, function(error){
//Error occured!
});
}
)();
Important Note
The code below has not been tested in real conditions
I only have one webcam attached to my computer and it may fail on some systems !
You just have to make a second call to the getUserMedia, and in the prompt choose an other device.
There may have been some way in some implementations to choose the device, using video constraints, but I think it's not in the still in draft specs anymore.
Here is a way, using a button, which will create a new video element with a new stream each time :
(function() {
// We declare once what our video elements should look like
var video = document.createElement('video');
video.width = 400;
video.height = 300;
video.autoplay = true;
video.controls = true;
// Where will those be appended in doc
var container = document.querySelector('.booth'),
butt = document.querySelector('button'),
vendorUrl = window.URL || window.webkitURL;
navigator.getMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
function requestCam() {
navigator.getMedia({
video: true,
audio: true
}, function(stream) {
// clone our model video
var videoEl = video.cloneNode(true);
container.appendChild(videoEl);
// wait for the stream has been loaded in the video (kind of useless with autoplay = true)
videoEl.onloadedmetadata = function() {
this.play();
};
videoEl.src = vendorUrl.createObjectURL(stream);
}, function(error) {
console.log(error);
});
}
// attach the function to the button
butt.addEventListener('click', requestCam, false);
})();
button {
position: absolute;
}
<div class="booth">
<button>Add a new stream</button>
</div>
Fiddle for chrome which blocks stack-snippetĀ® getUserMedia() requests
To avoid the use of a button, you could chain your call to requestCam, but you'll have to call it after the last one was either approved or denied.
One way would be to insert it in the callback of the getUserMedia() ; but you may need to add some counter to avoid an infinite chain of calls.
(function() {
var video = document.createElement('video');
video.width = 400;
video.height = 300;
video.autoplay = true;
video.controls = true;
var container = document.querySelector('.booth'),
vendorUrl = window.URL || window.webkitURL;
navigator.getMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
var maxVideos = 3;
function requestCam(count) {
// we made it ? stop right now.
if(count >= maxVideos) return;
navigator.getMedia({
video: true,
audio: true
}, function(stream) {
var videoEl = video.cloneNode(true);
container.appendChild(videoEl);
videoEl.onloadedmetadata = function() {this.play();};
videoEl.src = vendorUrl.createObjectURL(stream);
// increment our counter
requestCam(++count);
}, function(error) {
console.log(error);
});
}
// make our first call with count=0
requestCam(0);
})();
<div class="booth">
</div>
Fiddle for chrome
Using javascript or Jquery I want to get the current image from the webcam feed on my page and put it in an tag.
I have a bit of script which generates tags dynamically with unique Id's so after generating one all I want to do is capture an image from the webcam at that exact moment and save the image in the generated tag. After taking the image I just want the webcam to carry until the next time it takes a picture.
I already have a webcam feed running using a library which does face tracking, however I want to extend this with this feature to create a gallery of captured images on the page.
The library I am using is ClmTracker
Creator of the library suggested calling getImageData(x,y,w,h) on the video element and I have tried this. also tried to implement tutorials I have seen on other websites but to no avail. It would seem the answer would need to be specific to my code. I have tried to use canvas instead of tags to put the image in to, but I kept getting errors due to them being created dynamically in the code.
var vid = document.getElementById('videoel');
var overlay = document.getElementById('overlay');
var overlayCC = overlay.getContext('2d');
/********** check and set up video/webcam **********/
function enablestart() {
var startbutton = document.getElementById('startbutton');
startbutton.value = "start";
startbutton.disabled = null;
}
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL;
// check for camerasupport
if (navigator.getUserMedia) {
// set up stream
var videoSelector = {
video: true
};
if (window.navigator.appVersion.match(/Chrome\/(.*?) /)) {
var chromeVersion = parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10);
if (chromeVersion < 20) {
videoSelector = "video";
}
};
navigator.getUserMedia(videoSelector, function (stream) {
if (vid.mozCaptureStream) {
vid.mozSrcObject = stream;
} else {
vid.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
}
vid.play();
}, function () {
//insertAltVideo(vid);
alert("There was some problem trying to fetch video from your webcam. If you have a webcam, please make sure to accept when the browser asks for access to your webcam.");
});
} else {
//insertAltVideo(vid);
alert("This demo depends on getUserMedia, which your browser does not seem to support. :(");
}
vid.addEventListener('canplay', enablestart, false);
How can I capture an image from the webcam and put it in a div using the code above as a basis?
I'm not sure I can give any more details as I have not got the knowledge on how to do this.
First, draw it to a canvas:
var canvas = document.createElement('canvas');
canvas.height = video.height;
canvas.width = video.width;
canvas.getContext('2d').drawImage(video, 0, 0);
And now you can create the image:
var img = document.createElement('img');
img.src = canvas.toDataURL();
I cannot get to seem to get the screenshot porting working, but the webcam part is working fine, I'll update when complete.
JSFiddle
HTML
<div id="container">
<video autoplay="true" id="videoElement">dsasd</video>
<br>
<button onclick="snap()">Screenshot</button>
<canvas></canvas>
</div>
JS
var video = document.querySelector("#videoElement");
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({
video: true
}, handleVideo, videoError);
}
function handleVideo(stream) {
video.src = window.URL.createObjectURL(stream);
}
function videoError(e) {
// do something
}
// Get handles on the video and canvas elements
var video = document.querySelector('video');
var canvas = document.querySelector('canvas');
// Get a handle on the 2d context of the canvas element
var context = canvas.getContext('2d');
// Define some vars required later
var w, h, ratio;
// Add a listener to wait for the 'loadedmetadata' state so the video's dimensions can be read
video.addEventListener('loadedmetadata', function() {
// Calculate the ratio of the video's width to height
ratio = video.videoWidth / video.videoHeight;
// Define the required width as 100 pixels smaller than the actual video's width
w = video.videoWidth - 100;
// Calculate the height based on the video's width and the ratio
h = parseInt(w / ratio, 10);
// Set the canvas width and height to the values just calculated
canvas.width = w;
canvas.height = h;
}, false);
// Takes a snapshot of the video
function snap() {
// Define the size of the rectangle that will be filled (basically the entire element)
context.fillRect(0, 0, w, h);
// Grab the image from the video
context.drawImage(video, 0, 0, w, h);
}
CSS
container {
margin: 0px auto;
width: 500px;
height: 375px;
border: 10px #333 solid;
}
videoElement, canvas {
width: 500px;
height: 375px;
background-color: #666;
}