Videogular cue points: Synchronize video with Twitter

In Videogular 1.1.0 we introduced cue points, a new way to trigger functions related to time. Cue points are a very powerful way to synchronize video with anything you want, and in this tutorial we’re going to synchronize video with a twitter timeline.

For this demo we will use our Videogular talk at NG-NL conference and we will synchronize the video with the tweets that attendees did on our talk with the hashtag #ngnlconf.

If you want to see the final result just check out the demo page and you can fork the code on Github.

To proceed with this tutorial we suppose that you have installed SASS, NodeJS and Bower.

Preparing our project

First we need to prepare our directory structure. Create this folders:

Now we’re going to download the required dependencies. Create two files inside “videoguar-twitter-tutorial” folder:

.bowerrc

bower.json

Install dependencies with “bower install” and we’re ready to go.

Creating the HTML/CSS and our Application

First we need to create our “index.html” inside “app” folder with all our JS dependencies, CSS styles and the Google Analytics script.

app/index.html

With our index file configured we just can start our app file:

app/scripts/vg-twitter-app.js

In vg-twitter-app.js we’re going to have only the dependencies, we will have a separated file for our controllers, directives and routes.

Let’s going to write our routes file:

app/scripts/routes/vg-routes.js

Here we’re creating a TwitterCtrl controller in our root url called ctrl. But before we can reach our root url we need to load our tweets, so we just added a resolve function with a simple HTTP get. Probably you will have your custom service here, but we just simplified this part because it’s not the focus of this tutorial.

Also, we’re going to load our tweets from a JSON file, which could seem weird having the Twitter API. Since Twitter Search API doesn’t allow to get tweets older than a week you need to make some data mining and collect and store those tweets. We did this a few weeks ago and now we can use the data and the start time of the talk (10:00AM) to synchronize the content!

You can take a look to our tweets.json file here.

To finish this chapter, we will create the SCSS file. As you can see is pretty simple:

Creating our view controller

Like we did before, we’re going to start by our HTML file, which in this case is pretty simple, since it will contain only our widget directive:

app/views/twitter-view.html

As you may read in other tutorials AngularJS controllers are the “glue” between the view and the data, so we’re going to have only a scope variable with the config data for our widget:

app/scripts/controllers/vg-twitter-ctrl.js

Again, all this data could be in a service, but we want to keep this example as simple as possible, but take into account that with a service we can even doesn’t need this controller at all!

Additionally, you may notice that we are passing our tweets loaded in our routes.js file.

Creating our widget

Ok, now our boring part is done we can start with all the fun!

As always we will start with the HTML. For me this is the easiest way to start a directive, by planning its DOM structure. In this case we want a Videogular player and a list of tweets. So let’s do this:

app/scripts/directives/vg-twitter-widget/vg-twitter-widget.html

Easy as pie! We just added a basic Videogular player with all the plugins and a section with a ng-repeat for our tweets. We will need to modify this template later to add some interactivity, but for now it will work.

Now we will need to define our directive and its controller. In our directive we will basically the definition and in our controller all the business logic.

This is how our directive will be:

app/scripts/directives/vg-twitter-widget/vg-twitter-widget.js

Ok, quick explanation about our definition:

  • scope.vgConfig: If you remember we added vg-config=”ctrl.config” our controller view (twitter-view.html). This is how we’re “gluing” our directive view with our controller data. Notice that we’ve been defined our scope variable as vgConfig but in our template we’re using ctrl.config (instead of ctrl.vgConfig). That’s because we will create a new config with parsed data in our controller.
  • templateUrl: Our previously defined DOM.
  • controller: The controller for this directive.
  • controllerAs: The variable that will contain our controller in our directive scope.
  • link: The link function that will collect all the HTML elements necessary in our business logic.

Before we get into the business logic (yep, the fun part of this tutorial) we will define our vg-tweet directive. Again, we start with the HTML.

app/scripts/directives/vg-tweet/vg-tweet.html

This is a pretty basic HTML template with a header with the user details (avatar, screen name and user name) and the text of the tweet.

The definition is even more simple than the widget directive. We just need only our data provider and the template:

app/scripts/directives/vg-tweet/vg-tweet.js

Now, we have everything set up but we still need to populate our directives since we need to first parse our JSON file in our controller.

But we’re close to see it in action!!

Controlling our Twitter Widget directive

Now we can bring all together in our widget controller. First we will create our config just to be sure that everything is working fine:

app/scripts/directives/vg-twitter-widget/vg-twitter-widget-controller.js

Now we can test this and we will see something happening finally!

The player works and we can see a list of tweets, but now we need to sync them. Since the Twitter API give us a date we can extract from it the minute and second and synchronize it with the minute and second of the Youtube video!

app/scripts/directives/vg-twitter-widget/vg-twitter-widget-controller.js

In the init function we will prepare the cue points data provider for Videogular. Let’s try to explain this easily.

We’re creating a tweet object for each tweet in our tweets.json file. Because Videogular cue points needs time in seconds we will transform the created_at property to date and will calculate the exact second of the tweet. All the “tweet” objects will be stored in our “tweets” array which is going to be our cue point track in Videogular. You can set as many tracks as you want, but be careful to not have too much intensive processes. Also we’re storing the index of each tweet, we will use that to scroll to each element when it is updated.

Finally, we will need to update our template, because now the tweet data is inside tweet.params. Just change your vg-data-provider to vg-data-provider=”tweet.params”.

app/scripts/directives/vg-twitter-widget/vg-twitter-widget.html

With our cue point track created we just need to set up the callbacks, which are basically three, onLeave, onUpdate and onComplete.

  • onLeave: Triggered when the user will seek to a time position before the timeLapse.start property.
  • onUpdate: Triggered when the current time position is between timeLapse.start and timeLapse.end properties.
  • onComplete: Triggered when the user will seek to a time position or the current time position is higher than the timeLapse.end property.

With this in mind let’s going to create our callbacks:

app/scripts/directives/vg-twitter-widget/vg-twitter-widget-controller.js

Since params are inside in each tweet created by our ng-repeat and it is accessible in our callbacks we can just set classes for each state in each tweet.

First we will set our ng-class attribute in our vg-tweet:

app/scripts/directives/vg-twitter-widget/vg-twitter-widget.html

Our tweets are going to be on a normal state when it’s not selected (that means that it’s currently receiving onUpdate callbacks) or completed (it has been received an onComplete callback).

So the logic is pretty simple!

app/scripts/directives/vg-twitter-widget/vg-twitter-widget-controller.js

Yes, is that simple, there’s nothing more to do here. Just test and enjoy!

You will see that if you seek in the video the tweets will get

Awesome right? 🙂

Final details

To finish our widget we will add a couple of details.

  • A click on a tweet should seek on the video. What an awesome feature!
  • We will provide an offset to move all the tweets 5 minutes backwards to synchronize perfectly with the video. That’s because the talk probably started at 9:55 instead of 10:00 exactly.

First we will update our HTML with the ng-click attribute in our vg-tweet tag. To seek in time we will need also the API in our controller and we can take it from our vg-player-ready=”ctrl.onPlayerReady($API)” attribute.

app/scripts/directives/vg-twitter-widget/vg-twitter-widget.html

 

Now in the controller we can just grab the API and add the offset:

app/scripts/directives/vg-twitter-widget/vg-twitter-widget-controller.js

We finished!

To test you can just seek on the video or click for example on Aaron’s tweet and pause the player. You will see that there are two tweets selected at the same time, that’s not an error! Those tweets happened very close in time and that’s why they’re both selected!

Conclusions

Interact and synchronize video with other content could be extremely complex in some situations but cue points tracks could simplify the process a lot.

As always, we’re happy to know what are you doing with Videogular, so just get in touch with us through our contact form and show us your work!