YouTube Player API: How to get duration of a loaded/cued video without playing it?

47,055

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>

Demo here

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.

Demo here

Solution 2

Following these steps:

  1. Get youtube video id
  2. Use youtube API to get duration (ISO 8601 duration)
  3. 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>
Share:
47,055
Harry
Author by

Harry

Updated on July 05, 2022

Comments

  • Harry
    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&amp;enablejsapi=1&amp;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
    ShinNoNoir almost 13 years
    Your 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
    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
    ShinNoNoir almost 12 years
    Revisting 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 in playerVars.
  • ShinNoNoir
    ShinNoNoir almost 12 years
    Hmm, 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
    Synetech almost 10 years
    Unfortunately 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. :-(