HTML5 getUserMedia is not working with scientific microscopy camera Lumenera - javascript

I am using microscopy camera Lumenera INFINITY1-2 (https://www.lumenera.com/infinity1-2.html) and from the camera description it tells that it can be integrated into 3rd party software packages using TWAIN support. I try to capture image from web page using HTML5 but it gives me error.
I also tried to check video streaming with Adobe Flash but camera stream is not displayed properly and captured images is quite broken (in fact it is empty)
I checked camera's drivers and they all installed and works. Native camera application also captures images well.
Question, is it possible to capture images in the web browser from the microscopy camera like that? It is being recognized by browser as a device but video stream is not working.
Please see below script (code is getting from here https://github.com/jhuckaby/webcamjs/blob/master/DOCS.md)
Thank you in advance
window.addEventListener("load", function () {
// [1] GET ALL THE HTML ELEMENTS
var video = document.getElementById("vid-show"),
canvas = document.getElementById("vid-canvas"),
take = document.getElementById("vid-take");
navigator.mediaDevices.getUserMedia({ video: true })
.then(function (stream) {
// [3] SHOW VIDEO STREAM ON VIDEO TAG
video.srcObject = stream;
video.play();
take.addEventListener("click", function () {
// Create snapshot from video
var draw = document.createElement("canvas");
draw.width = video.videoWidth;
draw.height = video.videoHeight;
var context2D = draw.getContext("2d");
context2D.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
// Output as file
var anchor = document.createElement("a");
anchor.href = draw.toDataURL("image/png");
anchor.download = "webcam.png";
anchor.innerHTML = "Click to download";
canvas.innerHTML = "";
canvas.appendChild(anchor);
var imageBase64 = draw.toDataURL("image/png").replace("data:image/png;base64,", "");
document.getElementById("hdn_ImageByte").setAttribute("value", imageBase64);
});
})
.catch(function (err) {
debugger;
console.log(err)
document.getElementById("vid-controls").innerHTML = "Please enable access and attach a camera";
});
});
</script>```

Related

HTML5 video element request stay pending forever (on chrome in mobile) when toggle over front-rare camera

I'm developing an app where users can capture photo using a front/rare camera. it working perfectly but when toggle over camera front/rare var playPromise = videoStream.play() is gone in pending state. some times promise get resolve, the camera is working sometimes not.
this issue occurs only in chrome browser not in mozila and firefox
try {
stopWebCam(); // stop media stream when toggle over camera
stream = await navigator.mediaDevices.getUserMedia({video: true});
/* use the stream */
let videoStream = document.getElementById('captureCandidateId');
videoStream.srcObject = stream;
// videoStream.play();
var playPromise = videoStream.play();
if (playPromise !== undefined) {
playPromise.then(_ => {
// Automatic playback started!
// Show playing UI.
})
.catch(error => {
// Auto-play was prevented
// Show paused UI.
});
}
};
} catch(err) {
/* handle the error */
console.log(err.name + ": " + err.message);
}
let stopWebCam = function (pictureType) {
setTimeout(()=>{
let videoStream = document.getElementById('captureCandidateId');
const stream = videoStream.srcObject;
if (stream && stream.getTracks) {
const tracks = stream.getTracks();
tracks.forEach(function(track) {
track.stop();
});
}
videoStream.srcObject = null;
}, 0)
}
Here, I drafted a piece of code for you, this is much more simple and smaller approach than what you are trying to do. I am just taking the stream from the video element and drawing it to canvas. Image can be downloaded by right clicking.
NOTE: Example does not work in StackOverflow
<video id="player" controls autoplay></video>
<button id="capture">Capture</button>
<canvas id="canvas" width=320 height=240></canvas>
<script>
const player = document.getElementById('player');
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
const captureButton = document.getElementById('capture');
const constraints = {
video: true,
};
captureButton.addEventListener('click', () => {
// Draw the video frame to the canvas.
context.drawImage(player, 0, 0, canvas.width, canvas.height);
});
// Attach the video stream to the video element and autoplay.
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
player.srcObject = stream;
});
</script>
If you want, you can also make some edits according to your needs, like:
Choose which camera to use
Hide the video stream
Add a easier method to download the photo on your device
You can also add a functionality to upload the photo straight to the server if you have one

Create a popup media player using JS?

I have been trying to make an audio player that has basic controls allowing audio to be played instead of a video. It needs to be viewed in PIP mode, as well. Here is my code so far:
var audio = document.createElement('audio'); // The Audio
var canvas = document.createElement('canvas'); // New Canvas To Contain Video
canvas.width = canvas.height = 512;
var video = document.createElement('video'); // Create Video
video.srcObject = canvas.captureStream(); // Make Video Reflect The Canvas
video.muted = true;
function showPictureInPictureWindow() {
const image = new Image();
image.crossOrigin = true;
image.src = [...navigator.mediaSession.metadata.artwork].pop().src;
image.decode();
canvas.getContext('2d').drawImage(image, 0, 0, 512, 512);
video.onloadedmetadata = function() {
video.play();
video.requestPictureInPicture();
};
}
window.VID = video;
window.AU = audio;
function playAudio() {
audio.src = "mysong.mp3";
// Update Media Session metadata
navigator.mediaSession.metadata = new MediaMetadata({
title: "Audio Title",
artist: "MEEEEEEE",
album: "LOOOL",
artwork: [{src: "graphics/128x128.png", sizes: "128x128", type: "image/png"}]
});
// Play audio
audio.play();
// Show track album in a Picture-in-Picture window
showPictureInPictureWindow();
}
window.VID.requestPictureInPicture();
playAudio();
Any help that you can give me would be very much appreciated. (I already have the pause and play functions but I didn't include them for message size)
PS: (I don't know why, but earlier I was getting an error that said "JavaScript exception: Failed to execute 'requestPictureInPicture' on 'HTMLVideoElement': Metadata for the video element are not loaded yet" and now I have no errors at all... and no music either...)
PPS: (I fixed some of the bugs... and now I have the original error again.)
I have the same problem as you, but I have solved it
My solution:
My guess is that the video data did not load successfully when the RequestPicturePicture function was executed
So you can execute the RequestPicturePicture function in the loadedData function

How to access document.body from a script inside of document.write

Help! I am working on an application which downloads a report from an API which gives me HTML as part of the JSON return. Because it returns JSON I cannot simply open this in a new window.
In this script I am injecting this code:
let tmp = result.data;
let spot = tmp.indexOf('</body>');
let insert = `<div style="position:fixed; top:200px;left:20px; width:200px;font-size:15pt">
<div class="camera">
<video id="video" style='display:hidden'>Video stream not available.</video>
<button onClick='takepicture()'>Take photo</button>
</div>
<canvas id="canvas" style='display:none;'></canvas>
<!--<button onClick='genPDF()'>PDF</button>-->
Press CTRL+S to save page as HTML
<img id="testDownloadImage" src='' width=600 height=400 />
</div>
<script type='text/javascript'>
alert(document.body.innerHtml)
// function clearphoto() {
// var context = canvas.getContext('2d');
// context.fillStyle = "#AAA";
// context.fillRect(0, 0, canvas.width, canvas.height);
// var data = canvas.toDataURL('image/png');
// // photo.setAttribute('src', data);
// }
// Capture a photo by fetching the current contents of the video
// and drawing it into a canvas, then converting that to a PNG
// format data URL. By drawing it on an offscreen canvas and then
// drawing that to the screen, we can change its size and/or apply
// other changes before drawing it.
async function takepicture() {
let video = document.getElementById('video');
let canvas = document.getElementById('canvas');
let displayMediaOptions={video: true,displaySurface:'browser', logicalSurface:true, cursor:'never', audio: false};
try{
video.srcObject = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
// video.play();
var context = canvas.getContext('2d');
width=window.innerWidth;
height=window.scrollHeight;
if (width && height) {
canvas.width = width;
canvas.height = height;
context.drawImage(video, 0, 0, width, height);
var data = canvas.toDataURL('image/jpg'); //.replace(/^data:image\/(png|jpg);base64,/, "");
// photo.setAttribute('src', data);
document.getElementById('testDownloadImage').src=data;
// location.href=data;
} else {
// clearphoto();
}
}
catch(err) {
console.log("An error occurred: " + err);
}
finally{
let tracks = video.srcObject.getTracks();
tracks.forEach(track => track.stop());
video.srcObject = null;
}
}
</script>
`
let newStr = [tmp.slice(0, spot), insert, tmp.slice(spot)].join('');
document.write(newStr);
to allow me to add a print screen option so that the report can be imaged. I have tried other utilities to save the HTML as a PDF or even saving the page but because the report uses a lot of XSLT and scripting to display the results these methods fail, leaving me with the print screen as the only option.
WebRTC handles this aptly, with one minor difficult: Because I am using document.write I am unable to find the document.body even though the code I am passed is a properly formed page ( etc).
How can I use the inserted script to display the page and capture it as an image?
Thanks
This is not a genuine answer sadly but I resolved the problem by moving the entire write to an iFrame with the script on the outside. I then got the scrollHeight of the iFrame document and resized the frame to match that, effectively making it appear as if the document occupied the entire page. This way I can place my script outside the iFrame and still use it to capture the entire page, which is what I was shooting for.
Thank you for any comments. As of now this is no longer needed.

Web API MediaRecorder: How do I force record at 60fps?

Summary
The API I speak about
The context
The problem: Actual result + Expected result
What I already have tried
Clues to help you to help me
Minimal and Testable Example: Prerequisites and Steps to follow + Sources
The API I speak about
https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder
The context
I have a video element that I load & play several times with different src. Between two different videos, a transition occures and each video appears with a fade in. When a video is playing, I draw it in a canvas with the transition and the fade in.
Everything I draw in the canvas is recorded using the Web API MediaRecorder. Then I download the WEBM file corresponding to this recording.
The problem
Actual result
The resulting WEBM is jerky. When I drew in the canvas, the drawing was fluid. But the WEBM resulting from the recording of the canvas drawing is jerky.
Expected result
The WEBM resulting from the recording of the canvas drawing must be as fluid as the canvas drawing itself. If it's impossible to have exactly this result, then: the WEBM must be approximately as fluid as the canvas drawing itself in a way that we quite can't say it's jerky.
What I have already tried
First, I've tried to set a time slice of 1ms, of 16ms (corresponding to 60fps), of 100ms, then 1000, then 10000, etc. to the method start of the Media Recorder, but it didn't work.
Second, I've tried to call requestData every 16ms (in a simple JS timeoutlistener executed every 16ms), but it didn't work.
Clues to help you to help me
Perhaps I'm wrong but it would be possible that a material limit exist on my computer (I have a HP Spectre x360 that doesn't have graphic card, but just a little graphics chip), or a logical limit on my Chromium browser (I have Version 81.0.4044.138 on my Ubuntu 16.04 LTS).
If you can confirm this it would solve this question. If you can explain how to deal with this problem it would be very good (alternative solution to the Web API Media Recorder, or something else).
Minimal and Testable Example
Prerequisites and Steps to follow
Have at least 2 WEBM videos (which will be the input videos, remember: we want to output a new video that contains the canvas drawing, which itself contains these two input videos plus transitions and colors effects etc.)
Have a HTTP server and a file called "index.html" that you will open with Chromium v.81 e.g.. Copy/paste the following sources inside ; click on the "Start" button (you won't need to click on the "Stop" button) ; it will draw both videos on the canvas, with the transitions & colors effects, it will record the canvas drawing, and a "Download the final output video" will appear, allowing you to download the output video. You will see that it's jerky.
In the following sources, copy/paste the paths of your videos in the JS array called videos.
Sources
<html>
<head>
<title>Creating Final Video</title>
</head>
<body>
<button id="start">Start</button>
<button id="stop_recording">Stop recording</button>
<video id="video" width="320" height="240" controls>
<source type="video/mp4">
</video>
<canvas id="canvas" width=3200 height=1608></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var videos = []; // Populated by Selenium
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var video = document.querySelector("video");
startRecording();
$('#start').click(function() {
showSomeMedia(0, 0);
});
function showSomeMedia(videos_counter) {
resetVideo();
if(videos_counter == videos.length) {
$('#stop_recording').click();
return;
} else {
setVideoSrc(videos_counter);
setVideoListener();
videos_counter++;
}
video.addEventListener('ended', () => {
showSomeMedia(videos_counter);
}, false);
}
function resetVideo() {
var clone = video.cloneNode(true);
video.remove();
video = clone;
}
function setVideoSrc(videos_counter) {
video.setAttribute("src", videos[videos_counter]);
video.load();
video.play();
}
function setVideoListener() {
var alpha = 0.1;
video.addEventListener('playing', () => {
function step() {
if(alpha < 1) {
ctx.globalAlpha = alpha;
}
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
requestAnimationFrame(step)
if(alpha < 1) {
alpha += 0.00001;
}
}
requestAnimationFrame(step);
}, false)
}
function startRecording() {
const chunks = [];
const stream = canvas.captureStream();
const rec = new MediaRecorder(stream);
rec.ondataavailable = e => chunks.push(e.data);
$('#stop_recording').click(function() {
rec.stop();
});
rec.onstop = e => exportVid(new Blob(chunks, {type: 'video/webm'}));
window.setTimeout(function() {
rec.requestData();
}, 1);
rec.start();
}
function exportVid(blob) {
const vid = document.createElement('video');
vid.src = URL.createObjectURL(blob);
vid.controls = true;
document.body.appendChild(vid);
const a = document.createElement('a');
a.download = 'my_final_output_video.webm';
a.href = vid.src;
a.textContent = 'Download the final output video';
document.body.appendChild(a);
}
</script>
</body>
</html>
The problem is solved by using my gaming laptop (RoG), wich has a good graphic card, able to record at higher frequency than my Spectre x360 development laptop.

how to save a picture taken with window.getusermedia in js

Currently i am working on a open webapp camera, right now i have implemented the camera setup(live stream as viewport, take picture button, capture, display taken picture in corner... etc) but now i am running into the issue of how to save that picture for the user to their device or computer, this app is currently being designed for mobile b2g primarily. I know most people are gonna tell me security issues!!! i dont mean tell the device exactly where to put it. I mean something like
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script type="text/javascript">
window.onload = function () {
var img = document.getElementById('embedImage');
var button = document.getElementById('saveImage');
img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA'+
'AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO'+
'9TXL0Y4OHwAAAABJRU5ErkJggg==';
img.onload = function () {
button.removeAttribute('disabled');
};
button.onclick = function () {
window.location.href = img.src.replace('image/png', 'image/octet-stream');
};
};
</script>
</head>
<body>
<img id="embedImage" alt="Red dot"/>
<input id="saveImage" type="button" value="save image" disabled="disabled"/>
</body>
</html>
that specific code executed on mobile triggers the file to automatically be saved on click of the button. now what i want to do is use that to take my picture from its var its in and save it as that file, for example that will be in downloads folder.
this is what my code is currently https://github.com/1Jamie/1Jamie.github.io
any help would be appreciated and this is the current running implementation if you want to take a working look http://1Jamie.github.io
This worked for me when I was playing around with getUserMedia - I did notice that you did not have the name of the method in the proper case and it is a method of the navigator.mediaDevices interface - not a method of the window directly...
References:
[Navigator for mozilla]https://developer.mozilla.org/en-US/docs/Mozilla/B2G_OS/API/Navigator
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices
[mediaDevices for chrome and android]https://developers.google.com/web/updates/2015/10/media-devices?hl=en
var video = document.getElementById('monitor');
var canvas1 = document.getElementById('photo1');
var img1 = document.getElementById('canvasImg');
navigator.mediaDevices.getUserMedia({
video: true
}).then(function (stream) {
video.srcObject = stream;
video.onloadedmetadata = function () {
canvas1.width = video.videoWidth;
canvas1.height = video.videoHeight;
document.getElementById('splash').hidden = true;
document.getElementById('app').hidden = false;
};
}).catch(function (reason) {
document.getElementById('errorMessage').textContent = 'No camera available.';
});
function snapshot1() {
canvas1.getContext('2d').drawImage(video, 0, 0);
}
"save_snap" is the id of a button - Disclaimer I am using jQuery- but you should easily see where this corresponds to your code:
$("#save_snap").click(function (event){
// save canvas image as data url (png format by default)
var dataURL = canvas2.toDataURL();
// set canvasImg image src to dataURL
// so it can be saved as an image
$('#canvasImg').attr("src" , dataURL);
$('#downloader').attr("download" , "download.png");
$('#downloader').attr("href" , dataURL);
//* trying to force download - jQuery trigger does not apply
//Use CustomEvent Vanilla js: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
// In particular
var event1 = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': true
});
//NOW we are effectively clicking the element with the href attribute:
//Could use jQuery selector but then we would have to unwrap it
// to expose it to the native js function...
document.getElementById('downloader').dispatchEvent(event1);
});

Categories

Resources