I am developing a Google Chrome extension that needs to take over all the controls of a YouTube video (play, pause, next, previous, change the volume, start video at X seconds, etc). I tried the following approaches:
My manifest.json
contains the following:
"content_scripts": [
{
"matches": ["https://www.youtube.com/*"],
"js": ["scripts/jquery.js", "scripts/in_page.js"]
}
],
I'm loading the scripts for every YouTube link, and not only /watch*
because now YouTube navigation is fully using AJAX, therefore the page is not entirely refreshed, and if I was on a search page and then clicked on a video, the extension wouldn't have loaded my content_scripts
.
I successfully managed to trigger simple click events on the YouTube player, such as Play, Pause, Previous video, Next video.
For instance, this works to pause the video:
$("#player-api .html5-video-controls .ytp-button-pause").trigger("click");
But it seems that I can't trigger events such as clicking on the progress bar to play from a specific moment of the video or restart the video.
I tried this piece of code without success (using jQuery's $.Event
):
var click = $.Event("click");
click.clientX = 0; // Beginning of the video
click.clientY = 0; // I also tried several other coordinates
$("#player-api .html5-video-controls .html5-progress-bar").trigger(click);
(And I also tried clicking on every child of the .html5-progress-bar
, but nothing worked.)
As I seemed to have encountered a dead-end with my first approach, I then tried something else: injecting a script directly inside the page.
My manifest.json
contains the following:
"content_scripts": [
{
"matches": ["https://www.youtube.com/*"],
"js": ["scripts/jquery.js", "scripts/isolated.js"]
}
],
"web_accessible_resources": [
"scripts/injected.js"
],
isolated.js
var s = document.createElement("script");
s.src = chrome.extension.getURL("scripts/injected.js");
s.onload = function() {
this.parentNode.removeChild(this);
};
(document.head || document.documentElement).appendChild(s);
injected.js
Well, this is where I encountered my second dead-end. I may have overlooked some things, but I searched in every object inside the page, I found yt
, ytplayer
, player
, and others. But none of them seem to have proper functions to trigger changes on the player such as play/pause/next, etc.
I then downloaded the html5player.js
from YouTube (available here) and beautified it to take a peek at what was under the hood. I found some interesting function names such as playVideoAt
, playVideo
, pauseVideo
around the lines 20235-20315 (once beautified).
That would be exactly the functions I would want to call/invoke, but I don't know where they are, and how to call them.
I also know that YouTube has a JavaScript API to control the player, but it's only for embedded players (iframes), so it's not useful in my case.
Go to a video. Hover over the player and click Settings . Click Speed. Select the speed at which you'd like the video to play.
As you're watching a video, tap the three-dot hamburger menu in the top-right corner. This will bring up the video settings, much like the gear icon does on desktop. Select Playback speed. You'll see the familiar preset speeds ascending by 0.25 increments from 0.25 to 2.0.
It sounds like you're using YouTube's HTML5 video player. In that case you can just interface with the <video>
DOM element. It happens to be the only <video>
element on the page, so just do:
$('video').play()
$('video').pause()
$('video').currentTime = 100
The interface is here.
As for previous and next videos, you're almost certainly right that the easiest thing to do is:
$('.ytp-button-next').click()
$('.ytp-button-prev').click()
Since that obviously isn't a published API you have no guarantee those class names will stay the same in future.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With