youtube继续播放

当出现"影片已暂停,要继续观赏吗?"时忽略它继续播放

当前为 2020-07-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name youtube continue play
  3. // @name:en youtube continue play
  4. // @name:zh-CN youtube继续播放
  5. // @name:zh-TW youtube繼續播放
  6. // @name:ja youtube再生自動継続
  7. // @description When "Video paused, do you want to continue watching?" Appears, ignore it and continue playing automatically
  8. // @description:en When "Video paused, do you want to continue watching?" Appears, ignore it and continue playing automatically
  9. // @description:zh-TW 當出現"影片已暫停,要繼續觀賞嗎?"時忽略它繼續播放
  10. // @description:zh-CN 当出现"影片已暂停,要继续观赏吗?"时忽略它继续播放
  11. // @description:ja 「動画が一時停止されました。続きを視聴しますか?」が表示されても無視して再生を続けます
  12. // @namespace https://greasyfork.org/zh-TW/users/461233-jack850628
  13. // @version 1.17
  14. // @author jack850628
  15. // @include /^https?:\/\/(:?.*?\.)*youtube.com\/.*$/
  16. // @noframes
  17. // @run-at document-end
  18. // @license MIT
  19. // ==/UserScript==
  20.  
  21. (function() {
  22. let pausedFun = function({target: videoPlayer}){
  23. console.debug('暫停播放');
  24. setTimeout(function(){
  25. let ytConfirmDialog = document.querySelector('yt-confirm-dialog-renderer');
  26. if(
  27. ytConfirmDialog &&
  28. (
  29. ytConfirmDialog.parentElement.style.display != 'none' ||
  30. (
  31. document.hidden &&
  32. videoPlayer.getCurrentTime() < videoPlayer.getDuration()//防止重複播放
  33. )//當網頁不可見時,DOM元件不會即時渲染,所以對話方塊的display還會是none
  34. )
  35. ){
  36. console.debug('被暫停了,但是我要繼續播放');
  37. //ytConfirmDialog.querySelector('yt-button-renderer[dialog-confirm]').click();//當網頁不可見時,觸發click是不會繼續播放的,因為要等到網頁可見時觸發UI渲染後才會把對話方塊關掉,對話方塊關掉後才會出發video的play事件
  38. videoPlayer.play();
  39. console.debug('按下"是"');
  40. }else console.debug('對話方塊找不到或是隱藏了', ytConfirmDialog && ytConfirmDialog.parentElement, document.hidden, videoPlayer.getCurrentTime(), videoPlayer.getDuration());
  41. }, 500);//確保在暫停時對話方塊一定找得到
  42. }
  43. function listenerVideoPlayer(){
  44. let videoPlayer = document.querySelector('video');
  45. if(!videoPlayer){
  46. console.debug('找不到播放器');
  47. return false;
  48. }
  49. videoPlayer.addEventListener('pause', pausedFun);
  50. console.debug('找到播放器,開始監聽');
  51. return true;
  52. }
  53. let scriptBlocks = document.getElementsByTagName('script')[0];
  54. let ycpScript = document.createElement('script');
  55. ycpScript.setAttribute('id','ycp-script');
  56. ycpScript.setAttribute('ycp-data','wait');
  57. ycpScript.innerHTML = `
  58. window.spf._request = window.spf.request;//youtube的ajax是使用spf,https://github.com/youtube/spfjs
  59. Object.defineProperty(window.spf, 'request', {//改寫request函數
  60. value: function(){
  61. if(arguments[1]){
  62. if(arguments[1].onDone){//當請求完成後嘗試監聽VideoPlayer
  63. let onDone = arguments[1].onDone;
  64. arguments[1].onDone = function(){
  65. let result = onDone.apply(this,arguments);
  66. document.querySelector('#ycp-script').setAttribute('ycp-data','ok');
  67. return result;
  68. }
  69. }else{
  70. arguments[1].onDone = () => document.querySelector('#ycp-script').setAttribute('ycp-data','ok');
  71. }
  72. }
  73. return window.spf._request.apply(this,arguments);
  74. },
  75. writable: true,
  76. configurable: true
  77. });
  78. document.querySelector('#ycp-script').setAttribute('ycp-data','ok');
  79. `;
  80. let ycpScriptObserver = new MutationObserver(([{target: ycpScript}], observer) => {
  81. console.debug('#ycp-script屬性更動', ycpScript, ycpScriptObserver);
  82. if(ycpScript.getAttribute('ycp-data') == 'ok'){
  83. if(!listenerVideoPlayer()) ycpScript.setAttribute('ycp-data','wait')
  84. else ycpScriptObserver.disconnect();
  85. }
  86. });
  87. if(scriptBlocks){
  88. ycpScriptObserver.observe(
  89. ycpScript,
  90. {
  91. attributes: true
  92. }
  93. );
  94. scriptBlocks.parentNode.insertBefore(ycpScript,scriptBlocks);
  95. }
  96. })();