basically people take a pic with their phone and I should crop the pic and add a watermark.
how can I add a watermark to my picture?
my code below
function takeSnapshot(){
// Here we're using a trick that involves a hidden canvas element.
var hidden_canvas = document.querySelector('canvas'),
context = hidden_canvas.getContext('2d');
var width = 480,
height = 480;
hidden_canvas.width = width;
hidden_canvas.height = height;
// Make a copy of the current frame in the video on the canvas.
context.drawImage(video, 100, 0, 480, 480, 0, 0, hidden_canvas.width, hidden_canvas.width);
// Turn the canvas image into a dataURL that can be used as a src for our photo.
return hidden_canvas.toDataURL('image/png');
}
html
<div class="container">
<div class="app">
Touch here to start the app.
<video id="camera-stream" width="640" height="480"></video>
<img id="snap">
<img src="http://localhost/selfie/face-pic.png" style="z-index:100;position:absolute; top:0;left:0;"/>
<p id="error-message"></p>
<div class="controls" style="z-index:200;">
<i class="material-icons">delete</i>
<i class="material-icons">camera_alt</i>
<i class="material-icons">file_download</i>
</div>
<!-- Hidden canvas element. Used for taking snapshot of video. -->
<canvas>
</canvas>
</div>
</div>
js
document.addEventListener('DOMContentLoaded', function () {
// References to all the element we will need.
var video = document.querySelector('#camera-stream'),
image = document.querySelector('#snap'),
start_camera = document.querySelector('#start-camera'),
controls = document.querySelector('.controls'),
take_photo_btn = document.querySelector('#take-photo'),
delete_photo_btn = document.querySelector('#delete-photo'),
download_photo_btn = document.querySelector('#download-photo'),
error_message = document.querySelector('#error-message');
// The getUserMedia interface is used for handling camera input.
// Some browsers need a prefix so here we're covering all the options
navigator.getMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
if(!navigator.getMedia){
displayErrorMessage("Your browser doesn't have support for the navigator.getUserMedia interface.");
}
else{
// Request the camera.
navigator.getMedia(
{
video: true
},
// Success Callback
function(stream){
// Create an object URL for the video stream and
// set it as src of our HTLM video element.
video.srcObject=stream;
// Play the video element to start the stream.
video.play();
video.onplay = function() {
showVideo();
};
},
// Error Callback
function(err){
displayErrorMessage("There was an error with accessing the camera stream: " + err.name, err);
}
);
}
// Mobile browsers cannot play video without user input,
// so here we're using a button to start it manually.
start_camera.addEventListener("click", function(e){
e.preventDefault();
// Start video playback manually.
video.play();
showVideo();
});
take_photo_btn.addEventListener("click", function(e){
e.preventDefault();
var snap = takeSnapshot();
// Show image.
image.setAttribute('src', snap);
image.classList.add("visible");
// Enable delete and save buttons
delete_photo_btn.classList.remove("disabled");
download_photo_btn.classList.remove("disabled");
// Set the href attribute of the download button to the snap url.
download_photo_btn.href = snap;
// Pause video playback of stream.
video.pause();
});
delete_photo_btn.addEventListener("click", function(e){
e.preventDefault();
// Hide image.
image.setAttribute('src', "");
image.classList.remove("visible");
// Disable delete and save buttons
delete_photo_btn.classList.add("disabled");
download_photo_btn.classList.add("disabled");
// Resume playback of stream.
video.play();
});
function showVideo(){
// Display the video stream and the controls.
hideUI();
video.classList.add("visible");
controls.classList.add("visible");
}
function takeSnapshot(){
// Here we're using a trick that involves a hidden canvas element.
var hidden_canvas = document.querySelector('canvas'),
context = hidden_canvas.getContext('2d');
var width = 480,
height = 480;
hidden_canvas.width = width;
hidden_canvas.height = height;
// Make a copy of the current frame in the video on the canvas.
context.drawImage(video, 100, 0, 480, 480, 0, 0, hidden_canvas.width, hidden_canvas.width);
// Turn the canvas image into a dataURL that can be used as a src for our photo.
return hidden_canvas.toDataURL('image/png');
}
function displayErrorMessage(error_msg, error){
error = error || "";
if(error){
console.error(error);
}
error_message.innerText = error_msg;
hideUI();
error_message.classList.add("visible");
}
function hideUI(){
// Helper function for clearing the app UI.
controls.classList.remove("visible");
start_camera.classList.remove("visible");
video.classList.remove("visible");
snap.classList.remove("visible");
error_message.classList.remove("visible");
}
});
Related
I want to capture image every time socket.on('takePic') gets triggered. It works fine for the first time. but when the socket.on('takePic') gets triggered second time,the canvas div is just blank and so the img tag.
I have copied the takePicture() function from somewhere and added the setInterval() and localstream variable to stop camera.
how can I fix this?
here is my js code.
const socket = io('http://localhost:3001');
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
let roomId = params.roomId;
socket.emit('joinRoom',roomId);
var takePicture = function () {
// The width and height of the captured photo. We will set the
// width to the value defined here, but the height will be
// calculated based on the aspect ratio of the input stream.
var width = 320; // We will scale the photo width to this
var height = 0; // This will be computed based on the input stream
// |streaming| indicates whether or not we're currently streaming
// video from the camera. Obviously, we start at false.
var streaming = false;
var localstream;
// The various HTML elements we need to configure or control. These
// will be set by the startup() function.
var video = null;
var canvas = null;
var photo = null;
var startbutton = null;
function showViewLiveResultButton() {
if (window.self !== window.top) {
// Ensure that if our document is in a frame, we get the user
// to first open it in its own tab or window. Otherwise, it
// won't be able to request permission for camera access.
document.querySelector(".contentarea").remove();
const button = document.createElement("button");
button.textContent = "View live result of the example code above";
document.body.append(button);
button.addEventListener('click', () => window.open(location.href));
return true;
}
return false;
}
function startup() {
if (showViewLiveResultButton()) { return; }
video = document.getElementById('video');
canvas = document.getElementById('canvas');
photo = document.getElementById('photo');
startbutton = document.getElementById('startbutton');
navigator.mediaDevices.getUserMedia({video: true, audio: false})
.then(function(stream) {
video.srcObject = stream;
localstream = stream;
video.play();
})
.catch(function(err) {
console.log("An error occurred: " + err);
});
video.addEventListener('canplay', function(ev){
if (!streaming) {
height = video.videoHeight / (video.videoWidth/width);
// Firefox currently has a bug where the height can't be read from
// the video, so we will make assumptions if this happens.
if (isNaN(height)) {
height = width / (4/3);
}
video.setAttribute('width', width);
video.setAttribute('height', height);
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
streaming = true;
}
}, false);
startbutton.addEventListener('click', function(ev){
takepicture();
ev.preventDefault();
clearInterval(picInterval);
$('#heading').css('display','none')
video.pause();
video.src = "";
localstream.getTracks()[0].stop();
}, false);
clearphoto();
}
// Fill the photo with an indication that none has been
// captured.
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.
function takepicture() {
var context = canvas.getContext('2d');
if (width && height) {
canvas.width = width;
canvas.height = height;
context.drawImage(video, 0, 0, width, height);
var data = canvas.toDataURL('image/png');
photo.setAttribute('src', data);
} else {
clearphoto();
}
}
// Set up our event listener to run the startup process
// once loading is complete.
startup();
var i = 10;
let picInterval = setInterval(()=>{
i -= 1;
$('#heading').html(`taking picture in ${i}`);
if(i==0){
$('#startbutton').click()
}
}, 1000)
}
socket.on('takePic',()=>{
takePicture()
})
and this is the html code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>StudentVideo</title>
<link rel="stylesheet" href="css/studentVideo.css">
</head>
<body>
<div class="contentarea">
<h1 id="heading">
</h1>
<p>
This example demonstrates how to set up a media stream using your built-in webcam, fetch an image from that stream, and create a PNG using that image.
</p>
<div class="camera">
<video id="video" width="320" height="240">Video stream not available.</video>
<button id="startbutton">Take photo</button>
</div>
<canvas id="canvas" width="320" height="240">
</canvas>
<div class="output">
<img id="photo" alt="The screen capture will appear in this box." src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAACWCAYAAABkW7XSAAAAAXNSR0IArs4c6QAABGlJREFUeF7t1AEJADAMA8HVv5Oa3GAuHq4KwqVkdvceR4AAgYDAGKxASyISIPAFDJZHIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRB46/vA5AUJNVYAAAAASUVORK5CYII=">
</div>
<p>
Visit our article Taking still photos with WebRTC to learn more about the technologies used here.
</p>
</div>
</body>
<script src="https://cdn.socket.io/socket.io-3.0.1.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="js/video.js"></script>
</html>
In the click handler of #startbutton your code calls takepicture and then it goes on to remove the video's src and stop the MediaStream.
So the next time this handler is called, there is no source affected to the video element and thus nothing to be drawn on the canvas anymore.
It's quire unclear why you clear the video in this click handler, so you might want to remove this part of the code, or to move it to a "stop" button instead, but anyway, you would probably be better calling takepicture from your interval directly rather than relying on the event handler.
I have built a visitor management system and have recently swapped to a surface device as the driver. The html5 webcam stream is showing as blurry / out of focus on the front facing camera. If I swap to the rear camera however it is fine. And if i use the front facing camera on another public site that uses another webcam feature, it works absolutely fine.
Here is a capture of the camera element, it looks like some form of deliberate blurring as appose to the camera just being bad...
https://ibb.co/Dzf67nC/
I have tried scanning through the code and cannot find anything that scales the camera stream at all that may cause bluring or focus changing
Below is my photo.js file that provides the stream to my visitor sign in page and also handles the capturing of screenshots.
// References to all the element we will need.
var video = document.querySelector('#camera-stream'),
image = document.querySelector('#snap'),
my_photo = document.querySelector('#my-photo'),
container = document.querySelector('.camera-container'),
//start_camera = document.querySelector('#start-camera'),
controls = document.querySelector('.controls'),
take_photo_btn = document.querySelector('#take-photo'),
delete_photo_btn = document.querySelector('#delete-photo'),
download_photo_btn = document.querySelector('#download-photo'),
imgeurl = document.querySelector('#imagesource'),
open_camera = document.querySelector('#open-camera'),
error_message = document.querySelector('#error-message');
// The getUserMedia interface is used for handling camera input.
// Some browsers need a prefix so here we're covering all the options
navigator.getMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
// Mobile browsers cannot play video without user input,
// so here we're using a button to start it manually.
open_camera.addEventListener("click", function(e){
if($('#my-photo').attr('src') == '') {
e.preventDefault();
container.classList.add("visible");
// Start video playback manually.
//video.play();
//showVideo();
if(!navigator.getMedia){
displayErrorMessage("Your browser doesn't have support for the navigator.getUserMedia interface.");
}
else{
// Request the camera.
navigator.getMedia(
{
video: true
},
// Success Callback
function(stream){
// Create an object URL for the video stream and
// set it as src of our HTLM video element.
video.srcObject=stream;
// Play the video element to start the stream.
video.play();
video.onplay = function() {
showVideo();
};
},
// Error Callback
function(err){
displayErrorMessage("There was an error with accessing the camera stream: " + err.name, err);
}
);
}
}
});
open_camera.click();
take_photo_btn.addEventListener("click", function(e){
e.preventDefault();
var count=4;
var counter=setInterval(timer, 500); //1000 will run it every 1 second
$('.countdown-container').addClass('visible');
function timer(){
count=count-1;
if (count <= 0)
{
$('.countdown-number').html('<i class="far fa-smile"></i>');
clearInterval(counter);
//counter ended, do something here
return;
}
$('.countdown-number').text(count);
//Do code for showing the number of seconds here
}
setTimeout(function(){
$('.countdown-container').removeClass('visible');
$('.countdown-number').text('Get Ready');
},2500);
setTimeout(function(){
video.pause(snap);
var snap = takeSnapshot();
// Show image.
image.setAttribute('src', snap);
imgeurl.value = snap;
image.classList.add("visible");
//tumbnail image
my_photo.setAttribute('src', snap);
my_photo.value = snap;
// Enable delete and save buttons
delete_photo_btn.classList.remove("disabled");
download_photo_btn.classList.remove("disabled");
take_photo_btn.classList.add("disabled");
},3000);
// Set the href attribute of the download button to the snap url.
// Pause video playback of stream.
});
delete_photo_btn.addEventListener("click", function(e){
e.preventDefault();
// Hide image.
image.setAttribute('src', "");
image.classList.remove("visible");
my_photo.setAttribute('src', "");
// Disable delete and save buttons
delete_photo_btn.classList.add("disabled");
download_photo_btn.classList.add("disabled");
take_photo_btn.classList.remove("disabled");
// Resume playback of stream.
video.play();
});
function showVideo(){
// Display the video stream and the controls.
//hideUI();
video.classList.add("visible");
controls.classList.add("visible");
}
function takeSnapshot(){
// Here we're using a trick that involves a hidden canvas element.
var hidden_canvas = document.querySelector('canvas'),
context = hidden_canvas.getContext('2d');
var width = video.videoWidth,
height = video.videoHeight;
if (width && height) {
// Setup a canvas with the same dimensions as the video.
hidden_canvas.width = width;
hidden_canvas.height = height;
// Make a copy of the current frame in the video on the canvas.
context.drawImage(video, 0, 0, width, height);
// Turn the canvas image into a dataURL that can be used as a src for our photo.
return hidden_canvas.toDataURL('image/png');
}
}
download_photo_btn.addEventListener("click", function(e){
e.preventDefault();
container.classList.remove("visible");
my_photo.classList.add("visible");
});
function displayErrorMessage(error_msg, error){
error = error || "";
if(error){
console.log(error);
}
error_message.innerText = error_msg;
hideUI();
error_message.classList.add("visible");
}
function hideUI(){
// Helper function for clearing the app UI.
controls.classList.remove("visible");
//start_camera.classList.remove("visible");
video.classList.remove("visible");
snap.classList.remove("visible");
error_message.classList.remove("visible");
}
The camera should be a lot crisper than it is. No errors or anything in the console.
I have Webcam class, that uses for capturing data from webcam. This class streames data to video tag and also draw it on canvas., Also I have QRScanner class, that uses for parsing QR code from imageData of canvas.
class Webcam {
constructor(videoTag, canvasTag) {
// using for real-time video capture
this.videoTag = videoTag;
// qr scanner parses imageData from this element
this.canvasTag = canvasTag;
// waiting for qr code here
this.captureArea = {
x: 100,
y: 60,
width: 120,
height: 120
}
// getting access to webcam
navigator.mediaDevices
.getUserMedia({
video: true
})
.then(stream => this.videoTag.srcObject = stream)
.catch(console.log);
}
capture() {
setInterval(() => {
let ctx = this.canvasTag.getContext('2d');
ctx.drawImage(this.videoTag, 0, 0, 320, 240);
// drawing capture area
ctx.strokeStyle = 'red';
// this arguments also should be passed into qr scanner
ctx.strokeRect(
this.captureArea.x,
this.captureArea.y,
this.captureArea.width,
this.captureArea.height
);
}, 100);
}
}
class QRScanner {
constructor(canvas, router, captureArea) {
this.canvas = canvas;
this.router = router;
this.captureArea = captureArea;
this.qrCode = null;
}
scan() {
setInterval(() => {
let imageData = this.canvas
.getContext('2d')
.getImageData(
this.captureArea.x,
this.captureArea.y,
this.captureArea.width,
this.captureArea.height
).data;
// parsing qr code from canvas
this.qrCode = jsQR(imageData, this.captureArea.width, this.captureArea.height);
if (this.qrCode) {
router.redirect(Router.pages.result, this.qrCode);
let resultPage = document.querySelector('#result .qr-code-data');
resultPage.innerHTML = this.qrCode.data;
}
}, 100);
}
}
<div id="scan">
<video id="video" width="320" height="240" autoplay title="Real-time video stream from webcam"></video>
<canvas id="preview" width="320" height="240" title="Capture area for QR code"></canvas>
</div>
This works as expected, but when I removes canvas element from page and trying to use temporary canvas (using document.createElement('canvas') without appending to the page) - this solution do not work. Does it possible to using temporary canvas for getting video imageData without appending this canvas to the page?
P.S. I'm using https://github.com/cozmo/jsQR
Canvas elements have a default width height when they aren't explicitly set. Since you never set those for you created canvas it is going to default to 300 x 150, at least for Chrome might be different for other browsers implementations.
var canvas = document.createElement("canvas");
console.log(canvas.width,canvas.height)
And since this default size is different than the size that you are trying to draw the image/video to there is going to be some cropping going on and therefore effecting your QR library from properly reading the image.
Just set the width and height to what you need
var canvas = document.createElement('canvas')
canvas.width = 320;
canvas.height = 240;
I'm capturing an image using webcam and trying to read the text on it. Now it reads all the text. I want to filter only letters and numbers from the image. And also want to get the coordinates of text. To get the coordinates I have followed this link. But it's not working. No other references for this solution was not found.
<script src="ocrad.js"></script>
<script>
// Grab elements, create settings, etc.
var video = document.getElementById('video');
// Get access to the camera!
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// Not adding `{ audio: true }` since we only want video now
navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
video.src = window.URL.createObjectURL(stream);
video.play();
});
}
// Elements for taking the snapshot
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var video = document.getElementById('video');
// Trigger photo take
document.getElementById("snap").addEventListener("click", function() {
document.getElementById('transcription').innerText = "(Recognizing...)";
context.drawImage(video, 0, 0, 640, 480);
OCRAD( canvas, function(text){
document.getElementById('transcription').className = "done"
document.getElementById('transcription').innerText = text;
})
});
</script>
I am attempting to create a thumbnail preview from a video file (mp4,3gp) from a form input type='file'. Many have said that this can be done server side only. I find this hard to believe since I just recently came across this Fiddle using HTML5 Canvas and Javascript.
Thumbnail Fiddle
The only problem is this requires the video to be present and the user to click play before they click a button to capture the thumbnail. I am wondering if there is a way to get the same results without the player being present and user clicking the button. For example: User click on file upload and selects video file and then thumbnail is generated. Any help/thoughts are welcome!
Canvas.drawImage must be based on html content.
source
here is a simplier jsfiddle
//and code
function capture(){
var canvas = document.getElementById('canvas');
var video = document.getElementById('video');
canvas.getContext('2d').drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
}
The advantage of this solution is that you can select the thumbnail you want based on the time of the video.
Recently needed this so I wrote a function, to take in a video file and a desired timestamp, and return an image blob at that time of the video.
Sample Usage:
try {
// get the frame at 1.5 seconds of the video file
const cover = await getVideoCover(file, 1.5);
// print out the result image blob
console.log(cover);
} catch (ex) {
console.log("ERROR: ", ex);
}
Function:
function getVideoCover(file, seekTo = 0.0) {
console.log("getting video cover for file: ", file);
return new Promise((resolve, reject) => {
// load the file to a video player
const videoPlayer = document.createElement('video');
videoPlayer.setAttribute('src', URL.createObjectURL(file));
videoPlayer.load();
videoPlayer.addEventListener('error', (ex) => {
reject("error when loading video file", ex);
});
// load metadata of the video to get video duration and dimensions
videoPlayer.addEventListener('loadedmetadata', () => {
// seek to user defined timestamp (in seconds) if possible
if (videoPlayer.duration < seekTo) {
reject("video is too short.");
return;
}
// delay seeking or else 'seeked' event won't fire on Safari
setTimeout(() => {
videoPlayer.currentTime = seekTo;
}, 200);
// extract video thumbnail once seeking is complete
videoPlayer.addEventListener('seeked', () => {
console.log('video is now paused at %ss.', seekTo);
// define a canvas to have the same dimension as the video
const canvas = document.createElement("canvas");
canvas.width = videoPlayer.videoWidth;
canvas.height = videoPlayer.videoHeight;
// draw the video frame to canvas
const ctx = canvas.getContext("2d");
ctx.drawImage(videoPlayer, 0, 0, canvas.width, canvas.height);
// return the canvas image as a blob
ctx.canvas.toBlob(
blob => {
resolve(blob);
},
"image/jpeg",
0.75 /* quality */
);
});
});
});
}
Recently needed this and did quite some testing and boiling it down to the bare minimum, see https://codepen.io/aertmann/pen/mAVaPx
There are some limitations where it works, but fairly good browser support currently: Chrome, Firefox, Safari, Opera, IE10, IE11, Android (Chrome), iOS Safari (10+).
video.preload = 'metadata';
video.src = url;
// Load video in Safari / IE11
video.muted = true;
video.playsInline = true;
video.play();
You can use this function that I've written. You just need to pass the video file to it as an argument. It will return the dataURL of the thumbnail(i.e image preview) of that video. You can modify the return type according to your need.
const generateVideoThumbnail = (file: File) => {
return new Promise((resolve) => {
const canvas = document.createElement("canvas");
const video = document.createElement("video");
// this is important
video.autoplay = true;
video.muted = true;
video.src = URL.createObjectURL(file);
video.onloadeddata = () => {
let ctx = canvas.getContext("2d");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
video.pause();
return resolve(canvas.toDataURL("image/png"));
};
});
};
Please keep in mind that this is a async function. So make sure to use it accordingly.
For instance:
const handleFileUpload = async (e) => {
const thumbnail = await generateVideoThumbnail(e.target.files[0]);
console.log(thumbnail)
}
The easiest way to display a thumbnail is using the <video> tag itself.
<video src="http://www.w3schools.com/html/mov_bbb.mp4"></video>
Use #t in the URL, if you want the thumbnail of x seconds.
E.g.:
<video src="http://www.w3schools.com/html/mov_bbb.mp4#t=5"></video>
Make sure that it does not include any attributes like autoplay or controls and it should not have a source tag as a child element.
With a little bit of JavaScript, you may also be able to play the video, when the thumbnail has been clicked.
document.querySelector('video').addEventListener('click', (e) => {
if (!e.target.controls) { // Proceed, if there are no controls
e.target.src = e.target.src.replace(/#t=\d+/g, ''); // Remove the time, which is set in the URL
e.target.play(); // Play the video
e.target.controls = true; // Enable controls
}
});
<video src="http://www.w3schools.com/html/mov_bbb.mp4#t=5"></video>
With jQuery Lib you can use my code here. $video is a Video element.This function will return a string
function createPoster($video) {
//here you can set anytime you want
$video.currentTime = 5;
var canvas = document.createElement("canvas");
canvas.width = 350;
canvas.height = 200;
canvas.getContext("2d").drawImage($video, 0, 0, canvas.width, canvas.height);
return canvas.toDataURL("image/jpeg");;
}
Example usage:
$video.setAttribute("poster", createPoster($video));
I recently stumbled on the same issue and here is how I got around it.
firstly it will be easier if you have the video as an HTML element, so you either have it in the HTML like this
<video src="http://www.w3schools.com/html/mov_bbb.mp4"></video>
or you take from the input and create an HTML element with it.
The trick is to set the start time in the video tag to the part you want to seek and have as your thumbnail, you can do this by adding #t=1.5 to the end of the video source.
<video src="http://www.w3schools.com/html/mov_bbb.mp4#t=1.5"></video>
where 1.5 is the time you want to seek and get a thumbnail of.
This, however, makes the video start playing from that section of the video so to avoid that we add an event listener on the video's play button(s) and have the video start from the beginning by setting video.currentTime = 0
const video = document.querySelector('video');
video.addEventListener('click', (e)=> {
video.currentTime = 0 ;
video.play();
})