Extract thumbnails from html5 video


This is a simple example of a mini web page that extract a series of thumbnails from a chosen local video or remote video compatible with your broswer html5, these are currently compatible codecs:

  • Theora
  • Mp4 (h.264)
  • Webm (vp8)
  • Webm (vp9)

Here the complete source of the mini web page with some video example and in the image below you can see the structure of the page:
thumbnails_screenshoot_little
this was writen in html/css with pure javascript, the thumbnails are sorted in chronological order and are extract every 250 ms, in every page there are 10 seconds of thumbnails, and is possible navigate to next 10 seconds or previous 10 seconds of video by clicking on the relative buttons, here the javascript code:

document.addEventListener('DOMContentLoaded', function (event) {
    console.log('document is ready');

    init();
});

var thumbSizeW = 100;
var thumbSizeH = 50;
var boxThumbnail = null;
var inputFile = null;
var inputUrl = null;
var video = null;
var durationVideo = 0;
var videoName = '';
var timePosition = 0;
var generated = false;
var pageThumbnail = 0;

function init(name, age) {
    console.log('init var');

    video = document.getElementById('video');
    video.addEventListener('error', failedVideo, false);
    video.addEventListener('loadedmetadata', function () {
        console.log(video.duration);

        durationVideo = video.duration;
    });

    buttonGenerate = document.getElementById('btnUrlVideo');
    buttonGenerate.addEventListener('click', updateUrl, false);
    buttonGenerate = document.getElementById('btnGenerate');
    buttonGenerate.addEventListener('click', generateThumbnail, false);

    boxThumbnail = document.getElementById('thumbnailBox');

    inputFile = document.getElementById('fileVideo');
    inputFile.addEventListener('change', updateFile, false);
    inputUrl = document.getElementById('urlVideo');
}

function updateFile() {
    var file = inputFile.files;
    videoPath = file[0].name;

    videoName = 'video_sample/' + videoPath;

    console.log('path video: ' + file[0].name);
    console.log('Type: ' + file[0].type);
    console.log('Size: ' + file[0].size + ' bytes');

    //change video src
    var source = document.createElement('source');
    source.setAttribute('src', 'video_sample/' + videoPath);

    while (video.firstChild) {
        video.removeChild(video.firstChild);
    }
    if (boxThumbnail.childNodes.length > 0) {
        while (boxThumbnail.firstChild) {
            boxThumbnail.removeChild(boxThumbnail.firstChild);
        }
    }
    generated = false;

    video.appendChild(source);
}



function updateUrl() {
    var url = inputUrl.value;
    console.log('url video: ' + url);

    videoName = url;

    //change video src
    var source = document.createElement('source');
    source.setAttribute('src', url);

    while (video.firstChild) {
        video.removeChild(video.firstChild);
    }
    if (boxThumbnail.childNodes.length > 0) {
        while (boxThumbnail.firstChild) {
            boxThumbnail.removeChild(boxThumbnail.firstChild);
        }
    }
    generated = false;

    video.appendChild(source);
}


function generateThumbnail() {
    console.log('generate ' + generated + ' ' + video.currentSrc);
    if (generated === false && video.currentSrc !== '') {

        addBtnPrev();
        addInfo();
        addBtnNext();


        for (k = 0; k < 2; k++) {
            console.log('k(row): ' + k);
            var tmpRow = document.createElement('div');
            tmpRow.setAttribute('id', 'div_row_' + k);
            tmpRow.className = 'thumbnailRow';

            for (i = 1; i < 6; i++) {
                console.log('----> i(div second): ' + i);
                var tmpDiv = document.createElement('div');
                tmpDiv.setAttribute('id', 'div_sec_' + i);
                tmpDiv.className = 'thumbnailSec';

                for (j = 0; j < 4; j++) {
                    console.log('--> j(div micro 25): ' + j);

                    timePosition += 0.25;
                    var timePositionEND = timePosition + 0.50;
                    if (timePosition <= durationVideo) {
                        //change video src
                        var tmpSource = document.createElement('source');
                        var tmpVideo = document.createElement('video');
                        tmpSource.setAttribute('src', videoName + '#t=' + timePosition + ',' + timePositionEND);
                        tmpVideo.appendChild(tmpSource);
                        tmpVideo.setAttribute('width', '100px');
                        tmpVideo.setAttribute('height', '50px');
                        tmpVideo.className = 'thumbnailItem';
                        console.log('--> j(currentvideo): ' + videoName + '#t=' + timePosition + ',' + timePositionEND);

                        tmpVideo.onclick = (function (opt) {
                            return function () {
                                console.log('thumbnail clicked ' + opt);

                                Popup(opt);
                            };
                        })(timePosition);

                        tmpDiv.appendChild(tmpVideo);

                    } else {
                        var tmpEmpty = document.createElement('div');

                        tmpEmpty.setAttribute('width', '100px');
                        tmpEmpty.setAttribute('height', '50px');
                        tmpEmpty.className = 'thumbnailItem';
                        tmpEmpty.innerHTML += 'Empty';
                        console.log('--> j (empty)');

                        tmpDiv.appendChild(tmpEmpty);
                    }
                }
                tmpRow.appendChild(tmpDiv);
            }
            boxThumbnail.appendChild(tmpRow);
        }

        generated = true;
    } else {
        alert('Select a video first')
    }
}

function addInfo() {
    var tmp = document.createElement('div');

    tmp.setAttribute('id', 'infosec');
    tmp.className = 'info';
    tmp.innerHTML += 'from ' + timePosition + ' sec to ' + (timePosition + 10);
    boxThumbnail.appendChild(tmp);
}

function addBtnPrev() {
    var btnPrev = document.createElement('div');

    btnPrev.setAttribute('id', 'btnPRE');
    btnPrev.className = 'btnNav';
    btnPrev.innerHTML += 'PREV';
    btnPrev.addEventListener('click', prevPage, false);

    boxThumbnail.appendChild(btnPrev);
}

function addBtnNext() {
    var btnNext = document.createElement('div');

    btnNext.setAttribute('id', 'btnNEX');
    btnNext.className = 'btnNav';
    btnNext.innerHTML += 'NEXT';
    btnNext.addEventListener('click', nextPage, false);

    boxThumbnail.appendChild(btnNext);
}

function prevPage() {
    if (timePosition >= 20) {
        timePosition -= 20;

        console.log('prev page -' + timePosition);

        if (boxThumbnail.childNodes.length > 0) {
            while (boxThumbnail.firstChild) {
                boxThumbnail.removeChild(boxThumbnail.firstChild);
            }
        }
        generated = false;

        generateThumbnail();
    }
}

function nextPage() {
    if (timePosition < durationVideo) {
        console.log('next page ' + timePosition);

        if (boxThumbnail.childNodes.length > 0) {
            while (boxThumbnail.firstChild) {
                boxThumbnail.removeChild(boxThumbnail.firstChild);
            }
        }
        generated = false;

        generateThumbnail();
    }
}



function failedVideo(e) {
    console.log('Error video playback');
    switch (e.target.error.code) {
    case e.target.error.MEDIA_ERR_ABORTED:
        alert('You aborted the video playback.');
        break;
    case e.target.error.MEDIA_ERR_NETWORK:
        alert('A network error caused the video download to fail part-way.');
        break;
    case e.target.error.MEDIA_ERR_DECODE:
        alert('The video playback was aborted due to a corruption problem or because the video used features your browser did not support.');
        break;
    case e.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
        alert('The video could not be loaded, either because the server or network failed or because the format is not supported.');
        break;
    default:
        alert('An unknown error occurred.');
        break;
    }
}


function Popup(sec) {
    console.log('new popup ' + sec);
    var w = 800;
    var h = 500;
    var l = Math.floor((screen.width - w) / 2);
    var t = Math.floor((screen.height - h) / 2);

    var stile = "width=" + w + ",height=" + h + ",top=" + t + ",left=" + l + ',status=no, menubar=no, toolbar=no scrollbars=no';

    var testo = window.open("", "", stile);


    testo.document.write("<html>\n");
    testo.document.write(" <head>\n");
    testo.document.write("  <title>Video playback</title>\n");
    testo.document.write(" </head>\n");
    testo.document.write("<body topmargin=50>\n");
    testo.document.write("<video id=\'video\' preload=\"auto\" controls autoplay " + "src=" + videoName + "#t=" + sec + "\>I\m sorry; your browser doesn\'t support HTML5 video.\</video\>");
    testo.document.write("</body>\n");
    testo.document.write("</html>");
}

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...