Greasy Fork

来自缓存

Greasy Fork is available in English.

视频外挂悬浮可点复制翻译字幕,floating-plug-in-for-clickable-subtitle-copying

视频外挂悬浮可点复制翻译字幕,floating plug-in for clickable subtitle copying

当前为 2023-12-17 提交的版本,查看 最新版本

// ==UserScript==
// @name         视频外挂悬浮可点复制翻译字幕,floating-plug-in-for-clickable-subtitle-copying
// @description  视频外挂悬浮可点复制翻译字幕,floating plug-in for clickable subtitle copying
// @grant        GM_log
// @require      https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js
// @require      https://cdn.bootcss.com/vConsole/3.3.0/vconsole.min.js
// @include      *
// @match        *://*/*
// @namespace    http://tampermonkey.net/
// @version      2023.12.17.09.26.23
// @icon         https://www.google.com/s2/favicons?sz=64&domain=greasyfork.org
// @author       You
// ==/UserScript==

(()=>{ "use strict";
// import "./styles.css";
// GM_log("Hello world! GM_log")
// Your code here...
// 报错油猴脚本使用jquery报错eslint:no-undef-‘$‘ is not defined
// eslint-disable-next-line no-unused-vars
/* globals jQuery, $, waitForKeyElements */
// 彩色打印
  const clog = content=>{ console.log(`%c${content}`,"background-color: #811f21; color: white;line-height:1.5rem; padding:0 0.5rem;") };
  // 全屏封装
  function goFullScreen(element){ clog("全屏视频");
    // var element = document.getElementById("fullscreenElement");
    element.requestFullscreen ? element.requestFullscreen() : element.mozRequestFullScreen ? element.mozRequestFullScreen() : element.webkitRequestFullscreen ? element.webkitRequestFullscreen() : element.msRequestFullscreen && element.msRequestFullscreen() }function exitFullScreen(){ clog("退出全屏视频");document.exitFullscreen ? document.exitFullscreen() : document.mozCancelFullScreen ? document.mozCancelFullScreen() : document.webkitExitFullscreen ? document.webkitExitFullscreen() : document.msExitFullscreen && document.msExitFullscreen() }function checkFullScreen(element){
    // var element = document.getElementById("fullscreenElement");
    if(document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement){ if(element === document.fullscreenElement || element === document.mozFullScreenElement || element === document.webkitFullscreenElement || element === document.msFullscreenElement){ console.log("元素处于全屏状态");return true }console.log("元素不处于全屏状态");return false }console.log("不处于全屏状态");return false }function autoFullScreen(el){
    // var el = document,
    //   cfs = el.cancelFullScreen || el.webkitCancelFullScreen || el.mozCancelFullScreen || el.exitFullScreen,
    //   wscript;
    // if (typeof cfs != "undefined" && cfs) {
    //   cfs.call(el);
    //   return;
    // }
    if(checkFullScreen(el)){ exitFullScreen();return }goFullScreen(el);if(typeof window.ActiveXObject != "undefined"){
      // eslint-disable-next-line no-undef
      const wscript = new ActiveXObject("WScript.Shell");wscript != null && wscript.SendKeys("{F11}") } }
  // 等待网页完成加载
  window.addEventListener("load",function(){
    // 加载完成后执行的代码
    clog("视频外挂西悬浮可点复制翻译字幕-floating-plug-in-for-clickable-subtitle-copying");
    // 允许全屏
    $("iframe").each(function(){ $(this).attr("allowfullscreen","true") });
    // 移动端控制台
    // new VConsole();
    // 视频外层
    const videoElement = $("video");
    // 视频父元素
    // const videoParentElement = videoElement.wrapAll('<div class="videoWrapper" style="position: relative;"/>');
    const videoParentElement = videoElement.parent();videoParentElement.addClass("videoWrapper");videoParentElement.css({ position: "relative" });
    // 隐藏字幕轨道
    videoElement.append("<style>video::cue{opacity: 0 !important}</style>");videoElement.attr("controls","true");videoElement.attr("playsInline","true");
    // 全屏开关元素
    const clickable_subtitle_switch_button = $("<button class='switchButton'>全屏</button>");
    // 全屏开关事件
    clickable_subtitle_switch_button.on("click",function(event){ event.stopPropagation();clog("全屏开关点击");autoFullScreen(document.querySelector(".videoWrapper")) });
    // 公共样式
    const commontCss = { "z-index": "2147483647",color: "#fff",position: "absolute" };
    // 开关公共样式
    const buttonCommontCss = { margin: "1vw",display: "block",padding: "0.5vw","border-radius": ".5vw","background-color": "#1118","font-size": "1.5vw",cursor: "pointer","user-select": "text","line-height": "2.5rem !important",color: "#fffb" };
    // 全屏开关样式
    clickable_subtitle_switch_button.css({ ...buttonCommontCss });
    // 字幕显示开关元素
    const clickable_subtitle_show_switch_button = $("<button class='switchButton'>显隐</button>");let isShow_subtitle = true;
    // 字幕显示开关样式
    clickable_subtitle_show_switch_button.css({ ...buttonCommontCss });
    // 网页外挂字幕元素
    const clickable_subtitle_wapper = $("<div class='floating_plug_in_for_clickable_subtitle_copying'></div>");
    // 字幕显示开关事件
    clickable_subtitle_show_switch_button.on("click",function(event){ event.stopPropagation();clog("字幕显示开关点击");isShow_subtitle = !isShow_subtitle;clickable_subtitle_wapper.css({ display: isShow_subtitle ? "block" : "none" }) });
    // 网页外挂字幕事件
    clickable_subtitle_wapper.click(function(event){ clog("字幕外层点击");
      // console.log(' :', [videoElement]);
      // 阻止冒泡
      event.stopPropagation() });clickable_subtitle_wapper.on("mousedown",e=>{ e.stopPropagation();console.log(" :",[videoElement]);videoElement?.[0].pause() });clickable_subtitle_wapper.on("touchstart",e=>{ e.stopPropagation();console.log(" :",[videoElement]);videoElement?.[0].pause() });clickable_subtitle_wapper.on("mouseup",e=>{ e.stopPropagation();if(window?.getSelection()?.toString()){ console.log(" :",[videoElement]);videoElement?.[0].pause();return }console.log(" :",[videoElement]);videoElement?.[0].play() });clickable_subtitle_wapper.on("touchend",e=>{ e.stopPropagation();if(window?.getSelection()?.toString()){ console.log(" :",[videoElement]);videoElement?.[0].pause();return }console.log(" :",[videoElement]);videoElement?.[0].play() });
    // 网页外挂字幕样式
    clickable_subtitle_wapper.css({ ...commontCss,border: "2px solid #aaa8",transform: "translateX(-50%)",display: "block","user-select": "text",width: "80vw",bottom: "0",left: "50%",padding: "3vw 3vw 10vh 3vw","background-color": "#1b2129ee","line-height": "4rem !important","font-size": " 3vw","text-align": " center",mask: "linear-gradient(180deg, black 0%, rgba(0, 0, 0, 1) 80%,rgba(0, 0, 0, 0.0) 95%)","border-radius": "3vw 3vw 0 0","box-shadow": "inset 0 0 2vw #666" });
    // 字幕轨道
    const subtitleTrack = $('<track  class="videoTrack" kind = "subtitles" default /> ');videoElement.prepend(subtitleTrack);
    // 缓存字幕数据
    /* document.querySelector('.videoTrak') */subtitleTrack.on("loadeddata",e=>{ clog("轨道数据缓存");console.log("数据 :",e) });
    // 网页外挂字幕文件
    const clickable_subtitle_input_file = $(`<div><input id='input' style='font-size: 2vw;' class='clickable_subtitle_input_file' type='file'  accept='.vtt'>  </input><label style='font-size: 2vw;' for='input'>上传字幕文件(.vtt)</label>  </div> `);clickable_subtitle_input_file.css({ "font-size": " 2vw","background-color": "#0004","order-radius": " 2vw !important",padding: "1vw 4vw",display: "flex","justify-content": "space-between","align-items": "center" });const clickable_subtitle_input_file_transer = $(`<a style='color:#fff;display:block;' href='https://converter.app/srt-to-vtt/result.php?lang=cn' target='转格式'>字幕文件转格式(.srt->.vtt)网站</a>`);clickable_subtitle_input_file.css({ "font-size": "2vw" });
    // 字幕读取近内存
    clickable_subtitle_input_file.on("change",e=>{ e.stopPropagation();const file = e.target.files[0];console.log("file :",file);
      // window?.localStorage?.setItem(`${window.location.href}`, JSON.stringify(lastPlaybackPosition?.current))
      if(!file)return;document.querySelector(".videoTrack").src = URL.createObjectURL(file);
      // subtitleTrack.attr('src', URL.createObjectURL(file))
      console.log("视频元素 :",[videoElement]) });
    // 时间纠正
    let addTime = 0;
    // 上次播放秒
    let preSecondInt = -1;
    // 上次字幕小标
    let preSubIndex = -1;
    // 字幕显示时机
    videoElement.on("timeupdate",e=>{ e.stopPropagation();const videoEle = e?.target;const currentTime = videoEle?.currentTime + addTime;
      // console.log('视频元素 :', e);
      // console.log('视频时间 :', currentTime);
      // console.log('字幕数组1 :', videoEle?.textTracks[0]?.cues?.[0]);
      // console.log('字幕数组 :', videoEle?.textTracks[0]?.cues);
      const cues = videoEle?.textTracks[0]?.cues;
      // console.log('preSecondInt !== parseInt(videoEle?.currentTime) :', preSecondInt !== parseInt(videoEle?.currentTime), preSecondInt , parseInt(videoEle?.currentTime));
      // 节流每秒执行
      if(videoEle?.textTracks[0]?.cues?.length && preSecondInt !== parseInt(videoEle?.currentTime))
      // clog('数组有长度');
        for(let i = 0;i < cues.length;i++){ const item = cues[i];
          // console.log('debugger :', item?.startTime, currentTime, item?.endTime);
          const right = item?.startTime <= currentTime && item?.endTime >= currentTime;
          // 不是同一字幕才执行
          if(right){ if(preSubIndex !== i){ clog("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");console.log("当前时间 :",item?.startTime,currentTime,item?.endTime);console.log("当前时间秒 :",preSecondInt,parseInt(videoEle?.currentTime));console.log("当前字幕下标 :",preSubIndex,i);const textSele = item?.text?.split(/\s+/)?.map(v=>`<i>${v}</i>`).join("");clickable_subtitle_wapper.html(`<p class="clickable_subtitle_middle" style="user-select:text;">${textSele}</p>`);
            // 使用事件委派监听子元素的点击事件
            $(".clickable_subtitle_middle").on("click","i",function(){ clog($(this).text() + "被点击了");const word = e?.target?.textContent.match(/\b[\w]+\b/);navigator?.clipboard?.writeText(word)?.then(()=>{ clog("复制成功 " + word) })?.catch(()=>{ clog("复制失败 " + word) });
              // 选择元素配合欧路词典
              const range = document?.createRange();range?.selectNode(this);window?.getSelection()?.addRange(range) });
            // 上次字幕下标
            preSubIndex = i }break } }
      // const currentSubtitle = videoEle?.textTracks[0]?.cues?.find((item) => {
      //   const right = item?.startTime <= currentTime && item?.endTime >= currentTime
      //   // debugger
      //   return right
      // })?.text
      // clickable_subtitle_wapper.html(`<p style="user-select:text;">${currentSubtitle}</p>`)
      // 上一次时间
      preSecondInt = parseInt(videoEle?.currentTime) });
    // 射手字幕网找字幕
    const clickable_subtitle_find_subtitle_webSite = $("<a class='clickable_subtitle_find_subtitle_webSite' href='https://assrt.net/' target='字幕网'>找字幕文件网1 </a>");const clickable_subtitle_find_subtitle_webSite2 = $("<a class='clickable_subtitle_find_subtitle_webSite' href='https://www.opensubtitles.org/zh' target='字幕网'>找字幕文件网2 </a>");const clickable_subtitle_find_subtitle_webSite3 = $("<a class='clickable_subtitle_find_subtitle_webSite' href='https://subscene.com/' target='字幕网'>找字幕文件网3 </a>");clickable_subtitle_find_subtitle_webSite.css({ color: "#fff" });clickable_subtitle_find_subtitle_webSite2.css({ color: "#fff" });clickable_subtitle_find_subtitle_webSite3.css({ color: "#fff" });
    // 找字幕外层
    const clickable_subtitle_find_subtitle_wapper = $("<div class='clickable_subtitle_find_subtitle_wapper'></div>");const clickable_subtitle_find_subtitle_webSite_wapper = $("<div class='clickable_subtitle_find_subtitle_webSite_wapper'></div>");clickable_subtitle_find_subtitle_webSite_wapper.css({ display: "flex","justify-content": "space-between","align-items": "center","font-size": "2vw","order-radius": "2vw !important",padding: "1vw 4vw","background-color": "#0004" });clickable_subtitle_find_subtitle_webSite_wapper.append(clickable_subtitle_find_subtitle_webSite);clickable_subtitle_find_subtitle_webSite_wapper.append(clickable_subtitle_find_subtitle_webSite2);clickable_subtitle_find_subtitle_webSite_wapper.append(clickable_subtitle_find_subtitle_webSite3);clickable_subtitle_find_subtitle_wapper.append(clickable_subtitle_input_file);clickable_subtitle_find_subtitle_wapper.append(clickable_subtitle_input_file_transer);clickable_subtitle_find_subtitle_wapper.append(clickable_subtitle_find_subtitle_webSite_wapper);clickable_subtitle_wapper.prepend(clickable_subtitle_find_subtitle_wapper);
    // 准备改成父级嵌套
    // 挂载开关
    const videoWrapper = $(".videoWrapper");videoWrapper.css({ "font-size": "2vw","line-height": "2.5rem !important",padding: "0 1rem !important" });
    // 按钮外框
    const buttonWrapper = $(`<div class="buttonWrapper"/>`);buttonWrapper.css({ ...commontCss,top: "50%",right: "0",color: "#fff",transform: "translateY(-50%)" });
    // /移动端点击视频出现按钮
    videoElement.on("touchstart",e=>{ e.stopPropagation();buttonWrapper.css({ opacity: "1",transition: "all 0.5s ease-in-out" }) });videoElement.on("touchend",e=>{ e.stopPropagation();this.setTimeout(()=>{ buttonWrapper.css({ opacity: "0.1",transition: "all 0.5s ease-in-out" }) },1e3) });
    // 有定时器标识变量
    // eslint-disable-next-line no-unused-vars
    let mouseStopped = true;
    // 电脑滑动鼠标出现那妞
    $(document).on("mousemove",function(e){ e.stopPropagation();
      // 设置鼠标停止移动的标识为false
      mouseStopped = false;
      // 清除延迟定时器
      clearTimeout($.data(this,"timer"));
      // 电脑滑动鼠标出现那妞
      buttonWrapper.css({ opacity: "1",transition: "all 0.5s ease-in-out" });
      // 电脑鼠标停止移动隐藏按钮
      // 设置新的延迟定时器
      $.data(this,"timer",setTimeout(()=>{ mouseStopped = true;buttonWrapper.css({ opacity: "0.1",transition: "all 0.5s ease-in-out" }) },1e3)) });
    // 字幕加一秒
    const add = $("<button>加</button>");add.css({ ...buttonCommontCss });
    // 偏移速度显示屏
    const speed = $("<div>0秒</div>");speed.css({ ...buttonCommontCss });
    // 改变速度
    const changeTime = ()=>{ speed.text(addTime + "秒") };add.on("click",e=>{ e.stopPropagation();addTime++;changeTime() });
    // 字幕减一秒
    const reduce = $("<button>减</button>");reduce.css({ ...buttonCommontCss });reduce.on("click",e=>{ e.stopPropagation();addTime--;changeTime() });
    // 字幕广告插入速度纠正
    const subTitleSpeedWaper = $("<div/>");subTitleSpeedWaper.css({ display: "flex","justify-content": "space-between","align-items": "center" });
    // buttonCommontCss
    buttonWrapper.append(clickable_subtitle_switch_button);buttonWrapper.append(clickable_subtitle_show_switch_button);buttonWrapper.append(reduce);buttonWrapper.append(speed);buttonWrapper.append(add);
    // buttonWrapper.append(subTitleSpeedWaper);
    // 挂载字幕元素
    videoWrapper.append(buttonWrapper);videoWrapper.append(clickable_subtitle_wapper);
    //全部元素可选
    $("*").css("user-select","text") },false) })();