We saw a very exciting YouTube launch for developers today. People have long wanted to customize the YouTube player, and now you have complete control with a chromeless player that has JavaScript access so you can start, stop, go to a timing, and much more.
I took this API and implemented a simple DSL that allows me to build a simple transcript table of contents that lets you jump to a particular chapter in the video.
The HTML has special attributes and CSS classes, ending up like this:
-
-
<div id="ytplayer" class="ytplayer" url="http://www.youtube.com/v/2SgMHjmZO60"></div>
-
-
<div id="ytranscript" class="ytranscript" for="ytplayer">
-
<b>Click on the item you want to skip too</b>
-
<li starttime="0.0">Hand, hand, fingers, thumb</li>
-
<li starttime="8.0">Drumming and drumming</li>
-
<li starttime="28.0">Time to pick the apples and the plums</li>
-
<li starttime="42.0">Enter Jake</li>
-
<li starttime="44.0">Enter Jack</li>
-
<li starttime="51.0">The monkeys say bye bye</li>
-
-
<li starttime="60.0">Now they play bangos and fiddles</li>
-
<li starttime="78.0">Wooah, millions of monkeys!</li>
-
</ul>
-
</div>
-
My JavaScript trivially attaches behaviour to the list to talk to the player. It adds timing information from the DSL to the HTML content, and uses seekTo to get the player to the point you need.
-
-
window.onload = function() {
-
$$('.ytranscript').each(function(e) {
-
var player = e.readAttribute("for");
-
var playerEmbed = player + "Embed";
-
initPlayer(player, playerEmbed);
-
-
var lis = e.getElementsByTagName("li");
-
var odd = 1;
-
$A(lis).each(function(li) {
-
var starttime = li.readAttribute('starttime');
-
li.innerHTML = li.innerHTML + " <span class='timing'>" + parseInt(starttime) + " secs</span>";
-
li.addClassName( (odd++ % 2) ? "odd" : "even");
-
li.writeAttribute("title", "Send the player to this location");
-
li.onclick = function() {
-
makeSureVideoIsPlaying($(playerEmbed));
-
$(playerEmbed).seekTo(starttime, true);
-
};
-
});
-
});
-
}
-
-
function makeSureVideoIsPlaying(playerEmbed) {
-
if (playerEmbed.getState && $(playerEmbed).getState() == -1) { // -1 unstarted
-
playerEmbed.playVideo(); // play if we haven't started
-
}
-
}
-
-
function initPlayer(player, playerEmbed) {
-
var url = $(player).readAttribute('url');
-
var so = new SWFObject(url + "&enablejsapi=1&playerapiid=my" + playerEmbed, playerEmbed, 432, 400, 8);
-
so.addParam("AllowScriptAccess", "always");
-
so.write(player);
-
}
-
-
function onYouTubePlayerReady(playerId) {}
-
The one gotcha is that seekTo goes to the nearest keyframe, which can be a few seconds off. Hopefully it will at least go to the nearest one before the timing, but that isn't the case right now.
Learn more
We have an interview with the engineers, and a bunch of documentation.
Check out the JavaScript API and chromeless player reference to find out more.
UPDATE: Christian Heilmann has written a video captioning system that lets you annotate as you pause.
