返回首頁 

Greasy Fork is available in English.

阿里云盘字幕

让你的视频文件和字幕文件梦幻联动!


Installer dette script?
// ==UserScript==// @name         阿里云盘字幕// @namespace    http://tampermonkey.net/// @version      0.7// @description  让你的视频文件和字幕文件梦幻联动!// @author       polygon// @match        https://www.aliyundrive.com/drive*// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==// @grant        GM_addStyle// @grant        GM_xmlhttpRequest// @runat        document-end// ==/UserScript==!function(f){"object"==typeof exports&&"undefined"!=typeof module?module.exports=f():"function"==typeof define&&define.amd?define([],f):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).languageEncoding=f()}(function(){return function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var p="function"==typeof require&&require;if(!f&&p)return p(i,!0);if(u)return u(i,!0);throw(p=new Error("Cannot find module '"+i+"'")).code="MODULE_NOT_FOUND",p}p=n[i]={exports:{}},e[i][0].call(p.exports,function(r){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}({1:[function(require,module,exports){const byteOrderMarks=require("../config/byteOrderMarkObject.js");module.exports=uInt8Start=>{for(const element of byteOrderMarks)if(element.regex.test(uInt8Start))return element.encoding;return null}},{"../config/byteOrderMarkObject.js":6}],2:[function(require,module,exports){module.exports=content=>{for(let b=0;b<content.length;b++)if("�"===content[b])return!1;return!0}},{}],3:[function(require,module,exports){const countAllMatches=require("./processing-content/countAllMatches.js"),calculateConfidenceScore=require("./processing-content/calculateConfidenceScore.js");module.exports=(data,fileInfo)=>{data.languageArr=countAllMatches(data,fileInfo.encoding),fileInfo.language=data.languageArr.reduce((acc,val)=>acc.count>val.count?acc:val).name,data.pos=data.languageArr.findIndex(elem=>elem.name===fileInfo.language),fileInfo.encoding||(fileInfo.encoding=data.languageArr[data.pos].encoding);var calculations=calculateConfidenceScore(data,fileInfo);return data.testFile?calculations:(fileInfo.confidence.encoding||(fileInfo.confidence.encoding=calculations),fileInfo.confidence.language=calculations,data.languageArr[data.pos].count||(fileInfo.language=null,fileInfo.confidence.language=null),fileInfo)}},{"./processing-content/calculateConfidenceScore.js":4,"./processing-content/countAllMatches.js":5}],4:[function(require,module,exports){module.exports=(surplus,fileInfo)=>{var confidenceRaise=new RegExp(/\d|\n|\s|\-|\.|\,|\:|\;|\?|\!|\<|\>|\[|\]|\{|\}|\&|\=|\|/,"g"),totalCharacters=surplus.content.replace(confidenceRaise,"").length;const langArr=surplus.languageArr;var pos=surplus.pos;const testFile=surplus.testFile;var secondLanguage=langArr.reduce((acc,val)=>acc.name!==fileInfo.language&&(val.name===fileInfo.language||acc.count>=val.count)?acc:val);const languageRatio=langArr[pos].count/(secondLanguage.count+langArr[pos].count),characterWordRatio=langArr[pos].count/totalCharacters;let lowerLimit=null,upperLimit=null;upperLimit="UTF-8"===fileInfo.encoding||"UTF-16LE"===fileInfo.encoding?(lowerLimit=langArr[pos].utfFrequency?.8*langArr[pos].utfFrequency.low:null,langArr[pos].utfFrequency?(langArr[pos].utfFrequency.low+langArr[pos].utfFrequency.high)/2:null):(lowerLimit=langArr[pos].isoFrequency?.8*langArr[pos].isoFrequency.low:null,langArr[pos].isoFrequency?(langArr[pos].isoFrequency.low+langArr[pos].isoFrequency.high)/2:null);let confidenceScore;return confidenceScore=lowerLimit&&upperLimit?characterWordRatio>=upperLimit?1:characterWordRatio>lowerLimit?(confidenceRaise=upperLimit-lowerLimit,surplus=characterWordRatio-lowerLimit,confidenceRaise=(1-languageRatio)*(surplus/confidenceRaise),Number((languageRatio+confidenceRaise).toFixed(2))):Number((languageRatio*(characterWordRatio/lowerLimit)).toFixed(2)):null,testFile?{name:testFile.substr(testFile.lastIndexOf("/")+1),path:testFile,encoding:fileInfo.encoding,language:fileInfo.language,languageConfidence:confidenceScore,ratio:Number(languageRatio.toFixed(2)),count:langArr[pos].count,totalCharacters:totalCharacters,characterWordRatio:characterWordRatio.toFixed(6),secondLanguage:{name:secondLanguage.name,count:secondLanguage.count}}:confidenceScore}},{}],5:[function(require,module,exports){const languageArr=require("../../config/languageObject.js");module.exports=(data,encoding)=>{const newLanguageArr=[];languageArr.forEach(obj=>{const updatedLangObj={};Object.keys(obj).forEach(key=>{"count"!==key?updatedLangObj[key]=obj[key]:updatedLangObj.count=0}),newLanguageArr.push(updatedLangObj)});const regex=encoding?"utfRegex":"isoRegex";return newLanguageArr.forEach(lang=>{var matches;!lang[regex]||(matches=data.content.match(lang[regex]))&&(lang.count=matches.length)}),newLanguageArr}},{"../../config/languageObject.js":7}],6:[function(require,module,exports){module.exports=[{encoding:"UTF-EBCDIC",regex:new RegExp("221 115 102 115")},{encoding:"GB-18030",regex:new RegExp("132 49 149 51")},{encoding:"UTF-32LE",regex:new RegExp("255 254 0 0")},{encoding:"UTF-32BE",regex:new RegExp("0 0 254 255")},{encoding:"UTF-8",regex:new RegExp("239 187 191")},{encoding:"UTF-7",regex:new RegExp("43 47 118")},{encoding:"UTF-1",regex:new RegExp("247 100 76")},{encoding:"SCSU",regex:new RegExp("14 254 255")},{encoding:"BOCU-1",regex:new RegExp("251 238 40")},{encoding:"UTF-16BE",regex:new RegExp("254 255")},{encoding:"UTF-16LE",regex:new RegExp("255 254")}]},{}],7:[function(require,module,exports){var sharedRegex={czech:new RegExp(/jsem|jsi/,"gi"),hungarian:new RegExp(/\snem\s/,"gi"),slovak:new RegExp(/poriadku|myslím|\ssme\s/,"gi"),slovenian:new RegExp(/\skaj\s|lahko|zdaj/,"gi"),albanian:new RegExp(/nuk/,"gi"),english:new RegExp(/ the /,"gi"),french:new RegExp(/c'est/,"gi"),portuguese:new RegExp(/ não /,"gi"),spanish:new RegExp(/estaba|\smuy\s|siempre|ahora/,"gi"),german:new RegExp(/\sdas\s/,"gi"),italian:new RegExp(/\sche\s/,"gi"),danish:new RegExp(/hvad|noget/,"gi"),norwegian:new RegExp(/deg/,"gi"),swedish:new RegExp(/ jag /,"gi"),dutch:new RegExp(/ het /,"gi"),finnish:new RegExp(/hän/,"gi"),"serbo-croatian":new RegExp(/ sam | kako /,"gi"),estonian:new RegExp(/\sseda\s|\spole\s|midagi/,"gi"),icelandic:new RegExp(/Það/,"gi"),"malay-indonesian":new RegExp(/tidak/,"gi"),turkish:new RegExp(/ bir /,"gi"),lithuanian:new RegExp(/taip|\stai\s/,"gi"),bengali:new RegExp(/এটা/,"gi"),hindi:new RegExp(/हैं/,"gi"),urdu:new RegExp(/ایک/,"gi"),vietnamese:new RegExp(/ không /,"gi")},sharedFrequency={polish:{low:.004355,high:.005102},czech:{low:.004433,high:.007324},hungarian:{low:.004994,high:.005183},romanian:{low:.003319,high:.00419},slovak:{low:.001736,high:.002557},slovenian:{low:.004111,high:.004959},albanian:{low:.003773,high:.007313},ukrainian:{low:.002933,high:.005389},english:{low:.004679,high:.00758},french:{low:.003016,high:.004825},portuguese:{low:.003406,high:.005032},spanish:{low:.002348,high:.002881},german:{low:.004044,high:.004391},italian:{low:.003889,high:.005175},danish:{low:.00363,high:.004189},norwegian:{low:.00241,high:.003918},swedish:{low:.004916,high:.007221},dutch:{low:.003501,high:.00415},finnish:{low:.003308,high:.005135},"serbo-croatian":{low:.002568,high:.005182},estonian:{low:.002892,high:.003963},icelandic:{low:.004366,high:.004366},"malay-indonesian":{low:.002825,high:.003932},greek:{low:.00344,high:.004862},turkish:{low:.002915,high:.004588},hebrew:{low:.003663,high:.004666},lithuanian:{low:.003277,high:.003768},bengali:{low:.003155,high:.005236},hindi:{low:.004159,high:.006478},urdu:{low:.004118,high:.005851},vietnamese:{low:.003387,high:.005191}};module.exports=[{name:"polish",count:0,utfRegex:new RegExp(/się/,"gi"),isoRegex:new RegExp(/siê/,"gi"),encoding:"CP1250",utfFrequency:sharedFrequency.polish,isoFrequency:sharedFrequency.polish},{name:"czech",count:0,utfRegex:sharedRegex.czech,isoRegex:sharedRegex.czech,encoding:"CP1250",utfFrequency:sharedFrequency.czech,isoFrequency:sharedFrequency.czech},{name:"hungarian",count:0,utfRegex:sharedRegex.hungarian,isoRegex:sharedRegex.hungarian,encoding:"CP1250",utfFrequency:sharedFrequency.hungarian,isoFrequency:sharedFrequency.hungarian},{name:"romanian",count:0,utfRegex:new RegExp(/sunt|eşti/,"gi"),isoRegex:new RegExp(/sunt|eºti/,"gi"),encoding:"CP1250",utfFrequency:sharedFrequency.romanian,isoFrequency:sharedFrequency.romanian},{name:"slovak",count:0,utfRegex:sharedRegex.slovak,isoRegex:sharedRegex.slovak,encoding:"CP1250",utfFrequency:sharedFrequency.slovak,isoFrequency:sharedFrequency.slovak},{name:"slovenian",count:0,utfRegex:sharedRegex.slovenian,isoRegex:sharedRegex.slovenian,encoding:"CP1250",utfFrequency:sharedFrequency.slovenian,isoFrequency:sharedFrequency.slovenian},{name:"albanian",count:0,utfRegex:sharedRegex.albanian,isoRegex:sharedRegex.albanian,encoding:"CP1250",utfFrequency:sharedFrequency.albanian,isoFrequency:sharedFrequency.albanian},{name:"russian",count:0,utfRegex:new RegExp(/что/,"gi"),isoRegex:new RegExp(/÷òî/,"gi"),encoding:"CP1251",utfFrequency:{low:.004965,high:.005341},isoFrequency:{low:.003884,high:.003986}},{name:"ukrainian",count:0,utfRegex:new RegExp(/він|але/,"gi"),isoRegex:new RegExp(/â³í|àëå/,"gi"),encoding:"CP1251",utfFrequency:sharedFrequency.ukrainian,isoFrequency:sharedFrequency.ukrainian},{name:"bulgarian",count:0,utfRegex:new RegExp(/това|какво/,"gi"),isoRegex:new RegExp(/òîâà|äîáðå|êaêâo/,"gi"),encoding:"CP1251",utfFrequency:{low:.005225,high:.005628},isoFrequency:{low:.002767,high:.004951}},{name:"english",count:0,utfRegex:sharedRegex.english,isoRegex:sharedRegex.english,encoding:"CP1252",utfFrequency:sharedFrequency.english,isoFrequency:sharedFrequency.english},{name:"french",count:0,utfRegex:sharedRegex.french,isoRegex:sharedRegex.french,encoding:"CP1252",utfFrequency:sharedFrequency.french,isoFrequency:sharedFrequency.french},{name:"portuguese",count:0,utfRegex:sharedRegex.portuguese,isoRegex:sharedRegex.portuguese,encoding:"CP1252",utfFrequency:sharedFrequency.portuguese,isoFrequency:sharedFrequency.portuguese},{name:"spanish",count:0,utfRegex:sharedRegex.spanish,isoRegex:sharedRegex.spanish,encoding:"CP1252",utfFrequency:sharedFrequency.spanish,isoFrequency:sharedFrequency.spanish},{name:"german",count:0,utfRegex:sharedRegex.german,isoRegex:sharedRegex.german,encoding:"CP1252",utfFrequency:sharedFrequency.german,isoFrequency:sharedFrequency.german},{name:"italian",count:0,utfRegex:sharedRegex.italian,isoRegex:sharedRegex.italian,encoding:"CP1252",utfFrequency:sharedFrequency.italian,isoFrequency:sharedFrequency.italian},{name:"danish",count:0,utfRegex:sharedRegex.danish,isoRegex:sharedRegex.danish,encoding:"CP1252",utfFrequency:sharedFrequency.danish,isoFrequency:sharedFrequency.danish},{name:"norwegian",count:0,utfRegex:sharedRegex.norwegian,isoRegex:sharedRegex.norwegian,encoding:"CP1252",utfFrequency:sharedFrequency.norwegian,isoFrequency:sharedFrequency.norwegian},{name:"swedish",count:0,utfRegex:sharedRegex.swedish,isoRegex:sharedRegex.swedish,encoding:"CP1252",utfFrequency:sharedFrequency.swedish,isoFrequency:sharedFrequency.swedish},{name:"dutch",count:0,utfRegex:sharedRegex.dutch,isoRegex:sharedRegex.dutch,encoding:"CP1252",utfFrequency:sharedFrequency.dutch,isoFrequency:sharedFrequency.dutch},{name:"finnish",count:0,utfRegex:sharedRegex.finnish,isoRegex:sharedRegex.finnish,encoding:"CP1252",utfFrequency:sharedFrequency.finnish,isoFrequency:sharedFrequency.finnish},{name:"serbo-croatian",count:0,utfRegex:sharedRegex["serbo-croatian"],isoRegex:sharedRegex["serbo-croatian"],encoding:"CP1252",utfFrequency:sharedFrequency["serbo-croatian"],isoFrequency:sharedFrequency["serbo-croatian"]},{name:"estonian",count:0,utfRegex:sharedRegex.estonian,isoRegex:sharedRegex.estonian,encoding:"CP1252",utfFrequency:sharedFrequency.estonian,isoFrequency:sharedFrequency.estonian},{name:"icelandic",count:0,utfRegex:sharedRegex.icelandic,isoRegex:sharedRegex.icelandic,encoding:"CP1252",utfFrequency:sharedFrequency.icelandic,isoFrequency:sharedFrequency.icelandic},{name:"malay-indonesian",count:0,utfRegex:sharedRegex["malay-indonesian"],isoRegex:sharedRegex["malay-indonesian"],encoding:"CP1252",utfFrequency:sharedFrequency["malay-indonesian"],isoFrequency:sharedFrequency["malay-indonesian"]},{name:"greek",count:0,utfRegex:new RegExp(/είναι/,"gi"),isoRegex:new RegExp(/åßíáé/,"gi"),encoding:"CP1253",utfFrequency:sharedFrequency.greek,isoFrequency:sharedFrequency.greek},{name:"turkish",count:0,utfRegex:sharedRegex.turkish,isoRegex:sharedRegex.turkish,encoding:"CP1254",utfFrequency:sharedFrequency.turkish,isoFrequency:sharedFrequency.turkish},{name:"hebrew",count:0,utfRegex:new RegExp(/אתה/,"gi"),isoRegex:new RegExp(/àúä/,"gi"),encoding:"CP1255",utfFrequency:sharedFrequency.hebrew,isoFrequency:sharedFrequency.hebrew},{name:"arabic",count:0,utfRegex:new RegExp(/هذا/,"gi"),isoRegex:new RegExp(/åðç/,"gi"),encoding:"CP1256",utfFrequency:{low:.003522,high:.004348},isoFrequency:{low:.003773,high:.005559}},{name:"farsi-persian",count:0,utfRegex:new RegExp(/اون/,"gi"),isoRegex:new RegExp(/çíä/,"gi"),encoding:"CP1256",utfFrequency:{low:.002761,high:.004856},isoFrequency:{low:.00301,high:.006646}},{name:"lithuanian",count:0,utfRegex:sharedRegex.lithuanian,isoRegex:sharedRegex.lithuanian,encoding:"CP1257",utfFrequency:sharedFrequency.lithuanian,isoFrequency:sharedFrequency.lithuanian},{name:"chinese-simplified",count:0,utfRegex:new RegExp(/么/,"gi"),isoRegex:new RegExp(/´ó|¶¯|Å®/,"gi"),encoding:"GB18030",utfFrequency:{low:.009567,high:.011502},isoFrequency:{low:.003137,high:.005009}},{name:"chinese-traditional",count:0,utfRegex:new RegExp(/們/,"gi"),isoRegex:new RegExp(/¦b/,"gi"),encoding:"BIG5",utfFrequency:{low:.012484,high:.014964},isoFrequency:{low:.005063,high:.005822}},{name:"japanese",count:0,utfRegex:new RegExp(/ど/,"gi"),isoRegex:new RegExp(/‚»/,"gi"),encoding:"Shift-JIS",utfFrequency:{low:.004257,high:.006585},isoFrequency:{low:.004286,high:.004653}},{name:"korean",count:0,utfRegex:new RegExp(/도/,"gi"),isoRegex:new RegExp(/àö¾î|å¾ß|¡¼­/,"gi"),encoding:"EUC-KR",utfFrequency:{low:.01091,high:.01367},isoFrequency:{low:.004118,high:.004961}},{name:"thai",count:0,utfRegex:new RegExp(/แฮร์รี่|พอตเตอร์/,"gi"),isoRegex:new RegExp(/áîãìãõè|¾íµàµíãì­/,"gi"),encoding:"TIS-620",utfFrequency:{low:.003194,high:.003468},isoFrequency:{low:.002091,high:.002303}},{name:"bengali",count:0,utfRegex:sharedRegex.bengali,isoRegex:sharedRegex.bengali,utfFrequency:sharedFrequency.bengali,isoFrequency:sharedFrequency.bengali},{name:"hindi",count:0,utfRegex:sharedRegex.hindi,isoRegex:sharedRegex.hindi,utfFrequency:sharedFrequency.hindi,isoFrequency:sharedFrequency.hindi},{name:"urdu",count:0,utfRegex:sharedRegex.urdu,isoRegex:sharedRegex.urdu,utfFrequency:sharedFrequency.urdu,isoFrequency:sharedFrequency.urdu},{name:"vietnamese",count:0,utfRegex:sharedRegex.vietnamese,isoRegex:sharedRegex.vietnamese,utfFrequency:sharedFrequency.vietnamese,isoFrequency:sharedFrequency.vietnamese}]},{}],8:[function(require,module,exports){const checkUTF=require("./components/checkUTF.js"),processContent=require("./components/processContent.js"),checkByteOrderMark=require("./components/checkByteOrderMark.js");module.exports=file=>new Promise((resolve,reject)=>{const fileInfo={encoding:null,language:null,confidence:{encoding:null,language:null}},data={},byteOrderMarkBuffer=new FileReader;byteOrderMarkBuffer.onload=()=>{var byteOrderMark=new Uint8Array(byteOrderMarkBuffer.r###lt).slice(0,4).join(" "),byteOrderMark=checkByteOrderMark(byteOrderMark);if(byteOrderMark){fileInfo.encoding=byteOrderMark,fileInfo.confidence.encoding=1;const byteOrderMarkReader=new FileReader;byteOrderMarkReader.onload=()=>{data.content=byteOrderMarkReader.r###lt,resolve(processContent(data,fileInfo))},byteOrderMarkReader.onerror=err=>{reject(err)},byteOrderMarkReader.readAsText(file,fileInfo.encoding)}else{const utfReader=new FileReader;utfReader.onload=()=>{var utfContent=utfReader.r###lt,utf8=checkUTF(utfContent);if(utf8&&(fileInfo.encoding="UTF-8",fileInfo.confidence.encoding=1),utf8)data.content=utfContent,resolve(processContent(data,fileInfo));else{const isoReader=new FileReader;isoReader.onload=()=>{data.content=isoReader.r###lt,resolve(processContent(data,fileInfo))},isoReader.readAsText(file,"ISO-8859-1")}},utfReader.onerror=err=>{reject(err)},utfReader.readAsText(file,"UTF-8")}},byteOrderMarkBuffer.onerror=err=>{reject(err)},byteOrderMarkBuffer.readAsArrayBuffer(file)})},{"./components/checkByteOrderMark.js":1,"./components/checkUTF.js":2,"./components/processContent.js":3}]},{},[8])(8)});const notification = (function() {'use strict';GM_addStyle(`#notification {box-sizing: border-box;position: fixed;left: calc(50% - 365.65px / 2);display: flex;flex-direction: row;align-items: center;justify-content: center;height: 50px;background-color: #ff7675;border-radius: 50px;padding: 0 0px 0px 20px;top: -50px;transition: top .5s ease-out;z-index: 9999999999;}#notification .content {display: flex;align-items: center;justify-content: center;color: white;font-size: 25px;}#notification .closeBox {margin: 0 10px;transform: rotate(90deg);cursor: pointer;}#notification .closeBox .progress {margin: 0 10px;cursor: pointer;}#notification .closeBox .progress .circle {stroke-dasharray: 100;animation: progressOffset 0s linear;}@keyframes progressOffset {from {stroke-dashoffset: 100;}to {stroke-dashoffset: 0;}}`)return {open(info, timeout, autoClose=true) {let eles = document.querySelectorAll('#notification')for (let i=0;i<eles.length;i++) {document.body.removeChild(eles[i])}this.box = document.createElement('div')this.box.setAttribute('id', 'notification')this.box.innerHTML = `<div class="content"></div><svg class="closeBox" width="40" height="40"><g class="close" style="stroke: white; stroke-width: 2; stroke-linecap: round;"><line x1="13" y1="13" x2="27" y2="27"/><line x1="13" y1="27" x2="27" y2="13"/></g><g class="progress" fill="transparent" stroke-width="3"><circle class="background" cx="20" cy="20" r="16" stroke="rgba(255,255,255,0.15)"/><circle class="circle" cx="20" cy="20" r="16" stroke="rgba(255,255,255,1)"/></g></svg>`document.body.appendChild(this.box)this.box.querySelector('.content').innerHTML = infolet width = getComputedStyle(this.box).widththis.box.style.left = `clac(50%-${width}/2)`this.box.querySelector('.closeBox .progress .circle').style['animation-duration'] = `${timeout}s`this.box.style.top = '100px'this.box.querySelector('.closeBox .progress').addEventListener('click', () => {console.log('you close...')this.close()console.log('you clear...')})if (autoClose) {setTimeout(() => {console.log('timeout close...')this.close()console.log('timeout clear ...')}, timeout * 1000)}},close() {this.box.style['transition-duration'] = '.23s'this.box.style['transition-timing-function'] = 'eaer-out'this.box.style.top = '-50px'setTimeout(() => {try {document.body.removeChild(this.box)} catch {console.log('clear')}}, 1000)}}})();(function() {'use strict'// create new XMLHttpRequestconst subtitleParser = {ass: {getItems(text) { return text.match(/Dialogue:.+/g) },getInfo(item) {let [from, to, content] = /Dialogue: 0,(.+?),(.+?),.*?,.*?,.*?,.*?,.*?,.*?,([^\n]+)/.exec(item).slice(1)return {from: toSeconds(from),to: toSeconds(to),content: content.replace(/{[\s\S]*?}/g, '').replaceAll('\\N', '<br/>').replaceAll('\\h', " ")}},},ssa: {getItems(text) { return text.match(/Dialogue:.+/g) },getInfo(item) {let [from, to, content] = /Dialogue: Marked=\d*?,(.+?),(.+?),.*?,.*?,.*?,.*?,.*?,.*?,([^\n]+)/.exec(item).slice(1)return {from: toSeconds(from),to: toSeconds(to),content: content.replace(/{[\s\S]*?}/g, '').replaceAll('\\N', '<br/>')}},},srt: {getItems(text) { return text.split(/(\r\n|\n)\1+/) },getInfo(item) {let lineArray = item.match(/(.+)/g)let [from, to] = lineArray[1].split(' --> ')return {from: toSeconds(from),to: toSeconds(to),content: lineArray.slice(2).join('<br/>').replaceAll(/{[\s\S]*?}/g, '')}},},}let subtitleTypelet toSeconds = (timeStr) => {let timeArr = timeStr.replace(',', '.').split(':')let timeSec = 0for (let i = 0; i < timeArr.length; i++) {timeSec += 60 ** (timeArr.length - i - 1) * parseFloat(timeArr[i])}return timeSec}// readfunction read(blob) {return new Promise(function(resolve, reject) {let reader = new FileReader()reader.onload = function(e) {let text = reader.r###lt// 可能错误编码方式if (text.indexOf("�") !== -1) {console.log('ERROR in UTF-8')console.log(`GBK ${fileInfo.name}`)return reader.readAsText(blob, 'GBK')}// 可能错误编码方式if (text.indexOf("") !== -1) {console.log('ERROR in UTF-8')console.log(`ISO-8859-1 ${fileInfo.name}`)languageEncoding(blob).then(info => reader.readAsText(blob, info.encoding))}resolve(reader)}reader.onerror = rejectreader.readAsText(blob, 'UTF-8')})}// parse subtitleasync function parseTextToArray(fileInfo) {if (Object.keys(fileInfo).includes("text")) returnconsole.log('fetch ' + fileInfo.name)let reader = await fetch(fileInfo.url, {headers: {Referer: 'https://www.aliyundrive.com/'}}).then(e => e.blob()).then(blob => {console.log(`UTF-8 ${fileInfo.name}`)return read(blob)})let text = reader.r###ltlet itemArray = subtitleParser[subtitleType].getItems(text)console.log(itemArray)let InfoArray = []itemArray.forEach((item) => {try {let info = subtitleParser[subtitleType].getInfo(item)InfoArray.push(info)}catch {console.log(`[ERROR] ${item}`)}})return InfoArray}// add subtitle to videolet addSubtitle = (subtitles) => {console.log('add subtitle...')window.startTime = 0window.endTime = 0const fontsize = 4.23// 00:00let percentNode = document.querySelector("[class^=modal] [class^=progress-bar] [class^=current]")let totalTimeNode = document.querySelector("[class^=modal] [class^=progress-bar] span:last-child")// create a subtitle divconst videoStageNode = document.querySelector("[class^=video-stage]")subtitleNode && subtitleNode.parentNode && subtitleNode.parentNode.removeChild(subtitleNode)subtitleNode = document.createElement('div')subtitleNode.setAttribute('id', 'subtitle')GM_addStyle(`#subtitle {position: absolute;display: flex;flex-direction: column-reverse;align-items: flex-end;color: white;width: 100%;height: 100%;bottom: 4vh;transition: bottom .2s linear;z-index: 9;}#subtitle .subtitleText {position: absolute;display: flex;align-items: center;justify-content: center;text-align: center;width: 100%;color: white;bottom: 0vh;text-shadow: 0 0 1px var(--basic_black);font-size: ${fontsize}vh;visibility: hidden;}@keyframes subtitle {from {visibility: visible;}to {visibility: visible;}}`)videoStageNode.appendChild(subtitleNode)console.log('add subtitleNode')// 观察变化let video = document.querySelector('video')const totalSec = video.durationconsole.log(`total time is ${totalSec}s`)let insertSubtitle = function (mutationsList, observer) {// 00:00:00 => 秒let timeSec = video.currentTime// 保护时间,防止重复if (timeSec > window.endTime || timeSec < window.startTime) {// 此时用户可能在拖动进度条,反之拖动后重叠,清空subtitleNodesubtitleNode.innerHTML = ""} else {let pTags = subtitleNode.querySelectorAll('[animationend]')for (let i=0;i<pTags.length;i++) {subtitleNode.removeChild(pTags[i])}}let existIndex = (index) => {if (subtitleNode.childNodes.length) {for (let i=0; i<subtitleNode.childNodes.length; i++) {if (subtitleNode.childNodes[i].getAttribute('index') == String(index)) {return true}}}return false}let searchIndex = function (target, arr) {let indexes = []for (let index=0;index<arr.length;index++) {let e = arr[index]if (target >= e.from && target <= e.to) {if (!existIndex(index)) {indexes.push(index)}}}return indexes}searchIndex(timeSec, subtitles).forEach((index) => {let on###btitle = subtitles[index]let subtitleText = document.createElement('p')subtitleText.setAttribute('class', 'subtitleText')subtitleText.setAttribute('index', String(index))subtitleText.innerHTML = on###btitle.contentlet duration = on###btitle.to - on###btitle.from - (timeSec - on###btitle.from)subtitleText.addEventListener('animationend', function() {subtitleText.setAttribute('animationend', '')})// 合适位置插入if (subtitleNode.childNodes.length) {// debuggerlet bottom = '0px'let i = 0while (true) {if (subtitleNode.childNodes[i]) {if (parseFloat(bottom.replace('px', '')) < parseFloat(subtitleNode.childNodes[i].style.bottom.replace('px', ''))) {subtitleText.style.bottom = bottomsubtitleNode.insertBefore(subtitleText, subtitleNode.childNodes[i])break} else {bottom = parseFloat(bottom.replace('px', '')) + parseFloat(getComputedStyle(subtitleNode.childNodes[i]).height.replace('px', '')) + 'px'i ++continue}} else {// px -> vh 相对高度,调整窗口自适应subtitleText.style.bottom = parseFloat(bottom.replace('px', '')) / parseFloat(window.innerHeight) * 100 + 'vh'subtitleNode.appendChild(subtitleText)break}}} else {subtitleNode.appendChild(subtitleText)}subtitleText.style.animation = `subtitle ${duration}s linear`// 记录结束时间window.startTime = on###btitle.fromwindow.endTime = on###btitle.toreturn true})}var config = { attributes: true, childList: true, subtree: true }var observer = new MutationObserver(insertSubtitle)observer.observe(percentNode, config)// 暂停播放事件let playBtnEvent = () => {subtitleNode.innerHTML = ""while (true) {if (!insertSubtitle(null, null)) {break}}subtitleNode.childNodes.forEach((p) => {p.style.visibility = 'visible'})}window.addEventListener('keydown', () => {if (window.event.which == 32 | window.event.which == 39 | window.event.which == 37) {playBtnEvent()}})document.querySelector('[class^=video-player]').addEventListener('click', () => {playBtnEvent()}, false)return observer}// observer rootconst rootNode = document.querySelector('#root')// no root, existif (!rootNode) { return }let obsArray = [], subtitleNodeconst callback = function (mutationList, observer) {// add subtitlesubtitleNode = document.querySelector('#subtitle')if (subtitleNode) {subtitleNode.parentNode.removeChild(subtitleNode)}let Node = mutationList[0].addedNodes[0]if (!Node || !Node.getAttribute('class').includes('modal')) { return }// clear observerobsArray.forEach(obs => {console.log(obs)console.log('disconnect')obs.disconnect()})obsArray = []console.log('add a video modal')/////////////////////// 获取文件夹内文件let fileInfoList = nulllet params = JSON.parse(window.localStorage.token)let drive_id = params.default_drive_idlet access_token = params.access_tokenlet parent_file_id = window.location.pathname.split("/").slice(-1)[0]console.log(drive_id, access_token, parent_file_id)GM_xmlhttpRequest({method: "POST",url: "https://api.aliyundrive.com/adrive/v3/file/list?jsonmask=next_marker,items(name,file_id,drive_id,url,file_extension)",data: JSON.stringify({drive_id: drive_id,parent_file_id: parent_file_id}),headers: {"authorization": `Bearer ${access_token}`,},responseType: "json",onload: function(res) {console.log(res.response)fileInfoList = res.response["items"]}})let id = setInterval(async function() {let modal = Node// find title nameif (modal.querySelectorAll('[class^=filename] span').length == 0 || fileInfoList == null) return// 检查text是否加载完毕clearInterval(id)let filename = modal.querySelector('[class^=filename] span').innerTextlet title = filename.split('.').slice(0, -1).join('.')console.log(title)console.log(fileInfoList)// search the corresponding ass urllet isInclude = (c1, c2) => {return c1.match(new RegExp((c2.split('.').slice(0, -1).join('.') || c2).replace('(', '\\(').replace(')', '\\)'), 'i'))}// 先过滤出适配的字幕格式文件fileInfoList = fileInfoList.filter((fileInfo) => {if (Object.keys(subtitleParser).includes(fileInfo.name.split('.').slice(-1)[0])) {return true}})let fileInfo = fileInfoList.filter((fileInfo) => {if (!fileInfo.name.includes('.')) return falseif (fileInfo.name == filename) return false// 你中有我,或我中有你let flag = isInclude(fileInfo.name, title) || isInclude(title, fileInfo.name)// S01E01样式匹配const reg = /s\d+e\d+/ilet subtitleMatch = fileInfo.name.match(reg)let videoMatch = title.match(reg)if (!flag) {flag =  subtitleMatch && videoMatch && subtitleMatch[0].toUpperCase() == videoMatch[0].toUpperCase()}// 单音频单字幕文件直接匹配,因为没得选if (fileInfoList.length == 1) {flag = true}return flag})console.log(fileInfo)// no file, exitif (!fileInfo.length) {console.log('subtitle exit...'); return}fileInfo = fileInfo[0]console.log(fileInfo)subtitleType = fileInfo.name.split('.').slice(-1)console.log(`[subtitleType] ${subtitleType}`)let subtitles = await parseTextToArray(fileInfo)obsArray.push(addSubtitle(subtitles))console.log(`${subtitles.length}条字幕添加成功`)notification.open(`${subtitles.length}条字幕添加成功`, 3)// 是否变更视频let obs = new MutationObserver((mutationList, obs) => {let filenameNode = modal.querySelector('[class^=header] [class^=text]')if (filenameNode && filenameNode.innerText !== filename) {setTimeout(() => {callback([{addedNodes: [modal]}], null)}, 0)}})obs.observe(modal, {subtree: true, childList: true})obsArray.push(obs)// 是否触发控制条let playerTool = document.querySelector('[class^=video-player]')let offsetSubtitle = (mutationList, obs) => {// let subtitleNode = document.querySelector('#subtitle')if (subtitleNode && mutationList[0].attributeName == 'class') {if (mutationList[0].target.classList.length == 2 && document.fullscreenElement) {subtitleNode.style['bottom'] = '13vh'} else {subtitleNode.style['bottom'] = '4vh'}}}obs = new MutationObserver(offsetSubtitle)obs.observe(playerTool, {attributes: true, childList: true})offsetSubtitle([{attributeName: 'class', target: playerTool}])obsArray.push(obs)document.onfullscreenchange = () => {offsetSubtitle([{attributeName: 'class', target: playerTool}], obs)}}, 10)}const observer = new MutationObserver(callback)observer.observe(rootNode, {childList: true})})();