Greasy Fork is available in English.
视频外挂悬浮可点复制翻译字幕,floating plug-in for clickable subtitle copying
当前为
// ==UserScript==
// @name 视频外挂悬浮可点复制翻译字幕,floating-plug-in-for-clickable-subtitle-copying
// @description 视频外挂悬浮可点复制翻译字幕,floating plug-in for clickable subtitle copying
// @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.58.59
// @icon https://www.google.com/s2/favicons?sz=64&domain=greasyfork.org
// @author You
// ==/UserScript==
(() => { "use strict"; const _ = e => { console.log("%c" + e, "background-color: #811f21; color: white;line-height:1.5rem; padding:0 0.5rem;") }; function y(e) { !function (e) { if (document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement) { if (e === document.fullscreenElement || e === document.mozFullScreenElement || e === document.webkitFullscreenElement || e === document.msFullscreenElement) return console.log("元素处于全屏状态"), 1; console.log("元素不处于全屏状态") } else console.log("不处于全屏状态") }(e) ? (_("全屏视频"), e.requestFullscreen ? e.requestFullscreen() : e.mozRequestFullScreen ? e.mozRequestFullScreen() : e.webkitRequestFullscreen ? e.webkitRequestFullscreen() : e.msRequestFullscreen && e.msRequestFullscreen(), void 0 !== window.ActiveXObject && null != (e = new ActiveXObject("WScript.Shell")) && e.SendKeys("{F11}")) : (_("退出全屏视频"), document.exitFullscreen ? document.exitFullscreen() : document.mozCancelFullScreen ? document.mozCancelFullScreen() : document.webkitExitFullscreen ? document.webkitExitFullscreen() : document.msExitFullscreen && document.msExitFullscreen()) } window.addEventListener("load", (function () { _("视频外挂西悬浮可点复制翻译字幕-floating-plug-in-for-clickable-subtitle-copying"), $("iframe").each((function () { $(this).attr("allowfullscreen", "true") })); const t = $("video"); var e = t.parent(), o = (e = (e.addClass("videoWrapper"), e.css({ position: "relative" }), t.append("<style>video::cue{opacity: 0 !important}</style>"), t.attr("controls", "true"), t.attr("playsInline", "true"), $("<button class='switchButton'>全屏</button>")), e.on("click", (function (e) { e.stopPropagation(), _("全屏开关点击"), y(document.querySelector(".videoWrapper")) })), { "z-index": "2147483647", color: "#fff", position: "absolute" }), n = { 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" }, s = (e.css({ ...n }), $("<button class='switchButton'>显隐</button>")); let l = !0; s.css({ ...n }); const i = $("<div class='floating_plug_in_for_clickable_subtitle_copying'></div>"); s.on("click", (function (e) { e.stopPropagation(), _("字幕显示开关点击"), l = !l, i.css({ display: l ? "block" : "none" }) })), i.click((function (e) { _("字幕外层点击"), e.stopPropagation() })), i.on("mousedown", (e => { e.stopPropagation(), console.log(" :", [t]), t?.[0].pause() })), i.on("touchstart", (e => { e.stopPropagation(), console.log(" :", [t]), t?.[0].pause() })), i.on("mouseup", (e => { e.stopPropagation(), window?.getSelection()?.toString() ? (console.log(" :", [t]), t?.[0].pause()) : (console.log(" :", [t]), t?.[0].play()) })), i.on("touchend", (e => { e.stopPropagation(), window?.getSelection()?.toString() ? (console.log(" :", [t]), t?.[0].pause()) : (console.log(" :", [t]), t?.[0].play()) })), i.css({ ...o, 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" }); var c = $('<track class="videoTrack" kind = "subtitles" default /> '), a = (c = (t.prepend(c), c.on("loadeddata", (e => { _("轨道数据缓存"), console.log("数据 :", e) })), $("<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> ")), c.css({ "font-size": " 2vw", "background-color": "#0004", "order-radius": " 2vw !important", padding: "1vw 4vw", display: "flex", "justify-content": "space-between", "align-items": "center" }), $("<a style='color:#fff;display:block;' href='https://converter.app/srt-to-vtt/result.php?lang=cn' target='转格式'>字幕文件转格式(.srt->.vtt)网站</a>")); c.css({ "font-size": "2vw" }), c.on("change", (e => { e.stopPropagation(); e = e.target.files[0]; console.log("file :", e), e && (document.querySelector(".videoTrack").src = URL.createObjectURL(e), console.log("视频元素 :", [t])) })); let r = 0, u = -1, p = -1; t.on("timeupdate", (e => { e.stopPropagation(); var t = e?.target, o = t?.currentTime + r, n = t?.textTracks[0]?.cues; if (t?.textTracks[0]?.cues?.length && u !== parseInt(t?.currentTime)) for (let e = 0; e < n.length; e++) { var s = n[e]; if (s?.startTime <= o && s?.endTime >= o) { p !== e && (_("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"), console.log("当前时间 :", s?.startTime, o, s?.endTime), console.log("当前时间秒 :", u, parseInt(t?.currentTime)), console.log("当前字幕下标 :", p, e), s = s?.text?.split(/\s+/)?.map((e => `<i class="clickable_subtitle_word">${e}</i> `)).join(""), i.html(`<p class="clickable_subtitle_middle" style="user-select:text;">${s}</p>`), $(".clickable_subtitle_middle").on("click", "i", (function (e) { _($(this).text() + "被点击了"); var t = document?.createRange(); t?.selectNode(this), window?.getSelection()?.addRange(t); const o = e?.target?.textContent.match(/\b[\w]+\b/); console.log("单词元素 :", this), navigator?.clipboard?.writeText(o)?.then((() => { _("复制成功 " + o) }))?.catch((() => { _("复制失败 " + o) })) })), p = e); break } } u = parseInt(t?.currentTime) })); var d = $("<a class='clickable_subtitle_find_subtitle_webSite' href='https://assrt.net/' target='字幕网'>找字幕文件网1 </a>"), m = $("<a class='clickable_subtitle_find_subtitle_webSite' href='https://www.opensubtitles.org/zh' target='字幕网'>找字幕文件网2 </a>"), b = $("<a class='clickable_subtitle_find_subtitle_webSite' href='https://subscene.com/' target='字幕网'>找字幕文件网3 </a>"), g = (d.css({ color: "#fff" }), m.css({ color: "#fff" }), b.css({ color: "#fff" }), $("<div class='clickable_subtitle_find_subtitle_wapper'></div>")), f = $("<div class='clickable_subtitle_find_subtitle_webSite_wapper'></div>"); d = (f.css({ display: "flex", "justify-content": "space-between", "align-items": "center", "font-size": "2vw", "order-radius": "2vw !important", padding: "1vw 4vw", "background-color": "#0004" }), f.append(d), f.append(m), f.append(b), g.append(c), g.append(a), g.append(f), i.prepend(g), $(".videoWrapper")); d.css({ "font-size": "2vw", "line-height": "2.5rem !important", padding: "0 1rem !important" }); const w = $('<div class="buttonWrapper"/>'); w.css({ ...o, top: "50%", right: "0", color: "#fff", transform: "translateY(-50%)" }), t.on("touchstart", (e => { e.stopPropagation(), w.css({ opacity: "1", transition: "all 0.5s ease-in-out" }) })), t.on("touchend", (e => { e.stopPropagation(), this.setTimeout((() => { w.css({ opacity: "0.1", transition: "all 0.5s ease-in-out" }) }), 1e3) })); let v; $(document).on("mousemove", (function (e) { e.stopPropagation(), v = !1, clearTimeout($.data(this, "timer")), w.css({ opacity: "1", transition: "all 0.5s ease-in-out" }), $.data(this, "timer", setTimeout((() => { w.css({ opacity: "0.1", transition: "all 0.5s ease-in-out" }) }), 1e3)) })); m = $("<button>加</button>"); m.css({ ...n }); const h = $("<div>0秒</div>"), k = (h.css({ ...n }), () => { h.text(r + "秒") }); m.on("click", (e => { e.stopPropagation(), r++, k() })); b = $("<button>减</button>"); b.css({ ...n }), b.on("click", (e => { e.stopPropagation(), r--, k() })), $("<div/>").css({ display: "flex", "justify-content": "space-between", "align-items": "center" }), w.append(e), w.append(s), w.append(b), w.append(h), w.append(m), d.append(w), d.append(i), $("*").css("user-select", "text") }), !1) })();