Retrieving HTML5 video duration separately from the file
The issue is in WebKit browsers; the video metadata is loaded after the video so is not available when the JS runs. You need to query the readyState attribute; this has a series of values from 0 to 4, letting you know what state the video is in; when the metadata has loaded you'll get a value of 1.
So you need to do something like:
window.setInterval(function(t){
if (video.readyState > 0) {
var duration = $('#duration').get(0);
var vid_duration = Math.round(video.duration);
duration.firstChild.nodeValue = vid_duration;
clearInterval(t);
}
},500);
I haven't tested that code, but it (or something like it) should work.
There's more information about media element attributes on developer.mozilla.org.
Get video duration when input a video file
In modern browsers, You can use the URL API's URL.createObjectURL()
with an non appended video element to load the content of your file.
var myVideos = [];
window.URL = window.URL || window.webkitURL;
document.getElementById('fileUp').onchange = setFileInfo;
function setFileInfo() { var files = this.files; myVideos.push(files[0]); var video = document.createElement('video'); video.preload = 'metadata';
video.onloadedmetadata = function() { window.URL.revokeObjectURL(video.src); var duration = video.duration; myVideos[myVideos.length - 1].duration = duration; updateInfos(); }
video.src = URL.createObjectURL(files[0]);;}
function updateInfos() { var infos = document.getElementById('infos'); infos.textContent = ""; for (var i = 0; i < myVideos.length; i++) { infos.textContent += myVideos[i].name + " duration: " + myVideos[i].duration + '\n'; }}
<div id="input-upload-file" class="box-shadow"> <span>upload! (ღ˘⌣˘ღ)</span> <input type="file" class="upload" id="fileUp" name="fileUpload"></div><pre id="infos"></pre>
Trying to get full video duration but returning as Nan
Wait for onloadedmetadata
event, The loadedmetadata
event is fired when the metadata has been loaded.
var myVideo = document.getElementById("videoPlayerNew");myVideo.onloadedmetadata = function() { console.log('metadata loaded!'); console.log(this.duration);//this refers to myVideo};
<video id="videoPlayerNew" class="video-js vjs-default-skin vjs-controls-enabled" poster="http://camendesign.com/code/video_for_everybody/poster.jpg" data-setup="{}" controls=""> <source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"> <p class="vjs-no-js">Javascript was disabled or not supported</p></video>
How to get video's metadata (length) before uploading?
It's actually reasonably simple, but since this requires turning the file into a blob and then checking its duration with a video element, uploading a video longer than a couple of minutes will take a lot of processing and slow down your page immensly. I have added a filesize restriction (which is a reasonable start in my opinion). Here's a snippet (which will not work on Stack Overflow due to sandbox restrictions, but I did test it on a local server). I obviously also don't check MIME types or whether its a video at all, although loadedmetadata
will not trigger if you upload anything that is not a video.
const fileInput = document.querySelector( 'input[type=file]' );const fileDuration = document.getElementById( 'file-duration' )
// Listen for any change to the value of the file input
fileInput.addEventListener( 'change', event => {
fileDuration.textContent = 'Fetching video duration...';
// When the file selected by the user changes: // - create a fresh <video> element that has not yet fired any events // - create a file reader to safely retrieve and manipulate the file
const file = event.target.files[0]; const video = document.createElement( 'video' ); const reader = new FileReader();
// Cancel if the initial filesize just seems too large. // If the maximum allowed is 30 seconds, then a Gigabyte of file seems too much.
if( file.size > 10000000 ){
fileDuration.textContent = `File is too large (${file.size}). Refused to read duration.`; return;
}
// Before setting any source to the <video> element, // add a listener for `loadedmetadata` - the event that fires // when metadata such as duration is available. // As well as an error event is case something goes wrong.
video.addEventListener( 'loadedmetadata', event => {
// When the metadata is loaded, duration can be read.
fileDuration.textContent = `Video is ${video.duration} seconds long.`;
});
video.addEventListener( 'error', event => {
// If the file isn't a video or something went wrong, print out an error message.
fileDuration.textContent = `Could not get duration of video, an error has occurred.`;
});
// Before reading any file, attach an event listener for // when the file is fully read by the reader. // After that we can use this read result as a source for the <video>
reader.addEventListener( 'loadend', function(){
// reader.result now contains a `blob:` url. This seems like a // nonsensical collection of characters, but the <video> element // should be able to play it.
video.src = reader.result;
// After we assigned it to the `src` of the <video>, it will be // act like any other video source, and will trigger the related // events such as `loadedmetadata`, `canplay`, etc...
});
// Instruct the reader to read the file as a url. When its done // it will trigger the `loadend` event handler above.
reader.readAsDataURL( file );
});
<input type="file" /><p id="file-duration">No video file</p>
Related Topics
Why Is It Bad Practice to Use Links With the JavaScript: "Protocol"
How to Convert Base64 String to JavaScript File Object Like as from File Input Form
Html ≪Select≫ Selected Option Background-Color CSS Style
How to Detect When a Page Exits Fullscreen
Chrome Extension How to Send Data from Content Script to Popup.Html
For Loop Through Array Only Shows Last Value
Prevent Body from Scrolling When a Modal Is Opened
"Uncaught Typeerror: A.Indexof Is Not a Function" Error When Opening New Foundation Project
Css Transition Doesn't Work If Element Start Hidden
How to Return the Response from an Asynchronous Call
Confirmation Before Closing of Tab/Browser
How to Display an Image Stored as Byte Array in Html/JavaScript
Want to Add "Addeventlistener" on Multiple Elements With Same Class
How to Check Connection Type (Wifi/Lan/Wwan) Using Html5/JavaScript
Html5 Dragleave Fired When Hovering a Child Element
Canvas2D Todataurl() Different Output on Different Browser