Canvas drawImage of html5 video works on browsers but not Android - javascript

Why does this code work on normal browsers, but show the same screenshot for Android browsers?
Html
<div class="video">
<video id="video" src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" muted controls autoplay></video>
</div>
<div class="timeline" id="timeline"></div>
JavaScript
var timeline = document.getElementById('timeline'),
video = document.getElementById('video'),
interval = null;
video.addEventListener("playing", onStart);
video.addEventListener("pause", onStop);
video.addEventListener("ended", onEnd);
function onStart() {
if (interval == null) {
interval = window.setInterval(createImage, 1000);
}
}
function onStop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function onEnd() {
onStop();
video.removeEventListener("playing", onStart);
video.removeEventListener("pause", onStop);
video.removeEventListener("ended", onEnd);
}
function createImage() {
console.log('createImage', video.currentTime, video.videoWidth, video.videoHeight);
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
timeline.appendChild(canvas);
}
Here is the full code:
http://jsfiddle.net/kmturley/z99cmwtq/6/

how come this works for me in chrome android 4.4.4 ?
drawImage()
codepen

Related

Save images data of canvas in JavaScript

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>

jsQR Javascript mediadevices undefined

I am trying to implement the jsQR javascript library from git: jsQR
I am testing on Safari 13.0.4 and when i run their demo found on their webpage it runs with no problems.
Now when i implement the same exact code (copy&paste) from the demo's inspector to my page i get the message TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia') which after some console printing the actual undefined object is navigator.mediaDevices this is strange since their demo is working i do not think it is a browser issue.
Additionally i run my page on firefox and it works perfectly fine.
What might be the problem?
Here is the code i have (it is the exact as demo anyway):
Javascript:
var video = document.createElement("video");
var canvasElement = document.getElementById("canvas");
var canvas = canvasElement.getContext("2d");
var loadingMessage = document.getElementById("loadingMessage");
var outputContainer = document.getElementById("output");
var outputMessage = document.getElementById("outputMessage");
var outputData = document.getElementById("outputData");
function drawLine(begin, end, color) {
canvas.beginPath();
canvas.moveTo(begin.x, begin.y);
canvas.lineTo(end.x, end.y);
canvas.lineWidth = 4;
canvas.strokeStyle = color;
canvas.stroke();
}
$(document).ready(function () {
console.log(navigator.mediaDevices);
})
// Use facingMode: environment to attemt to get the front camera on phones
navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then(function(stream) {
video.srcObject = stream;
video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
video.play();
requestAnimationFrame(tick);
});
function tick() {
loadingMessage.innerText = "⌛ Loading video..."
if (video.readyState === video.HAVE_ENOUGH_DATA) {
loadingMessage.hidden = true;
canvasElement.hidden = false;
outputContainer.hidden = false;
canvasElement.height = video.videoHeight;
canvasElement.width = video.videoWidth;
canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
var code = jsQR(imageData.data, imageData.width, imageData.height, {
inversionAttempts: "dontInvert",
});
if (code) {
drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
outputMessage.hidden = true;
outputData.parentElement.hidden = false;
outputData.innerText = code.data;
} else {
outputMessage.hidden = false;
outputData.parentElement.hidden = true;
}
}
requestAnimationFrame(tick);
}
Html:
<div id="loadingMessage">🎥 Unable to access video stream (please make sure you have a webcam enabled)</div>
<canvas id="canvas" hidden></canvas>
<div id="output" hidden>
<div id="outputMessage">No QR code detected.</div>
<div hidden><b>Data:</b> <span id="outputData"></span></div>
</div>
Solved it. The development server is not secure and thus safari does not allow the use of WebRTC on insecure connections.
To allow the use (on safari at least) you have to go to Develop>WebRTC>Allow media capture on insecure sites.

HTML video tag to fill whole screen on phones

Right now, I am trying to create a "snapchat" kind of web app, for my education.
The app makes use of HTML5 tags, like video and canvas.
Then i use getUserMedia to get the camera output, but my problem is that i can't get the video tag to fill the whole screen.
I have tried everything from width: 100%; height: 100%;, height: 100vh, jquery, but that messed up the getUserMedia function, so it didn't even work.
Right now, this is my code:
HTML File:
<!doctype html>
<html lang="da">
<head>
<title>Camera output</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="css/style.css" type="text/css" rel="stylesheet">
<script src="jquery-3.1.1.min.js"></script>
</head>
<body>
<video id="video" autoplay></video>
<button id="snap" class="snapButton">Snap Photo</button>
<canvas id="canvas" width="640" height="480"></canvas>
<script src="js/script.js" type="text/javascript"></script>
</body>
</html>
CSS File:
* {
margin: 0;
padding: 0;
}
#video {
-webkit-transition: all 1s ease;
-moz-transition: all 1s ease;
-o-transition: all 1s ease;
transition: all 1s ease;
transform-origin: center center;
}
JS File:
function setElementFullScreen(selector) {
var ele= $(selector);
// Set left/top, can be done in directly in css
ele.css('top',0).css('left',0);
// Set size from window
ele.height($(window).height()).width($(window).width());
}
$(document).ready(function () {
setElementFullScreen('video');
});
// Add resize event
$(window).on('resize', function () {
setElementFullScreen('video');
});
// Put event listeners into place
window.addEventListener("DOMContentLoaded", function() {
// Grab elements, create settings, etc.
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var video = document.getElementById('video');
var mediaConfig = { video: true };
var errBack = function(e) {
console.log('An error has occurred!', e)
};
// Put video listeners into place
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia(mediaConfig).then(function(stream) {
video.src = window.URL.createObjectURL(stream);
video.play();
});
}
/* Legacy code below! */
else if(navigator.getUserMedia) { // Standard
navigator.getUserMedia(mediaConfig, function(stream) {
video.src = stream;
video.play();
}, errBack);
} else if(navigator.webkitGetUserMedia) { // WebKit-prefixed
navigator.webkitGetUserMedia(mediaConfig, function(stream){
video.src = window.webkitURL.createObjectURL(stream);
video.play();
}, errBack);
} else if(navigator.mozGetUserMedia) { // Mozilla-prefixed
navigator.mozGetUserMedia(mediaConfig, function(stream){
video.src = window.URL.createObjectURL(stream);
video.play();
}, errBack);
}
// Trigger photo take
document.getElementById('snap').addEventListener('click', function() {
context.drawImage(video, 0, 0, 640, 480);
});
}, false);
So my question is: Is there any way to make the video tag fill every bit of a phone screen? I tried on desktop, it had no problem with filling in horizontally.
Thanks in advance.
Try this,
<video id="video" autoplay></video>
<script>
var elem = document.getElementById("myvideo");
if(elem.requestFullscreen) {
elem.requestFullscreen();
}
</script>
This will ask the browser to use full screen on video playback. I think you'll have some issues with browser compatibility on mobile devices.
Reference:
https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API
Edit:
Seems to be your ele.height($(window).height()).width($(window).width()); giving you trouble. Try logging window.height() and window.width() to your debugging console to determine what it returns.
If you haven't already, look at this:
https://www.w3schools.com/tags/canvas_drawimage.asp
Here is a tutorial with similar application examples:
https://www.html5rocks.com/en/tutorials/getusermedia/intro/
Here you have a snipplet with working example.
function setElementFullScreen(selector) {
var ele = $(selector);
// Get window size
var maxWidth = $(window).width();
var maxHeight = $(window).height();
// Get video size
var videoWidth = ele.width();
var videoHeight = ele.height();
// Calcul relative size
if (maxWidth > maxHeight) {
var relatifWidth = videoWidth / (videoHeight / maxHeight);
var relatifHeight = maxHeight;
} else {
var relatifWidth = maxWidth;
var relatifHeight = videoHeight / (videoWidth / maxWidth);
}
// Check if result size is not bigger than canvas size
if (relatifWidth > maxWidth) {
relatifWidth = maxWidth;
relatifHeight = (relatifWidth * videoHeight) / videoWidth;
} else if (relatifHeight > maxHeight) {
relatifHeight = maxHeight;
relatifWidth = (relatifHeight * videoWidth) / videoHeight;
}
// Set size from window
ele.height(relatifHeight).width(relatifWidth);
}
$(document).ready(function () {
setElementFullScreen('#video');
// Put event listeners into place
window.addEventListener("DOMContentLoaded", function () {
// Grab elements, create settings, etc.
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var video = document.getElementById('video');
var mediaConfig = {video: true};
var errBack = function (e) {
console.log('An error has occurred!', e)
};
// Put video listeners into place
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia(mediaConfig).then(function (stream) {
video.src = window.URL.createObjectURL(stream);
video.play();
});
}
/* Legacy code below! */
else if (navigator.getUserMedia) { // Standard
navigator.getUserMedia(mediaConfig, function (stream) {
video.src = stream;
video.play();
}, errBack);
} else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
navigator.webkitGetUserMedia(mediaConfig, function (stream) {
video.src = window.webkitURL.createObjectURL(stream);
video.play();
}, errBack);
} else if (navigator.mozGetUserMedia) { // Mozilla-prefixed
navigator.mozGetUserMedia(mediaConfig, function (stream) {
video.src = window.URL.createObjectURL(stream);
video.play();
}, errBack);
}
// Trigger photo take
document.getElementById('snap').addEventListener('click', function () {
context.drawImage(video, 0, 0, 640, 480);
});
}, false);
});
// Add resize event
$(window).on('resize', function () {
setElementFullScreen('video');
});
video {
margin: 0;
padding: 0;
top: 0;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<video id="video" autoplay>
<source src="http://techslides.com/demos/sample-videos/small.mp4" type="video/mp4">
</video>
<br>
<button id="snap" class="snapButton">Snap Photo</button>
<br>
<canvas id="canvas" width="640" height="480"></canvas>

How to make HTML5 video fade in when it has finished loading?

I'm trying to have my HTML5 video element fade in when it loads, (I'm currently having it appear using Javascript canplaythrough as you can see in the code you see below, but it's a little harsh.) How can I get the HTML5 video element to fade in gently? I'm OK with JavaScript or jquery, but I don't know either one very well, so some complete code would be very helpful!
Here's the code: (if you run the code with the Run Code Snippet, it doesn't work well, so I highly suggest to go to my website, it's on is my video page here and works if you wait a 30 seconds/minute (until the video loads): jeffarries.com/videos.
<script>
var e = document.getElementById("myVideo");
e.style.display = 'none'
var vid = document.getElementById("myVideo");
vid.oncanplaythrough = function() {
var e = document.getElementById("myVideo");
e.style.display = 'block'
};
</script>
<video style="display: block;" id="myVideo" width="320" height="176" controls>
<source src="http://www.jeffarries.com/videos/jeff_arries_productions_intro.mp4" type="video/mp4">
Your browser does not support HTML5 video.
</video>
Thanks for you time and effort!
Here's how to fade in the video with javascript
var e = document.getElementById("myVideo");
e.style.opacity = 0;
var vid = document.getElementById("myVideo");
vid.oncanplaythrough = function() {
setTimeout(function() {
var e = document.getElementById('myVideo');
fade(e);
}, 5000);
};
function fade(element) {
var op = 0;
var timer = setInterval(function() {
if (op >= 1) clearInterval(timer);
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op += op * 0.1 || 0.1;
}, 50);
}
FIDDLE

How use canvas from external video?

I have the following code:
<!DOCTYPE html>
<title>Video/Canvas Gray Effect</title>
<script>
document.addEventListener('DOMContentLoaded', function(){
var v = document.getElementById('v');
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
var back = document.createElement('canvas');
var backcontext = back.getContext('2d');
var cw,ch;
v.addEventListener('play', function(){
cw = v.clientWidth;
ch = v.clientHeight;
canvas.width = cw;
canvas.height = ch;
back.width = cw;
back.height = ch;
draw(v,context,backcontext,cw,ch);
},false);
},false);
function draw(v,c,bc,w,h) {
if(v.paused || v.ended) return false;
// First, draw it into the backing canvas
bc.drawImage(v,0,0,w,h);
// Grab the pixel data from the backing canvas
var idata = bc.getImageData(0,0,w,h);
var data = idata.data;
// Loop through the pixels, turning them grayscale
for(var i = 0; i < data.length; i+=4) {
var r = data[i];
var g = data[i+1];
var b = data[i+2];
var brightness = (3*r+4*g+b)>>>3;
data[i] = brightness;
data[i+1] = brightness;
data[i+2] = brightness;
}
idata.data = data;
// Draw the pixels onto the visible canvas
c.putImageData(idata,0,0);
// Start over!
setTimeout(draw,20,v,c,bc,w,h);
}
</script>
<video id=v controls loop>
<source src=video.webm type=video/webm>
</video>
<canvas id=c></canvas>
<style>
#c {
position: absolute;
top: 50%;
left: 50%;
margin: -180px 0 0 20px;
}
#v {
position: absolute;
top: 50%;
left: 50%;
margin: -180px 0 0 -500px;
}
</style>
The canvas work only if the video hosted in my site, but if a external video the canvas not working only work if make a proxy using the same domain, for example:
Working if a hosted the video on my site:
<video id=v controls loop>
<source src=video.webm type=video/webm>
</video>
Working if a use a proxy, but I will not use a proxy:
<video id=v controls loop>
<source src=./proxy.php?url_toexternal_video=http://host.com/video.webm type=video/webm>
</video>
Not working if a use the direct link to the video:
<video id=v controls loop>
<source src=http://host.com/video.webm type=video/webm>
</video>
any way to make it work if it is from an external video? Thanks! ;)
Nope, there's no way to use getImageData on a canvas that has been tainted by cross-origin content.

Categories