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.
The PHP
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);
The Javascript
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()); } }); }
The HTML
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>
Live example