File API File and Reader Objects Video First Frame Tutorial

File API File and Reader Objects Video First Frame Tutorial

File API File and Reader Objects Video First Frame Tutorial

Yesterday’s File API File and Reader Objects Mimetype Tutorial‘s “Client Browsing” web application gets enhanced today using the knowledge from two days ago, when we presented Video File Browse Preview Tutorial, and started gleaning a “first frame” image given an HTML video element populated with data.

And so we flag the “Image” summary element with a thumbnail “first frame” image should the user browse for a video file and use …

… to display and, as applicably, play that element, whether that be …

  • video display and be able to play, as well as adding a thumbnail img (image) that can be clicked to play the video or display a full sized “first frame” img (image)
  • audio display and be able to play
  • img display

… via modified body onload logic, as per …


var thecanvas = null;
var thecontext = null;
var thevideo = null;



function dolhsh() {
thecanvas = document.querySelector("#video-canvas");
thecontext = thecanvas.getContext("2d");
thevideo = document.querySelector("#main-video");


if (document.URL.indexOf('vionly=') != -1) {
document.getElementById('files').accept='video/*,image/*';
}


document.querySelector("#files").addEventListener('change', function() {
var xtomt='', xthext='', ixthext=0;
if (document.querySelector("#files").files[0].type != 'application/octet-stream') { xtomt=document.querySelector("#files").files[0].type; }
if (document.querySelector("#files").files[0].name.indexOf('.') != -1) { xthext='.' + document.querySelector("#files").files[0].name.split('.')[eval(-1 + file.name.split('.').length)].toLowerCase(); }
if (xthext != '') {
for (ixthext=0; ixthext<mexts.length; ixthext++) {
if (mexts[ixthext] == xthext) {
xtomt=mtypes[ixthext];
//alert('Tomt=' + tomt);
}
}
}
//alert('xtomt=' + xtomt);
documentURL=document.URL;
if (xtomt.indexOf('video/') != 0 && document.getElementById('sumimg')) {
document.getElementById('sumimg').innerHTML='Image';
}
if (xtomt.indexOf('video/') == 0) {
documentURL+='#vionly=y';
// Object Url as the video source
document.querySelector("#main-video source").setAttribute('src', URL.createObjectURL(document.querySelector("#files").files[0]));

// Load the video and show it
thevideo.load();

// Load metadata of the video to get video duration and dimensions
thevideo.addEventListener('loadedmetadata', function() {
// Set canvas dimensions same as video dimensions
thecanvas.width = thevideo.videoWidth;
thecanvas.height = thevideo.videoHeight;
setTimeout(() => {
//thecanvas.style.display = 'inline';
//thecanvas.style.border = '2px solid pink';
thecontext.drawImage(thevideo, 0, 0, thevideo.videoWidth, thevideo.videoHeight);
if (parent.document.getElementById('tdright') || documentURL.indexOf('vionly=') != -1) {
if (!document.getElementById('ibchkbox').checked && wponeokay) {
if (document.getElementById('dtli')) {
if ((document.getElementById('dtli').innerHTML + '~').replace('<hr>','').trim().indexOf('</summary>~') != -1) {
if (document.getElementById('dtli').innerHTML.indexOf('<hr') != -1) {
document.getElementById('dtli').innerHTML=document.getElementById('dtli').innerHTML.replace('<hr', '<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img><hr');
} else {
document.getElementById('dtli').innerHTML+='<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
}
if (document.getElementById('sumimg')) {
document.getElementById('sumimg').innerHTML='Image&nbsp;<img onclick="event.stopPropagation(); document.querySelector(' + "'" + 'video' + "'" + ').play(); setTimeout(dtlvize,2000); " style="width:60px;border:1px dotted yellow;" title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
document.getElementById('dtli').open=false;
}
}
}
ourwois=window.open(wp1,wp2);
ourwois.document.write('<html><body><img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img></body></html>');
ourwois.document.title='First frame of video';
} else if (document.getElementById('dtli')) {
if ((document.getElementById('dtli').innerHTML + '~').replace('<hr>','').trim().indexOf('</summary>~') != -1) {
if (document.getElementById('dtli').innerHTML.indexOf('<hr') != -1) {
document.getElementById('dtli').innerHTML=document.getElementById('dtli').innerHTML.replace('<hr', '<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img><hr');
} else {
document.getElementById('dtli').innerHTML+='<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
}
if (document.getElementById('sumimg')) {
document.getElementById('sumimg').innerHTML='Image&nbsp;<img onclick="event.stopPropagation(); document.querySelector(' + "'" + 'video' + "'" + ').play(); setTimeout(dtlvize,2000); " style="width:60px;border:1px dotted yellow;" title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
document.getElementById('dtli').open=false;
}
}
}
//document.body.style.background='URL(' + thecanvas.toDataURL() + ')';
//document.body.style.backgroundRepeat='no-repeat';
if (parent.document.getElementById('tdright')) {
parent.document.getElementById('tdright').style.width='' + thecanvas.width + 'px';
parent.document.getElementById('tdright').style.height='' + thecanvas.height + 'px';
parent.document.getElementById('tdright').style.background='URL(' + thecanvas.toDataURL() + ')';
parent.document.getElementById('tdright').style.backgroundSize='contain';
parent.document.getElementById('tdright').style.backgroundRepeat='no-repeat';
parent.document.getElementById('tdright').style.backgroundPosition='0px 80px';
}
//alert(thecanvas.toDataURL());
} else if (parent.document.getElementById('tdleft')) {
if (!document.getElementById('ibchkbox').checked && wponeokay) {
if (document.getElementById('dtli')) {
if ((document.getElementById('dtli').innerHTML + '~').replace('<hr>','').trim().indexOf('</summary>~') != -1) {
if (document.getElementById('dtli').innerHTML.indexOf('<hr') != -1) {
document.getElementById('dtli').innerHTML=document.getElementById('dtli').innerHTML.replace('<hr', '<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img><hr');
} else {
document.getElementById('dtli').innerHTML+='<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
}
if (document.getElementById('sumimg')) {
document.getElementById('sumimg').innerHTML='Image&nbsp;<img onclick="event.stopPropagation(); document.querySelector(' + "'" + 'video' + "'" + ').play(); setTimeout(dtlvize,2000); " style="width:60px;border:1px dotted yellow;" title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
document.getElementById('dtli').open=false;
}
}
}
ourwois=window.open(wp1,wp2);
ourwois.document.write('<html><body><img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img></body></html>');
ourwois.document.title='First frame of video';
} else if (document.getElementById('dtli')) {
if ((document.getElementById('dtli').innerHTML + '~').replace('<hr>','').trim().indexOf('</summary>~') != -1) {
if (document.getElementById('dtli').innerHTML.indexOf('<hr') != -1) {
document.getElementById('dtli').innerHTML=document.getElementById('dtli').innerHTML.replace('<hr', '<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img><hr');
} else {
document.getElementById('dtli').innerHTML+='<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
}
if (document.getElementById('sumimg')) {
document.getElementById('sumimg').innerHTML='Image&nbsp;<img onclick="event.stopPropagation(); document.querySelector(' + "'" + 'video' + "'" + ').play(); setTimeout(dtlvize,2000); " style="width:60px;border:1px dotted yellow;" title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
document.getElementById('dtli').open=false;
}
}
}
parent.document.getElementById('tdleft').style.background='URL(' + thecanvas.toDataURL() + ')';
parent.document.getElementById('tdleft').style.backgroundSize='contain';
parent.document.getElementById('tdleft').style.backgroundRepeat='no-repeat';
parent.document.getElementById('tdleft').style.backgroundPosition='0px 80px';
//alert(thecanvas.toDataURL());
} else {
if (!document.getElementById('ibchkbox').checked && wponeokay) {
if (document.getElementById('dtli')) {
if ((document.getElementById('dtli').innerHTML + '~').replace('<hr>','').trim().indexOf('</summary>~') != -1) {
if (document.getElementById('dtli').innerHTML.indexOf('<hr') != -1) {
document.getElementById('dtli').innerHTML=document.getElementById('dtli').innerHTML.replace('<hr', '<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img><hr');
} else {
document.getElementById('dtli').innerHTML+='<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
}
if (document.getElementById('sumimg')) {
document.getElementById('sumimg').innerHTML='Image&nbsp;<img onclick="event.stopPropagation(); document.querySelector(' + "'" + 'video' + "'" + ').play(); setTimeout(dtlvize,2000); " style="width:60px;border:1px dotted yellow;" title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
document.getElementById('dtli').open=false;
}
}
}
ourwois=window.open(wp1,wp2);
ourwois.document.write('<html><body><img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img></body></html>');
ourwois.document.title='First frame of video';
} else if (document.getElementById('dtli')) {
if ((document.getElementById('dtli').innerHTML + '~').replace('<hr>','').trim().indexOf('</summary>~') != -1) {
if (document.getElementById('dtli').innerHTML.indexOf('<hr') != -1) {
document.getElementById('dtli').innerHTML=document.getElementById('dtli').innerHTML.replace('<hr', '<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img><hr');
} else {
document.getElementById('dtli').innerHTML+='<img title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
}
if (document.getElementById('sumimg')) {
document.getElementById('sumimg').innerHTML='Image&nbsp;<img onclick="event.stopPropagation(); document.querySelector(' + "'" + 'video' + "'" + ').play(); setTimeout(dtlvize,2000); " style="width:60px;border:1px dotted yellow;" title="First frame of video" src="' + thecanvas.toDataURL() + '"></img>';
document.getElementById('dtli').open=false;
}
}
}
parent.document.getElementById('resultvi').innerHTML=thecanvas.toDataURL();
}
//document.getElementById('nowplay').innerHTML=' <button onclick=nowplay(); style="background:URL(' + thecanvas.toDataURL() + ');background-size:cover;background-repeat:no-repeat;">Play</button>'
}, 100);
});


} // end of video check if


});


if (window.parent != window) {
document.body.style.backgroundColor='transparent';
document.getElementById('files').style.marginTop='-10px';
document.getElementById('files').style.marginLeft='-12px';
document.getElementById('files').style.backgroundColor='#d7d7d7';
document.getElementById('distyle').innerHTML='<style> input { -webkit-appearance: border-bevel !important; border: 0 !important; } </style>'; // thanks to https://forum.webflow.com/t/disable-ios-safari-round-corners-on-form-elements/591
if (parent.document.getElementById('resultout')) {
document.getElementById('files').accept='.pdf,.doc,.docx,.htm,.html,.txt';
} else if (parent.document.getElementById('resultav')) {
document.getElementById('files').accept='.pdf,audio/*,video/*,image/*';
} else if (parent.document.getElementById('resultvi') || document.URL.indexOf('vionly=') != -1) {
document.getElementById('files').accept='video/*,image/*';
}
}
if (('' + window.location.hash).replace('#','') != '') {
document.getElementById('lhsh').innerHTML=window.location.hash.substring(1);
if (window.parent) {
if (parent.document.URL.indexOf('macos_say_record.php') != -1) {
//alert(document.URL);
if (document.URL.indexOf('//localhost') != -1) {
document.getElementById('ttag').innerHTML='<iframe style=display:none; name=posttid id=posttid src=""></iframe><iframe name=tid id=tid onload=actoit(this); style=display:none; src="' + document.URL.split('client_browsing')[0] + '../Htdocs/PHP/animegif/tutorial_to_animated_gif.php?rand=' + Math.floor(Math.random() * 19876543) + window.location.hash.replace(/\ /g,'%20') + '"></iframe>';
} else {
document.getElementById('ttag').innerHTML='<iframe style=display:none; name=posttid id=posttid src=""></iframe><iframe name=tid id=tid onload=actoit(this); style=display:none; src="' + document.URL.split('client_browsing')[0] + '../PHP/animegif/tutorial_to_animated_gif.php?rand=' + Math.floor(Math.random() * 19876543) + window.location.hash.replace(/\ /g,'%20') + '"></iframe>';
}
}
}
} else if (parent.window) {
if (parent.document.URL.indexOf('macos_say_record.php') != -1) {
if (parent.document.getElementById('lhsh')) {
if (parent.document.getElementById('lhsh').innerHTML != '') {
document.getElementById('lhsh').innerHTML=parent.document.getElementById('lhsh').innerHTML;
if (document.URL.indexOf('//localhost') != -1) {
document.getElementById('ttag').innerHTML='<iframe style=display:none; name=posttid id=posttid src=""></iframe><iframe name=tid id=tid onload=actoit(this); style=display:none; src="' + document.URL.split('client_browsing')[0] + '../Htdocs/PHP/animegif/tutorial_to_animated_gif.php?rand=' + Math.floor(Math.random() * 19876543) + window.location.hash.replace(/\ /g,'%20') + '"></iframe>';
} else {
document.getElementById('ttag').innerHTML='<iframe style=display:none; name=posttid id=posttid src=""></iframe><iframe name=tid id=tid onload=actoit(this); style=display:none; src="' + document.URL.split('client_browsing')[0] + '../PHP/animegif/tutorial_to_animated_gif.php?rand=' + Math.floor(Math.random() * 19876543) + window.location.hash.replace(/\ /g,'%20') + '"></iframe>';
}
}
}
}
}
}

… in the changed client_browsing.htm web application you can try for yourself.


Previous relevant File API File and Reader Objects Mimetype Tutorial is shown below.

File API File and Reader Objects Mimetype Tutorial

File API File and Reader Objects Mimetype Tutorial

A while back with File API File and Reader Objects Primer Tutorial we started on a Client Browsing web application which uses …

… excellent Javascript functionality which can access and read Files off your underlying (client) device file system.

It’s been changed a lot over three years and today we tackle a mimetype annoyance we want to work around as we create HTML …

  • video
  • audio
  • img

… media elements, the first two of which are more likely to natively work if the mimetype is an accurate reflection of the file’s data. And yet, often off the FileReader logic, we found it often returned the mimetype “application/octet-stream” (a mimetype often associated with email attachments). Better would be to use the FileReader file’s …

  • file extension … and associate that with a more apt …
  • usual mimetype … as per

    var mtypes = ["audio/x-aiff","audio/wav","audio/x-wav","audio/x-pn-realaudio","audio/x-mpegurl","audio/x-aiff","audio/mpeg","audio/mid",
    "audio/basic","audio/ogg","video/x-sgi-movie","video/x-msvideo","video/quicktime","audio/mp3","video/mp4","video/mpeg",
    "video/x-la-asf","video/ogg","video/webm","audio/mp4", "image/jpeg", "image/jpeg", "image/png", "image/gif", "image/bmp", "image/tif"];
    var mexts = [".aiff",".wav",".wav",".ram",".m3u",".aiff",".mp3",".rmi",
    ".snd",".ogg",".movie",".avi",".mov",".mp3",".m4v",".mpeg",
    ".lsx",".ogv",".webm",".m4a", ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tif"];


    reader[ij].onloadend = (function(mfile) {
    return function(evt) {
    var dp='', ds=dssuffix, slideshowparent=false, ssuffix='0', nsuffix='2', blnks=' ', xhsf='', zhsfs=[];
    var tomt='video/mp4', thext='', ithext=0;
    if (evt.target.readyState == FileReader.DONE) { // DONE == 2
    if (mfile.type != 'application/octet-stream') { tomt=mfile.type; }
    if (mfile.name.indexOf('.') != -1) { thext='.' + mfile.name.split('.')[eval(-1 + file.name.split('.').length)].toLowerCase(); }
    if (thext != '') {
    for (ithext=0; ithext<mexts.length; ithext++) {
    if (mexts[ithext] == thext) {
    tomt=mtypes[ithext];
    }
    }
    }

    // Lots of code follows ... some of which now contains evt.target.result.replace('application/octet-stream', tomt).replace('application/octet-stream', tomt) to get around the application/octet-stream mimetypes
    //
    }
    } };
    })(files[ij]);

… in such scenarios, to improve on the chances of playing that media file successfully in the changed client_browsing.htm web application you can try for yourself, and perhaps get to see what we mean!


Previous relevant File API File and Reader Objects Primer Tutorial is shown below.

File API File and Reader Objects Primer Tutorial

File API File and Reader Objects Primer Tutorial

Thanks to this great link we discovered a better way to combine the wonders of …

… in the scenario of a web application (remaining correct and asynchronous in its) use of an input type=file “multiple” browser element accessing the wonderful File API, such as …


<head>
<script type='text/javascript'>
function onl() {
document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);
}
</script>
</head>
<body style="background-color:#f0f0f0;" onload="onl();">
<input onclick="this.value=null;" onchange="document.getElementById('ibut').click();" style='width:50%;background-color:orange;' type="file" id="files" name="file" accept="image/*,video/*,audio/*,application/*,text/*" multiple />
<span class="readBytesButtons">
<button style='display:none;' data-startbyte="0" data-endbyte="4">1-5</button>
<button style='display:none;' data-startbyte="5" data-endbyte="14">6-15</button>
<button style='display:none;' data-startbyte="6" data-endbyte="7">7-8</button>
<button id=ibut style='background-color:pink;display:none;'>Send to Server Top Half</button>
</span>

You can see us applying new ideas to our usual readBlob (that we get to output data URIs today) …


function readBlob(opt_startByte, opt_stopByte) {
files = document.getElementById('files').files;
xx=[];
yy=[];
ten=500;
ixy=0;
awis=[];
ahis=[];
awx=[];
awy=[];
awid=[];
reader=[];
blob=[];
var ij=0;
kij=0;
kkij=0;
lastiw=0;
lastih=0;
if (!files.length) {
alert('Please select a file!');
return;
}
for (ij=0; ij<files.length; ij++) {
file = files[ij];
filen = file.name;
lasttype = file.type;
fs.push(file.name.replace(/\\/g,'/').split('/')[eval(-1 + file.name.replace(/\\/g,'/').split('/').length)]);
start = parseInt(opt_startByte) || 0;
stop = parseInt(opt_stopByte) || file.size - 1;


reader.push(new FileReader());

// If we use onloadend, we need to check the readyState.
// Thanks to https://stackoverflow.com/questions/12546775/get-filename-after-filereader-asynchronously-loaded-a-file
reader[ij].onloadend = (function(mfile) {
return
function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
if (mfile.type.indexOf('image/') == 0) {
if (document.getElementById('ibchkbox').checked) {
if (document.getElementById('gb')) {
document.getElementById('gb').src=evt.target.result.replace('data:;', 'data:' + mfile.type + ';');
} else {
document.getElementById('icontent').innerHTML+=ipre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + isuf;
}
} else {
wo=window.open(wp1,wp2);
wo.document.write(ipre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + isuf);
wo.document.title = mfile.name.replace(/\\/g,'/').split('/')[eval(-1 + mfile.name.replace(/\\/g,'/').split('/').length)];
}
} else if (mfile.type.indexOf('audio/') == 0) {
if (document.getElementById('ibchkbox').checked) {
if (document.getElementById('ab')) {
document.getElementById('ab').src=evt.target.result.replace('data:;', 'data:' + mfile.type + ';');
} else {
document.getElementById('icontent').innerHTML+=apre + mfile.type + amid + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + asuf.replace('><', ' id=v' + mfile.name + '><');
}
} else {
wo=window.open(wp1,wp2);
wo.document.write(apre + mfile.type + amid + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + asuf.replace('><', ' id=a' + mfile.name + '><'));
wo.document.title = mfile.name.replace(/\\/g,'/').split('/')[eval(-1 + mfile.name.replace(/\\/g,'/').split('/').length)];
}
} else if (mfile.type.indexOf('video/') == 0) {
if (document.getElementById('ibchkbox').checked) {
if (document.getElementById('vb')) {
document.getElementById('vb').src=evt.target.result.replace('data:;', 'data:' + mfile.type + ';');
} else {
document.getElementById('icontent').innerHTML+=vpre + mfile.type + vmid + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + vsuf.replace('><', ' id=v' + mfile.name + '><');
}
} else {
wo=window.open(wp1,wp2);
wo.document.write(vpre + mfile.type + vmid + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + vsuf.replace('><', ' id=v' + mfile.name + '><'));
wo.document.title = mfile.name.replace(/\\/g,'/').split('/')[eval(-1 + mfile.name.replace(/\\/g,'/').split('/').length)];
}
} else {
if (document.getElementById('ibchkbox').checked) {
if (document.getElementById('ib')) {
document.getElementById('ib').src=evt.target.result.replace('data:;', 'data:' + mfile.type + ';');
} else {
document.getElementById('icontent').innerHTML+=opre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + osuf;
}
} else {
wo=window.open(wp1,wp2);
wo.document.write(opre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + osuf);
wo.document.title = mfile.name.replace(/\\/g,'/').split('/')[eval(-1 + mfile.name.replace(/\\/g,'/').split('/').length)];
}
}
} };
})(files[ij]);

blob.push(file.slice(start, stop + 1));
reader[ij].readAsDataURL(blob[ij]);
kij++;
}
}

… featuring in our proof of concept File API “Client Browsing” client_browsing.html web application’s live run link. Notice how the File object’s “mfile.type” is used within the FileReader object’s “onloadend” event logic … a powerful combination of objects in an asynchronous scenario, that asynchronicity ensured by involving a return scenario … cute,huh?!

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

This entry was posted in Animation, eLearning, Event-Driven Programming, Tutorials and tagged , , , , , , , , , , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *