A concept to manually create a thumbnail from a video by using a slider to view the video at a certain timestamp.
The easy slider integration is from the noUiSlider framework. With FFmpeg on the backend to create the thumbnail file.
View the full index.php file here. The video link.
Defines the video file and the thumbnail image file name. Next is a check for if a new thumbnail needs to be created (slider was changed, POST request sent) or if none exists (first time running) create one from the 1 second fragment.
<?php $file = "jellyfish.mkv"; $thumb = "thumbnail.jpg"; if (isset($_POST['time_string'])) { exec("ffmpeg -y -ss {$_POST['time_string']} -i $file -vframes 1 -q:v 1 $thumb"); } elseif (!file_exists("thumbnail.jpg")) { exec("ffmpeg -y -ss 00:00:01 -i $file -vframes 1 -q:v 1 $thumb"); }
A check is done for the length of the video in seconds. This value is used as the max value for the slider.
<?php function getSeconds(string $file): float { return exec("ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $file"); } $seconds = getSeconds($file);
This requires jQuery and the noUiSlider library.
Define the slider with its config. Note PHP is used to state the max range for the slider.
let slider = document.getElementById("slider"); noUiSlider.create(slider, { start: 0, connect: true, step: 1, range: { min: 0, max: <?=$seconds?> } });
Assign the seconds text for the slider. Create an “on change” function for the slider to update the second’s text using a one-line solution to convert seconds into an HH:MM:SS string. Finally, send a POST request to generate a new thumbnail at that time segment.
On success in the Ajax POST update the thumbnail image tag src to have the new thumbnail image by appending a date string thus beating the cache and forcing the new image to show.
let seconds_element = document.getElementById("seconds"); slider.noUiSlider.on("change", function (values, handle) { let slider_value = slider.noUiSlider.get(); let seconds_string = new Date(slider_value * 1000).toISOString().substr(11, 8); seconds_element.innerHTML = seconds_string; createThumb(seconds_string) }); function createThumb(time) { $.ajax({ type: "POST", url: "index.php", data: {"time_string": time}, success: function (result) { let d = new Date(); $("#thumbnail").attr("src", "thumbnail.jpg?" + d.getTime()); } }); }
A basic Bootstrap card with the noui slider with a download button to easily get the thumbnail.
<div className="container"> <div className="row"> <div className="col-12"> <div className="card shadow"> <div className="card-header"> <h2 className="text-center">Drag toggle to create thumbnail</h2> </div> <div className="card-body px-4"> <img id="thumbnail" className="img-fluid" src="<?= $thumb ?>" width="100%" alt="<?= $file ?> video thumbnail"> <div className="row text-center mt-4"> <div id="slider"></div> </div> <div className="row text-center mt-3"> <div className="col-12"> <p>Thumbnail from video time: <code><span id="seconds">00:00:01</span></code></p> <a id="download" href="thumbnail.jpg" download="thumbnail.jpg" className="btn btn-primary" role="button">Download thumbnail</a> </div> </div> </div> </div> </div> </div> </div>
A drained and empty Kennington reservoir images from a drone in early July 2024. The…
Merrimu Reservoir from drone. Click images to view larger.
Using FTP and PHP to get an array of file details such as size and…
Creating and using Laravel form requests to create cleaner code, separation and reusability for your…
Improving the default Laravel login and register views in such a simple manner but making…
Laravel validation for checking if a field value exists in the database. The validation rule…