YoutubeDefaultSpeed

Set a default playback rate for YouTube videos.

当前为 2015-11-12 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        YoutubeDefaultSpeed
// @namespace   youtubedefaultspeed
// @description Set a default playback rate for YouTube videos.
// @include     https://www.youtube.com/*
// @include     http://www.youtube.com/*
// @version     1
// @grant       none
// @require     https://greasyfork.org/scripts/10208-gm-api-script/code/GM%20API%20script.js?version=54964
// @run-at      document-end
// ==/UserScript==

// Needs to emulate Greasemonkey APIs since specifying a "grant" other than none will enable the sandbox,
// which blocks access to the movie_player YouTube object

(function() {
  var RATE_OPTIONS = ["0.25", "0.5", "1", "1.25", "1.5", "2"];
  
  function getMoviePlayer(callback) {
    if (typeof movie_player === "undefined" ||
        typeof movie_player.setPlaybackRate !== "function") {
      window.setTimeout(function() { getMoviePlayer(callback); }, 5000);
    }
    else {
      callback(movie_player);
    }
  }
  
  function setPlaybackRate() {
    var rate = GM_getValue("playbackRate", 1); // default to 1 if not set
    getMoviePlayer(function (player) { 
      console.log("playback rate: " + rate);
      player.setPlaybackRate(rate); 
    });
  }

  function onElementSourceUpdate(target, callback) {
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
    var observer = new MutationObserver(function (mutations) {
      mutations.forEach(function (mutation) {
        callback();
      });
    });
    observer.observe(target, {attributes: true, attributeFilter: ["src"]});
  }
  
  function getVideoElement(callback) {
    var videoElements = document.getElementsByTagName("video");
    if (videoElements.Length <= 0 || typeof videoElements[0] === "undefined") {
      window.setTimeout(function() { getVideoElement(callback); }, 500);
    }
    else {
      callback(videoElements[0]);
    }
  }
  
  function handleRateButtonClick(rate) {
    // save as new default
    GM_setValue("playbackRate", rate);
    
    // set playback rate
    setPlaybackRate();
  }
  
  function injectButtons() {
    var head = document.getElementById("yt-masthead-user");
    
    var form = document.createElement("form");
    
    RATE_OPTIONS.forEach(function (rate) {
      var input = document.createElement("input");
      input.type = "radio";
      input.name = "playbackRate";
      input.id = "playbackRate" + rate;
      input.onclick = function () { handleRateButtonClick(rate); };
      input.checked = (rate == GM_getValue("playbackRate", 1));
      var label = document.createElement("label");
      label.htmlFor = "playbackRate" + rate;
      label.innerHTML = rate;
      label.style = "margin-right: 5px";
      form.appendChild(input);
      form.appendChild(label);
    });
    
    head.appendChild(form);
  }
  
  function main() {
    if (window.self != window.top) return;
    
    // add buttons
    injectButtons();
    
    // immediately try to change playback rate
    setPlaybackRate();
    
    // apply playback rate again if video changes
    getVideoElement(function (video) {
      if (video.hasAttribute("src")) console.log("video source changed: " + video.src);
      onElementSourceUpdate(video, function () { 
        console.log("video source changed: " + video.src);
        setPlaybackRate(); 
      });
    });
  }

  try {
    main();
  }
  catch (e) {
    console.log(e);
  }

})();