YouTube Player API: How to get duration of a loaded/cued video without playing it?
Solution 1
Solution 1
You can use YouTube Data API to access most of the information about the video, including duration:
<script type="text/javascript">
function youtubeFeedCallback(json){
document.write(json["data"]["duration"] + " second(s)");
}
</script>
<script type="text/javascript" src="http://gdata.youtube.com/feeds/api/videos/4TSJhIZmL0A?v=2&alt=jsonc&callback=youtubeFeedCallback&prettyprint=true"></script>
When using jQuery you can use $.getJSON()
to make things easier.
Solution 2
Seems like YouTube JavaScript API v3 allows you to get the correct duration inside the onYouTubePlayerReady()
event. All you need to do is pass &version=3
when calling swfobject.embedSWF()
method.
Solution 2
Following these steps:
- Get youtube video id
- Use youtube API to get duration (ISO 8601 duration)
- Convert ISO 8601 duration to time
Using Jquery:
// convert ISO 8601 duration
function formatISODate(youtube_time){
array = youtube_time.match(/(\d+)(?=[MHS])/ig)||[];
var formatted = array.map(function(item){
if(item.length<2) return '0'+item;
return item;
}).join(':');
return formatted;
}
// print video duration
$('iframe').each(function(i) {
var ifr = $(this);
var regExp = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
var match = ifr.attr('src').match(regExp); // get youtube video id
if (match && match[2].length == 11) {
var youtubeUrl = "https://www.googleapis.com/youtube/v3/videos?id=" + match[2]
+ "&key=AIzaSyDYwPzLevXauI-kTSVXTLroLyHEONuF9Rw&part=snippet,contentDetails";
$.ajax({
async: false,
type: 'GET',
url: youtubeUrl,
success: function(data) {
var youtube_time = data.items[0].contentDetails.duration;
var duration = formatISODate(youtube_time);
if(ifr.next().is('.time')) {
ifr.next().html(duration);
}
}
});
}
});
Solution 3
"Loading, and immediately playing and pausing the player would be not my favorite method."
I don't think there is any other method.
In my case it works well, even for a satellite internet user.
Here is my code :
// I set youtube player-ready event to a variable for irrelevant reasons
function onYouTubePlayerReady(playerid) {
youtube_player_ready;
}
youtube_player_ready = function(playerid) {
// load video
document.getElementById(playerid).cueVideoById(yt_video_id);
// mute video
document.getElementById(playerid).mute();
// play video to get meta data
document.getElementById(playerid).playVideo();
yt_get_duration[index] = function(){
// if duration is available
if (document.getElementById(playerid).getDuration() > 0) {
// pause video
document.getElementById(playerid).pauseVideo();
// unmute
document.getElementById(playerid).unMute();
// save duration
video_duration = document.getElementById(playerid).getDuration();
}
// else keep trying
else {
setTimeout(yt_get_duration[index], 150)
}
}
// get duration
yt_get_duration[index]();
}
Solution 4
Here one that converts the time over for you.
<script type="text/javascript">
function youtubeFeedCallback(json){
var totalSec = json["data"]["duration"];
var hours = parseInt( totalSec / 3600 ) % 24;
var minutes = parseInt( totalSec / 60 ) % 60;
var seconds = totalSec % 60;
var result = (hours < 1 ? "" : hours + ":") + (minutes < 1 ? "0" : minutes) + ":" + (seconds < 10 ? "0" + seconds : seconds);
document.write(result);
}
</script>
<script type="text/javascript" src="http://gdata.youtube.com/feeds/api/videos/LzPWWpKlvqQ?v=2&alt=jsonc&callback=youtubeFeedCallback&prettyprint=true"></script>
Harry
Updated on July 05, 2022Comments
-
Harry almost 2 years
I'm not able to get the correct video duration/length (in seconds) of a loaded/cued video via the getDuration() method of the YouTube Player API; the same method, however, returns a valid value once the video starts playing! Wondering how YouTube is able to show the valid duration of a loaded/cued video.
When I load this HTML page with a 15 second video clip, I get the following debug output:
state = 5 duration = -0.000025
When I hit the Play button, I get the following debug output:
state = 3 duration = 15,
Would greatly appreciate a solution or a workaround. Loading, and immediately playing and pausing the player would be not my favorite method.
<html> <head> <script type="text/javascript"> var videoId; videoId = 'http://www.youtube.com/v/4TSJhIZmL0A'; // bbc // videoId = 'http://www.youtube.com/v/ezwyHNs_W_A'; // physics function $(id) { return document.getElementById(id); } </script> <script src="http://www.google.com/jsapi"></script> <script> google.load("swfobject", "2.1"); </script> </head> <body> <table> <tr><td> <div id="player"> You need Flash player 8+ and JavaScript enabled to view this video. </div> <script> var ytplayer; function myOnPlayerStateChange(state) { switch(state) { case 1: // playing $("out").innerHTML += " playing"; break; case 2: // paused $("out").innerHTML += " paused"; break; case 0: // ended $("out").innerHTML += " ended"; break; case -1: // unstarted case 3: // buffering case 5: // cued $("out").innerHTML += " state = " + state; break; default: // unknown $("out").innerHTML += " state = " + state; break; } $("out").innerHTML += " duration = " + ytplayer.getDuration() + ","; } function myOnPlayerError(errorCode) { $("out").innerHTML += " Error occurred: " + errorCode; } function onYouTubePlayerReady(playerId) { ytplayer = ytplayer || $(playerId); ytplayer.addEventListener("onStateChange", "myOnPlayerStateChange"); ytplayer.addEventListener("onError", "myOnPlayerError"); } var params = { allowScriptAccess: "always", bgcolor: "#cccccc" }; var atts = { }; swfobject.embedSWF(videoId + "?border=0&enablejsapi=1&playerapiid=" + 'player', 'player', 425, 344, "8", null, null, params, atts); </script> </td></tr> </table> <div id="out"></div> <div id="err"></div> </body> </html>
-
ShinNoNoir almost 13 yearsYour solution 2 demo doesn't give the correct duration here. The alert still shows 0. However, when I play the video on your demo page, close the tab and reopen it, the alert does show the correct duration.
-
Salman A almost 13 years@ShinNoNoir: actually I am not sure myself. The documentation is not clear about whether onYouTubePlayerReady is fired before or after the metadata is loaded. You can try adding a 2 second delay.
-
ShinNoNoir almost 12 yearsRevisting my old comment, it seems that nowadays solution 2 does work. It also seems to work for the iframe YouTube API if you set
version=3
inplayerVars
. -
ShinNoNoir almost 12 yearsHmm, unfortunately,
getDuration()
only works in solution 2 for the very first video. After cueing a different video,getDuration()
calls may return 0 again. Example: jsfiddle.net/5p5sq -
Synetech almost 10 yearsUnfortunately the use of
gdata.youtube.com
can be problematic because Chrome blocks access to it as insecure, so you cannot write a userscript to for example, add the video length to the page so that people can see the length even if Flash is disabled or set to click-to-play. And the second (V3) method doesn’t work unless the video is actually loaded.:-(