A2P

Anime2Potplayer,用Potplayer打开浏览器播放的动漫,这样就可以使用SVP4补帧啦!

当前为 2025-05-01 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name A2P
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0.2
  5. // @description Anime2Potplayer,用Potplayer打开浏览器播放的动漫,这样就可以使用SVP4补帧啦!
  6. // @author MakotoArai(https://github.com/MakotoArai-CN)
  7. // @supportURL https://blog.ciy.cool
  8. // @license GPL-v3
  9. // @icon https://cravatar.cn/avatar/1e84fce3269537e4aa7473602516bf6d?s=256
  10. // @match *anich.emmmm.eu.org/*
  11. // @match *.mutedm.com/*
  12. // @match *.iyinghua.com/*
  13. // @match *.5dm.link/*
  14. // @grant GM_setValue
  15. // @grant GM_getValue
  16. // ==/UserScript==
  17.  
  18. 'use strict';
  19.  
  20. window.onload = function () {
  21. console.info("%cA2P%c%s", "color:red;font-size:40px;font-weight:bold;", "color:black;font-size:16px;font-weight:normal", GM_info.script.version);
  22.  
  23. // 定时器用于动态嗅探视频链接
  24. const videoTimer = setInterval(findVideoUrl, 1000);
  25. function findVideoUrl() {
  26. const videoElement = document.querySelector("video");
  27. if (videoElement && videoElement.src) {
  28. clearInterval(videoTimer);
  29. preparePotplayerInteraction(videoElement, GM_getValue("check") ?? false);
  30. }
  31. }
  32.  
  33. function preparePotplayerInteraction(videoElement, check = true) {
  34. const videoUrl = videoElement.src;
  35. console.log(`检测到视频链接: ${videoUrl}`);
  36.  
  37. creatBtn(videoElement);
  38. if (check) {
  39. window.location.href = `potplayer://${videoUrl}`;
  40. // 检测是否播放,如果正在播放则暂停网页的播放
  41. var pause_Flag = 0;
  42. const checkTimer = setInterval(() => {
  43. if (!videoElement.paused) {
  44. videoElement.pause();
  45. clearInterval(checkTimer);
  46. }
  47. pause_Flag++;
  48. if (pause_Flag > 30) clearInterval(checkTimer);
  49. }, 1000);
  50. };
  51.  
  52. }
  53.  
  54. function creatBtn(videoElement) {
  55. // 插入自定义CDN
  56. document.head.insertAdjacentHTML("beforeend", `
  57. <link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
  58. `);
  59. // 右键菜单
  60. var menu = document.createElement("div");
  61. // 插入自定义css
  62. document.head.insertAdjacentHTML("beforeend", `
  63. <style>
  64. a {text-decoration: none;}
  65. div.usercm{background-repeat:no-repeat;background-position:center center;background-size:cover;background-color:#fff;font-size:13px!important;width:160px;-moz-box-shadow:1px 1px 3px rgba
  66. (0,0,0,.3);box-shadow:0px 0px 15px #333;position:absolute;display:none;z-index:10000;opacity:0.9; border-radius: 8px;}
  67. div.usercm ul{list-style-type:none;list-style-position:outside;margin:0px;padding:0px;display:block}
  68. div.usercm ul li{margin:0px;padding:0px;line-height:35px;}
  69. div.usercm ul li a{color:#666;padding:0 15px;display:block}
  70. /* div.usercm ul li a:hover{color:#fff;background:rgba(170,222,18,0.88)} */
  71. div.usercm ul li a:hover{color:#fff;background:rgba(15, 120, 233, 0.88)} /* 蓝色 */
  72. div.usercm ul li a i{margin-right:10px}
  73. a.disabled{color:#c8c8c8!important;cursor:not-allowed}
  74. a.disabled:hover{background-color:rgba(255,11,11,0)!important}
  75. div.usercm{background:#fff !important;}
  76. </style>
  77. )`);
  78.  
  79. /* 右键菜单 */
  80. menu.innerHTML = `
  81. <div class="usercm" style="left: 199px; top: 5px; display: none;">
  82. <ul>
  83. <li><a href="/"><i class="fa fa-home fa-fw"></i><span>首页</span></a></li>
  84. <li><a href="javascript:void(0);" onclick="'' == (window.getSelection ? window.getSelection() : document.selection.createRange().text) ? console.log() : document.execCommand('Copy')"><i class="fa fa-copy fa-fw"></i><span>复制</span></a></li>
  85. <li><a href="javascript:history.go(1);"><i class="fa fa-arrow-right fa-fw"></i><span>前进</span></a></li>
  86. <li><a href="javascript:history.go(-1);"><i class="fa fa-arrow-left fa-fw"></i><span>后退</span></a></li>
  87. <li style="border-bottom:1px solid gray"><a href="javascript:window.location.reload();"><i class="fa fa-refresh fa-fw"></i><span>重载网页</span></a></li>
  88. <li><a href="javascript:void(0);" class="potplayer"><i class="fa fa-arrow-right fa-fw"></i><span>Potplayer</span></a></li>
  89. <li><a href="javascript:void(0);" class="aa2p"><i class="fa fa-arrow-right fa-fw"></i><span>自动跳转</span></a></li>
  90. <li><a href="https://blog.ciy.cool"><i class="fa fa-pencil-square-o fa-fw"></i><span>关于我</span></a></li>
  91. </ul>
  92. </div>
  93. `;
  94. document.body.appendChild(menu);
  95. // 自定义鼠标右键
  96. // 自定义鼠标右键菜单行为
  97. (function () {
  98. let mouseX = 0;
  99. let mouseY = 0;
  100. let windowWidth = 0;
  101. let windowHeight = 0;
  102.  
  103. // 获取元素
  104. const menu = document.querySelector('.usercm');
  105.  
  106. // 鼠标移动事件
  107. window.addEventListener('mousemove', function (e) {
  108. windowWidth = window.innerWidth;
  109. windowHeight = window.innerHeight;
  110. mouseX = e.clientX;
  111. mouseY = e.clientY;
  112.  
  113. // 设置菜单位置
  114. let left = e.pageX;
  115. let top = e.pageY;
  116.  
  117. if (mouseX + menu.offsetWidth >= windowWidth) {
  118. left = left - menu.offsetWidth - 5;
  119. }
  120. if (mouseY + menu.offsetHeight >= windowHeight) {
  121. top = top - menu.offsetHeight - 5;
  122. }
  123.  
  124. // 绑定右键点击事件
  125. document.documentElement.addEventListener('contextmenu', function (event) {
  126. if (event.button === 2) { // 右键点击
  127. event.preventDefault();
  128. menu.style.left = `${left}px`;
  129. menu.style.top = `${top}px`;
  130. menu.style.display = 'block';
  131. }
  132. });
  133.  
  134. // 点击隐藏菜单
  135. document.documentElement.addEventListener('click', function () {
  136. menu.style.display = 'none';
  137. });
  138. });
  139.  
  140. // 禁用默认右键菜单
  141. window.oncontextmenu = function (e) {
  142. e.preventDefault();
  143. return false;
  144. };
  145.  
  146. // 判断是否是移动端
  147. const userAgent = navigator.userAgent;
  148. const mobileKeywords = ['Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod'];
  149. let isMobile = false;
  150.  
  151. for (let keyword of mobileKeywords) {
  152. if (userAgent.indexOf(keyword) > -1) {
  153. isMobile = true;
  154. break;
  155. }
  156. }
  157.  
  158. // 非移动端才启用自定义右键菜单
  159. if (!isMobile) {
  160. // 上面已经实现了 mouseMoveShow 和 disabledContextMenu
  161. // console.log('已启用自定义右键菜单');
  162. }
  163. })();
  164. const potplayer = document.querySelector(".potplayer");
  165. const aa2p = document.querySelector(".aa2p");
  166. const videoUrl = videoElement.src;
  167. potplayer.addEventListener("click", function () {
  168. window.location.href = `potplayer://${videoUrl}`;
  169. // 暂停播放
  170. videoElement.pause();
  171. })
  172.  
  173. aa2p.innerHTML = `<i class="fa fa-arrow-right fa-fw"></i><span>${GM_getValue("check") ? "关闭自动跳转" : "开启自动跳转"}</span>`;
  174. aa2p.addEventListener("click", function () {
  175. const check = GM_getValue("check") ?? false;
  176. if (check) {
  177. GM_setValue("check", false);
  178. aa2p.innerHTML = `<i class="fa fa-arrow-right fa-fw"></i><span>开启自动跳转</span>`;
  179. } else {
  180. GM_setValue("check", true);
  181. aa2p.innerHTML = `<i class="fa fa-arrow-right fa-fw"></i><span>关闭自动跳转</span>`;
  182. }
  183. })
  184. }
  185. }