youtube video in chrome extension content script

2019-09-15 01:25发布

问题:

I am trying to insert youtube videos with the iframe API in to an existing page with the help of a chrome extension content script. But I cannot get the onYouTubeIframeAPIReady to trigger.

manifest.json

"content_scripts": [
        {
            "matches": ["http://*/*", "https://*/*", "file://*/*", "*://*/*"],
            "js": ["content-script.js"]
        }
    ],

content-script.js

const appEl = document.createElement('div');
appEl.id = 'my-app';
appEl.innerHTML = `<div id="youtube-iframe"></div>`;
const bodyEl = document.querySelector('body');
bodyEl.insertBefore(appEl, bodyEl.firstChild);

var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
document.querySelector('body').appendChild(tag);
window.onYouTubeIframeAPIReady = () => {
    this.player = new YT.Player('youtube-iframe', {
        height: '390',
        width: '640',
        videoId: 'M7lc1UVf-VE',
        events: {
            'onReady': onPlayerReady,
        }
    });
}

function onPlayerReady(event) {
    console.log('player ready');
    event.target.playVideo();
};

In a chrome-app I was able to make it work with a webview but this does not seem to be available in extensions.

回答1:

I solved the problem, here is the solution.

I tried all variants of the code injection method but the problem was the the YouTube API script was defining an anonymous function that expected the window as an input argument. So even after following the advice of not loading external scripts (chrome web store might remove your extension) and having a local file that I included with different means I was not able to get the onYouTubeIframeAPIReady to be triggered by the YouTube API script. Only after pasting the script into the same file where I defined onYouTubeIframeAPIReady I was able to see the video. However to organize the code better, so it works with ES6 imports (via Webpack) I did the following steps.

Download the YouTube API script (https://www.youtube.com/iframe_api see https://developers.google.com/youtube/iframe_api_reference) to a local file.

Adopt the script to work as module by changing the the script from

(function(){var g,k=this;function l(a){a=a.split(".");
...
Ub=l("onYouTubePlayerAPIReady");Ub&&Ub();})();

to

export default function(){var g,k=window;function l(a){a=a.split(".")
...
Ub=l("onYouTubePlayerAPIReady");Ub&&Ub();}

This changes the anonymous function call to a function that is exported in a ES6 module style and the this object in the anonymous function is exchanged with the window. I saved it in the file as youtube-iframe-api.js

Now I was able to use the YouTube API in another module with the following code

import youtubeApi from './youtube-iframe-api';

function onPlayerReady(event) {
  event.target.playVideo();
},

window.onYouTubeIframeAPIReady = () => {
  this.player = new YT.Player('youtube-iframe', {
    height: '100',
    width: '100',
    videoId: 'M7lc1UVf-VE',
    events: {
      'onReady': onPlayerReady,
    }
  });
}
youtubeApi();