Working with the YouTube Player API for iframe Embeds

Choosing YouTube for Video Embeds

While working on the component library for our partner Maui Jim, one of the requests we received was to have a video autoplay on the last slide of a carousel. We knew that the best thing to do would be to embed a YouTube player on the last slide using the iFrame Player API, which allows us to control the player using JavaScript. We like letting YouTube play our videos to avoid the hassle of having to convert videos to other formats so they work in other browsers and platforms. Even when new platforms come along down the line, the onus is on YouTube to ensure that the playback continues to function properly.

For all the components in the library requiring video, we made sure that we only created the video when it was in view—such as when a user opens a modal or arrives at a specific carousel slide. We do this in order to prevent unnecessary downloads that can incur high overhead.

To add the video that autoplays on the last slide, I had to set a condition of: if (lastSlide) {createVideo}. In order to show how we went about this, I am using a sample Bootstrap 4 Carousel that I pulled from the official docs, in order to show a truncated version of what we accomplished in the style guide.

First, I want to check whenever the carousel transitions into the last slide where the video should be playing. The <div class="carousel"> in Bootstrap 4 exposes a couple of events that are hooked into the carousel functionality. We want to use slide.bs.carousel, which “fires immediately when the slide instance method is invoked.”

The first part where we are checking if we are transitioning into the video slide would look something like this:

$(function() {
$('.carousel').on('slide.bs.carousel',function(e){
var prev = $(this).find('.active').index();
var next = $(e.relatedTarget).index();
var video = $('#video-player')[0];
var videoSlide = $('#video-player').closest('.carousel-item').index();
if (next === videoSlide) {
createVideo(video);
}
});
});

Note that we are using jQuery here for demonstration purposes since Bootstrap 4.0 Components still require it, but if you are adamant about using vanilla JavaScript and gaining a performance advantage, check out Bootstrap Native and see their vanilla example of the Carousel Component.

Also, we went ahead and declared a videoSlide variable that checks which slide #video-player is in. This way, it can be dynamic for when the slide order or number of slides change.

The next part would be to add the functionality to create the video createVideo() {}, which will contain Step 2 and Step 3 from the Getting Started sample in the YouTube Player API docs.

We have to modify these two steps a little. First, we should wrap the code that loads the IFrame Player API code asynchronously in a condition if (youtubeScript === null) {} that checks whether or not it already exists on the page.

After this, we will add the function that creates the iframe and YouTube player, though instead of a function declaration like in the sample, we want to turn it into an expression like window.onYouTubeIframeAPIReady = function() {}, which appends it to the window object, ensuring it is evoked globally. This is important when you are trying to put onYouTubeIframeAPIReady inside another function such as the case here where it’s inside createVideo() {}, otherwise it will not get triggered properly.

The createVideo() function should look something like this:

function createVideo(video) {
var youtubeScriptId = 'youtube-api';
var youtubeScript = document.getElementById(youtubeScriptId);
var videoId = video.getAttribute('data-video-id');

if (youtubeScript === null) {
var tag = document.createElement('script');
var firstScript = document.getElementsByTagName('script')[0];

tag.src = 'https://www.youtube.com/iframe_api';
tag.id = youtubeScriptId;
firstScript.parentNode.insertBefore(tag, firstScript);
}

window.onYouTubeIframeAPIReady = function() {
window.player = new window.YT.Player(video, {
videoId: videoId,
playerVars: {
autoplay: 1,
modestbranding: 1,
rel: 0
}
});
}
}

Note that we are using ES5 here just to keep consistent with the previous jQuery syntax that is recommended by Bootstrap. You can check out how it works so far here.

Exploring the YouTube API Functions for Playback Control

As you can see, we are far from finished. The video will continue to play even after you move to a new slide and the video is no longer in view, which would annoy users. We need to add conditions that check when we leave the video slide. The Player API has useful functions for playback controls and player settings, and we can use player.pauseVideo() to pause the currently playing video when we need to. If the user goes back to the video slide again, we can also use player.playVideo().

To check whether or not we need to pause the video, we can add an else after the if (next === videoSlide) {} statement that checks whether or not we have arrived in the video slide, and then check whether or not the player has already been loaded: if (typeof player !== 'undefined') {}. If so, we should pause the video.

We should also distinguish between whether or not we should create a video or play a video when the user transitions back to the video slide after the iframe has already been loaded. For that, we can do something like this:

if (video.tagName == 'IFRAME') {
player.playVideo();
} else {
createVideo(video);
}

Altogether, the new function should look something like this:

$(function() {
$('.carousel').on('slide.bs.carousel',function(e) {
var prev = $(this).find('.active').index();
var next = $(e.relatedTarget).index();
var video = $('#video-player')[0];
var videoSlide = $('#video-player').closest('.carousel-item').index();
if (next === videoSlide) {
if (video.tagName == 'IFRAME') {
player.playVideo();
} else {
createVideo(video);
}
} else {
if (typeof player !== 'undefined') {
player.pauseVideo();
}
}
});
});

If you check out the example below, you can see that we have a better user experience where the video no longer keeps playing even after we've left the video slide (as was the situation before).

Final Thoughts

We like the YouTube IFrame Player API for simplifying the process of embedding videos in web applications. There are various types of events that the API can send and the documentation is organized well enough to show how to write event listeners and respond to events. I’ve found that it’s easy to control the video player using different JavaScript functions and that customizing it to your needs is painless.

If you’re interested in learning more about the process of building a component library, check out a great post from another member of our team.