Creating Rich Video Experiences with Popcorn.js

Brad Barrow
Share

Considering just how easy it is to embed videos in websites it’s a marvel that developers often stop at just that: plain old embedded videos. What if you could create an entire experience for your user that’s directed by the video itself? With Popcorn.js you can do just that – and this article will teach you how.

Popcorn.js Fundamentals

Let’s start small. We’ll get Popcorn.js installed, and then get a “Hello World” example up and running in no time.

1. Create a Simple HTML Page

We’ll start off by creating an index.html file with the following content. The .video div is, unsurprisingly, where our video will eventually appear.

<!doctype html>
<html>
  <head>
    <title>Hello World Popcorn.js</title>
  </head>
  <body>
    <div class="video"></div>
  </body>
</html>

2. Include Our Custom Styles

Next, let’s include some basic styles for our project. The updated head section of the previous HTML page is shown below.

<head>
  <title>Hello World Popcorn.js</title>
  <style>
    .video, #map
    {
      width:300px;
      height:200px;
      float:left;
    }
  </style>
</head>

3. Include Popcorn.js

Next, we need to include the Popcorn.js library itself. There are a number of options to choose from on the Popcorn.js download page. We’re going to use the ‘complete’ version, which includes all of the official Popcorn.js plugins. We’ll use the minified version in this tutorial, but you can use the development version if you’d like to have a poke around the source. Note the additional imports in the following code sample.

<head>
  <title>Hello World Popcorn.js</title>
  <link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
  <style>
    ...
  </style>
  <script type="text/javascript" src="http://cdn.popcornjs.org/code/dist/popcorn-complete.min.js"></script>
</head>

4. Create and Include app.js

Next, let’s create the main JavaScript file for our app. This is where we’ll initialize our Popcorn.js instance. Create app.js and include it in your index.html file. The contents of app.js are shown below.

// Wait for the DOM to load
window.onload = function() {
  // Create popcorn instance from the YouTube video and insert it into the .video div
  var pop = Popcorn.youtube(".video", "http//www.youtube.com/watch?v=x88Z5txBc7w");

  // Play the video automatically
  pop.play();
};

And, the updated index.html head section is shown here.

<head>
  <title>Hello World Popcorn.js</title>
  <style>
    ...
  </style>
  <script type="text/javascript" src="http://cdn.popcornjs.org/code/dist/popcorn-complete.min.js"></script>
  <script type="text/javascript" src="app.js"></script>
</head>

In app.js we’ve used the Popcorn object’s youtube() method to create a video instance from a YouTube URL. The first parameter is a selector for our .video div. This is where Popcorn.js will insert our video. The second parameter is the YouTube URL. At the end of the file, we call pop.play() which does exactly what it says – it plays our video.

5. Lights, Camera, Action!

To ensure that the YouTube player functions correctly, we’ll need to serve this page from an http:// server, rather than by simply opening the file in our browser (file:///). On Mac OS X this is as simple as running the following command in your project directory.

python -m SimpleHTTPServer 2723

You can now access your site at http://localhost:2723. Windows users might consider lighttpd or Mongoose.

Once you’ve got your HTTP server set up, fire up the page in your browser and you should see Yakko singing a song about the countries of the world! Next, we’ll use Popcorn.js to manipulate our page as the video plays.

Directing Your Page with Popcorn.js

We’re going to allow our video to “direct” the DOM by running some custom JavaScript snippets at specific points in the video. You can see a live demo of what we’ll eventually end up with here:

See the Pen FudAq by Brad (@Haizyfox) on CodePen.

First, we’ll add a text element. Then, for each of the countries that Yakko mentions, we’ll update the text element with the name of that country. For this tutorial, I’ve already mapped out the time codes for each of the first seven countries that Yakko sings. For your own projects, you’d need to watch the video and identify the timestamps to use for your cues.

1. Add an h2 Text Element to the Page

In index.html, add the following markup as the page’s body.

<body>
  <h2>Yakko's singing about <span class="country-name">---</span></h2>
  <div class="video"></div>
</body>

2. Update the DOM

We’ll use the code plugin to update the DOM at certain times during the video. Make the following updates to app.js. Test the page in your browser. When the video reaches 20.2 seconds and Yakko says “United States”, the h2 should say United States as well.

// When Yakko says United States, update the h2
pop.code({
  start: 20.2,
  end: 20.7,
  onStart: function() {
    document.querySelector(".country-name").innerHTML = "United States";
  }
});

// Play the video automatically
pop.play();

3. Showing all of the Countries’ Names

Let’s add in a few more countries and refactor the code a little. We’ll create a list of countries and their timestamps, and then we’ll loop through the list, calling the code() method for each country.

...

// Set the h2 to the specified country name
var setCountry = function(country) {
  document.querySelector(".country-name").innerHTML = country;
};

// Countries List
var countries = [
  { start: 20.2, end: 20.7, country_name: "United States" },
  { start: 20.7, end: 21.2, country_name: "Canada" },
  { start: 21.2, end: 21.7, country_name: "Mexico" },
  { start: 21.7, end: 22.2, country_name: "Panama" },
  { start: 22.2, end: 22.7, country_name: "Haiti" },
  { start: 22.7, end: 23.2, country_name: "Jamaica" },
  { start: 23.2, end: 23.7, country_name: "Peru" }
];

// Loop through the countries
countries.forEach(function(country) {
  // Call setCountry() at the start of each country's start time.
  pop.code({
    start: country.start,
    end: country.end,
    onStart: function() { setCountry(country.country_name); }
  });
});

// Play the video automatically
pop.play();

Open the page in your browser and watch the h2 change as Yakko sings. Pretty cool right? We’ve successfully used Popcorn’s code plugin to update our DOM based on the video’s time.

Note: We used the ECMAScript forEach() loop here, but you could use jQuery or UnderscoreJS if you prefer.

Let’s Liven Things Up with Images

Popcorn has quite a few plugins. There are plugins for Wikipedia, Facebook, Tumblr, and more. We can use the Flickr plugin to show some images of our countries while the video plays. First, we need to add a div to our page to hold the photos:

...
<h2>Yakko's singing about <span class="country-name">---</span></h2>
<div class=".video"></div>
<div id="photos"></div>
...

Next, we’ll use the Flickr plugin which requires a few parameters:

  • numberofimages – The number of photos to fetch from Flickr.
  • tags – A search phrase/tags to match images.
  • height and width – The height and width of the photos.
  • target – The ID of the div to append the photos to.
  • start and end – The window during which we should show the photos.

For each country, use the flickr() method to do an image search for the country’s flag:

...

// Loop through the countries
countries.forEach(function(country) {
  // Call setCountry() at the start of each country's start time.
  pop.code({
    start: country.start,
    end: country.end,
    onStart: function() { setCountry(country.country_name); }
  });
  
  // Search Flick for "Country Flag" and add it to the #photo div
  pop.flickr({
    start: country.start,
    end: country.end,
    tags: country.country_name + " Flag",
    numberofimages: 5,
    height: "100px",
    width: "100px",
    target: "photos"
  });
});

Reload the page in your browser and watch as Popcorn.js pulls in five colorful images per country.

Enriching the Experience with Other Libraries

So far we’ve used some simple code snippets and plugins to update the text of our page and bring in some related images. While the Popcorn.js plugins are great, there’s really no limit to what you can do with directions from your video. With that in mind, let’s use the Google Maps V3 JavaScript API to recreate Yakko’s whirlwind tour on a real map!

1. Include the Google Maps API

Include the Google Maps JavaScript API in the HTML page:

...
  <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
  <script type="text/javascript" src="http://cdn.popcornjs.org/code/dist/popcorn-complete.min.js"></script>
  <script type="text/javascript" src="app.js"></script>
...

2. Create a div to Contain Our Map Canvas

Add the div#map element shown in the following example.

...
<h2>Yakko's singing about <span class="country-name">---</span></h2>
<div class=".video"></div>
<div id="map"></div>
<div id="photos"></div>
...

3. Initialize the Google Map

In your app.js file, add the following code. When you reload the page, you should see a map appear in the #map div zoomed out quite far.

// Popcorn country code from earlier
...

// Center the map on Chicago
var center = new google.maps.LatLng(41.850033, -87.6500523);

// Create a Road Map in the #map div  
var map = new google.maps.Map(document.getElementById("map"), {
  zoom: 1, // Zoom the map out really far
  center: center,
  mapTypeId: google.maps.MapTypeId.ROADMAP
});

4. Add a Marker to the Map

Let’s add a marker to the map so that we can move it around as Yakko sings:

...
// Add a maker to the map, placed at Chicago
var marker = new google.maps.Marker({
  map: map,
  position: center,
  visible: true
});

5. Using the Google Geocoder

Now comes the fun part. We’re going to use the Google Maps geocoder to find each country’s latitude and longitude using the country’s name. First, instantiate the geocoder, as shown below.

var geocoder = new google.maps.Geocoder();

Next, we’ll embelish our setCountry() method to use the geocoder to geocode each of our countries:

...
// Set the current country
var setCountry = function(country) {
  // Set the h2 to the specified country name
  document.querySelector(".country-name").innerHTML = country;

  // Geocode the country and move the marker
  geocoder.geocode({address : country}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      // Move the marker
      marker.setPosition(results[0].geometry.location);
    }
  });
};

You can read more about the Google Maps API and geocoder on their documentation page. For each country, as part of the setCountry() function, we’re geocoding the country as an address. We get back a result with a LatLng coordinate which we use to move our marker with marker.setPosition().

Final Cut

I hope this article has managed to show you just a smidgen of the potential that Popcorn.js has to provide rich, video driven interfaces for your site. There’s all manner of creative applications just waiting to be implemented. I’d love to see yours!