Greasy Fork

Greasy Fork is available in English.

floating-plug-in-for-clickable-subtitle-copying

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

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

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         floating-plug-in-for-clickable-subtitle-copying

// @namespace    http://tampermonkey.net/
// @version      2023.12.15.14.20.50
// @description  视频外挂西悬浮可点复制翻译字幕,floating plug-in for clickable subtitle copying
// @author       You

// @match        *://*/*

// @icon         https://www.google.com/s2/favicons?sz=64&domain=greasyfork.org
// @grant        none

// @require      https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js
// @include      *

// @license      MIT

// ==/UserScript==

(function () {
  'use strict';

  // Your code here...

  // 报错油猴脚本使用jquery报错eslint:no-undef-‘$‘ is not defined
  /* globals jQuery, $, waitForKeyElements */

  // 彩色打印
  console.clog = (content) => {
    console.log(
      `%c${content}`,
      "background-color: #811f21; color: white;line-height:1.5rem; padding:0 0.5rem;"
    );
  }

  // 移动端控制台
  $('head').append($('<script src="https://cdn.bootcss.com/vConsole/3.3.0/vconsole.min.js"></script>< script >new VConsole();</script >'))

  // 全屏封装
  function goFullScreen(element) {

    console.clog('全屏视频');
    // var element = document.getElementById("fullscreenElement");
    if (element.requestFullscreen) {
      element.requestFullscreen();
    } else if (element.mozRequestFullScreen) {
      element.mozRequestFullScreen();
    } else if (element.webkitRequestFullscreen) {
      element.webkitRequestFullscreen();
    } else if (element.msRequestFullscreen) {
      element.msRequestFullscreen();
    }
  }

  function exitFullScreen() {
    console.clog('退出全屏视频');
    if (document.exitFullscreen) {
      document.exitFullscreen();
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen();
    } else if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen();
    } else if (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
      } else {
        console.log("元素不处于全屏状态");
        return false
      }
    } else {
      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)) {
      goFullScreen(el)
    } else {
      exitFullScreen()
      return
    }
    if (typeof window.ActiveXObject != "undefined") {
      wscript = new ActiveXObject("WScript.Shell");
      if (wscript != null) {
        wscript.SendKeys("{F11}");
      }
    }
  }

  // 等待网页完成加载
  window.addEventListener('load', function () {
    // 加载完成后执行的代码
    console.clog('视频外挂西悬浮可点复制翻译字幕-floating-plug-in-for-clickable-subtitle-copying');

    // 视频外层
    const videoElement = $('video')

    // 视频父元素
    const videoParentElement = videoElement.parent()
    videoParentElement.addClass("videoWrapper");
    videoParentElement.css({
      position: 'relative',
    })
    // videoElement.wrapAll('<div class="videoWrapper" style="position: relative;"/>');
    // 隐藏字幕轨道
    videoElement.append("<style>video::cue{opacity: 0 !important}</style>");
    videoElement.attr('controls','true')
    videoElement.attr('playsInline','true')
    // 全屏开关元素
    const clickable_subtitle_switch_button = $("<div class='switchButton'>全屏</div>")
    // 全屏开关事件
    clickable_subtitle_switch_button.on('click',function (event) {
      console.clog('全屏开关点击');
      autoFullScreen(document.querySelector('.videoWrapper'));
      // 阻止冒泡
      event.stopPropagation();
    });
    // 公共样式
    const commontCss = {
      'z-index': '2147483647',
      'color': '#fff',
      'position': 'absolute',
      'padding': '0 1rem !important',
    }

    // 全屏开关样式
    clickable_subtitle_switch_button.css({
      ...commontCss,

      'transform': 'translate(-50%,-50%)',
      'top': '50%',
      'left': '95%',
      'background-color': '#888',
      'cursor': 'pointer',
      'user-select': 'none',
      'line-height': '2.5rem !important',
    });

    // 网页外挂字幕元素
    const clickable_subtitle_wapper = $("<div class='floating_plug_in_for_clickable_subtitle_copying'>可点击字幕</div>")

    // 网页外挂字幕事件
    clickable_subtitle_wapper.click(function (event) {
      console.clog('字幕外层点击');
      // console.log(' :', [videoElement]);

      // 阻止冒泡
      event.stopPropagation();
    });
    clickable_subtitle_wapper.on('mousedown', (e) => {
      console.log(' :', [videoElement]);

      videoElement?.[0].pause()
    })
    clickable_subtitle_wapper.on('touchstart', (e) => {
      console.log(' :', [videoElement]);

      videoElement?.[0].pause()
    })

    clickable_subtitle_wapper.on('mouseup', () => {
      if (window?.getSelection()?.toString()) {
        console.log(' :', [videoElement]);


        videoElement?.[0].pause()
        return
      }
      console.log(' :', [videoElement]);

      videoElement?.[0].play()
    })
    clickable_subtitle_wapper.on('touchend', () => {
      if (window?.getSelection()?.toString()) {
        console.log(' :', [videoElement]);


        videoElement?.[0].pause()
        return
      }
      console.log(' :', [videoElement]);

      videoElement?.[0].play()
    })
    // 网页外挂字幕样式
    clickable_subtitle_wapper.css({
      ...commontCss,

      'transform': 'translateX(-50%)',
      'display': 'block',
      'user-select': 'auto',
      'width': '80vw',
      'bottom': '0',
      'left': '50%',
      'padding': '1vw 1vw 10vh 1vw',
      'background-color': '#444',
      'line-height': '4rem !important',
      'font-size': ' 3vw',
      'text-align': ' center',
      mask: 'linear-gradient(180deg, rgba(0, 0, 0, 0.0) 0%, rgba(0, 0, 0, 1) 1%, black 5%, rgba(0, 0, 0, 1) 80%,rgba(0, 0, 0, 0.0) 95%)',
      'border-radius': '3vw 3vw 0 0',
    });

    // 字幕轨道
    const subtitleTrack = $('<track  class="videoTrack" kind = "subtitles" default /> ')

    videoElement.prepend(subtitleTrack)

    // 缓存字幕数据
    /* document.querySelector('.videoTrak') */subtitleTrack.on('load', (e) => {
      // videoElement.textTracks[0].oncuechange = (e) => {
      //   console.log(' :', e?.currentTarget?.activeCues);
      // }
      // console.clog('字幕数据缓存 :', 字幕数据缓存);

      // console.log(' :', [videoElement]);

      // const cues = e?.target?.track?.cues
      // const subArr = []
      // const arrCues = cues?.length
      // if (arrCues) {
      //   for (let index = 0; index < arrCues; index++) {
      //     const element = cues?.[index];
      //     if (element) {
      //       element.id = `${index}`
      //       subArr?.push({
      //         align: element?.align,//"center",
      //         endTime: element?.endTime,//18.27,
      //         id: element?.id,//"0",
      //         line: element?.line,//"auto",
      //         pauseOnExit: element?.pauseOnExit,//false,
      //         position: element?.position,//"auto",
      //         size: element?.size,//100,
      //         snapToLines: element?.snapToLines,//true,
      //         startTime: element?.startTime,//15.68,
      //         text: element?.text,//"我叫玛丽·艾莉丝·杨\nMy name is Mary Alice Young.",
      //         text0: element?.text?.split('\n')?.[0],//"我叫玛丽·艾莉丝·杨",
      //         // text0: (element?.text?.includes('\n') && subHidenType?.type !=='5') ? element?.text?.split('\n')?.[0] : element?.text,//"我叫玛丽·艾莉丝·杨",
      //         text0Show: text0Show,
      //         text1: element?.text?.split('\n')?.[1],//"My name is Mary Alice Young.",
      //         // text1: (element?.text?.includes('\n') && subHidenType?.type !=='5') ? element?.text?.split('\n')?.[1] : element?.text,//"My name is Mary Alice Young.",
      //         text1Show: text1Show,
      //       })
      //     }
      //   }
      // }

      // console.clog(subArr);
    });




    // 网页外挂字幕文件
    const clickable_subtitle_input_file = $(` <input  class='clickable_subtitle_input_file' type='file'  accept='.vtt'> 上传字幕文件(.vtt) <a style='color:#fff' href='https://converter.app/srt-to-vtt/result.php?lang=cn' target='转格式'>转格式(srt->vtt)网站</a></input> `)

    // 字幕读取近内存
    clickable_subtitle_input_file.on('change', (e) => {
      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]);
      document.querySelector('video').textTracks[0].oncuechange = (e) => {
        console.log(' :', e?.currentTarget?.activeCues[0]?.text);
        clickable_subtitle_wapper.text(e?.currentTarget?.activeCues[0]?.text)
      }
    })


    // 射手字幕网找字幕
    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-around',
      'align-items': 'center',
    })


    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_find_subtitle_webSite_wapper)
    clickable_subtitle_find_subtitle_wapper.append(clickable_subtitle_input_file)
    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',
    })




    // 挂载字幕元素
    videoWrapper.append(clickable_subtitle_switch_button);
    videoWrapper.append(clickable_subtitle_wapper);
  }, false);

})();