Почему объект youtube ytplayer не обновляется при переходе между видео на youtube? - PullRequest
0 голосов
/ 10 февраля 2019

Я работаю над расширением chrome, которое использует объект ytplayer со страницы youtube в моем файле contentscript.js.В прошлом объект ytplayer обновлялся каждый раз, когда вы переходите к новому видео на YouTube.На данный момент, я не вижу его обновления больше.

Как скопировать

  1. Перейти на страницу видео YouTube в Chrome (Например, https://www.youtube.com/watch?v=KUh2O8HylUM)
  2. Открыть консоль инструментов разработчика
  3. Введите в консоли «ytplayer.config.args»
  4. Захват объекта ytplayer.config.args
  5. Перейдите к другому видео на YouTube, щелкнув другое видео из рекомендованного списка.
  6. Введите снова ytplayer.config.args
  7. Сравните с предыдущими захваченными ранее ytplayer.config.args

Вы увидите, что ytplayer не обновляется после навигациико второму видео. Мое расширение использует этот объект. Проблема в том, что объект устарел после перехода к другому видео. Когда я перетаскиваю объект ytplayer после каждой навигации по видео, я представляю неверные данные, потому что ytplayer всегда из первого видео.

Вопросы.

  1. Есть ли способ получить обновленный ytplayer?

  2. Есть ли способ сделатьytplayer перезагрузить? (я могу добавить location.reload () к моему js-коду, который решает проблему, но она хакерская и неудачная)

  3. Есть ли другой способ получить данные ytplayer.conf.args со страницы видео YouTube вхром?

1 Ответ

0 голосов
/ 10 февраля 2019

Youtube - это современный сайт, который обновляет страницу только частично, используя данные с сервера.Это означает, что есть только одна полная загрузка страницы, во время которой ytplayer состоит из встроенного тега <script>.Это также означает, что ваш скрипт контента запускается только один раз.

Предлагаемое решение - перехватить сетевое взаимодействие сайта, переопределив метод XHR open в контексте страницы , чтобы получить новый ytplayer.object.

manifest.json:

"content_scripts": [{
  "run_at": "document_start",
  "matches": ["https://www.youtube.com/*"],
  "js": ["content.js"]
}]

content.js:

const token = chrome.runtime.id + ':' + performance.now() + ':' + Math.random();

window.addEventListener(token, e => {
  console.log('gotPlayerArgs', e.detail);
  chrome.runtime.sendMessage({
    action: 'gotPlayerArgs',
    data: e.detail,
  });
});

const script = document.createElement('script');
script.textContent = '(' + (token => {
  const origOpen = XMLHttpRequest.prototype.open;
  const dispatch = data => window.dispatchEvent(new CustomEvent(token, {detail: data}));
  const onLoad = e => {
    const json = e.target.response;
    const player = (Array.isArray(json) && json.find(_ => _.player) || {}).player || {};
    dispatch(player.args);
  };
  // get the initial config
  try {
    dispatch(window.ytplayer.config.args);
  } catch (e) {}
  // intercept the subsequent config queries
  XMLHttpRequest.prototype.open = function (method, url) {
    if (url.startsWith('https://www.youtube.com/watch?')) {
      this.addEventListener('load', onLoad);
    }
    return origOpen.apply(this, arguments);
  };
}) + `)("${token}")`;
document.documentElement.appendChild(script);
script.remove();

Остается одно предупреждение: если (1) ваше расширение было обновлено / перезагружено илиотключено / повторно включено, и (2) страница YouTube не является первой навигацией, первоначальный объект конфигурации будет неправильным.Чтобы это исправить, вы можете сравнить идентификатор видео (извлечь его из URL) с идентификатором внутри конфигурации (например, свойством «loaderUrl»), и, если он не совпадает, просто получить аргументы через конечную точку get_video_info, котораялегко анализировать (разделить на &, затем на =, затем использовать decodeURIComponent): 'https://www.youtube.com/get_video_info?video_id=' + id + '&hl=en_US&html5=1&el=embedded'

...