Speeding Up Invisible Video Players

When watching videos online, I always make sure to change the video speed to 2x if the player exposes such a control. It’s become a habit, since I can still (usually) understand everything within a video at 2x the speed, saving time.

Some players don’t expose video speed control, for whatever reason. That’s okay, because most websites nowadays use HTML5 for video playback, and the playback rate can be adjusted manually using DevTools.

However, while watching a news segment on Naver today, I went into DevTools to adjust the video playback rate and noticed that DevTools couldn’t find the video tag. Time to investigate!

How do you adjust playback speed in DevTools?

With either:

document.querySelector('video').defaultPlaybackRate = 2.0;

or:

document.getElementsByTagName('video')[0].playbackRate = 2;

(Notice the second way of speeding up the video has an extra [0] as a parameter. This is because getElementsByTagName() returns an array of elements (even if there is one element in the array) so we need to access the element in the array using [0] (get the first item in the array).)

This works 95% of the time, in my experience. But on Naver’s website, the two commands only return errors about undefined elements. So what’s going on with Naver’s site?

Testing, testing

Here’s a sample news segment that you can use to follow along. I’ll use this article in this post to show you what happened. You can try the two commands above right now if you want - they’ll spit out errors about undefined elements and won’t work.

You can see that the video playback starts when we hit the play button. So let’s jump into DevTools and look for the video tag.

no-video-tag

Well, that’s odd! Using the picker tool to find the video doesn’t work either, because it focuses on the <div> that covers the video player. Grr!

overlay-div

Time to find it manually, then. I combed through the HTML file until I found the tag, buried within a thousand <div> tags:

video-tag-found

Hmm, the video tag exists, but the find tool can’t find it. Why?

Let’s save the entire page as an HTML file, and then use a text editor and see if we can find the tag:

text-editor-fail

(Ignore the broken Korean text - this is probably because the file opened up the UTF-8 encoding instead of the proper EUC-KR encoding. As is shown above, the HTML tags survived.)

Still no! So we know now that this video player is loaded dynamically using JavaScript. My leading theory is that the browser can’t find the video element because it’s added to the DOM after the page completely loads.

But wait! Shouldn’t you be able to access the item within the console since the console executes after the page has fully loaded?

Safari time

I use Firefox as my default browser. What if this is a bug with Firefox?

Let’s test with Safari. Loading up the page and using Ctrl-F within DevTools:

safari-finds

Wow, Safari actually found the element! Let’s see now if the command will work:

safari-commands

The first command executed without any undefined errors, but didn’t have any effect on the video player (it still played at normal speed). The second command worked, however, and the video began to play back at 2x speed!

So did we uncover a bug with Firefox?

Context, people, context

Let’s go back to the Firefox console. What did we miss? Well, we missed the context in which the JavaScript debugging console ran in.

firefox-context-button

Because the website had multiple frames, Firefox decided to choose the first frame to execute JavaScript commands within. However, our video element was within another context/frame, so it wasn’t being picked up by the JavaScript console.

firefox-second-context

After choosing the correct context, the command listed above correctly picked up the video element and let me speed it up. Yay!

What did we learn today?

We learned that JavaScript in DevTools can run under different contexts, and that sometimes elements are cordoned off to specific contexts.

One area where Firefox can improve is to check other contexts if the getElement*() function fails to find elements within the current context, and ask the developer if they want to switch to a different context. Also, the button should be changed to a dropdown that clearly shows what context we are currently in.

Also, Firefox seems to have a bug where it can’t find HTML elements added to the page by scripts after the page finishes loading. Seeing as the element is correctly detected on Safari DevTools, this seems like a Firefox bug.

(P.S. Naver should really, really add speed controls to their video players.)

comments