I am having an issue with turning the webcam off once I have taken a snapshot. The code below works well - but I just cant figure out how to turn off the webcam once I have everything in the canvas.
I have tried a few methods that I have found by some some research, however none seem to help.
I have tried to add video.stop(); in the "snap" eventListener, and it says "undefined is not a function", however most things I have read says it should work?
Error screenshot: https://www.dropbox.com/s/h7g4cidqhimc5ij/Screenshot%202014-08-04%2013.08.04.png
To sum it all up, when someone clicks "Take Picture", I want the picture to be taken and the camera hardware turned off. The eventlister in later half of the code below is for the "Take Picture" button.
function startCam() {
$('#can').hide();
$('#video').show();
$('#tab1-retry').hide();
$('#save-tab1').hide();
var video = document.getElementById("video"),
mask = document.getElementById("mask"),
videoObj = {
"video": true
},
errBack = function(error) {
console.log("Video capture error: ", error.code);
};
// Put video listeners into place
if (navigator.getUserMedia) { // Standard
navigator.getUserMedia(videoObj, function(stream) {
video.src = stream;
video.play();
}, errBack);
} else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
navigator.webkitGetUserMedia(videoObj, function(stream) {
video.src = window.webkitURL.createObjectURL(stream);
video.play();
}, errBack);
} else if (navigator.mozGetUserMedia) { // WebKit-prefixed
navigator.mozGetUserMedia(videoObj, function(stream) {
video.src = window.URL.createObjectURL(stream);
video.play();
}, errBack);
}
document.getElementById("snap").addEventListener("click", function() {
window.canvas1 = new fabric.Canvas('canvas');
video.pause();
$('#video').hide();
$('#snap').hide();
$('#can').show();
$('#save-tab1').show();
$('#tab1-retry').show();
// VIDEO CAPTURE
var imgInstance = new fabric.Image(video, {
left: 0,
top: 0,
});
imgInstance.set('selectable', false);
canvas1.add(imgInstance);
// FIRST LAYER
mask = document.getElementById("mask");
var imgInstance1 = new fabric.Image(mask, {
left: 100,
top: 100,
cornerSize: 20
});
imgInstance1.set('selectable', true);
canvas1.add(imgInstance1);
// CANVAS LAYER
canvas1.setActiveObject(canvas1.item(1));
canvas1.item(1)['evented'] = true;
canvas1.calcOffset();
canvas1.renderAll();
});
}
inside your success callback function you could initialize the stream to a variable say:
var cameraStream = stream;
video.src = window.URL.createObjectURL(stream);
then in your 'snap' eventListener you could just pause() the video stream after taking the screenshot and close/stop the cameraStream:
video.pause();
cameraStream.stop();
.stop() closes the webcam input.
Related
My question is, how can I save COMPLETE images from a HTML5 camera live stream?
Here you can find me current code ( I'm a JavaScript beginner ):
const video = document.getElementById('video');
const canvas = document.getElementById('faceImage');
const hdConstraints = {
audio: false,
video: { width: { min: 1280 }, height: { min: 720 } }
};
var options = { mimeType: 'video/webm' };
navigator.mediaDevices.getUserMedia(hdConstraints, options)
.then(
(stream) => {
video.srcObject = stream;
video.play();
setInterval(function() {
var context = canvas.getContext('2d');
context.drawImage(video, 0, 0, 1280, 720);
var data = canvas.toDataURL('image/jpeg');
ws.send(data);
}, 1000);
}
);
With this code on the server side I receive not complete jpeg images ( only 10% of the canvas is on the picture and the other parts are blank).
So my question is, how can I correct this code to send only complete images to the server ?
thanks
I am using fabric js version 1.7.22
when image set in a repetitive manner in a rectangle of fabric js, at
the first time it will be loaded and saved into JSON using toJSON()
and save an image using todataUrl() method, but when cal canvas a loadFromJson method at that time, this canvas not savable, because it throws tainted canvas error.
Please help me,
I already set crossOrigin in a pattern but it not working. and not
added in canvas JSON.
I have made one Fiddle For Generate Issue :
[http://jsfiddle.net/Mark_1998/kt387vLc/1/][1]
Steps to generate issue :
click on 'set pattern'
then click on 'save canvas'
then click on 'reload canvas' // load canvas from JSON
then click on 'save canvas' // cause issue of tainted canvas
This issue is fixed in new version of fabricjs already. If you are still using 1.7.20 the override fabric.Pattern.prototype.toObject and fabric.Pattern.prototype.initialize, find code in snippet.
var canvas = new fabric.Canvas('canvas', {
height: 500,
width: 500,
});
canvas.backgroundColor = '#ff0000';
canvas.renderAll();
var canvasJSON = {};
document.getElementById('setPat').addEventListener('click', function() {
fabric.util.loadImage('https://cdn.dribbble.com/assets/icon-backtotop-1b04df73090f6b0f3192a3b71874ca3b3cc19dff16adc6cf365cd0c75897f6c0.png', function(image) {
var pattern = new fabric.Pattern({
source: image,
repeat: 'repeat',
crossOrigin: 'Anonymous'
});
var patternObject = new fabric.Rect({
left: 0,
top: 0,
height: canvas.height,
width: canvas.width,
angle: 0,
fill: pattern,
objectCaching: false
})
canvas.add(patternObject);
}, null, {
crossOrigin: 'Anonymous'
});
})
document.getElementById('saveCanvas').addEventListener('click', function() {
console.log('save canvas');
canvasJSON = canvas.toJSON();
var image = canvas.toDataURL("image/png", {
crossOrigin: 'Anonymous'
}); // don't remove this, i need it as thumbnail.
//console.log('canvas.Json', canvasJSON);
//console.log('image', image);
canvas.clear();
canvas.backgroundColor = '#ff0000';
canvas.renderAll();
});
document.getElementById('reloadCanvas').addEventListener('click', function() {
console.log('save canvas');
canvas.loadFromJSON(canvasJSON, function() {
canvas.set({
crossOrigin: 'Anonymous'
})
});
console.log('canvas.Json', canvasJSON);
});
//cross origin was not added in toObject JSON
fabric.Pattern.prototype.toObject = (function(toObject) {
return function() {
return fabric.util.object.extend(toObject.call(this), {
crossOrigin: this.crossOrigin,
patternTransform: this.patternTransform ? this.patternTransform.concat() : null
});
};
})(fabric.Pattern.prototype.toObject);
//cross origin was not added while creating image
fabric.Pattern.prototype.initialize = function(options, callback) {
options || (options = {});
this.id = fabric.Object.__uid++;
this.setOptions(options);
if (!options.source || (options.source && typeof options.source !== 'string')) {
callback && callback(this);
return;
}
// function string
if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') {
this.source = new Function(fabric.util.getFunctionBody(options.source));
callback && callback(this);
} else {
// img src string
var _this = this;
this.source = fabric.util.createImage();
fabric.util.loadImage(options.source, function(img) {
_this.source = img;
callback && callback(_this);
}, null, this.crossOrigin);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.js"></script>
<button id="setPat">
Set pattern
</button>
<button id="saveCanvas">
Save canvas
</button>
<button id="reloadCanvas">
Reload CAnvas
</button>
<canvas id="canvas"></canvas>
Audio is being heard even though no audio element seems to be put inserted in the DOM.
Scenario:
Create PeerConnection without streams
Add a stream but disable the code that adds MediaElements (audio,video) to DOM
Issue:
After the stream gets across, audio can be heard from headphones (or speakers).
What should happen:
Since I'm not attaching anything to the dom I expect no audio to be heard.
Code for replicating the scenario
// <body>
// <script src="https://cdn.webrtc-experiment.com/RTCMultiConnection.js"></script>
// <button id="start">Start!</button>
// </body>
$('#start').click(function() {
var NO_MEDIA_SESSION = {video: false, audio: false, oneway: true};
var caller = new RTCMultiConnection('lets-try');
caller.session = NO_MEDIA_SESSION;
caller.dontAttachStream = true;
caller.onstream = function() { console.log("Got stream but not attaching") };
var receiver = new RTCMultiConnection('lets-try');
receiver.session = NO_MEDIA_SESSION;
receiver.dontAttachStream = true;
receiver.onstream = function() { console.log("Got stream but not attaching") };
caller.open();
receiver.connect();
receiver.onconnected = function() {
console.log("Connected!");
caller.addStream({audio: true});
}
});
I'm interested how is it possible to hear MediaStream without there being audio DOM element?
If any RTCMultiConnection specialists answering, then maybe point me how to avoid audio stream being made audible? (I want to get the stream and attach it later myself).
RTCMultiConnection creates mediaElement on the fly to make sure onstream event is fired only when media stream started flowing.
connection.onstream = function(event) {
event.mediaElement.pause(); // or volume=0
// or
event.mediaElement = null;
// or
delete event.mediaElement;
};
Updated:
Use following snippet:
var connection = new RTCMultiConnection();
connection.session = {
data: true
};
btnOpenRoom.onclick = function() {
connection.open('roomid');
};
btnJoinRoom.onclick = function() {
connection.join('roomid');
};
btnAddAudioStream.onclick = function() {
connection.addStream({
audio: true
});
};
btnAddAudioVideoStream.onclick = function() {
connection.addStream({
audio: true,
video: true
});
};
The question is not why is mobile important, I get that.
The question is how can it be the case that there is not a single HTML5 browser for the desktop that has these same get user media extensions in place yet??
Basing this on this post.
HTML
<video id="video" width="300" height="220" autoplay></video>
<button id="snap">Take Photo</button>
<canvas id="canvas" width="300" height="220"></canvas>
JS:
<Script>
// Put event listeners into place
window.addEventListener("DOMContentLoaded", function() {
// Grab elements, create settings, etc.
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
video = document.getElementById("video"),
videoObj = {
"video": true
},
errBack = function(error) {
console.log("Video capture error: ", error.code);
};
// Put video listeners into place
if (navigator.getUserMedia) { // Standard
navigator.getUserMedia(videoObj, function(stream) {
video.src = stream;
video.play();
}, errBack);
} else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
navigator.webkitGetUserMedia(videoObj, function(stream) {
video.src = window.webkitURL.createObjectURL(stream);
video.play();
}, errBack);
} else if (navigator.mozGetUserMedia) { // Firefox-prefixed
navigator.mozGetUserMedia(videoObj, function(stream) {
video.src = window.URL.createObjectURL(stream);
video.play();
}, errBack);
}
document.getElementById("snap").addEventListener("click", function() {
context.drawImage(video, 0, 0, 300, 220);
});
}, false);
</Script>
that works on both chrome and firefox :)
Look at this link. This document is not complete. It is subject to major changes and, while early experimentations are encouraged, it is therefore not intended for implementation.
That's why it's not fully supported across browsers.
I am attempting to write my own HTML5 audio player: you can peek at it here.
It works fine in IE9, FF, Chrome but in Safari for some reason even though i have listened for
audio.addEventListener("loadedmetadata", tryThis, false);
It displays NaN duration data just before playing.
audio.setAttribute("src", a[trackNo][1]);
audio.load();
audio.addEventListener("loadedmetadata", tryThis, false);
function tryThis()
{
this.addEventListener("timeupdate", function() { document.getElementById(radioPointer.toString()).innerHTML = formatTime(this.duration, this.currentTime);}, false);
this.addEventListener("ended", function () { document.getElementById(radioPointer.toString()).innerHTML = formatTime(this.duration, 0); document.rootsPlaylist.roots[radioPointer].checked = false; }, false);
this.play();
}
<audio id="rootsPlayer" style="display:none;"></audio>
Could you offer any help please?
Many thanks.
NOTE: You have to flip between songs frequently to see what I mean, sorry I forgot to mention this.
The reason for this is that duration property is initialized only after the durationchange event is emitted. So, you can either use isNan() function or some dummy durationInitialized variable:
var durationInitialized = 0;
audio.setAttribute("src", a[trackNo][1]);
audio.load();
audio.addEventListener("loadedmetadata", tryThis, false);
audio.addEventListener("durationchange", function() {durationInitialized = 1;}, false);
function tryThis() {
this.addEventListener("timeupdate", function() {
var time = '';
if (durationInitialized) time = formatTime(this.duration, this.currentTime);
else time = formatTime(this.currentTime);
document.getElementById(radioPointer.toString()).innerHTML = time;
}, false);
this.addEventListener("ended", function () {
var time = '';
if (durationInitialized) time = formatTime(this.duration, 0);
else time = formatTime(0);
document.getElementById(radioPointer.toString()).innerHTML = time;
document.rootsPlaylist.roots[radioPointer].checked = false;
}, false);
this.play();
}