I am trying to build a Chrome Extension that can interact with videos in YouTube.
I can get the player element and use the Youtube's IFrame API functions on them in my browser console without no issue, like:
var player = document.getElementById('movie_player');
player.playVideo()
player.pauseVideo()
player.seekTo(30)
player.getStatsForNerds(0)
But I want to do these kinds of operation through a Chrome Extension. The issue is when I try to use the player
element to use these functions in an extension it returns errors like this:
Uncaught TypeError: player.playVideo is not a function
I thought I may need to load the IFrame API, but when I try to load it it returns:
Refused to load the script 'https://www.youtube.com/iframe_api' because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
My project directory:
├── manifest.json
├── content-scripts.js
└── background.js
manifest.json
:
{
"name": "My Project",
"description": "Some Description",
"version": "1.0",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["https://www.youtube.com/*"],
"exclude_matches": ["https://studio.youtube.com/*"],
"js": ["content-scripts.js"]
}
],
"web_accessible_resources": [
{
"resources": ["content-scripts.js"],
"matches": ["https://www.youtube.com/*"]
}
],
"permissions": [
"activeTab",
"tabs",
"contextMenus",
"storage",
"scripting"
],
"host_permissions": ["https://www.youtube.com/*"]
}
content-scripts.js
:
function inject_yt() {
player = document.getElementById('movie_player');
var speeds = new Array();
var resolutions = new Array();
var times = new Array();
var buffer = new Array();
stats_collect = setInterval(stats, 1000);
}
function stats() {
try {
bandwidth = player.getStatsForNerds(0).bandwidth_kbps;
res = player.getStatsForNerds(0).resolution;
buffers = player.getStatsForNerds(0).buffer_health_seconds;
speeds.push(bandwidth);
resolutions.push(res);
buffer.push(buffers);
currentTime = player.getCurrentTime();
times.push(currentTime);
}
catch(err) {
console.error(err);
}
}
var tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubeIframeAPIReady() {
console.log('--- the YT player API is ready from content script! ---');
};
inject_yt()
And background.js
is just an empty file.
How can I make this work?