I have a simple block in which I would like to capture a frame from video every 5 seconds and display them something like this below.
Here is a solution I have tried.
<video id="video" controls="controls">
<source src="http://www.w3schools.com/html/mov_bbb.mp4">
</source>
</video>
<div id="time-ruler"></div>
<canvas id="canvas" width="300" height="300"></canvas>
<div id="thumbnailContainer"></div>
Here is javascript
video.addEventListener('loadeddata', function() {
var duration = video.duration;
var i = 0;
var interval = setInterval(function() {
video.currentTime = i;
generateThumbnail(i);
i = i+5;
if (i > duration) clearInterval(interval);
}, 300);
});
function generateThumbnail(i) {
//generate thumbnail URL data
var context = canvas.getContext('2d');
context.drawImage(video, 0, 0, 220, 150);
var dataURL = canvas.toDataURL();
//create img
var img = document.createElement('img');
img.setAttribute('src', dataURL);
//append img in container div
document.getElementById('thumbnailContainer').appendChild(img);
}
Here is jsfiddle: live demo
Unfortunately, this is not working as expected.
What do I need to do to get what I want?
Check the following:
https://jsfiddle.net/psbqn9d0/1/
It won't create the view you shown in the picture, but will change the thumbnail every 5 second. I have also added few logging to help you understand the code.
Now, if you want to achieve what is shown in figure then this is possible:-
if you have loaded the video completely. Then create all the thumbnails and add them to the container.
you create the thumbnails on the server and send them to user (like done by most video sites (so we can see what is in the video without loading!))
OR you can create all the thumbnails without loading the whole video. I am not sure if this is the best way, but this will definitely work.
You should create another video tag with the same source link, and hide it using css. Then you will create a javascript function which will seek it to every 5th second programmatically and keep saving the thumbnails and adding them in your container. This way, your thumbnails will be generated for the whole video without loading the whole video.
I hope it clarifies your doubts!
Related
I am working on an academic project in which I am making a PHP project that is similar to a website https://promo.com/. This website edit videos by embedding overlay text effects on them. I made a website in which there is an overlay canvas section over the video section and I can take screenshots of canvas animation on video and then these screenshots of "Text animation" are merged as a gif and then I combine the gif and video (all this is done by FFmpeg);and the final product is a video having an overlay text animation. I take screenshots by using the code :
var canvas = document.getElementById("canvas");
var png = canvas.toDataURL("image/png");
But if the video size is 10 mins long then I have to wait for almost 10 mins so that this code in setInterval can take screenshots after every 50ms. Is that there is some library to accomplish this screenshot taking task of canvas animation so that the screenshots of text animation can be captured without playing them from start to end? I don't know what trick the promo.com website is using to record overlay text on video!
I want that I can record canvas animation as array of images without playing the whole canvas animation. Please help me in this. Thanks in advance.
Instead of first creating a canvas and then extracting images from it, You should use the video element directly. I am saying this because seeking from canvas is not in your hand, but seeking from video is. Use javascript along with setinterval both to seek the video forward 50 milisecond and capture the video's thumbnail in each milisecond, this just reduced your time by 5000 times! Here is an example:
// global or parent scope of handlers
var video = document.getElementById("video"); // added for clarity: this is needed
var i = 0;
video.addEventListener('loadeddata', function() {
this.currentTime = i;
});
video.addEventListener('seeked', function() {
// now video has seeked and current frames will show
// at the time as we expect
generateThumbnail(i);
// when frame is captured, increase here by 5 seconds
i += 5;
// if we are not past end, seek to next interval
if (i <= this.duration) {
// this will trigger another seeked event
this.currentTime = i;
}
else {
// Done!, next action
}
});
Otherwise, if it is absolutely necessary to add a canvas before, then you should create another video tag with the same source link, and hide it using css. Then you will create a javascript function which will seek it to every 5th second programmatically and keep saving the thumbnails and adding them in your container. This way, your thumbnails will be generated for the whole video without loading the whole video.
I'm developing a website with an image gallery. There is a grid of images with dozens of thumbnails. When a user clicks on an image a div slides down from the top. That div's CSS gets edited with JavaScript to change the background-image.
My problem is that the div slides down, but the background image "flickers" in randomly. What I want is the div to slide down with the image already loaded. I'm not sure how to solve this problem because I think it would be unreasonable to pre-load every thumbnail's larger version when the user most likely won't click on them all.
You can convert the image to base64 and enable it in src of the img tag, after that send in the dormulário.
this use example: https://hdtuto.com/article/how-to-convert-image-into-base64-string-jquery
One way to preload images is to create an image object using javascript
Here's an example:
HTML:
<img src="photo1.jpg" id="photo" />
Javascript:
var photo = document.getElementById("photo");
var loadImage = new Image();
loadImage.src = "YourSrc/image.jpg";
Last step, use this code in your event handler when you want to change to the preloaded image:
photo.src = loadImage.src;
If you are looking to preload multiple images use an array and a loop.
imageSrcs = ["imgsrc1.jpg", "imgsrc2jpg", "imgsrc3jpg"];
preloadedImages = [];
for(var i = 0; i < imgSrcs.length; i++)
{
preloadedImages[i] = new Image();
preloadedImages[i].src = preloadedImages[i];
}
This question already has an answer here:
Why is the image drawn in the canvas when debugging but not when running?
(1 answer)
Closed 5 years ago.
I have a canvas :
<canvas id="mandarin" width="235" height="300" style="border:1px solid #000000;"></canvas>
And I want to insert an image into the canvas when the window loads, however this code doesn't render anything:
window.onload = function() {
var context = document.getElementById("mandarin").getContext("2d");
var ourImage = document.createElement("IMG");
ourImage.src = "mandarin.jpg";
ourImage.setAttribute("width", 235);
ourImage.setAttribute("height", 300);
context.drawImage(ourImage, 10, 10);
};
But when I include this line , irrelevant of the code above and outside the body it works.
<img id="mandarinImg" src="mandarin.jpg" alt="The Scream" width="250" height="350">
But the problem is I have the canvas and the image side by side. All I need to display is the canvas with the image inside.
How would I insert this DOM image into the canvas ?
When you set the source of the image (ourImage.src = "mandarin.jpg") it is not loaded yet. This means if you draw the image afterwards it will not do it. Because your image isnt loaded. You should wait for the image to load and then draw it:
ourImage.onload = function(){
context.drawImage(ourImage, 10, 10);
}
ourImage.src = "mandarin.jpg"
(Note that it's important to hook the event before setting src. There may be only one main JavaScript UI thread, but the browser is not single-threaded. It's perfectly valid for the browser to respond to your setting src by immediately triggering a load event, seeing the element doesn't have any handlers for it, and therefore not queuing a callback. And at least one browser circa ~2008 did, if the image was in cache and usable.)
guys!
I am working on a project for my portfolio that I think would be absolutely sweet with the following feature: A responsive slideshow, fit to the browser that is made of clickable images that link you to more information about the specific product.
This idea was inspired by Triumph's home page (as of 2/16/17) here: http://www.triumphmotorcycles.com/
With that being said, I have selected several nice images that will fit the entire browser (though they are all not the same size). I used them to create a slideshow with Javascript (I want to use an array for the images just to get used to good habit) and set the height to 400x400px just to get a feel for creating the slideshow. It works great! Now it it is time to get this slideshow to fit the browser nice and neatly like Triumph's site! :)
Here is a screenshot of their homepage
Here is my code:
<script type="text/javascript">
var image1=new Image();
image1.src="Africa Twin Mountainside.jpg";
var image2=new Image();
image2.src="FZ-10.jpg";
var image3=new Image();
image3.src="GSXR track.jpg";
var image4=new Image();
image4.src="Pioneer 1k mountain.jpg";
var image5=new Image();
image5.src="Raptor sand.jpg";
</script>
<img src="Africa Twin Mountainside.jpg" name="slide" width="400" height="400" alt=""/>
<script type="text/javascript">
var step=1;
function slideit(){
document.images.slide.src=eval("image"+step+".src");
if(step<5)
step++;
else
step=1;
setTimeout("slideit()", 2500);
}
slideit();
</script>
My current objective is to fit the images responsively to the browser window. To create a non scrolling, nice, slideshow background. Any help with fitting this to the browser window would be greatly appreciated!
Cheers from Texas! :P
This script loops through all urls in the images array:
// List your image urls
var images = [
"https://homepages.cae.wisc.edu/~ece533/images/airplane.png",
"https://homepages.cae.wisc.edu/~ece533/images/arctichare.png",
"https://homepages.cae.wisc.edu/~ece533/images/baboon.png",
"https://homepages.cae.wisc.edu/~ece533/images/barbara.png",
"https://homepages.cae.wisc.edu/~ece533/images/boat.png",
]
// Array indexes start with 0
var step=0;
function slideit(){
// set the src of the image tag to the url from the array
var imageUrl = images[step];
document.getElementById('slide').src = imageUrl;
// count up
step++;
// reset if the end of the array was reached
if(step>=images.length)
step=0;
// and repeat
setTimeout("slideit()", 2500);
}
slideit();
<img src="https://homepages.cae.wisc.edu/~ece533/images/airplane.png" id="slide" width="400" height="400" alt=""/>
Or to set the image to your page background:
var body = document.getElementsByTagName('body')[0];
body.style.backgroundImage = 'url(' + imageUrl + ')';
But then you'll want to set some css attributes to disable repeat and resize it to 100%.
Please be more specific on your next question.
I'm trying to fetch and print out width and height attributes from video with a simple javascript, but for some reason I'm not managing.
This is the javascript
video = document.getElementsByTagName("video")[1];
span1 = document.getElementById("dimensions");
span1.innerHTML = video.videoWidth + " x " + video.videoHeight;
and this is html5 code which it affects (this is the second video tag in html structure)
<figure>
<video controls>
<source src="video.webm" type="video/webm">
</video>
</figure>
<p>
Dimensions: <span id="dimensions"></span>
</p>
Thanks a lot, I'm a beginner so be light on me.
Your index, based on your markup, won't return you the element you want. The index is zero-based as node lists are array-like and start indexing at 0.
var video = document.getElementsByTagName("video")[0];
Edit: sorry, didn't see you said it was the second video tag. In that case, I'm not certain, because it works for me: http://jsfiddle.net/3wCYz/1/
One thing you might want to try is putting the code you use to get the width and height inside a handler on your video tag that listens for the loadedmetadata event:
video.addEventListener("loadedmetadata", dimensionFunction, false);
where dimensionFunction is a function that does what you're already doing to grab the dimensions.
What this does is make sure the metadata for the video has downloaded before you try to grab it.