Открываем YouTube ролики в медиаплеере прямо из браузера

от
Linux    url protocol, browser, desktop, youtube, video

Задача следующая. Есть удобный видеоплеер, который нам очень нравится: mpv, vlc, ffplay или любой другой. При открытии YouTube ролика хотелось бы иметь возможность воспроизвести видео в любимом плеере. Копировать ссылку, запускать плеер и открывать эту ссылку в нём не хочется, долго. Хочется нажать кнопку в браузере и чтобы сразу открывался плеер с нужной ссылкой.

2018-08-04_11-33-23.png

1. Регистрируем свой URL Protocol
Мы можем зарегистрировать свой url-протокол, например, mpv://, vlc://, ffplay:// или coolvideo://, формировать ссылку вида mpv://https://youtube.com/videoid и обрабатывать такие ссылки в своём скрипте.

Создаём ярлык для рабочего стола с обязательным указанием MimeType=x-scheme-handler, именно эта директива регистрирует URL протокол:
  1. echo "[Desktop Entry]
  2. Version=1.0
  3. Name=MPV protocol
  4. Comment=Open mpv:// links with MPV.
  5. Exec=protocol-mpv %u
  6. TryExec=protocol-mpv
  7. Terminal=false
  8. Type=Application
  9. NoDisplay=true
  10. Categories=AudioVideo;
  11. MimeType=x-scheme-handler/mpv;" > protocol-mpv.desktop

В качестве обработчика будет выступать скрипт protocol-mpv:
  1. echo '#!/bin/bash
  2. # gnome-mpv "${1:6}"' > protocol-mpv
  3. mpv --player-operation-mode=pseudo-gui -- "${1:6}"' > protocol-mpv
Скрипту будет приходить ссылка вида mpv://https://youtube.com/videoid, а чтобы получить действительную ссылку на YouTube ролик, первые 6 символов нужно обрезать.

Добавляем скрипту права на исполнение и помещаем в /usr/local/bin/ или любую другую удобную директорию, содержащуюся в $PATH. Ярлык регистрируем в системе.
  1. chmod +x protocol-mpv
  2. sudo mv protocol-mpv /usr/local/bin/
  3. xdg-desktop-menu install protocol-mpv.desktop

Проверяем:
  1. xdg-open "mpv://https://www.youtube.com/watch?v=dQw4w9WgXcQ"
Если плеер не поддерживает открытие ссылок YouTube, придётся дополнить скрипт получением прямой ссылки при помощи youtube-dl.
Всё вместе

Способы регистрации URL-протокола на других операционных системах можно посмотреть в репозитории: https://github.com/stefansundin/vlc-protocol

2. Добавляем кнопку с url на страницу в YouTube
Теперь, когда ссылки правильно обрабатываются, можно встраивать их в страницу. Вот скрипт для Greasemonkey:
  1. // ==UserScript==
  2. // @name         YouTube open in MPV
  3. // @version      1.0
  4. // @description  Adds an Open in MPV button to YouTube
  5. // @include      http*://*.youtube.com/*
  6. // @include      http*://youtube.com/*
  7. // @include      http*://*.youtu.be/*
  8. // @include      http*://youtu.be/*
  9. // @run-at       document-end
  10. // ==/UserScript==
  11.  
  12. function polymerInject() {
  13.   /* Create button */
  14.   var btnDiv = document.createElement("div");
  15.   btnDiv.style.width = "100%";
  16.   btnDiv.id = "parentButton";
  17.   var btn = document.createElement("a");
  18.   btn.style.display = "block";
  19.   btn.style.width = "100%";
  20.   btn.style.backgroundColor = "#181717";
  21.   btn.style.color = "white";
  22.   btn.style.textAlign = "center";
  23.   btn.style.padding = "10px 0";
  24.   btn.style.marginTop = "5px";
  25.   btn.style.fontSize = "14px";
  26.   btn.style.border = "0";
  27.   btn.style.cursor = "pointer";
  28.   btn.style.textDecoration = "none";
  29.   btn.style.borderRadius = "2px";
  30.   btn.style.fontFamily = "Roboto, Arial, sans-serif";
  31.   btn.href = "mpv://" + window.location.href;
  32.   btn.appendChild(document.createTextNode("Open in MPV"));
  33.   btnDiv.appendChild(btn);
  34.  
  35.   /* Find and add to target */
  36.   var te = document.querySelectorAll("[id='subscribe-button']");
  37.   for (var i = 0; i < te.length; i++) {
  38.     if (te[i].className.indexOf("ytd-video-secondary-info-renderer") > -1) {
  39.       te[i].appendChild(btnDiv);
  40.     }
  41.   }
  42.  
  43.   /* Fix hidden description bug */
  44.   var dscBox = document.querySelectorAll("ytd-video-secondary-info-renderer");
  45.   if (dscBox[0].className.indexOf("loading") > -1){
  46.     dscBox[0].classList.remove("loading");
  47.   }
  48. }
  49.  
  50. if (document.getElementById("polymer-app") || document.getElementById("masthead") || window.Polymer) {
  51.   setInterval(function() {
  52.     if (window.location.href.indexOf("watch?v=") < 0) {
  53.       return false;
  54.     }
  55.     if (document.getElementById("count") && document.getElementById("parentButton") === null) {
  56.       polymerInject();
  57.     }
  58.   }, 100);
  59. }
2018-08-04_11-33-23.png
2018-08-04 12-21-45.png
  • +8
  • views 7763