Development

Create video thumbnail from a slider concept

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

 

Share

Recent Posts

Kennington reservoir drained drone images

A drained and empty Kennington reservoir images from a drone in early July 2024. The…

1 year ago

Merrimu Reservoir drone images

Merrimu Reservoir from drone. Click images to view larger.

1 year ago

FTP getting array of file details such as size using PHP

Using FTP and PHP to get an array of file details such as size and…

2 years ago

Creating Laravel form requests

Creating and using Laravel form requests to create cleaner code, separation and reusability for your…

2 years ago

Improving the default Laravel login and register views

Improving the default Laravel login and register views in such a simple manner but making…

2 years ago

Laravel validation for checking if value exists in the database

Laravel validation for checking if a field value exists in the database. The validation rule…

2 years ago