We recently completed a web project for a client where videos were an integral part of the site. When the client came to us, they had already vetted their design ideas and had an outside firm create a final site design. Nearly every page of the site was to have a video on it that would help inform and guide the user. After reviewing the designs with the client, we decided to create an HTML5 site as a single-page implementation where we would swap content in and out. Having settled on HTML5, we thought the videos would be easy to implement since we could leverage the new HTML5 video tag. Never having done any HTML5 video work before, we were surprised when things didn’t work out of the box as expected.
Browsers Don’t Manage Multiple Videos Well
Removing Video.js didn’t seem to improve the situation much, if at all. Frustrated and annoyed, we decided to reduce the number of videos in the Document Object Model (DOM) in hopes that it was a video management issue. After all, we had eight video elements in the DOM which can be a lot to keep in memory. We tested the site with just three video elements in the DOM, but some browsers still failed to load and play videos. Our next step went to an extreme: have only one video element in the DOM at a time. The idea was to have the video be in the DOM only if it was being shown to the user, otherwise it was removed and destroyed. By doing this, we finally achieved the consistency we were expecting. The videos loaded and started playing every time in all browsers. We were surprised by this as we expected browsers to be able to manage multiple video elements in the DOM.
NOTE: We later found another plugin called flowplayer that does something similar to our final solution. It removes the video element from the page and adds it only when it needs to play. It also appears to allow only one video element in the DOM at a time. Even though we haven’t used this player in a project yet, we thought it’d be worth pointing out for future projects.
.load() ‘em up!
Once we reduced the DOM to containing only one video element at a time, we needed to ensure the videos were loading and playing when the user needed them to. We started by invoking the “.play()” function on the video, but noticed that Safari on the Mac wouldn’t load the video at all. We solved this problem by invoking the “.load()” function before invoking the “.play()” function. This seemed to work for the other browsers as well, with one minor lesson learned: don’t call it more than once.
In adding the manual “.load()” call, we accidently invoked that function twice on the video element which broke video caching in Chrome. It appeared to work on first load of the page, but subsequent refreshes did not work unless it was a hard refresh. Even though this was a mistake on our part, we were surprised that Chrome couldn’t handle it better.
After we reduced the number of videos in the DOM to just one, we wrote a helper function that managed the video. The function used jQuery to create the new video element and appended it a container already on the DOM. In a few cases, however, we heard double voices in the video as though an echo effect had been placed on the audio. After searching the web, we weren’t able to pinpoint the exact issue, but found suggestions that it could be the “.appendTo()” function duplicating the element. We got around this minor hiccup by injecting the video as HTML into the container, bypassing any jQuery representation of it.
One other caveat we learned along the way is that Safari only supports HTML5 video if QuickTime is installed. If QuickTime isn’t installed, Safari pretends it knows nothing about video. Any function that is supposed to be supported by HTML5 video, including “.load()”, “.play()”, and “.canPlayType()”, aren’t defined at all. Safari errors if you try to call them and doesn’t give an explanation of why.
This project taught us quite a bit about embedding videos in websites, and I feel we are now better equipped to deal with them in the future. For anyone taking on a similar project, I would definitely recommend using only one video element on the page at a time (at least until all major browsers can handle more than one in the DOM). Perhaps something like flowplayer would help accomplish that fairly quickly in the meantime. Also, be more mindful of how many “.play()” and “.load()” calls are being made so as not to confuse the browser. Lastly, be sure to test video playback in all browsers and on all mobile devices to make sure the site is as robust as possible.
With web technology evolving every day, it can be tricky to make a website usable on every platform, but based on what we learned during this project we now feel more confident in our ability to take on a project like this again. And hopefully we’ve provided information that will help others get over some of the bumps in the road we encountered.