Reputation: 549
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.
Upvotes: 8
Views: 6140
Reputation: 11
I'm too late, but I think it can still help someone. If you wish to control HTML5 video player using jQuery within content_scripts
, then you can get the video element using $("video")[0]
and then use that to trigger a valid event, e.g.
$("video")[0].pause()
$("video")[0].play()
..
Upvotes: 0
Reputation: 1827
It's too late but I recently created a chrome extension for same: https://chrome.google.com/webstore/detail/youtube-playback-control/okbcoijdeebocmahlanbfemnckjonfnh
Hope it helps.
Upvotes: 0
Reputation: 35
I'm late to the party, but you can use the API's Youtube provides. Take a look here: https://github.com/kurtextrem/StopAutoplay/blob/master/src/main.js
However, there is another way: The element '#movie_player' provides all these functions as well. So getting movie_player by its ID and then executing "playVideoAt" works.
Upvotes: 0
Reputation: 9952
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.
Upvotes: 13