From cd96cdfce29c623fd21aa6c953cf4b7f3ec90b70 Mon Sep 17 00:00:00 2001 From: the1812 Date: Sat, 2 Nov 2019 23:45:13 +0800 Subject: [PATCH] Refactor VideoDownloader --- @types/global/index.d.ts | 2 + bilibili-evolved.offline.user.js | 17 +- bilibili-evolved.preview-offline.user.js | 17 +- bilibili-evolved.preview.user.js | 15 +- bilibili-evolved.user.js | 15 +- min/bundle.json | 8 +- min/bundle.zip | Bin 1430330 -> 1431006 bytes min/download-video-package.min.js | 2 +- min/download-video.min.html | 2 +- min/download-video.min.js | 2 +- min/video-dash.min.js | 2 +- src/client/resource-manifest.js | 6 +- src/client/settings.js | 1 + .../download-video/download-video-package.ts | 70 +++-- src/video/download-video/download-video.html | 5 + src/video/download-video/download-video.ts | 240 +++++++++++------- src/video/download-video/video-dash.ts | 8 +- 17 files changed, 267 insertions(+), 145 deletions(-) diff --git a/@types/global/index.d.ts b/@types/global/index.d.ts index fcef0b498..0aaee3f58 100644 --- a/@types/global/index.d.ts +++ b/@types/global/index.d.ts @@ -35,6 +35,7 @@ declare global { } type RunAtOptions = "document-start" | "document-end" | "document-idle" | "document-body" | "context-menu"; type DanmakuOption = '无' | 'XML' | 'ASS' + type FfmpegOption = '无' | '文件列表' | '文件列表+脚本' type Pattern = string interface RpcOption { secretKey: string @@ -369,6 +370,7 @@ declare global { customNavbarSeasonLogo: boolean, selectableColumnText: boolean, downloadVideoFormat: 'flv' | 'dash', + downloadVideoFfmpegSupport: FfmpegOption, enableDashDownload: boolean, watchlaterExpireWarnings: boolean, watchlaterExpireWarningDays: number, diff --git a/bilibili-evolved.offline.user.js b/bilibili-evolved.offline.user.js index a55d0369e..69f800fce 100644 --- a/bilibili-evolved.offline.user.js +++ b/bilibili-evolved.offline.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name Bilibili Evolved (Offline) -// @version 473.02 +// @version 474.33 // @description Bilibili Evolved 的离线版, 所有功能都已内置于脚本中. // @author Grant Howard, Coulomb-G // @copyright 2019, Grant Howard (https://github.com/the1812) & Coulomb-G (https://github.com/Coulomb-G) @@ -365,6 +365,7 @@ const settings = { customNavbarSeasonLogo: false, selectableColumnText: true, downloadVideoFormat: 'flv', + downloadVideoFfmpegSupport: '无', enableDashDownload: false, watchlaterExpireWarnings: true, watchlaterExpireWarningDays: 14, @@ -1084,10 +1085,10 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/double-click-fullscreen.min.js"] = (()=>{return(i,e)=>{(async()=>{const e=["https://www.bilibili.com/bangumi/","https://www.bilibili.com/video/"];if(!e.some(i=>document.URL.startsWith(i))){return}if(i.touchVideoPlayer&&i.touchVideoPlayerDoubleTapControl){Toast.info("在开启了播放器触摸支持-启用双击控制后, 双击全屏功能将无效.","提示");i.doubleClickFullscreen=false;return}await SpinQuery.unsafeJquery();const l=await SpinQuery.condition(()=>dq(".bilibili-player-area"),i=>i!==null&&unsafeWindow.$(".bilibili-player-video").data("events"));if(l===null){return}const n="double-click-fullscreen";if(!l.classList.contains(n)){l.classList.add(n);const e=unsafeWindow.$(".bilibili-player-video");const t=i.doubleClickFullscreenPreventSingleClick?e.data("events").click[0].handler:()=>{};const c=new DoubleClickEvent(()=>dq(".bilibili-player-video-btn-fullscreen").click(),i=>t(i));if(i.doubleClickFullscreenPreventSingleClick){e.unbind("click")}c.bind(e[0])}})()}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-audio.min.js"] = (()=>{return(e,t)=>{class n{constructor(){this.sid=null;this.progress=null}async getDownloadUrl(){const e=`https://www.bilibili.com/audio/music-service-c/web/url?sid=${this.sid}&privilege=2&quality=2`;const t=await Ajax.getJsonWithCredentials(e);if(t.code===0){return t.data.cdns.shift()}else{logError("获取下载链接失败, 请确保当前账号有下载权限.","下载音频",1e4);return null}}async download(){const e=await this.getDownloadUrl();return new Promise((t,n)=>{const s=new XMLHttpRequest;s.open("GET",e);s.responseType="blob";s.addEventListener("load",()=>t(s.response));s.addEventListener("error",()=>n(s.status));s.addEventListener("progress",e=>this.progress&&this.progress(100*e.loaded/e.total));s.send()})}}const s="下载音频";return{export:n,widget:{content:`\n\n\n${s}\n\n`,condition:()=>document.URL.includes("bilibili.com/audio"),success:async()=>{await SpinQuery.select(()=>document.querySelector("#app"));const e=document.querySelector("#download-audio");const t=e.querySelector("span");const o=new n;o.progress=(e=>{t.innerHTML=`${Math.round(e)}%`});const i=document.querySelector("#download-audio-link");e.addEventListener("click",async e=>{if(o.sid===null||e.target===i){return}const n=await o.download();t.innerHTML=s;const r=i.getAttribute("href");if(r){URL.revokeObjectURL(r)}i.setAttribute("href",URL.createObjectURL(n));const d=(()=>{const e=document.querySelector(".song-title");if(e){return e.getAttribute("title")}else{return"神秘音频"}})();i.setAttribute("download",d+".m4a");i.click()});Observer.childList("#app",()=>{const t=document.URL.match(/bilibili\.com\/audio\/au([\d]+)/);if(t&&t[1]){e.disabled=false;o.sid=t[1]}else{e.disabled=true}})}}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-danmaku.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:n}=e.import("title");const{DanmakuInfo:i}=e.import("video-info");const{DanmakuConverter:a}=e.import("danmaku-converter");async function o(t){const e=n();let i={title:e};try{await loadDanmakuSettingsPanel();const t=t=>{const e=parseFloat(dq(t).style.transform.replace(/translateX\(([\d\.]+)/,"$1"));const n={0:0,44:1,94:2,144:3,188:4}[e];return n};i.font=dq(".bilibili-player-video-danmaku-setting-right-font .bui-select-result").innerText;i.alpha=parseFloat(dq(".bilibili-player-setting-opacity .bui-bar").style.transform.replace(/scaleX\(([\d\.]+)\)/,"$1"));i.duration=(()=>{const e=[18,14,10,8,6][t(".bilibili-player-setting-speedplus .bui-thumb")];return t=>{switch(t.type){case 4:case 5:return 4;default:return e}}})();i.blockTypes=(()=>{let t=[];const e={".bilibili-player-block-filter-type[ftype=scroll]":[1,2,3],".bilibili-player-block-filter-type[ftype=top]":[5],".bilibili-player-block-filter-type[ftype=bottom]":[4],".bilibili-player-block-filter-type[ftype=color]":["color"]};for(const[n,i]of Object.entries(e)){if(dq(n).classList.contains("disabled")){t=t.concat(i)}}return t.concat(7,8)})();const e=[1.4,1.2,1,.8,.6][t(".bilibili-player-setting-fontsize .bui-thumb")];i.resolution={x:1920*e,y:1080*e};i.bottomMarginPercent=[.75,.5,.25,0,0][t(".bilibili-player-setting-area .bui-thumb")];if(i.bottomMarginPercent===0&&dq(".bilibili-player-video-danmaku-setting-left-preventshade input").checked){i.bottomMarginPercent=.15}i.bold=dq(".bilibili-player-video-danmaku-setting-right-font-bold input").checked}catch(t){i={font:"微软雅黑",alpha:.6,duration:t=>{switch(t.type){case 4:case 5:return 4;default:return 6}},blockTypes:[7,8],resolution:{x:1920,y:1080},bottomMarginPercent:.15,bold:false}}const o=new a(i);const l=o.convertToAssDocument(t);return l.generateAss()}async function l(t,e){const a=n();const l=new i((unsafeWindow||window).cid);await l.fetchInfo();const r=await(async()=>{if(t===true){return new Blob([await o(l.rawXML)],{type:"text/plain"})}else{return new Blob([l.rawXML],{type:"text/plain"})}})();const s=URL.createObjectURL(r);const c=dq("#danmaku-link");const d=c.getAttribute("href");if(d){URL.revokeObjectURL(d)}clearTimeout(e);dq("#download-danmaku>span").innerHTML="下载弹幕";c.setAttribute("download",`${a}.${t?"ass":"xml"}`);c.setAttribute("href",s);c.click()}return{export:{downloadDanmaku:l,convertToAss:o},widget:{content:`\n\n\n下载弹幕\n\n`,condition:async()=>{let t=await SpinQuery.select(()=>(unsafeWindow||window).cid);return Boolean(t)},success:()=>{const t=document.querySelector("#danmaku-link");dq("#download-danmaku").addEventListener("click",e=>{if(e.target!==t){const t=setTimeout(()=>dq("#download-danmaku>span").innerHTML="请稍侯...",200);l(e.shiftKey,t)}})}}}}})(); -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video-package.min.js"] = (()=>{return(e,t)=>{class n{constructor(e={}){this.config=e;this.entries=[]}download(e,t){const n=document.createElement("a");const i=URL.createObjectURL(t);n.setAttribute("href",i);n.setAttribute("download",e);document.body.appendChild(n);n.click();n.remove();URL.revokeObjectURL(i)}add(e,t){if(t===null||t===undefined){return}this.entries.push({name:e,data:t})}async emit(e){if(this.entries.length===0){return}if(!e||this.entries.length===1){e=this.entries[0].name}if(this.entries.length===1){const t=this.entries[0].data;this.download(e,typeof t==="string"?new Blob([t]):t);return}const t=new JSZip;this.entries.forEach(({name:e,data:n})=>{t.file(e,n)});const n=await t.generateAsync({type:"blob"});this.download(e,n)}static async single(e,t){const i=new n;i.add(e,t);await i.emit()}}return{export:{DownloadVideoPackage:n}}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video-package.min.js"] = (()=>{return(e,t)=>{class n{constructor(e={}){this.config=e;this.entries=[]}download(e,t){const i=document.createElement("a");const a=URL.createObjectURL(t);if(n.lastPackageUrl){URL.revokeObjectURL(n.lastPackageUrl)}n.lastPackageUrl=a;i.setAttribute("href",a);i.setAttribute("download",e);document.body.appendChild(i);i.click();i.remove()}add(e,t){if(t===null||t===undefined){return}this.entries.push({name:e,data:t})}async preEmit(){const e=this.entries.filter(e=>[".flv",".mp4",".m4s"].some(t=>e.name.endsWith(t)));if(this.config.ffmpeg!==undefined&&e.length>=2){if(this.config.ffmpeg==="文件列表"||this.config.ffmpeg==="文件列表+脚本"){this.entries.push({name:"ffmpeg-files.txt",data:e.map(e=>`file '${e.name}'`).join("\n")})}if(this.config.ffmpeg==="文件列表+脚本"){const e=`ffmpeg -f concat -i ffmpeg-files.txt -c copy ""`;this.entries.push({name:"ffmpeg.bat",data:e},{name:"ffmpeg.sh",data:e.replace(/"/g,"'")})}}}async blob(){await this.preEmit();if(this.entries.length===0){return null}if(this.entries.length===1){const e=this.entries[0].data;return typeof e==="string"?new Blob([e]):e}const e=new JSZip;this.entries.forEach(({name:t,data:n})=>{e.file(t,n)});return await e.generateAsync({type:"blob"})}async emit(e){if(!e||this.entries.length===1){e=this.entries[0].name}const t=await this.blob();if(!t){return}return this.download(e,t)}static async single(e,t,i={}){const a=new n(i);a.add(e,t);return await a.emit()}}n.lastPackageUrl="";return{export:{DownloadVideoPackage:n}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.css"] = `.download-video{--download-video-background:white;--download-video-foreground:black;position:absolute;top:64px;left:50%;transform:translateX(-50%) scale(.95);background:var(--download-video-background);color:var(--download-video-foreground);box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;z-index:10001;pointer-events:none;opacity:0;padding:16px;width:300px;display:flex;flex-direction:column;align-items:stretch;justify-content:space-between}.download-video,.download-video *{transition:.2s ease-out;-webkit-tap-highlight-color:transparent!important}.download-video.opened{pointer-events:initial;opacity:1;transform:translateX(-50%) scale(1)}body.dark .download-video{--download-video-background:#222;--download-video-foreground:#eee}.round-corner .download-video,.round-corner .download-video .episode-list .v-checkbox,.round-corner .download-video .rpc-settings{border-radius:var(--large-corner-radius)}.round-corner .download-video .button,.round-corner .download-video .cover,.round-corner .download-video .direct-download .progress .background,.round-corner .download-video .direct-download .progress .foreground,.round-corner .download-video .rpc-settings input[type=text],.round-corner .download-video .title,.round-corner .download-video button{border-radius:var(--corner-radius)}.download-video .cover{width:240px;min-height:135px;max-height:200px;object-fit:contain}.download-video .header{display:flex;justify-content:space-between;align-items:center}.download-video h1{font-size:16pt;font-weight:700;color:var(--download-video-foreground)}.download-video .header .mdi-close{font-size:16pt;color:var(--download-video-foreground);cursor:pointer}.download-video .header .mdi-close:hover{color:var(--theme-color)}.download-video .info{display:flex;flex-direction:column;align-items:center;margin-top:12px}.download-video .title{display:flex;flex-direction:column;justify-content:space-between;align-items:stretch;margin-top:12px}.download-video .title .bold{width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.download-video .title .size{font-size:10pt;color:var(--download-video-foreground);align-self:center;display:flex;align-items:center;height:24px}.download-video .bold{color:var(--download-video-foreground);font-weight:700;font-size:12pt}.download-video .option-item{display:flex;justify-content:space-between;align-items:center;padding-top:12px;font-size:10pt}.download-video .tabs{display:flex;padding-top:12px;font-size:10pt}.download-video .tabs .tab{padding:6px 12px;border-bottom:2px solid transparent;cursor:pointer}.download-video .tabs .tab.active{color:var(--theme-color);border-bottom-color:var(--theme-color)}.download-video .separator{height:1px;background:#8884;width:100%;margin:12px 0;flex-shrink:0}.download-video h2{font-size:12pt;font-weight:700;color:var(--download-video-foreground)}.download-video .direct-download{display:flex;flex-direction:column;align-items:start;justify-content:space-between}.download-video .button,.download-video button{border:none;outline:0!important;padding:6px 16px;font-size:10pt;cursor:pointer;background:#8884;color:var(--download-video-foreground)}.download-video .button:hover,.download-video button:hover{background:#8886}.download-video .primary{background:var(--theme-color);color:var(--foreground-color);align-self:center}.download-video .primary:hover{background:var(--theme-color-90)}.download-video .busy .button,.download-video .busy .primary,.download-video .busy button,.download-video button:disabled{background-color:#0001;color:#8884;cursor:not-allowed}.download-video .busy .button,.download-video .busy button{cursor:wait!important}.download-video .direct-download .progress{align-self:stretch;display:flex;align-items:center;margin-top:8px}.download-video .direct-download .progress .background{flex-grow:1;height:4px;background:#8884;margin-right:4px;position:relative}.download-video .direct-download .progress .background .foreground{position:absolute;top:0;left:0;height:4px;background:linear-gradient(to right,var(--theme-color),var(--theme-color-60))}.download-video .direct-download .progress .percent{width:50px;text-align:right}.download-video .actions{display:flex;flex-wrap:wrap;justify-content:space-between;margin:8px -4px 0}.download-video .actions>*{margin:4px;flex-grow:1;flex-basis:calc(50% - 16px);display:flex;justify-content:center;align-items:center}.download-video i.mdi-alert-circle{font-size:14pt;color:#ff9800}.download-video .size-warning{position:relative;padding:0 8px}.download-video .size-warning-tip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:var(--download-video-background);color:var(--download-video-foreground);border:1px dashed var(--theme-color);z-index:2;font-size:10pt;width:200px;padding:8px;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;pointer-events:none;opacity:0}.download-video .size-warning:hover .size-warning-tip{opacity:1}.download-video .episode-list .v-checkbox{padding:4px 8px;margin:4px 0;position:relative;background-color:transparent}.download-video .episode-list .v-checkbox.checked{background-color:#8882}.download-video .episode-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.download-video .episode-list{overflow:auto;max-height:320px}.download-video button.list-tool{padding:4px;line-height:1;font-size:12pt;margin:0 4px}.download-video .episode-header h2{flex-grow:1}.download-video .selected-count{width:64px;text-align:right}.download-video .aria2-rpc .mdi{margin-left:8px;font-size:14pt;line-height:1}.download-video .aria2-rpc{position:relative}.download-video .rpc-settings{position:absolute;display:flex;flex-direction:column;align-items:stretch;color:var(--download-video-foreground);background:#fff;bottom:120%;left:50%;cursor:initial;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;transform-origin:bottom;transform:translateX(-50%) scale(.9);opacity:0;pointer-events:none;padding:8px;z-index:3;transition:.3s cubic-bezier(.18,.89,.32,1.28);width:120%}body.dark .download-video .rpc-settings{background:#282828}.download-video .rpc-settings>*{margin:8px}.download-video .rpc-settings.show{opacity:1;transform:translateX(-50%) scale(1);pointer-events:initial}.download-video .rpc-settings input[type=text]{background:0 0;color:var(--download-video-foreground);border:1px solid #8884;padding:4px;margin-left:8px}.download-video .rpc-settings input[type=text]:focus{border-color:var(--theme-color)}.download-video .rpc-settings .operations{display:flex;align-items:center;justify-content:space-evenly}.download-video .final-dir{word-break:break-all}.download-video .rpc-settings-item{display:flex;align-items:center;justify-content:space-between;white-space:nowrap}.download-video .rpc-settings-item input[type=text]{flex-grow:1;margin-left:24px}.download-video button.cancel-download,.download-video button.start-download{margin-top:8px}.download-video .direct-download-header{align-self:stretch;display:flex;justify-content:space-between;align-items:center}body.dark .download-video .direct-download .progress .foreground{background:linear-gradient(to right,var(--theme-color-70),var(--theme-color))}`; -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.html"] = `

下载视频

单个视频
批量导出
警告: 过大的视频大小会在直接下载时占用大量内存, 并可能导致浏览器标签页崩溃. 请考虑降低清晰度或使用导出选项.
预计大小: {{displaySize}}
格式
清晰度
弹幕

直接下载

{{speed}}
{{progressPercent}}%

选集

{{selectedEpisodeCount}}/{{episodeList.length}}

导出

{{showRpcSettings ? '取消' : 'aria2 RPC'}}

aria2 RPC

配置

主机
端口
密钥
限速
默认路径
路径
最终路径: {{rpcSettings.baseDir + rpcSettings.dir}}
方法
开始下载
{{saveRpcSettingsText}}
`; -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:a}=e.import("title");const{VideoInfo:s,DanmakuInfo:i}=e.import("video-info");class o{async getDashUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json&fnver=0&fnval=16`}else{return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&otype=json&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&otype=json`}}}class n extends o{async getDashUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&qn=${t}&otype=json&fourk=1&fnval=16`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&otype=json&fourk=1&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=${r.aid}&cid=${r.cid}&qn=&otype=json`}}}const r={entity:new o,aid:"",cid:""};let l=[];let c=null;class d{constructor(t,e,a){this.quality=t;this.internalName=e;this.displayName=a}async downloadInfo(t=false){const e=new h(this);await e.fetchVideoInfo(t);return e}static parseFormats(t){const e=t.accept_quality;const a=t.accept_format.split(",");const s=t.accept_description;const i=e.map((t,e)=>{return new d(t,a[e],s[e])});return i}static async getAvailableDashFormats(){const t=await r.entity.getDashUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}return d.parseFormats(e.data||e.result||e)}static async getAvailableFormats(){const t=await r.entity.getUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}const a=e.data||e.result||e;return d.parseFormats(a)}}class h{constructor(t,e){this.fragmentSplitFactor=6*2;this.workingXhr=null;this.progressMap=new Map;this.format=t;this.fragments=e||[];this.videoSpeed=new p(this)}get totalSize(){return this.fragments.map(t=>t.size).reduce((t,e)=>t+e)}async fetchVideoInfo(t=false){if(!t){const t=await r.entity.getUrl(this.format.quality);const e=await Ajax.getTextWithCredentials(t);const a=JSON.parse(e.replace(/http:/g,"https:"));const s=a.data||a.result||a;if(s.quality!==this.format.quality){throw new Error("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const i=s.durl;this.fragments=i.map(t=>{return{length:t.length,size:t.size,url:t.url,backupUrls:t.backup_url}})}else{const{dashToFragment:t,getDashInfo:a}=await e.importAsync("video-dash");const s=await a(await r.entity.getDashUrl(this.format.quality),this.format.quality);const i=s.videoDashes.sort(ascendingSort(t=>t.bandWidth))[0];const o=s.audioDashes.sort(ascendingSort(t=>t.bandWidth))[0];this.fragments=[t(i),t(o)]}return this.fragments}updateProgress(){const t=this.progressMap?[...this.progressMap.values()].reduce((t,e)=>t+e,0)/this.totalSize:0;if(t>1||t<0){console.error(`[下载视频] 进度异常: ${t}`,this.progressMap.values())}this.progress&&this.progress(t)}cancelDownload(){this.videoSpeed.stopMeasure();if(this.workingXhr!==null){this.workingXhr.forEach(t=>t.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(t){const e=[];this.workingXhr=[];this.progressMap=new Map;this.updateProgress();let a;if(t.size<=96*1024*1024){a=t.size/this.fragmentSplitFactor}else{a=16*1024*1024}let s=0;const i=t=>[...this.progressMap.keys()].indexOf(t)+1;while(s{const s=new XMLHttpRequest;s.open("GET",t.url);s.responseType="arraybuffer";s.withCredentials=false;s.addEventListener("progress",t=>{console.log(`[下载视频] 视频片段${i(s)}下载进度: ${t.loaded}/${r} bytes loaded, ${n}`);this.progressMap.set(s,t.loaded);this.updateProgress()});s.addEventListener("load",()=>{if((""+s.status)[0]==="2"){console.log(`[下载视频] 视频片段${i(s)}下载完成`);e(s.response)}else{a(`视频片段${i(s)}请求失败, response = ${s.status}`)}});s.addEventListener("abort",()=>a("canceled"));s.addEventListener("error",()=>{console.error(`[下载视频] 视频片段${i(s)}下载失败: ${n}`);this.progressMap.set(s,0);this.updateProgress();s.open("GET",t.url);s.setRequestHeader("Range",n);s.send()});s.setRequestHeader("Range",n);this.progressMap.set(s,0);s.send();this.workingXhr.push(s)}));s=Math.round(s+a)+1}return Promise.all(e)}async copyUrl(){const t=this.fragments.map(t=>t.url).reduce((t,e)=>t+"\r\n"+e);GM.setClipboard(t,"text")}async showUrl(){const t=this.fragments.map(t=>`\n${t.url}\n`).reduce((t,e)=>t+"\r\n"+e);Toast.success(t+`复制全部`,"显示链接");const e=await SpinQuery.select("#copy-link");e.addEventListener("click",async()=>{await this.copyUrl()})}async exportData(t=false){const s=JSON.stringify([{fragments:this.fragments,title:a(),totalSize:this.fragments.map(t=>t.size).reduce((t,e)=>t+e),referer:document.URL.replace(window.location.search,"")}]);if(t){GM.setClipboard(s,"text")}else{const t=new Blob([s],{type:"text/json"});const i=await this.downloadDanmaku();const{DownloadVideoPackage:o}=await e.importAsync("download-video-package");const n=new o;n.add(`${a()}.json`,t);n.add(a()+"."+this.danmakuOption.toLowerCase(),i);await n.emit(`${a()}.zip`)}}async exportAria2(s=false){if(s){const s=await this.downloadDanmaku();if(s!==null){const{DownloadVideoPackage:t}=await e.importAsync("download-video-package");t.single(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,s)}const i=t.aria2RpcOption;const o=this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}const o=[];if(i.secretKey!==""){o.push(`token:${i.secretKey}`)}o.push([t.url]);o.push({referer:document.URL.replace(window.location.search,""),"user-agent":UserAgent,out:`${a()}${s}${this.extension(t)}`,split:this.fragmentSplitFactor,dir:i.baseDir+i.dir||undefined,"max-download-limit":i.maxDownloadLimit||undefined});const n=encodeURIComponent(`${a()}${s}`);return{params:o,id:n}});const{sendRpc:n}=await e.importAsync("aria2-rpc");await n(o)}else{const t=`\n# Generated by Bilibili Evolved Video Export\n# https://github.com/the1812/Bilibili-Evolved/\n${this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}return`\n${t.url}\n referer=${document.URL.replace(window.location.search,"")}\n user-agent=${UserAgent}\n out=${a()}${s}${this.extension(t)}\n split=${this.fragmentSplitFactor}\n`.trim()}).join("\n")}\n`.trim();const s=new Blob([t],{type:"text/plain"});const i=await this.downloadDanmaku();const{DownloadVideoPackage:o}=await e.importAsync("download-video-package");const n=new o;n.add(`${a()}.txt`,s);n.add(a()+"."+this.danmakuOption.toLowerCase(),i);await n.emit(`${a()}.zip`)}}extension(t){const e=t||this.fragments[0];const a=[".flv",".mp4",".m4s"].find(t=>e.url.includes(t));if(a){return a}else{console.warn("No extension detected.");return".flv"}}makeBlob(t,e){return new Blob(Array.isArray(t)?t:[t],{type:this.extension(e)===".flv"?"video/x-flv":"video/mp4"})}cleanUpOldBlobUrl(){const t=dq("a#video-complete").getAttribute("href");if(t&&!dq(`.link[href="${t}"]`)){URL.revokeObjectURL(t)}dqa(".toast-card-header").filter(t=>t.innerText.includes("下载视频")).forEach(t=>t.querySelector(".toast-card-dismiss").click())}async downloadDanmaku(){if(this.danmakuOption!=="无"){const t=new i(r.cid);await t.fetchInfo();if(this.danmakuOption==="XML"){return t.rawXML}else{const{convertToAss:a}=await e.importAsync("download-danmaku");return a(t.rawXML)}}else{return null}}async downloadSingle(t){const e=await this.downloadDanmaku();const[s]=t;if(e===null){const t=this.makeBlob(s);const e=a()+this.extension();return{blob:t,filename:e}}else{const t=new JSZip;t.file(a()+this.extension(),this.makeBlob(s));t.file(a()+"."+this.danmakuOption.toLowerCase(),e);const i=await t.generateAsync({type:"blob"});const o=a()+".zip";return{blob:i,filename:o}}}async downloadMultiple(t){const e=new JSZip;const s=a();if(t.length>1){t.forEach((t,a)=>{const i=this.fragments[a];e.file(`${s} - ${a+1}${this.extension(i)}`,this.makeBlob(t,i))})}else{const[a]=t;e.file(`${s}${this.extension()}`,this.makeBlob(a))}const i=await this.downloadDanmaku();if(i!==null){e.file(a()+"."+this.danmakuOption.toLowerCase(),i)}const o=await e.generateAsync({type:"blob"});const n=s+".zip";return{blob:o,filename:n}}async download(){const t=[];this.videoSpeed.startMeasure();for(const e of this.fragments){const a=await this.downloadFragment(e);t.push(a)}if(t.length<1){throw new Error("下载失败.")}let{blob:e,filename:a}=await(async()=>{if(t.length===1){return await this.downloadSingle(t)}else{return await this.downloadMultiple(t)}})();this.cleanUpOldBlobUrl();const s=URL.createObjectURL(e);this.progress&&this.progress(0);this.videoSpeed.stopMeasure();return{url:s,filename:a}}}class p{constructor(t){this.lastProgress=0;this.measureInterval=1e3;this.workingDownloader=t}startMeasure(){this.intervalTimer=setInterval(()=>{const t=this.workingDownloader.progressMap?[...this.workingDownloader.progressMap.values()].reduce((t,e)=>t+e,0):0;const e=t-this.lastProgress;if(this.speedUpdate!==undefined){this.speedUpdate(formatFileSize(e)+"/s")}this.lastProgress=t},this.measureInterval)}stopMeasure(){clearInterval(this.intervalTimer)}}async function u(){const t=await SpinQuery.select(()=>(unsafeWindow||window).aid);const e=await SpinQuery.select(()=>(unsafeWindow||window).cid);if(!(t&&e)){return false}r.aid=t;r.cid=e;if(document.URL.indexOf("bangumi")!==-1){r.entity=new n}else{r.entity=new o}try{l=await d.getAvailableFormats()}catch(t){return false}return true}async function f(){c=l[0];e.applyStyle("downloadVideoStyle");dq("#download-video").addEventListener("click",()=>{dq(".download-video").classList.toggle("opened");dq(".gui-settings-mask").click()});dq("#download-video").addEventListener("mouseover",()=>{document.body.insertAdjacentHTML("beforeend",e.import("downloadVideoHtml"));w()},{once:true})}async function w(){let o;const n=new Map;const h=new Vue({el:".download-video",components:{VDropdown:()=>e.importAsync("v-dropdown.vue"),VCheckbox:()=>e.importAsync("v-checkbox.vue"),RpcProfiles:()=>e.importAsync("aria2-rpc-profiles.vue")},data:{downloadSingle:true,coverUrl:EmptyImageUrl,aid:r.aid,cid:r.cid,dashModel:{value:t.downloadVideoFormat,items:["flv","dash"]},qualityModel:{value:c.displayName,items:l.map(t=>t.displayName)},danmakuModel:{value:t.downloadVideoDefaultDanmaku,items:["无","XML","ASS"]},progressPercent:0,size:"获取大小中",blobUrl:"",episodeList:[],downloading:false,speed:"",batch:false,rpcSettings:t.aria2RpcOption,showRpcSettings:false,busy:false,saveRpcSettingsText:"保存配置",enableDash:t.enableDashDownload},computed:{displaySize(){if(typeof this.size==="string"){return this.size}return formatFileSize(this.size)},sizeWarning(){if(typeof this.size==="string"){return false}return this.size>1073741824},selectedEpisodeCount(){return this.episodeList.filter(t=>t.checked).length},dash(){return this.dashModel.value==="dash"}},methods:{close(){this.$el.classList.remove("opened")},danmakuOptionChange(){t.downloadVideoDefaultDanmaku=this.danmakuModel.value},async dashChange(){const t=this.dashModel.value;let e=[];if(t==="flv"){e=await d.getAvailableFormats()}else{e=await d.getAvailableDashFormats()}l=e;[c]=t;this.qualityModel.items=e.map(t=>t.displayName);[this.qualityModel.value]=this.qualityModel.items;await this.formatChange()},async formatChange(){const t=this.getFormat();const e=n.get(t);if(e){this.size=e;return}try{this.size="获取大小中";const e=await t.downloadInfo(this.dash);this.size=e.totalSize;n.set(t,this.size)}catch(t){this.size="获取大小失败"}},getFormat(){const t=l.find(t=>t.displayName===this.qualityModel.value);if(!t){console.error(`No format found. model value = ${this.qualityModel.value}`);return null}return t},async exportData(t){if(this.busy===true){return}try{this.busy=true;if(!this.downloadSingle){await this.exportBatchData(t);return}const e=this.getFormat();const a=await e.downloadInfo(this.dash);a.danmakuOption=this.danmakuModel.value;switch(t){case"copyLink":await a.copyUrl();Toast.success("已复制链接到剪贴板.","下载视频",3e3);break;case"showLink":await a.showUrl();break;case"aria2":await a.exportAria2(false);break;case"aria2RPC":await a.exportAria2(true);break;case"copyVLD":await a.exportData(true);Toast.success("已复制VLD数据到剪贴板.","下载视频",3e3);break;case"exportVLD":await a.exportData(false);break;default:break}}catch(t){logError(t)}finally{this.busy=false}},async exportBatchData(t){const s=this.episodeList;if(s.every(t=>t.checked===false)){Toast.info("请至少选择1集或以上的数量!","批量导出",3e3);return}const o=t=>{const e=s.find(e=>e.cid===t.cid);if(e===undefined){return false}return e.checked};const n=this.getFormat();const{DownloadVideoPackage:r}=await e.importAsync("download-video-package");if(this.danmakuModel.value!=="无"){const t=Toast.info("下载弹幕中...","批量导出");const a=new r;try{if(this.danmakuModel.value==="XML"){for(const t of s.filter(o)){const e=new i(t.cid);await e.fetchInfo();a.add(t.title+".xml",e.rawXML)}}else{const{convertToAss:t}=await e.importAsync("download-danmaku");for(const e of s.filter(o)){const s=new i(e.cid);await s.fetchInfo();a.add(e.title+".ass",await t(s.rawXML))}}await a.emit(this.cid+".danmakus.zip")}catch(t){logError(`弹幕下载失败`)}finally{t.dismiss()}}const l=Toast.info("获取链接中...","批量导出");this.batchExtractor.itemFilter=o;let c;try{switch(t){case"aria2":c=await this.batchExtractor.collectAria2(n,l);await r.single(a(false)+".txt",new Blob([c],{type:"text/plain"}));return;case"aria2RPC":await this.batchExtractor.collectAria2(n,l,true);Toast.success(`成功发送了批量请求.`,"aria2 RPC",3e3);return;case"copyVLD":GM.setClipboard(await this.batchExtractor.collectData(n,l),{mimetype:"text/plain"});Toast.success("已复制批量vld数据到剪贴板.","批量导出",3e3);return;case"exportVLD":c=await this.batchExtractor.collectData(n,l);await r.single(a(false)+".json",new Blob([c],{type:"text/json"}));return;default:return}}catch(t){logError(t)}finally{l.dismiss()}},async checkBatch(){const t=["/www.bilibili.com/bangumi","/www.bilibili.com/video/av"];if(!t.some(t=>document.URL.includes(t))){this.batch=false;this.episodeList=[];return}const{BatchExtractor:a}=await e.importAsync("batch-download");if(await a.test()!==true){this.batch=false;this.episodeList=[];return}this.batchExtractor=new a;this.batch=true;this.episodeList=(await this.batchExtractor.getItemList()).map((t,e)=>{return{aid:t.aid,cid:t.cid,title:t.title,index:e,checked:true}})},cancelDownload(){if(o){o.cancelDownload()}},async startDownload(){const t=this.getFormat();try{this.downloading=true;const e=await t.downloadInfo(this.dash);e.videoSpeed.speedUpdate=(t=>this.speed=t);e.danmakuOption=this.danmakuModel.value;e.progress=(t=>{this.progressPercent=Math.trunc(t*100)});o=e;const a=await e.download();const s=document.getElementById("video-complete");s.setAttribute("href",a.url);s.setAttribute("download",a.filename);s.click();Toast.success(`下载完成: ${a.filename} 再次保存`,"下载视频")}catch(t){if(t!=="canceled"){logError(t)}this.progressPercent=0}finally{this.downloading=false;this.speed=""}},selectAllEpisodes(){this.episodeList.forEach(t=>t.checked=true)},unselectAllEpisodes(){this.episodeList.forEach(t=>t.checked=false)},inverseAllEpisodes(){this.episodeList.forEach(t=>t.checked=!t.checked)},toggleRpcSettings(){this.showRpcSettings=!this.showRpcSettings},saveRpcSettings(){if(this.rpcSettings.host===""){this.rpcSettings.host="127.0.0.1"}if(this.rpcSettings.port===""){this.rpcSettings.port="6800"}t.aria2RpcOption=this.rpcSettings;const e=t.aria2RpcOptionProfiles.find(e=>e.name===t.aria2RpcOptionSelectedProfile);if(e){Object.assign(e,this.rpcSettings);t.aria2RpcOptionProfiles=t.aria2RpcOptionProfiles}this.saveRpcSettingsText="已保存";setTimeout(()=>this.saveRpcSettingsText="保存配置",2e3)},updateProfile(e){t.aria2RpcOption=this.rpcSettings=_.omit(e,"name")}}});Observer.videoChange(async()=>{h.close();h.batch=false;h.downloadSingle=true;const t=dq("#download-video");const e=await u();t.style.display=e?"flex":"none";if(!e){return}h.aid=r.aid;h.cid=r.cid;const a=new s(r.aid);await a.fetchInfo();h.coverUrl=a.coverUrl.replace("http:","https:");l=await d.getAvailableFormats();[c]=l;h.qualityModel={value:c.displayName,items:l.map(t=>t.displayName)};h.formatChange();await h.checkBatch()})}return{widget:{content:`\n`,condition:u,success:f}}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.html"] = `

下载视频

单个视频
批量导出
警告: 过大的视频大小会在直接下载时占用大量内存, 并可能导致浏览器标签页崩溃. 请考虑降低清晰度或使用导出选项.
预计大小: {{displaySize}}
格式
清晰度
弹幕
ffmpeg支持

直接下载

{{speed}}
{{progressPercent}}%

选集

{{selectedEpisodeCount}}/{{episodeList.length}}

导出

{{showRpcSettings ? '取消' : 'aria2 RPC'}}

aria2 RPC

配置

主机
端口
密钥
限速
默认路径
路径
最终路径: {{rpcSettings.baseDir + rpcSettings.dir}}
方法
开始下载
{{saveRpcSettingsText}}
`; +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:a}=e.import("title");const{VideoInfo:s,DanmakuInfo:i}=e.import("video-info");const{DownloadVideoPackage:n}=e.import("download-video-package");class o{async getDashUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&fnver=0&fnval=16`}else{return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&otype=json`}}}class r extends o{async getDashUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&qn=${t}&otype=json&fourk=1&fnval=16`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&otype=json&fourk=1&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=&otype=json`}}}class l extends o{constructor(t){super();this.ep=t}async getDashUrl(t){if(t){return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16`}else{return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&ep_id=${this.ep}`}else{return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&ep_id=${this.ep}`}}}const c={entity:new o,aid:"",cid:""};let d=[];let p=null;class h{constructor(t,e,a){this.quality=t;this.internalName=e;this.displayName=a}async downloadInfo(t=false){const e=new u(this);await e.fetchVideoInfo(t);return e}static parseFormats(t){const e=t.accept_quality;const a=t.accept_format.split(",");const s=t.accept_description;const i=e.map((t,e)=>{return new h(t,a[e],s[e])});return i}static async getAvailableDashFormats(){const t=await c.entity.getDashUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}return h.parseFormats(e.data||e.result||e)}static async getAvailableFormats(){const t=await c.entity.getUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}const a=e.data||e.result||e;return h.parseFormats(a)}}class u{constructor(t,e){this.fragmentSplitFactor=6*2;this.workingXhr=null;this.progressMap=new Map;this.danmakuOption="无";this.ffmpegOption="无";this.format=t;this.fragments=e||[];this.videoSpeed=new f(this)}get totalSize(){return this.fragments.map(t=>t.size).reduce((t,e)=>t+e)}async fetchVideoInfo(t=false){if(!t){const t=await c.entity.getUrl(this.format.quality);const e=await Ajax.getTextWithCredentials(t);const a=JSON.parse(e.replace(/http:/g,"https:"));const s=a.data||a.result||a;if(s.quality!==this.format.quality){throw new Error("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const i=s.durl;this.fragments=i.map(t=>{return{length:t.length,size:t.size,url:t.url,backupUrls:t.backup_url}})}else{const{dashToFragment:t,getDashInfo:a}=await e.importAsync("video-dash");const s=await a(await c.entity.getDashUrl(this.format.quality),this.format.quality);const i=s.videoDashes.sort(ascendingSort(t=>t.bandWidth))[0];const n=s.audioDashes.sort(ascendingSort(t=>t.bandWidth))[0];this.fragments=[t(i),t(n)]}return this.fragments}updateProgress(){const t=this.progressMap?[...this.progressMap.values()].reduce((t,e)=>t+e,0)/this.totalSize:0;if(t>1||t<0){console.error(`[下载视频] 进度异常: ${t}`,this.progressMap.values())}this.progress&&this.progress(t)}cancelDownload(){this.videoSpeed.stopMeasure();if(this.workingXhr!==null){this.workingXhr.forEach(t=>t.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(t){const e=[];this.workingXhr=[];this.progressMap=new Map;this.updateProgress();let a;if(t.size<=48*1024*1024){a=t.size/this.fragmentSplitFactor}else{a=4*1024*1024}let s=0;const i=t=>[...this.progressMap.keys()].indexOf(t)+1;while(s{const s=new XMLHttpRequest;s.open("GET",t.url);s.responseType="arraybuffer";s.withCredentials=false;s.addEventListener("progress",t=>{console.log(`[下载视频] 视频片段${i(s)}下载进度: ${t.loaded}/${r} bytes loaded, ${o}`);this.progressMap.set(s,t.loaded);this.updateProgress()});s.addEventListener("load",()=>{if((""+s.status)[0]==="2"){console.log(`[下载视频] 视频片段${i(s)}下载完成`);e(s.response)}else{a(`视频片段${i(s)}请求失败, response = ${s.status}`)}});s.addEventListener("abort",()=>a("canceled"));s.addEventListener("error",()=>{console.error(`[下载视频] 视频片段${i(s)}下载失败: ${o}`);this.progressMap.set(s,0);this.updateProgress();s.open("GET",t.url);s.setRequestHeader("Range",o);s.send()});s.setRequestHeader("Range",o);this.progressMap.set(s,0);s.send();this.workingXhr.push(s)}));s=Math.round(s+a)+1}return Promise.all(e)}async copyUrl(){const t=this.fragments.map(t=>t.url).reduce((t,e)=>t+"\r\n"+e);GM.setClipboard(t,"text")}async showUrl(){const t=this.fragments.map(t=>`\n${t.url}\n`).reduce((t,e)=>t+"\r\n"+e);Toast.success(t+`复制全部`,"显示链接");const e=await SpinQuery.select("#copy-link");e.addEventListener("click",async()=>{await this.copyUrl()})}async exportData(t=false){const e=JSON.stringify([{fragments:this.fragments,title:a(),totalSize:this.fragments.map(t=>t.size).reduce((t,e)=>t+e),referer:document.URL.replace(window.location.search,"")}]);if(t){GM.setClipboard(e,"text")}else{const t=new Blob([e],{type:"text/json"});const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.json`,t);i.add(a()+"."+this.danmakuOption.toLowerCase(),s);await i.emit(`${a()}.zip`)}}async exportAria2(s=false){if(s){const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,s);await i.emit();const o=t.aria2RpcOption;const r=this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}const i=[];if(o.secretKey!==""){i.push(`token:${o.secretKey}`)}i.push([t.url]);i.push({referer:document.URL.replace(window.location.search,""),"user-agent":UserAgent,out:`${a()}${s}${this.extension(t)}`,split:this.fragmentSplitFactor,dir:o.baseDir+o.dir||undefined,"max-download-limit":o.maxDownloadLimit||undefined});const n=encodeURIComponent(`${a()}${s}`);return{params:i,id:n}});const{sendRpc:l}=await e.importAsync("aria2-rpc");await l(r)}else{const t=`\n# Generated by Bilibili Evolved Video Export\n# https://github.com/the1812/Bilibili-Evolved/\n${this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}return`\n${t.url}\n referer=${document.URL.replace(window.location.search,"")}\n user-agent=${UserAgent}\n out=${a()}${s}${this.extension(t)}\n split=${this.fragmentSplitFactor}\n`.trim()}).join("\n")}\n`.trim();const e=new Blob([t],{type:"text/plain"});const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.txt`,e);i.add(a()+"."+this.danmakuOption.toLowerCase(),s);await i.emit(`${a()}.zip`)}}extension(t){const e=t||this.fragments[0];const a=[".flv",".mp4",".m4s"].find(t=>e.url.includes(t));if(a){return a}else{console.warn("No extension detected.");return".flv"}}async downloadDanmaku(){if(this.danmakuOption!=="无"){const t=new i(c.cid);await t.fetchInfo();if(this.danmakuOption==="XML"){return t.rawXML}else{const{convertToAss:a}=await e.importAsync("download-danmaku");return a(t.rawXML)}}else{return null}}async download(){const t=[];this.videoSpeed.startMeasure();for(const e of this.fragments){const a=await this.downloadFragment(e);t.push(a)}if(t.length<1){throw new Error("下载失败.")}const e=new n({ffmpeg:this.ffmpegOption});const s=a();t.forEach((a,i)=>{let n;const o=this.fragments[i];if(t.length>1){n=`${s} - ${i+1}${this.extension(o)}`}else{n=`${s}${this.extension(o)}`}e.add(n,new Blob(Array.isArray(a)?a:[a],{type:this.extension(o)===".flv"?"video/x-flv":"video/mp4"}))});const i=await this.downloadDanmaku();e.add(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,i);await e.emit(s+".zip");this.progress&&this.progress(0);this.videoSpeed.stopMeasure()}}class f{constructor(t){this.lastProgress=0;this.measureInterval=1e3;this.workingDownloader=t}startMeasure(){this.intervalTimer=setInterval(()=>{const t=this.workingDownloader.progressMap?[...this.workingDownloader.progressMap.values()].reduce((t,e)=>t+e,0):0;const e=t-this.lastProgress;if(this.speedUpdate!==undefined){this.speedUpdate(formatFileSize(e)+"/s")}this.lastProgress=t},this.measureInterval)}stopMeasure(){clearInterval(this.intervalTimer)}}async function m(){const t=await SpinQuery.select(()=>(unsafeWindow||window).aid);const e=await SpinQuery.select(()=>(unsafeWindow||window).cid);if(!(t&&e)){return false}c.aid=t;c.cid=e;if(document.URL.includes("bangumi")){c.entity=new r}else if(document.URL.includes("cheese")){const t=document.URL.match(/cheese\/play\/ep([\d]+)/);c.entity=new l(t[1])}else{c.entity=new o}try{d=await h.getAvailableFormats()}catch(t){return false}return true}async function w(){p=d[0];e.applyStyle("downloadVideoStyle");dq("#download-video").addEventListener("click",()=>{dq(".download-video").classList.toggle("opened");dq(".gui-settings-mask").click()});dq("#download-video").addEventListener("mouseover",()=>{document.body.insertAdjacentHTML("beforeend",e.import("downloadVideoHtml"));g()},{once:true})}async function g(){let o;const r=new Map;const l=new Vue({el:".download-video",components:{VDropdown:()=>e.importAsync("v-dropdown.vue"),VCheckbox:()=>e.importAsync("v-checkbox.vue"),RpcProfiles:()=>e.importAsync("aria2-rpc-profiles.vue")},data:{downloadSingle:true,coverUrl:EmptyImageUrl,aid:c.aid,cid:c.cid,dashModel:{value:t.downloadVideoFormat,items:["flv","dash"]},qualityModel:{value:p.displayName,items:d.map(t=>t.displayName)},danmakuModel:{value:t.downloadVideoDefaultDanmaku,items:["无","XML","ASS"]},ffmpegModel:{value:t.downloadVideoFfmpegSupport,items:["无","文件列表","文件列表+脚本"]},progressPercent:0,size:"获取大小中",blobUrl:"",episodeList:[],downloading:false,speed:"",batch:false,rpcSettings:t.aria2RpcOption,showRpcSettings:false,busy:false,saveRpcSettingsText:"保存配置",enableDash:t.enableDashDownload,lastDirectDownloadLink:""},computed:{displaySize(){if(typeof this.size==="string"){return this.size}return formatFileSize(this.size)},sizeWarning(){if(typeof this.size==="string"){return false}return this.size>1073741824},selectedEpisodeCount(){return this.episodeList.filter(t=>t.checked).length},dash(){return this.dashModel.value==="dash"}},methods:{close(){this.$el.classList.remove("opened")},danmakuOptionChange(){t.downloadVideoDefaultDanmaku=this.danmakuModel.value},async dashChange(){const t=this.dashModel.value;let e=[];if(t==="flv"){e=await h.getAvailableFormats()}else{e=await h.getAvailableDashFormats()}d=e;[p]=t;this.qualityModel.items=e.map(t=>t.displayName);[this.qualityModel.value]=this.qualityModel.items;await this.formatChange()},async formatChange(){const t=this.getFormat();const e=r.get(t);if(e){this.size=e;return}try{this.size="获取大小中";const e=await t.downloadInfo(this.dash);this.size=e.totalSize;r.set(t,this.size)}catch(t){this.size="获取大小失败"}},getFormat(){const t=d.find(t=>t.displayName===this.qualityModel.value);if(!t){console.error(`No format found. model value = ${this.qualityModel.value}`);return null}return t},async exportData(t){if(this.busy===true){return}try{this.busy=true;if(!this.downloadSingle){await this.exportBatchData(t);return}const e=this.getFormat();const a=await e.downloadInfo(this.dash);a.danmakuOption=this.danmakuModel.value;switch(t){case"copyLink":await a.copyUrl();Toast.success("已复制链接到剪贴板.","下载视频",3e3);break;case"showLink":await a.showUrl();break;case"aria2":await a.exportAria2(false);break;case"aria2RPC":await a.exportAria2(true);break;case"copyVLD":await a.exportData(true);Toast.success("已复制VLD数据到剪贴板.","下载视频",3e3);break;case"exportVLD":await a.exportData(false);break;default:break}}catch(t){logError(t)}finally{this.busy=false}},async exportBatchData(t){const s=this.episodeList;if(s.every(t=>t.checked===false)){Toast.info("请至少选择1集或以上的数量!","批量导出",3e3);return}const o=t=>{const e=s.find(e=>e.cid===t.cid);if(e===undefined){return false}return e.checked};const r=this.getFormat();if(this.danmakuModel.value!=="无"){const t=Toast.info("下载弹幕中...","批量导出");const a=new n;try{if(this.danmakuModel.value==="XML"){for(const t of s.filter(o)){const e=new i(t.cid);await e.fetchInfo();a.add(t.title+".xml",e.rawXML)}}else{const{convertToAss:t}=await e.importAsync("download-danmaku");for(const e of s.filter(o)){const s=new i(e.cid);await s.fetchInfo();a.add(e.title+".ass",await t(s.rawXML))}}await a.emit(this.cid+".danmakus.zip")}catch(t){logError(`弹幕下载失败`)}finally{t.dismiss()}}const l=Toast.info("获取链接中...","批量导出");this.batchExtractor.itemFilter=o;let c;try{switch(t){case"aria2":c=await this.batchExtractor.collectAria2(r,l);await n.single(a(false)+".txt",new Blob([c],{type:"text/plain"}),{ffmpeg:this.ffmpegOption});return;case"aria2RPC":await this.batchExtractor.collectAria2(r,l,true);Toast.success(`成功发送了批量请求.`,"aria2 RPC",3e3);return;case"copyVLD":GM.setClipboard(await this.batchExtractor.collectData(r,l),{mimetype:"text/plain"});Toast.success("已复制批量vld数据到剪贴板.","批量导出",3e3);return;case"exportVLD":c=await this.batchExtractor.collectData(r,l);await n.single(a(false)+".json",new Blob([c],{type:"text/json"}),{ffmpeg:this.ffmpegOption});return;default:return}}catch(t){logError(t)}finally{l.dismiss()}},async checkBatch(){const t=["/www.bilibili.com/bangumi","/www.bilibili.com/video/av"];if(!t.some(t=>document.URL.includes(t))){this.batch=false;this.episodeList=[];return}const{BatchExtractor:a}=await e.importAsync("batch-download");if(await a.test()!==true){this.batch=false;this.episodeList=[];return}this.batchExtractor=new a;this.batch=true;this.episodeList=(await this.batchExtractor.getItemList()).map((t,e)=>{return{aid:t.aid,cid:t.cid,title:t.title,index:e,checked:true}})},cancelDownload(){if(o){o.cancelDownload()}},async startDownload(){const t=this.getFormat();try{this.downloading=true;const e=await t.downloadInfo(this.dash);e.videoSpeed.speedUpdate=(t=>this.speed=t);e.danmakuOption=this.danmakuModel.value;e.ffmpegOption=this.ffmpegModel.value;e.progress=(t=>{this.progressPercent=Math.trunc(t*100)});o=e;await e.download();this.lastDirectDownloadLink=n.lastPackageUrl}catch(t){if(t!=="canceled"){logError(t)}this.progressPercent=0}finally{this.downloading=false;this.speed=""}},selectAllEpisodes(){this.episodeList.forEach(t=>t.checked=true)},unselectAllEpisodes(){this.episodeList.forEach(t=>t.checked=false)},inverseAllEpisodes(){this.episodeList.forEach(t=>t.checked=!t.checked)},toggleRpcSettings(){this.showRpcSettings=!this.showRpcSettings},saveRpcSettings(){if(this.rpcSettings.host===""){this.rpcSettings.host="127.0.0.1"}if(this.rpcSettings.port===""){this.rpcSettings.port="6800"}t.aria2RpcOption=this.rpcSettings;const e=t.aria2RpcOptionProfiles.find(e=>e.name===t.aria2RpcOptionSelectedProfile);if(e){Object.assign(e,this.rpcSettings);t.aria2RpcOptionProfiles=t.aria2RpcOptionProfiles}this.saveRpcSettingsText="已保存";setTimeout(()=>this.saveRpcSettingsText="保存配置",2e3)},updateProfile(e){t.aria2RpcOption=this.rpcSettings=_.omit(e,"name")}}});Observer.videoChange(async()=>{l.close();l.batch=false;l.downloadSingle=true;const t=dq("#download-video");const e=await m();t.style.display=e?"flex":"none";if(!e){return}l.aid=c.aid;l.cid=c.cid;try{const t=new s(c.aid);await t.fetchInfo();l.coverUrl=t.coverUrl.replace("http:","https:")}catch(t){l.coverUrl=EmptyImageUrl}d=await h.getAvailableFormats();[p]=d;l.qualityModel={value:p.displayName,items:d.map(t=>t.displayName)};l.formatChange();await l.checkBatch()})}return{widget:{content:`\n`,condition:m,success:w}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/dpi-img.vue.min.js"] = (()=>{return(t,s)=>{const e=``;return{export:Object.assign({template:e},{props:["size","src","blur","root","rootMargin","threshold"],data(){return{srcset:null,actualSrc:null}},methods:{calcSrc(){if(!this.src||!this.size){return null}const t=this.src.substring(this.src.lastIndexOf(".")+1);this.srcset=getDpiSourceSet(this.src,this.size,t);this.actualSrc=this.src}},mounted(){const t={root:this.root,rootMargin:this.rootMargin||"200px",threshold:this.threshold};const s=new IntersectionObserver(t=>{t.forEach(t=>{if(t.isIntersecting){this.calcSrc();s.disconnect()}})},t);s.observe(this.$el)},computed:{width(){if(typeof this.size==="object"&&"width"in this.size){return this.size.width}return null},height(){if(typeof this.size==="object"&&"height"in this.size){return this.size.height}return null}}})}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/expand-danmaku.min.js"] = (()=>{return(e,a)=>{if(typeof isEmbeddedPlayer!=="undefined"&&isEmbeddedPlayer()){return}Observer.videoChange(async()=>{const e=await SpinQuery.select(".bui-collapse-wrap");if(e&&e.classList.contains("bui-collapse-wrap-folded")){const e=await SpinQuery.select(".bui-collapse-header");e.click()}})}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/expand-description.min.css"] = `.play-up-info .play-up-self,.video-desc .info{height:auto!important}.play-up-info .play-up-self-btn,.video-desc .btn{display:none!important}`; @@ -1207,7 +1208,7 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/v-dropdown.vue.min.js"] = (()=>{return(o,e)=>{const n=`
{{ value }}
`;e.applyStyleFromText(`.v-dropdown{--background-color:#eee;position:relative;background-color:var(--background-color);cursor:pointer;display:flex;align-items:center;justify-content:space-between;min-width:100px}body.dark .v-dropdown{--background-color:#333}.v-dropdown .dropdown-menu{transform-origin:top;transform:translateY(-4px) translateX(-50%);pointer-events:none;opacity:0;position:absolute;top:calc(100% + 2px);left:50%;background-color:var(--background-color);z-index:1;transition:.2s ease-out;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0}.v-dropdown .dropdown-menu.opened{transform:translateY(0) translateX(-50%);pointer-events:initial;opacity:1}.v-dropdown .dropdown-menu li{padding:4px 16px;white-space:nowrap;min-width:64px;text-align:center;cursor:pointer;color:inherit;background-color:transparent}.v-dropdown .dropdown-menu li:hover{background-color:rgba(0,0,0,.16)}.v-dropdown .mdi-chevron-down{font-size:16pt;line-height:1;transform:rotate(0)}.v-dropdown .dropdown-menu.opened~.mdi-chevron-down{transform:rotate(180deg)}.v-dropdown .selected{user-select:none;padding:4px 8px}.round-corner .v-dropdown,.round-corner .v-dropdown .dropdown-menu,.round-corner .v-dropdown .dropdown-menu li{border-radius:var(--corner-radius)}`,"v-dropdown-style");return{export:Object.assign({template:n},{props:["items","value"],data(){return{dropdownOpen:false}},methods:{toggleDropdown(){this.dropdownOpen=!this.dropdownOpen;if(this.dropdownOpen){document.addEventListener("click",o=>{const e=o.target;if(e===this.$el||this.$el.contains(e)){return}this.dropdownOpen=false},{once:true,capture:true})}},select(o){this.$emit("update:value",o);this.$emit("change",o)}}})}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-card-info.min.js"] = (()=>{return(r,e)=>{}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-card.vue.min.js"] = (()=>{return(e,i)=>{const t=`
{{durationText}}
{{watchlater ? '已添加' : '稍后再看'}}

{{title}}

{{description}}

{{upName}}
{{playCount}}
`;i.applyStyleFromText(`.video-card{display:grid;grid-template-columns:200px 1fr;grid-template-rows:1fr 1fr 1fr;grid-template-areas:"cover title" "cover description" "cover up";height:var(--card-height);width:var(--card-width);color:#000;background-color:#fff;border-radius:16px;box-shadow:0 4px 8px 0 #0001;margin-right:var(--card-margin);margin-bottom:var(--card-margin);position:relative}body.dark .video-card,body.dark .video-card:hover{background-color:#282828;color:#eee}.video-card:hover{color:#000}.video-card.vertical{grid-template-columns:auto auto;grid-template-rows:2fr 1fr 1fr;grid-template-areas:"cover cover" "title title" "up up"}.video-card.vertical .description,.video-card.vertical .topics{display:none}.video-card.vertical .cover-container{border-radius:16px 16px 0 0}.video-card.vertical .title{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;max-height:3em;word-break:break-all;white-space:normal;line-height:1.5;font-size:11pt}.video-card.vertical .up{align-self:start;white-space:nowrap}.video-card.vertical .up .name{text-overflow:ellipsis;overflow:hidden}.video-card.vertical .up:not(.no-face){margin-left:8px;max-width:calc(var(--card-width) - 16px)}.video-card.vertical .up.no-face{margin-top:8px;max-width:calc(var(--card-width) - 24px)}.video-card.vertical .stats{align-self:end;justify-self:start;margin-bottom:8px;margin-right:0}.video-card>*{justify-self:self-start;align-self:center}.video-card:hover .cover{transform:scale(1.05);transition:.1s cubic-bezier(.39,.58,.57,1)}.video-card:hover .duration,.video-card:hover .watchlater{opacity:1}.video-card .duration,.video-card .watchlater{opacity:0}.video-card .cover-container{grid-area:cover;border-radius:16px 0 0 16px;position:relative;width:100%;height:100%;overflow:hidden}.video-card .cover-container .cover{object-fit:cover;width:100%;height:100%}.video-card .cover-container>:not(.cover){position:absolute}.video-card .cover-container .duration,.video-card .cover-container .watchlater{bottom:6px;padding:4px 8px;background-color:#000a;color:#fff;border-radius:14px;height:24px}.video-card .cover-container .duration .mdi,.video-card .cover-container .watchlater .mdi{font-size:12pt;line-height:1;margin-right:4px}.video-card .cover-container .duration{left:6px}.video-card .cover-container .watchlater{right:6px;display:flex;align-items:center;padding-left:4px}.video-card .title{grid-area:title;font-size:12pt;font-weight:700;color:inherit;padding:0 12px;white-space:nowrap;overflow:hidden;justify-self:stretch;text-overflow:ellipsis}.video-card .topics{grid-area:description;display:flex;align-items:center;margin-left:12px}.video-card .topics .topic{color:inherit;padding:6px 8px;background-color:#8882;margin-right:8px;border-radius:14px;white-space:nowrap;max-width:120px;overflow:hidden;text-overflow:ellipsis}.video-card .topics .topic:hover{background-color:#8884;color:var(--theme-color)}.video-card .description{grid-area:description;color:inherit;overflow:hidden;align-self:stretch;justify-self:stretch;margin:0 12px;line-height:1.5;height:3em;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;scrollbar-width:none!important}.video-card .description::-webkit-scrollbar{width:0!important}.video-card .description.single-line{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.video-card .stats,.video-card .up{grid-area:up}.video-card .up{margin-left:12px;display:flex;align-items:center;padding:2px;background-color:#8882;border-radius:14px;color:inherit}.video-card .up.no-face{background-color:transparent;padding:0}.video-card .up.no-face .be-icon{font-size:14pt;opacity:.75}.video-card .up .face{border-radius:50%}.video-card .up .name{margin:0 8px}.video-card .up:not(.no-face):hover{background-color:#8884}.video-card .up:hover .be-icon,.video-card .up:hover .name{color:var(--theme-color)}.video-card .stats{justify-self:self-end;margin-right:12px;display:flex;align-items:center;opacity:.5}.video-card .stats .be-icon{font-size:12pt;margin:0 4px 0 12px}.video-card .stats .be-icon.be-iconfont-favorites-outline{font-size:14pt}.video-card .stats .be-icon.be-iconfont-coin-outline{font-size:11pt}`,"video-card-style");return{export:Object.assign({template:t},{props:["data","orientation"],components:{"dpi-img":()=>i.importAsync("dpi-img.vue"),Icon:()=>i.importAsync("icon.vue")},data(){return{upFaceUrl:"",danmakuCount:"",like:"",coins:"",favorites:"",dynamic:"",topics:[],upID:0,epID:0,...this.data}},computed:{vertical(){return this.orientation==="vertical"}},methods:{async toggleWatchlater(){try{this.watchlater=!this.watchlater;const{toggleWatchlater:e}=await i.importAsync("watchlater-api");e(this.aid.toString(),this.watchlater)}catch(e){this.watchlater=!this.watchlater;Toast.error(e.message,"稍后再看操作失败",3e3)}}}})}}})(); -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-dash.min.js"] = (()=>{return(t,a)=>{const d=t=>{return{url:t.downloadUrl,backupUrls:t.backupUrls,length:t.duration,size:Math.trunc(t.bandWidth*t.duration/8)}};const r=async(t,a)=>{const d=await Ajax.getJsonWithCredentials(t);const r=d.data||d.result||d;if(d.code!==0||!r.dash){throw new Error("DASH api failed")}const e=r.accept_quality;if(!e.includes(a)){throw new Error("没有找到请求的清晰度")}if(r.quality!==a){throw new Error("无法获取请求的清晰度, 请确认当前账号有相应的权限")}const o=r.accept_description;const n=o[e.indexOf(a)];const c=r.dash.duration;const i=r.dash.video.filter(t=>t.id===a).map(t=>{const d={quality:a,qualityText:n,width:t.width,height:t.height,codecs:t.codecs,codecId:t.codecid,bandWidth:t.bandwidth,frameRate:t.frameRate,backupUrls:t.backupUrl,downloadUrl:t.baseUrl,duration:c};return d});const s=r.dash.audio.map(t=>{return{bandWidth:t.bandwidth,codecs:t.codecs,codecId:t.codecid,backupUrls:t.backupUrl,downloadUrl:t.baseUrl,duration:c}});return{videoDashes:i,audioDashes:s}};return{export:{getDashInfo:r,dashToFragment:d}}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-dash.min.js"] = (()=>{return(t,a)=>{const r=t=>{return{url:t.downloadUrl,backupUrls:t.backupUrls,length:t.duration,size:Math.trunc(t.bandWidth*t.duration/8)}};const e=async(t,a)=>{const r=await Ajax.getJsonWithCredentials(t);const e=r.data||r.result||r;if(r.code!==0||!e.dash){throw new Error("DASH api failed")}const d=e.accept_quality;if(!d.includes(a)){throw new Error("没有找到请求的清晰度")}if(e.quality!==a){throw new Error("无法获取请求的清晰度, 请确认当前账号有相应的权限")}const c=e.accept_description;const o=c[d.indexOf(a)];const s=e.dash.duration;const n=e.dash.video.filter(t=>t.id===a).map(t=>{const r={quality:a,qualityText:o,width:t.width,height:t.height,codecs:t.codecs,codecId:t.codecid,bandWidth:t.bandwidth,frameRate:t.frameRate,backupUrls:(t.backupUrl||t.backup_url||"").replace("http:","https:"),downloadUrl:(t.baseUrl||t.base_url||"").replace("http:","https:"),duration:s};return r});const i=e.dash.audio.map(t=>{return{bandWidth:t.bandwidth,codecs:t.codecs,codecId:t.codecid,backupUrls:(t.backupUrl||t.backup_url||"").replace("http:","https:"),downloadUrl:(t.baseUrl||t.base_url||"").replace("http:","https:"),duration:s}});return{videoDashes:n,audioDashes:i}};return{export:{getDashInfo:e,dashToFragment:r}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-downloader-fragment.min.js"] = (()=>{return(r,e)=>{}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-info.min.js"] = (()=>{return(t,i)=>{class e{constructor(t){this.aid=t}async fetchInfo(){const t=JSON.parse(await Ajax.getText(`https://api.bilibili.com/x/web-interface/view?aid=${this.aid}`));if(t.code!==0){throw new Error(t.message)}const i=t.data;this.cid=i.cid;this.pageCount=i.videos;this.coverUrl=i.pic;this.tagId=i.tid;this.tagName=i.tname;this.title=i.title;this.description=i.desc;this.up={uid:i.owner.mid,name:i.owner.name,faceUrl:i.owner.face};this.pages=i.pages.map(t=>{return{cid:t.cid,title:t.part,pageNumber:t.page}});return this}async fetchDanmaku(){this.danmaku=new s(this.cid.toString());return this.danmaku.fetchInfo()}}class a{constructor(t,i){this.text=t;this.p=i}}class s{constructor(t){this.cid=t}async fetchInfo(){const t=await Ajax.getText(`https://api.bilibili.com/x/v1/dm/list.so?oid=${this.cid}`);this.rawXML=t;const i=(new DOMParser).parseFromString(t,"application/xml").documentElement;this.xml=i;this.danmakus=[...i.querySelectorAll("d[p]")].map(t=>{return new a(t.innerHTML,t.getAttribute("p"))})}}class n{constructor(t){this.ep=t;this.videos=[]}async fetchInfo(){const t=await Ajax.getText(`https://www.bilibili.com/bangumi/play/ep${this.ep}/`);const i=JSON.parse(t.match(/window\.__INITIAL_STATE__=(.*);\(function\(\){/)[1]);this.title=i.mediaInfo.title;this.cover=i.mediaInfo.cover;this.squareCover=i.mediaInfo.square_cover;this.aid=i.epInfo.aid;this.cid=i.epInfo.cid;this.videos=i.epList.map(async t=>{return{title:t.index_title,aid:t.aid,cid:t.cid,info:await new e(t.aid).fetchInfo()}});return this}}return{export:{VideoInfo:e,BangumiInfo:n,Danmaku:a,DanmakuInfo:s}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-list.vue.min.js"] = (()=>{return(i,a)=>{const t=`
加载中...
空空如也哦 = ̄ω ̄=
`;a.applyStyleFromText(`.minimal-home .video-list .empty,.minimal-home .video-list .loading{height:48px;display:flex;align-items:center;justify-content:center;font-size:11pt;color:#707070}.minimal-home .video-list .empty .mdi,.minimal-home .video-list .loading .mdi{margin-right:8px}body.dark .minimal-home .video-list .empty,body.dark .minimal-home .video-list .loading{color:#eee}.minimal-home .video-list .cards{display:flex;flex-wrap:wrap;align-items:flex-end}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1),.minimal-home .video-list .cards.show-rank .video-card:nth-child(17),.minimal-home .video-list .cards.show-rank .video-card:nth-child(9){margin-top:48px}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1)::before,.minimal-home .video-list .cards.show-rank .video-card:nth-child(17)::before,.minimal-home .video-list .cards.show-rank .video-card:nth-child(9)::before{position:absolute;top:-42px;left:0;font-size:14pt;font-weight:700}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1)::before{content:"昨日"}.minimal-home .video-list .cards.show-rank .video-card:nth-child(9)::before{content:"三日"}.minimal-home .video-list .cards.show-rank .video-card:nth-child(17)::before{content:"一周"}`,"video-list-style");return{export:Object.assign({template:t},{components:{VideoCard:()=>a.importAsync("video-card.vue")},props:["showRank"],data(){return{cards:[],loading:true}},methods:{async getRankList(){const{getTrendingVideos:i}=await a.importAsync("trending-videos");const{getWatchlaterList:t}=await a.importAsync("watchlater-api");const e=await t();const o=async a=>{const t=await i(a,e);this.cards.push(...t)};await Promise.all([1,3,7].map(o))},async getActivityVideos(){const i=await Ajax.getJsonWithCredentials(`https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new?uid=${getUID()}&type_list=8`);const{getWatchlaterList:t}=await a.importAsync("watchlater-api");const e=await t();if(i.code!==0){throw new Error(i.message)}this.cards=i.data.cards.map(i=>{const a=JSON.parse(i.card);const t=_.get(i,"display.topic_info.topic_details",[]).map(i=>{return{id:i.topic_id,name:i.topic_name}});return{id:i.desc.dynamic_id_str,aid:a.aid,title:a.title,upID:i.desc.user_profile.info.uid,upName:i.desc.user_profile.info.uname,upFaceUrl:i.desc.user_profile.info.face,coverUrl:a.pic,description:a.desc,timestamp:i.timestamp,time:new Date(i.timestamp*1e3),topics:t,dynamic:a.dynamic,like:formatCount(i.desc.like),duration:a.duration,durationText:formatDuration(a.duration,0),playCount:formatCount(a.stat.view),danmakuCount:formatCount(a.stat.danmaku),watchlater:e.includes(a.aid)}})}},async mounted(){try{if(this.showRank){await this.getRankList()}else{await this.getActivityVideos()}}catch(i){Toast.error(i.message,this.showRank?"热门视频":"视频动态",3e3)}finally{this.loading=false}}})}}})(); @@ -1637,13 +1638,17 @@ Resource.manifest = { useCache: '启用缓存' } }, + videoDownloadPackage: { + path: 'download-video-package.min.js', + }, downloadVideo: { path: 'download-video.min.js', html: true, style: 'instant', - dependencies: ['title', 'videoInfo'], + dependencies: ['title', 'videoInfo', 'videoDownloadPackage'], displayNames: { 'downloadVideo': '下载视频', + 'videoDownloadPackage': '下载视频打包器', 'batchDownload': '批量下载', 'aria2Rpc': 'aria2 RPC', } diff --git a/bilibili-evolved.preview-offline.user.js b/bilibili-evolved.preview-offline.user.js index 16144a1b3..df9301dd3 100644 --- a/bilibili-evolved.preview-offline.user.js +++ b/bilibili-evolved.preview-offline.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name Bilibili Evolved (Preview Offline) -// @version 473.02 +// @version 474.33 // @description Bilibili Evolved 的预览离线版, 可以抢先体验新功能, 并且所有功能都已内置于脚本中. // @author Grant Howard, Coulomb-G // @copyright 2019, Grant Howard (https://github.com/the1812) & Coulomb-G (https://github.com/Coulomb-G) @@ -365,6 +365,7 @@ const settings = { customNavbarSeasonLogo: false, selectableColumnText: true, downloadVideoFormat: 'flv', + downloadVideoFfmpegSupport: '无', enableDashDownload: false, watchlaterExpireWarnings: true, watchlaterExpireWarningDays: 14, @@ -1084,10 +1085,10 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/double-click-fullscreen.min.js"] = (()=>{return(i,e)=>{(async()=>{const e=["https://www.bilibili.com/bangumi/","https://www.bilibili.com/video/"];if(!e.some(i=>document.URL.startsWith(i))){return}if(i.touchVideoPlayer&&i.touchVideoPlayerDoubleTapControl){Toast.info("在开启了播放器触摸支持-启用双击控制后, 双击全屏功能将无效.","提示");i.doubleClickFullscreen=false;return}await SpinQuery.unsafeJquery();const l=await SpinQuery.condition(()=>dq(".bilibili-player-area"),i=>i!==null&&unsafeWindow.$(".bilibili-player-video").data("events"));if(l===null){return}const n="double-click-fullscreen";if(!l.classList.contains(n)){l.classList.add(n);const e=unsafeWindow.$(".bilibili-player-video");const t=i.doubleClickFullscreenPreventSingleClick?e.data("events").click[0].handler:()=>{};const c=new DoubleClickEvent(()=>dq(".bilibili-player-video-btn-fullscreen").click(),i=>t(i));if(i.doubleClickFullscreenPreventSingleClick){e.unbind("click")}c.bind(e[0])}})()}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-audio.min.js"] = (()=>{return(e,t)=>{class n{constructor(){this.sid=null;this.progress=null}async getDownloadUrl(){const e=`https://www.bilibili.com/audio/music-service-c/web/url?sid=${this.sid}&privilege=2&quality=2`;const t=await Ajax.getJsonWithCredentials(e);if(t.code===0){return t.data.cdns.shift()}else{logError("获取下载链接失败, 请确保当前账号有下载权限.","下载音频",1e4);return null}}async download(){const e=await this.getDownloadUrl();return new Promise((t,n)=>{const s=new XMLHttpRequest;s.open("GET",e);s.responseType="blob";s.addEventListener("load",()=>t(s.response));s.addEventListener("error",()=>n(s.status));s.addEventListener("progress",e=>this.progress&&this.progress(100*e.loaded/e.total));s.send()})}}const s="下载音频";return{export:n,widget:{content:`\n\n\n${s}\n\n`,condition:()=>document.URL.includes("bilibili.com/audio"),success:async()=>{await SpinQuery.select(()=>document.querySelector("#app"));const e=document.querySelector("#download-audio");const t=e.querySelector("span");const o=new n;o.progress=(e=>{t.innerHTML=`${Math.round(e)}%`});const i=document.querySelector("#download-audio-link");e.addEventListener("click",async e=>{if(o.sid===null||e.target===i){return}const n=await o.download();t.innerHTML=s;const r=i.getAttribute("href");if(r){URL.revokeObjectURL(r)}i.setAttribute("href",URL.createObjectURL(n));const d=(()=>{const e=document.querySelector(".song-title");if(e){return e.getAttribute("title")}else{return"神秘音频"}})();i.setAttribute("download",d+".m4a");i.click()});Observer.childList("#app",()=>{const t=document.URL.match(/bilibili\.com\/audio\/au([\d]+)/);if(t&&t[1]){e.disabled=false;o.sid=t[1]}else{e.disabled=true}})}}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-danmaku.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:n}=e.import("title");const{DanmakuInfo:i}=e.import("video-info");const{DanmakuConverter:a}=e.import("danmaku-converter");async function o(t){const e=n();let i={title:e};try{await loadDanmakuSettingsPanel();const t=t=>{const e=parseFloat(dq(t).style.transform.replace(/translateX\(([\d\.]+)/,"$1"));const n={0:0,44:1,94:2,144:3,188:4}[e];return n};i.font=dq(".bilibili-player-video-danmaku-setting-right-font .bui-select-result").innerText;i.alpha=parseFloat(dq(".bilibili-player-setting-opacity .bui-bar").style.transform.replace(/scaleX\(([\d\.]+)\)/,"$1"));i.duration=(()=>{const e=[18,14,10,8,6][t(".bilibili-player-setting-speedplus .bui-thumb")];return t=>{switch(t.type){case 4:case 5:return 4;default:return e}}})();i.blockTypes=(()=>{let t=[];const e={".bilibili-player-block-filter-type[ftype=scroll]":[1,2,3],".bilibili-player-block-filter-type[ftype=top]":[5],".bilibili-player-block-filter-type[ftype=bottom]":[4],".bilibili-player-block-filter-type[ftype=color]":["color"]};for(const[n,i]of Object.entries(e)){if(dq(n).classList.contains("disabled")){t=t.concat(i)}}return t.concat(7,8)})();const e=[1.4,1.2,1,.8,.6][t(".bilibili-player-setting-fontsize .bui-thumb")];i.resolution={x:1920*e,y:1080*e};i.bottomMarginPercent=[.75,.5,.25,0,0][t(".bilibili-player-setting-area .bui-thumb")];if(i.bottomMarginPercent===0&&dq(".bilibili-player-video-danmaku-setting-left-preventshade input").checked){i.bottomMarginPercent=.15}i.bold=dq(".bilibili-player-video-danmaku-setting-right-font-bold input").checked}catch(t){i={font:"微软雅黑",alpha:.6,duration:t=>{switch(t.type){case 4:case 5:return 4;default:return 6}},blockTypes:[7,8],resolution:{x:1920,y:1080},bottomMarginPercent:.15,bold:false}}const o=new a(i);const l=o.convertToAssDocument(t);return l.generateAss()}async function l(t,e){const a=n();const l=new i((unsafeWindow||window).cid);await l.fetchInfo();const r=await(async()=>{if(t===true){return new Blob([await o(l.rawXML)],{type:"text/plain"})}else{return new Blob([l.rawXML],{type:"text/plain"})}})();const s=URL.createObjectURL(r);const c=dq("#danmaku-link");const d=c.getAttribute("href");if(d){URL.revokeObjectURL(d)}clearTimeout(e);dq("#download-danmaku>span").innerHTML="下载弹幕";c.setAttribute("download",`${a}.${t?"ass":"xml"}`);c.setAttribute("href",s);c.click()}return{export:{downloadDanmaku:l,convertToAss:o},widget:{content:`\n\n\n下载弹幕\n\n`,condition:async()=>{let t=await SpinQuery.select(()=>(unsafeWindow||window).cid);return Boolean(t)},success:()=>{const t=document.querySelector("#danmaku-link");dq("#download-danmaku").addEventListener("click",e=>{if(e.target!==t){const t=setTimeout(()=>dq("#download-danmaku>span").innerHTML="请稍侯...",200);l(e.shiftKey,t)}})}}}}})(); -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video-package.min.js"] = (()=>{return(e,t)=>{class n{constructor(e={}){this.config=e;this.entries=[]}download(e,t){const n=document.createElement("a");const i=URL.createObjectURL(t);n.setAttribute("href",i);n.setAttribute("download",e);document.body.appendChild(n);n.click();n.remove();URL.revokeObjectURL(i)}add(e,t){if(t===null||t===undefined){return}this.entries.push({name:e,data:t})}async emit(e){if(this.entries.length===0){return}if(!e||this.entries.length===1){e=this.entries[0].name}if(this.entries.length===1){const t=this.entries[0].data;this.download(e,typeof t==="string"?new Blob([t]):t);return}const t=new JSZip;this.entries.forEach(({name:e,data:n})=>{t.file(e,n)});const n=await t.generateAsync({type:"blob"});this.download(e,n)}static async single(e,t){const i=new n;i.add(e,t);await i.emit()}}return{export:{DownloadVideoPackage:n}}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video-package.min.js"] = (()=>{return(e,t)=>{class n{constructor(e={}){this.config=e;this.entries=[]}download(e,t){const i=document.createElement("a");const a=URL.createObjectURL(t);if(n.lastPackageUrl){URL.revokeObjectURL(n.lastPackageUrl)}n.lastPackageUrl=a;i.setAttribute("href",a);i.setAttribute("download",e);document.body.appendChild(i);i.click();i.remove()}add(e,t){if(t===null||t===undefined){return}this.entries.push({name:e,data:t})}async preEmit(){const e=this.entries.filter(e=>[".flv",".mp4",".m4s"].some(t=>e.name.endsWith(t)));if(this.config.ffmpeg!==undefined&&e.length>=2){if(this.config.ffmpeg==="文件列表"||this.config.ffmpeg==="文件列表+脚本"){this.entries.push({name:"ffmpeg-files.txt",data:e.map(e=>`file '${e.name}'`).join("\n")})}if(this.config.ffmpeg==="文件列表+脚本"){const e=`ffmpeg -f concat -i ffmpeg-files.txt -c copy ""`;this.entries.push({name:"ffmpeg.bat",data:e},{name:"ffmpeg.sh",data:e.replace(/"/g,"'")})}}}async blob(){await this.preEmit();if(this.entries.length===0){return null}if(this.entries.length===1){const e=this.entries[0].data;return typeof e==="string"?new Blob([e]):e}const e=new JSZip;this.entries.forEach(({name:t,data:n})=>{e.file(t,n)});return await e.generateAsync({type:"blob"})}async emit(e){if(!e||this.entries.length===1){e=this.entries[0].name}const t=await this.blob();if(!t){return}return this.download(e,t)}static async single(e,t,i={}){const a=new n(i);a.add(e,t);return await a.emit()}}n.lastPackageUrl="";return{export:{DownloadVideoPackage:n}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.css"] = `.download-video{--download-video-background:white;--download-video-foreground:black;position:absolute;top:64px;left:50%;transform:translateX(-50%) scale(.95);background:var(--download-video-background);color:var(--download-video-foreground);box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;z-index:10001;pointer-events:none;opacity:0;padding:16px;width:300px;display:flex;flex-direction:column;align-items:stretch;justify-content:space-between}.download-video,.download-video *{transition:.2s ease-out;-webkit-tap-highlight-color:transparent!important}.download-video.opened{pointer-events:initial;opacity:1;transform:translateX(-50%) scale(1)}body.dark .download-video{--download-video-background:#222;--download-video-foreground:#eee}.round-corner .download-video,.round-corner .download-video .episode-list .v-checkbox,.round-corner .download-video .rpc-settings{border-radius:var(--large-corner-radius)}.round-corner .download-video .button,.round-corner .download-video .cover,.round-corner .download-video .direct-download .progress .background,.round-corner .download-video .direct-download .progress .foreground,.round-corner .download-video .rpc-settings input[type=text],.round-corner .download-video .title,.round-corner .download-video button{border-radius:var(--corner-radius)}.download-video .cover{width:240px;min-height:135px;max-height:200px;object-fit:contain}.download-video .header{display:flex;justify-content:space-between;align-items:center}.download-video h1{font-size:16pt;font-weight:700;color:var(--download-video-foreground)}.download-video .header .mdi-close{font-size:16pt;color:var(--download-video-foreground);cursor:pointer}.download-video .header .mdi-close:hover{color:var(--theme-color)}.download-video .info{display:flex;flex-direction:column;align-items:center;margin-top:12px}.download-video .title{display:flex;flex-direction:column;justify-content:space-between;align-items:stretch;margin-top:12px}.download-video .title .bold{width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.download-video .title .size{font-size:10pt;color:var(--download-video-foreground);align-self:center;display:flex;align-items:center;height:24px}.download-video .bold{color:var(--download-video-foreground);font-weight:700;font-size:12pt}.download-video .option-item{display:flex;justify-content:space-between;align-items:center;padding-top:12px;font-size:10pt}.download-video .tabs{display:flex;padding-top:12px;font-size:10pt}.download-video .tabs .tab{padding:6px 12px;border-bottom:2px solid transparent;cursor:pointer}.download-video .tabs .tab.active{color:var(--theme-color);border-bottom-color:var(--theme-color)}.download-video .separator{height:1px;background:#8884;width:100%;margin:12px 0;flex-shrink:0}.download-video h2{font-size:12pt;font-weight:700;color:var(--download-video-foreground)}.download-video .direct-download{display:flex;flex-direction:column;align-items:start;justify-content:space-between}.download-video .button,.download-video button{border:none;outline:0!important;padding:6px 16px;font-size:10pt;cursor:pointer;background:#8884;color:var(--download-video-foreground)}.download-video .button:hover,.download-video button:hover{background:#8886}.download-video .primary{background:var(--theme-color);color:var(--foreground-color);align-self:center}.download-video .primary:hover{background:var(--theme-color-90)}.download-video .busy .button,.download-video .busy .primary,.download-video .busy button,.download-video button:disabled{background-color:#0001;color:#8884;cursor:not-allowed}.download-video .busy .button,.download-video .busy button{cursor:wait!important}.download-video .direct-download .progress{align-self:stretch;display:flex;align-items:center;margin-top:8px}.download-video .direct-download .progress .background{flex-grow:1;height:4px;background:#8884;margin-right:4px;position:relative}.download-video .direct-download .progress .background .foreground{position:absolute;top:0;left:0;height:4px;background:linear-gradient(to right,var(--theme-color),var(--theme-color-60))}.download-video .direct-download .progress .percent{width:50px;text-align:right}.download-video .actions{display:flex;flex-wrap:wrap;justify-content:space-between;margin:8px -4px 0}.download-video .actions>*{margin:4px;flex-grow:1;flex-basis:calc(50% - 16px);display:flex;justify-content:center;align-items:center}.download-video i.mdi-alert-circle{font-size:14pt;color:#ff9800}.download-video .size-warning{position:relative;padding:0 8px}.download-video .size-warning-tip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:var(--download-video-background);color:var(--download-video-foreground);border:1px dashed var(--theme-color);z-index:2;font-size:10pt;width:200px;padding:8px;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;pointer-events:none;opacity:0}.download-video .size-warning:hover .size-warning-tip{opacity:1}.download-video .episode-list .v-checkbox{padding:4px 8px;margin:4px 0;position:relative;background-color:transparent}.download-video .episode-list .v-checkbox.checked{background-color:#8882}.download-video .episode-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.download-video .episode-list{overflow:auto;max-height:320px}.download-video button.list-tool{padding:4px;line-height:1;font-size:12pt;margin:0 4px}.download-video .episode-header h2{flex-grow:1}.download-video .selected-count{width:64px;text-align:right}.download-video .aria2-rpc .mdi{margin-left:8px;font-size:14pt;line-height:1}.download-video .aria2-rpc{position:relative}.download-video .rpc-settings{position:absolute;display:flex;flex-direction:column;align-items:stretch;color:var(--download-video-foreground);background:#fff;bottom:120%;left:50%;cursor:initial;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;transform-origin:bottom;transform:translateX(-50%) scale(.9);opacity:0;pointer-events:none;padding:8px;z-index:3;transition:.3s cubic-bezier(.18,.89,.32,1.28);width:120%}body.dark .download-video .rpc-settings{background:#282828}.download-video .rpc-settings>*{margin:8px}.download-video .rpc-settings.show{opacity:1;transform:translateX(-50%) scale(1);pointer-events:initial}.download-video .rpc-settings input[type=text]{background:0 0;color:var(--download-video-foreground);border:1px solid #8884;padding:4px;margin-left:8px}.download-video .rpc-settings input[type=text]:focus{border-color:var(--theme-color)}.download-video .rpc-settings .operations{display:flex;align-items:center;justify-content:space-evenly}.download-video .final-dir{word-break:break-all}.download-video .rpc-settings-item{display:flex;align-items:center;justify-content:space-between;white-space:nowrap}.download-video .rpc-settings-item input[type=text]{flex-grow:1;margin-left:24px}.download-video button.cancel-download,.download-video button.start-download{margin-top:8px}.download-video .direct-download-header{align-self:stretch;display:flex;justify-content:space-between;align-items:center}body.dark .download-video .direct-download .progress .foreground{background:linear-gradient(to right,var(--theme-color-70),var(--theme-color))}`; -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.html"] = `

下载视频

单个视频
批量导出
警告: 过大的视频大小会在直接下载时占用大量内存, 并可能导致浏览器标签页崩溃. 请考虑降低清晰度或使用导出选项.
预计大小: {{displaySize}}
格式
清晰度
弹幕

直接下载

{{speed}}
{{progressPercent}}%

选集

{{selectedEpisodeCount}}/{{episodeList.length}}

导出

{{showRpcSettings ? '取消' : 'aria2 RPC'}}

aria2 RPC

配置

主机
端口
密钥
限速
默认路径
路径
最终路径: {{rpcSettings.baseDir + rpcSettings.dir}}
方法
开始下载
{{saveRpcSettingsText}}
`; -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:a}=e.import("title");const{VideoInfo:s,DanmakuInfo:i}=e.import("video-info");class o{async getDashUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json&fnver=0&fnval=16`}else{return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&otype=json&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&otype=json`}}}class n extends o{async getDashUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&qn=${t}&otype=json&fourk=1&fnval=16`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&otype=json&fourk=1&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=${r.aid}&cid=${r.cid}&qn=&otype=json`}}}const r={entity:new o,aid:"",cid:""};let l=[];let c=null;class d{constructor(t,e,a){this.quality=t;this.internalName=e;this.displayName=a}async downloadInfo(t=false){const e=new h(this);await e.fetchVideoInfo(t);return e}static parseFormats(t){const e=t.accept_quality;const a=t.accept_format.split(",");const s=t.accept_description;const i=e.map((t,e)=>{return new d(t,a[e],s[e])});return i}static async getAvailableDashFormats(){const t=await r.entity.getDashUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}return d.parseFormats(e.data||e.result||e)}static async getAvailableFormats(){const t=await r.entity.getUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}const a=e.data||e.result||e;return d.parseFormats(a)}}class h{constructor(t,e){this.fragmentSplitFactor=6*2;this.workingXhr=null;this.progressMap=new Map;this.format=t;this.fragments=e||[];this.videoSpeed=new p(this)}get totalSize(){return this.fragments.map(t=>t.size).reduce((t,e)=>t+e)}async fetchVideoInfo(t=false){if(!t){const t=await r.entity.getUrl(this.format.quality);const e=await Ajax.getTextWithCredentials(t);const a=JSON.parse(e.replace(/http:/g,"https:"));const s=a.data||a.result||a;if(s.quality!==this.format.quality){throw new Error("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const i=s.durl;this.fragments=i.map(t=>{return{length:t.length,size:t.size,url:t.url,backupUrls:t.backup_url}})}else{const{dashToFragment:t,getDashInfo:a}=await e.importAsync("video-dash");const s=await a(await r.entity.getDashUrl(this.format.quality),this.format.quality);const i=s.videoDashes.sort(ascendingSort(t=>t.bandWidth))[0];const o=s.audioDashes.sort(ascendingSort(t=>t.bandWidth))[0];this.fragments=[t(i),t(o)]}return this.fragments}updateProgress(){const t=this.progressMap?[...this.progressMap.values()].reduce((t,e)=>t+e,0)/this.totalSize:0;if(t>1||t<0){console.error(`[下载视频] 进度异常: ${t}`,this.progressMap.values())}this.progress&&this.progress(t)}cancelDownload(){this.videoSpeed.stopMeasure();if(this.workingXhr!==null){this.workingXhr.forEach(t=>t.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(t){const e=[];this.workingXhr=[];this.progressMap=new Map;this.updateProgress();let a;if(t.size<=96*1024*1024){a=t.size/this.fragmentSplitFactor}else{a=16*1024*1024}let s=0;const i=t=>[...this.progressMap.keys()].indexOf(t)+1;while(s{const s=new XMLHttpRequest;s.open("GET",t.url);s.responseType="arraybuffer";s.withCredentials=false;s.addEventListener("progress",t=>{console.log(`[下载视频] 视频片段${i(s)}下载进度: ${t.loaded}/${r} bytes loaded, ${n}`);this.progressMap.set(s,t.loaded);this.updateProgress()});s.addEventListener("load",()=>{if((""+s.status)[0]==="2"){console.log(`[下载视频] 视频片段${i(s)}下载完成`);e(s.response)}else{a(`视频片段${i(s)}请求失败, response = ${s.status}`)}});s.addEventListener("abort",()=>a("canceled"));s.addEventListener("error",()=>{console.error(`[下载视频] 视频片段${i(s)}下载失败: ${n}`);this.progressMap.set(s,0);this.updateProgress();s.open("GET",t.url);s.setRequestHeader("Range",n);s.send()});s.setRequestHeader("Range",n);this.progressMap.set(s,0);s.send();this.workingXhr.push(s)}));s=Math.round(s+a)+1}return Promise.all(e)}async copyUrl(){const t=this.fragments.map(t=>t.url).reduce((t,e)=>t+"\r\n"+e);GM.setClipboard(t,"text")}async showUrl(){const t=this.fragments.map(t=>`\n${t.url}\n`).reduce((t,e)=>t+"\r\n"+e);Toast.success(t+`复制全部`,"显示链接");const e=await SpinQuery.select("#copy-link");e.addEventListener("click",async()=>{await this.copyUrl()})}async exportData(t=false){const s=JSON.stringify([{fragments:this.fragments,title:a(),totalSize:this.fragments.map(t=>t.size).reduce((t,e)=>t+e),referer:document.URL.replace(window.location.search,"")}]);if(t){GM.setClipboard(s,"text")}else{const t=new Blob([s],{type:"text/json"});const i=await this.downloadDanmaku();const{DownloadVideoPackage:o}=await e.importAsync("download-video-package");const n=new o;n.add(`${a()}.json`,t);n.add(a()+"."+this.danmakuOption.toLowerCase(),i);await n.emit(`${a()}.zip`)}}async exportAria2(s=false){if(s){const s=await this.downloadDanmaku();if(s!==null){const{DownloadVideoPackage:t}=await e.importAsync("download-video-package");t.single(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,s)}const i=t.aria2RpcOption;const o=this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}const o=[];if(i.secretKey!==""){o.push(`token:${i.secretKey}`)}o.push([t.url]);o.push({referer:document.URL.replace(window.location.search,""),"user-agent":UserAgent,out:`${a()}${s}${this.extension(t)}`,split:this.fragmentSplitFactor,dir:i.baseDir+i.dir||undefined,"max-download-limit":i.maxDownloadLimit||undefined});const n=encodeURIComponent(`${a()}${s}`);return{params:o,id:n}});const{sendRpc:n}=await e.importAsync("aria2-rpc");await n(o)}else{const t=`\n# Generated by Bilibili Evolved Video Export\n# https://github.com/the1812/Bilibili-Evolved/\n${this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}return`\n${t.url}\n referer=${document.URL.replace(window.location.search,"")}\n user-agent=${UserAgent}\n out=${a()}${s}${this.extension(t)}\n split=${this.fragmentSplitFactor}\n`.trim()}).join("\n")}\n`.trim();const s=new Blob([t],{type:"text/plain"});const i=await this.downloadDanmaku();const{DownloadVideoPackage:o}=await e.importAsync("download-video-package");const n=new o;n.add(`${a()}.txt`,s);n.add(a()+"."+this.danmakuOption.toLowerCase(),i);await n.emit(`${a()}.zip`)}}extension(t){const e=t||this.fragments[0];const a=[".flv",".mp4",".m4s"].find(t=>e.url.includes(t));if(a){return a}else{console.warn("No extension detected.");return".flv"}}makeBlob(t,e){return new Blob(Array.isArray(t)?t:[t],{type:this.extension(e)===".flv"?"video/x-flv":"video/mp4"})}cleanUpOldBlobUrl(){const t=dq("a#video-complete").getAttribute("href");if(t&&!dq(`.link[href="${t}"]`)){URL.revokeObjectURL(t)}dqa(".toast-card-header").filter(t=>t.innerText.includes("下载视频")).forEach(t=>t.querySelector(".toast-card-dismiss").click())}async downloadDanmaku(){if(this.danmakuOption!=="无"){const t=new i(r.cid);await t.fetchInfo();if(this.danmakuOption==="XML"){return t.rawXML}else{const{convertToAss:a}=await e.importAsync("download-danmaku");return a(t.rawXML)}}else{return null}}async downloadSingle(t){const e=await this.downloadDanmaku();const[s]=t;if(e===null){const t=this.makeBlob(s);const e=a()+this.extension();return{blob:t,filename:e}}else{const t=new JSZip;t.file(a()+this.extension(),this.makeBlob(s));t.file(a()+"."+this.danmakuOption.toLowerCase(),e);const i=await t.generateAsync({type:"blob"});const o=a()+".zip";return{blob:i,filename:o}}}async downloadMultiple(t){const e=new JSZip;const s=a();if(t.length>1){t.forEach((t,a)=>{const i=this.fragments[a];e.file(`${s} - ${a+1}${this.extension(i)}`,this.makeBlob(t,i))})}else{const[a]=t;e.file(`${s}${this.extension()}`,this.makeBlob(a))}const i=await this.downloadDanmaku();if(i!==null){e.file(a()+"."+this.danmakuOption.toLowerCase(),i)}const o=await e.generateAsync({type:"blob"});const n=s+".zip";return{blob:o,filename:n}}async download(){const t=[];this.videoSpeed.startMeasure();for(const e of this.fragments){const a=await this.downloadFragment(e);t.push(a)}if(t.length<1){throw new Error("下载失败.")}let{blob:e,filename:a}=await(async()=>{if(t.length===1){return await this.downloadSingle(t)}else{return await this.downloadMultiple(t)}})();this.cleanUpOldBlobUrl();const s=URL.createObjectURL(e);this.progress&&this.progress(0);this.videoSpeed.stopMeasure();return{url:s,filename:a}}}class p{constructor(t){this.lastProgress=0;this.measureInterval=1e3;this.workingDownloader=t}startMeasure(){this.intervalTimer=setInterval(()=>{const t=this.workingDownloader.progressMap?[...this.workingDownloader.progressMap.values()].reduce((t,e)=>t+e,0):0;const e=t-this.lastProgress;if(this.speedUpdate!==undefined){this.speedUpdate(formatFileSize(e)+"/s")}this.lastProgress=t},this.measureInterval)}stopMeasure(){clearInterval(this.intervalTimer)}}async function u(){const t=await SpinQuery.select(()=>(unsafeWindow||window).aid);const e=await SpinQuery.select(()=>(unsafeWindow||window).cid);if(!(t&&e)){return false}r.aid=t;r.cid=e;if(document.URL.indexOf("bangumi")!==-1){r.entity=new n}else{r.entity=new o}try{l=await d.getAvailableFormats()}catch(t){return false}return true}async function f(){c=l[0];e.applyStyle("downloadVideoStyle");dq("#download-video").addEventListener("click",()=>{dq(".download-video").classList.toggle("opened");dq(".gui-settings-mask").click()});dq("#download-video").addEventListener("mouseover",()=>{document.body.insertAdjacentHTML("beforeend",e.import("downloadVideoHtml"));w()},{once:true})}async function w(){let o;const n=new Map;const h=new Vue({el:".download-video",components:{VDropdown:()=>e.importAsync("v-dropdown.vue"),VCheckbox:()=>e.importAsync("v-checkbox.vue"),RpcProfiles:()=>e.importAsync("aria2-rpc-profiles.vue")},data:{downloadSingle:true,coverUrl:EmptyImageUrl,aid:r.aid,cid:r.cid,dashModel:{value:t.downloadVideoFormat,items:["flv","dash"]},qualityModel:{value:c.displayName,items:l.map(t=>t.displayName)},danmakuModel:{value:t.downloadVideoDefaultDanmaku,items:["无","XML","ASS"]},progressPercent:0,size:"获取大小中",blobUrl:"",episodeList:[],downloading:false,speed:"",batch:false,rpcSettings:t.aria2RpcOption,showRpcSettings:false,busy:false,saveRpcSettingsText:"保存配置",enableDash:t.enableDashDownload},computed:{displaySize(){if(typeof this.size==="string"){return this.size}return formatFileSize(this.size)},sizeWarning(){if(typeof this.size==="string"){return false}return this.size>1073741824},selectedEpisodeCount(){return this.episodeList.filter(t=>t.checked).length},dash(){return this.dashModel.value==="dash"}},methods:{close(){this.$el.classList.remove("opened")},danmakuOptionChange(){t.downloadVideoDefaultDanmaku=this.danmakuModel.value},async dashChange(){const t=this.dashModel.value;let e=[];if(t==="flv"){e=await d.getAvailableFormats()}else{e=await d.getAvailableDashFormats()}l=e;[c]=t;this.qualityModel.items=e.map(t=>t.displayName);[this.qualityModel.value]=this.qualityModel.items;await this.formatChange()},async formatChange(){const t=this.getFormat();const e=n.get(t);if(e){this.size=e;return}try{this.size="获取大小中";const e=await t.downloadInfo(this.dash);this.size=e.totalSize;n.set(t,this.size)}catch(t){this.size="获取大小失败"}},getFormat(){const t=l.find(t=>t.displayName===this.qualityModel.value);if(!t){console.error(`No format found. model value = ${this.qualityModel.value}`);return null}return t},async exportData(t){if(this.busy===true){return}try{this.busy=true;if(!this.downloadSingle){await this.exportBatchData(t);return}const e=this.getFormat();const a=await e.downloadInfo(this.dash);a.danmakuOption=this.danmakuModel.value;switch(t){case"copyLink":await a.copyUrl();Toast.success("已复制链接到剪贴板.","下载视频",3e3);break;case"showLink":await a.showUrl();break;case"aria2":await a.exportAria2(false);break;case"aria2RPC":await a.exportAria2(true);break;case"copyVLD":await a.exportData(true);Toast.success("已复制VLD数据到剪贴板.","下载视频",3e3);break;case"exportVLD":await a.exportData(false);break;default:break}}catch(t){logError(t)}finally{this.busy=false}},async exportBatchData(t){const s=this.episodeList;if(s.every(t=>t.checked===false)){Toast.info("请至少选择1集或以上的数量!","批量导出",3e3);return}const o=t=>{const e=s.find(e=>e.cid===t.cid);if(e===undefined){return false}return e.checked};const n=this.getFormat();const{DownloadVideoPackage:r}=await e.importAsync("download-video-package");if(this.danmakuModel.value!=="无"){const t=Toast.info("下载弹幕中...","批量导出");const a=new r;try{if(this.danmakuModel.value==="XML"){for(const t of s.filter(o)){const e=new i(t.cid);await e.fetchInfo();a.add(t.title+".xml",e.rawXML)}}else{const{convertToAss:t}=await e.importAsync("download-danmaku");for(const e of s.filter(o)){const s=new i(e.cid);await s.fetchInfo();a.add(e.title+".ass",await t(s.rawXML))}}await a.emit(this.cid+".danmakus.zip")}catch(t){logError(`弹幕下载失败`)}finally{t.dismiss()}}const l=Toast.info("获取链接中...","批量导出");this.batchExtractor.itemFilter=o;let c;try{switch(t){case"aria2":c=await this.batchExtractor.collectAria2(n,l);await r.single(a(false)+".txt",new Blob([c],{type:"text/plain"}));return;case"aria2RPC":await this.batchExtractor.collectAria2(n,l,true);Toast.success(`成功发送了批量请求.`,"aria2 RPC",3e3);return;case"copyVLD":GM.setClipboard(await this.batchExtractor.collectData(n,l),{mimetype:"text/plain"});Toast.success("已复制批量vld数据到剪贴板.","批量导出",3e3);return;case"exportVLD":c=await this.batchExtractor.collectData(n,l);await r.single(a(false)+".json",new Blob([c],{type:"text/json"}));return;default:return}}catch(t){logError(t)}finally{l.dismiss()}},async checkBatch(){const t=["/www.bilibili.com/bangumi","/www.bilibili.com/video/av"];if(!t.some(t=>document.URL.includes(t))){this.batch=false;this.episodeList=[];return}const{BatchExtractor:a}=await e.importAsync("batch-download");if(await a.test()!==true){this.batch=false;this.episodeList=[];return}this.batchExtractor=new a;this.batch=true;this.episodeList=(await this.batchExtractor.getItemList()).map((t,e)=>{return{aid:t.aid,cid:t.cid,title:t.title,index:e,checked:true}})},cancelDownload(){if(o){o.cancelDownload()}},async startDownload(){const t=this.getFormat();try{this.downloading=true;const e=await t.downloadInfo(this.dash);e.videoSpeed.speedUpdate=(t=>this.speed=t);e.danmakuOption=this.danmakuModel.value;e.progress=(t=>{this.progressPercent=Math.trunc(t*100)});o=e;const a=await e.download();const s=document.getElementById("video-complete");s.setAttribute("href",a.url);s.setAttribute("download",a.filename);s.click();Toast.success(`下载完成: ${a.filename} 再次保存`,"下载视频")}catch(t){if(t!=="canceled"){logError(t)}this.progressPercent=0}finally{this.downloading=false;this.speed=""}},selectAllEpisodes(){this.episodeList.forEach(t=>t.checked=true)},unselectAllEpisodes(){this.episodeList.forEach(t=>t.checked=false)},inverseAllEpisodes(){this.episodeList.forEach(t=>t.checked=!t.checked)},toggleRpcSettings(){this.showRpcSettings=!this.showRpcSettings},saveRpcSettings(){if(this.rpcSettings.host===""){this.rpcSettings.host="127.0.0.1"}if(this.rpcSettings.port===""){this.rpcSettings.port="6800"}t.aria2RpcOption=this.rpcSettings;const e=t.aria2RpcOptionProfiles.find(e=>e.name===t.aria2RpcOptionSelectedProfile);if(e){Object.assign(e,this.rpcSettings);t.aria2RpcOptionProfiles=t.aria2RpcOptionProfiles}this.saveRpcSettingsText="已保存";setTimeout(()=>this.saveRpcSettingsText="保存配置",2e3)},updateProfile(e){t.aria2RpcOption=this.rpcSettings=_.omit(e,"name")}}});Observer.videoChange(async()=>{h.close();h.batch=false;h.downloadSingle=true;const t=dq("#download-video");const e=await u();t.style.display=e?"flex":"none";if(!e){return}h.aid=r.aid;h.cid=r.cid;const a=new s(r.aid);await a.fetchInfo();h.coverUrl=a.coverUrl.replace("http:","https:");l=await d.getAvailableFormats();[c]=l;h.qualityModel={value:c.displayName,items:l.map(t=>t.displayName)};h.formatChange();await h.checkBatch()})}return{widget:{content:`\n`,condition:u,success:f}}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.html"] = `

下载视频

单个视频
批量导出
警告: 过大的视频大小会在直接下载时占用大量内存, 并可能导致浏览器标签页崩溃. 请考虑降低清晰度或使用导出选项.
预计大小: {{displaySize}}
格式
清晰度
弹幕
ffmpeg支持

直接下载

{{speed}}
{{progressPercent}}%

选集

{{selectedEpisodeCount}}/{{episodeList.length}}

导出

{{showRpcSettings ? '取消' : 'aria2 RPC'}}

aria2 RPC

配置

主机
端口
密钥
限速
默认路径
路径
最终路径: {{rpcSettings.baseDir + rpcSettings.dir}}
方法
开始下载
{{saveRpcSettingsText}}
`; +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:a}=e.import("title");const{VideoInfo:s,DanmakuInfo:i}=e.import("video-info");const{DownloadVideoPackage:n}=e.import("download-video-package");class o{async getDashUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&fnver=0&fnval=16`}else{return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&otype=json`}}}class r extends o{async getDashUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&qn=${t}&otype=json&fourk=1&fnval=16`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&otype=json&fourk=1&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=&otype=json`}}}class l extends o{constructor(t){super();this.ep=t}async getDashUrl(t){if(t){return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16`}else{return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&ep_id=${this.ep}`}else{return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&ep_id=${this.ep}`}}}const c={entity:new o,aid:"",cid:""};let d=[];let p=null;class h{constructor(t,e,a){this.quality=t;this.internalName=e;this.displayName=a}async downloadInfo(t=false){const e=new u(this);await e.fetchVideoInfo(t);return e}static parseFormats(t){const e=t.accept_quality;const a=t.accept_format.split(",");const s=t.accept_description;const i=e.map((t,e)=>{return new h(t,a[e],s[e])});return i}static async getAvailableDashFormats(){const t=await c.entity.getDashUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}return h.parseFormats(e.data||e.result||e)}static async getAvailableFormats(){const t=await c.entity.getUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}const a=e.data||e.result||e;return h.parseFormats(a)}}class u{constructor(t,e){this.fragmentSplitFactor=6*2;this.workingXhr=null;this.progressMap=new Map;this.danmakuOption="无";this.ffmpegOption="无";this.format=t;this.fragments=e||[];this.videoSpeed=new f(this)}get totalSize(){return this.fragments.map(t=>t.size).reduce((t,e)=>t+e)}async fetchVideoInfo(t=false){if(!t){const t=await c.entity.getUrl(this.format.quality);const e=await Ajax.getTextWithCredentials(t);const a=JSON.parse(e.replace(/http:/g,"https:"));const s=a.data||a.result||a;if(s.quality!==this.format.quality){throw new Error("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const i=s.durl;this.fragments=i.map(t=>{return{length:t.length,size:t.size,url:t.url,backupUrls:t.backup_url}})}else{const{dashToFragment:t,getDashInfo:a}=await e.importAsync("video-dash");const s=await a(await c.entity.getDashUrl(this.format.quality),this.format.quality);const i=s.videoDashes.sort(ascendingSort(t=>t.bandWidth))[0];const n=s.audioDashes.sort(ascendingSort(t=>t.bandWidth))[0];this.fragments=[t(i),t(n)]}return this.fragments}updateProgress(){const t=this.progressMap?[...this.progressMap.values()].reduce((t,e)=>t+e,0)/this.totalSize:0;if(t>1||t<0){console.error(`[下载视频] 进度异常: ${t}`,this.progressMap.values())}this.progress&&this.progress(t)}cancelDownload(){this.videoSpeed.stopMeasure();if(this.workingXhr!==null){this.workingXhr.forEach(t=>t.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(t){const e=[];this.workingXhr=[];this.progressMap=new Map;this.updateProgress();let a;if(t.size<=48*1024*1024){a=t.size/this.fragmentSplitFactor}else{a=4*1024*1024}let s=0;const i=t=>[...this.progressMap.keys()].indexOf(t)+1;while(s{const s=new XMLHttpRequest;s.open("GET",t.url);s.responseType="arraybuffer";s.withCredentials=false;s.addEventListener("progress",t=>{console.log(`[下载视频] 视频片段${i(s)}下载进度: ${t.loaded}/${r} bytes loaded, ${o}`);this.progressMap.set(s,t.loaded);this.updateProgress()});s.addEventListener("load",()=>{if((""+s.status)[0]==="2"){console.log(`[下载视频] 视频片段${i(s)}下载完成`);e(s.response)}else{a(`视频片段${i(s)}请求失败, response = ${s.status}`)}});s.addEventListener("abort",()=>a("canceled"));s.addEventListener("error",()=>{console.error(`[下载视频] 视频片段${i(s)}下载失败: ${o}`);this.progressMap.set(s,0);this.updateProgress();s.open("GET",t.url);s.setRequestHeader("Range",o);s.send()});s.setRequestHeader("Range",o);this.progressMap.set(s,0);s.send();this.workingXhr.push(s)}));s=Math.round(s+a)+1}return Promise.all(e)}async copyUrl(){const t=this.fragments.map(t=>t.url).reduce((t,e)=>t+"\r\n"+e);GM.setClipboard(t,"text")}async showUrl(){const t=this.fragments.map(t=>`\n${t.url}\n`).reduce((t,e)=>t+"\r\n"+e);Toast.success(t+`复制全部`,"显示链接");const e=await SpinQuery.select("#copy-link");e.addEventListener("click",async()=>{await this.copyUrl()})}async exportData(t=false){const e=JSON.stringify([{fragments:this.fragments,title:a(),totalSize:this.fragments.map(t=>t.size).reduce((t,e)=>t+e),referer:document.URL.replace(window.location.search,"")}]);if(t){GM.setClipboard(e,"text")}else{const t=new Blob([e],{type:"text/json"});const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.json`,t);i.add(a()+"."+this.danmakuOption.toLowerCase(),s);await i.emit(`${a()}.zip`)}}async exportAria2(s=false){if(s){const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,s);await i.emit();const o=t.aria2RpcOption;const r=this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}const i=[];if(o.secretKey!==""){i.push(`token:${o.secretKey}`)}i.push([t.url]);i.push({referer:document.URL.replace(window.location.search,""),"user-agent":UserAgent,out:`${a()}${s}${this.extension(t)}`,split:this.fragmentSplitFactor,dir:o.baseDir+o.dir||undefined,"max-download-limit":o.maxDownloadLimit||undefined});const n=encodeURIComponent(`${a()}${s}`);return{params:i,id:n}});const{sendRpc:l}=await e.importAsync("aria2-rpc");await l(r)}else{const t=`\n# Generated by Bilibili Evolved Video Export\n# https://github.com/the1812/Bilibili-Evolved/\n${this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}return`\n${t.url}\n referer=${document.URL.replace(window.location.search,"")}\n user-agent=${UserAgent}\n out=${a()}${s}${this.extension(t)}\n split=${this.fragmentSplitFactor}\n`.trim()}).join("\n")}\n`.trim();const e=new Blob([t],{type:"text/plain"});const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.txt`,e);i.add(a()+"."+this.danmakuOption.toLowerCase(),s);await i.emit(`${a()}.zip`)}}extension(t){const e=t||this.fragments[0];const a=[".flv",".mp4",".m4s"].find(t=>e.url.includes(t));if(a){return a}else{console.warn("No extension detected.");return".flv"}}async downloadDanmaku(){if(this.danmakuOption!=="无"){const t=new i(c.cid);await t.fetchInfo();if(this.danmakuOption==="XML"){return t.rawXML}else{const{convertToAss:a}=await e.importAsync("download-danmaku");return a(t.rawXML)}}else{return null}}async download(){const t=[];this.videoSpeed.startMeasure();for(const e of this.fragments){const a=await this.downloadFragment(e);t.push(a)}if(t.length<1){throw new Error("下载失败.")}const e=new n({ffmpeg:this.ffmpegOption});const s=a();t.forEach((a,i)=>{let n;const o=this.fragments[i];if(t.length>1){n=`${s} - ${i+1}${this.extension(o)}`}else{n=`${s}${this.extension(o)}`}e.add(n,new Blob(Array.isArray(a)?a:[a],{type:this.extension(o)===".flv"?"video/x-flv":"video/mp4"}))});const i=await this.downloadDanmaku();e.add(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,i);await e.emit(s+".zip");this.progress&&this.progress(0);this.videoSpeed.stopMeasure()}}class f{constructor(t){this.lastProgress=0;this.measureInterval=1e3;this.workingDownloader=t}startMeasure(){this.intervalTimer=setInterval(()=>{const t=this.workingDownloader.progressMap?[...this.workingDownloader.progressMap.values()].reduce((t,e)=>t+e,0):0;const e=t-this.lastProgress;if(this.speedUpdate!==undefined){this.speedUpdate(formatFileSize(e)+"/s")}this.lastProgress=t},this.measureInterval)}stopMeasure(){clearInterval(this.intervalTimer)}}async function m(){const t=await SpinQuery.select(()=>(unsafeWindow||window).aid);const e=await SpinQuery.select(()=>(unsafeWindow||window).cid);if(!(t&&e)){return false}c.aid=t;c.cid=e;if(document.URL.includes("bangumi")){c.entity=new r}else if(document.URL.includes("cheese")){const t=document.URL.match(/cheese\/play\/ep([\d]+)/);c.entity=new l(t[1])}else{c.entity=new o}try{d=await h.getAvailableFormats()}catch(t){return false}return true}async function w(){p=d[0];e.applyStyle("downloadVideoStyle");dq("#download-video").addEventListener("click",()=>{dq(".download-video").classList.toggle("opened");dq(".gui-settings-mask").click()});dq("#download-video").addEventListener("mouseover",()=>{document.body.insertAdjacentHTML("beforeend",e.import("downloadVideoHtml"));g()},{once:true})}async function g(){let o;const r=new Map;const l=new Vue({el:".download-video",components:{VDropdown:()=>e.importAsync("v-dropdown.vue"),VCheckbox:()=>e.importAsync("v-checkbox.vue"),RpcProfiles:()=>e.importAsync("aria2-rpc-profiles.vue")},data:{downloadSingle:true,coverUrl:EmptyImageUrl,aid:c.aid,cid:c.cid,dashModel:{value:t.downloadVideoFormat,items:["flv","dash"]},qualityModel:{value:p.displayName,items:d.map(t=>t.displayName)},danmakuModel:{value:t.downloadVideoDefaultDanmaku,items:["无","XML","ASS"]},ffmpegModel:{value:t.downloadVideoFfmpegSupport,items:["无","文件列表","文件列表+脚本"]},progressPercent:0,size:"获取大小中",blobUrl:"",episodeList:[],downloading:false,speed:"",batch:false,rpcSettings:t.aria2RpcOption,showRpcSettings:false,busy:false,saveRpcSettingsText:"保存配置",enableDash:t.enableDashDownload,lastDirectDownloadLink:""},computed:{displaySize(){if(typeof this.size==="string"){return this.size}return formatFileSize(this.size)},sizeWarning(){if(typeof this.size==="string"){return false}return this.size>1073741824},selectedEpisodeCount(){return this.episodeList.filter(t=>t.checked).length},dash(){return this.dashModel.value==="dash"}},methods:{close(){this.$el.classList.remove("opened")},danmakuOptionChange(){t.downloadVideoDefaultDanmaku=this.danmakuModel.value},async dashChange(){const t=this.dashModel.value;let e=[];if(t==="flv"){e=await h.getAvailableFormats()}else{e=await h.getAvailableDashFormats()}d=e;[p]=t;this.qualityModel.items=e.map(t=>t.displayName);[this.qualityModel.value]=this.qualityModel.items;await this.formatChange()},async formatChange(){const t=this.getFormat();const e=r.get(t);if(e){this.size=e;return}try{this.size="获取大小中";const e=await t.downloadInfo(this.dash);this.size=e.totalSize;r.set(t,this.size)}catch(t){this.size="获取大小失败"}},getFormat(){const t=d.find(t=>t.displayName===this.qualityModel.value);if(!t){console.error(`No format found. model value = ${this.qualityModel.value}`);return null}return t},async exportData(t){if(this.busy===true){return}try{this.busy=true;if(!this.downloadSingle){await this.exportBatchData(t);return}const e=this.getFormat();const a=await e.downloadInfo(this.dash);a.danmakuOption=this.danmakuModel.value;switch(t){case"copyLink":await a.copyUrl();Toast.success("已复制链接到剪贴板.","下载视频",3e3);break;case"showLink":await a.showUrl();break;case"aria2":await a.exportAria2(false);break;case"aria2RPC":await a.exportAria2(true);break;case"copyVLD":await a.exportData(true);Toast.success("已复制VLD数据到剪贴板.","下载视频",3e3);break;case"exportVLD":await a.exportData(false);break;default:break}}catch(t){logError(t)}finally{this.busy=false}},async exportBatchData(t){const s=this.episodeList;if(s.every(t=>t.checked===false)){Toast.info("请至少选择1集或以上的数量!","批量导出",3e3);return}const o=t=>{const e=s.find(e=>e.cid===t.cid);if(e===undefined){return false}return e.checked};const r=this.getFormat();if(this.danmakuModel.value!=="无"){const t=Toast.info("下载弹幕中...","批量导出");const a=new n;try{if(this.danmakuModel.value==="XML"){for(const t of s.filter(o)){const e=new i(t.cid);await e.fetchInfo();a.add(t.title+".xml",e.rawXML)}}else{const{convertToAss:t}=await e.importAsync("download-danmaku");for(const e of s.filter(o)){const s=new i(e.cid);await s.fetchInfo();a.add(e.title+".ass",await t(s.rawXML))}}await a.emit(this.cid+".danmakus.zip")}catch(t){logError(`弹幕下载失败`)}finally{t.dismiss()}}const l=Toast.info("获取链接中...","批量导出");this.batchExtractor.itemFilter=o;let c;try{switch(t){case"aria2":c=await this.batchExtractor.collectAria2(r,l);await n.single(a(false)+".txt",new Blob([c],{type:"text/plain"}),{ffmpeg:this.ffmpegOption});return;case"aria2RPC":await this.batchExtractor.collectAria2(r,l,true);Toast.success(`成功发送了批量请求.`,"aria2 RPC",3e3);return;case"copyVLD":GM.setClipboard(await this.batchExtractor.collectData(r,l),{mimetype:"text/plain"});Toast.success("已复制批量vld数据到剪贴板.","批量导出",3e3);return;case"exportVLD":c=await this.batchExtractor.collectData(r,l);await n.single(a(false)+".json",new Blob([c],{type:"text/json"}),{ffmpeg:this.ffmpegOption});return;default:return}}catch(t){logError(t)}finally{l.dismiss()}},async checkBatch(){const t=["/www.bilibili.com/bangumi","/www.bilibili.com/video/av"];if(!t.some(t=>document.URL.includes(t))){this.batch=false;this.episodeList=[];return}const{BatchExtractor:a}=await e.importAsync("batch-download");if(await a.test()!==true){this.batch=false;this.episodeList=[];return}this.batchExtractor=new a;this.batch=true;this.episodeList=(await this.batchExtractor.getItemList()).map((t,e)=>{return{aid:t.aid,cid:t.cid,title:t.title,index:e,checked:true}})},cancelDownload(){if(o){o.cancelDownload()}},async startDownload(){const t=this.getFormat();try{this.downloading=true;const e=await t.downloadInfo(this.dash);e.videoSpeed.speedUpdate=(t=>this.speed=t);e.danmakuOption=this.danmakuModel.value;e.ffmpegOption=this.ffmpegModel.value;e.progress=(t=>{this.progressPercent=Math.trunc(t*100)});o=e;await e.download();this.lastDirectDownloadLink=n.lastPackageUrl}catch(t){if(t!=="canceled"){logError(t)}this.progressPercent=0}finally{this.downloading=false;this.speed=""}},selectAllEpisodes(){this.episodeList.forEach(t=>t.checked=true)},unselectAllEpisodes(){this.episodeList.forEach(t=>t.checked=false)},inverseAllEpisodes(){this.episodeList.forEach(t=>t.checked=!t.checked)},toggleRpcSettings(){this.showRpcSettings=!this.showRpcSettings},saveRpcSettings(){if(this.rpcSettings.host===""){this.rpcSettings.host="127.0.0.1"}if(this.rpcSettings.port===""){this.rpcSettings.port="6800"}t.aria2RpcOption=this.rpcSettings;const e=t.aria2RpcOptionProfiles.find(e=>e.name===t.aria2RpcOptionSelectedProfile);if(e){Object.assign(e,this.rpcSettings);t.aria2RpcOptionProfiles=t.aria2RpcOptionProfiles}this.saveRpcSettingsText="已保存";setTimeout(()=>this.saveRpcSettingsText="保存配置",2e3)},updateProfile(e){t.aria2RpcOption=this.rpcSettings=_.omit(e,"name")}}});Observer.videoChange(async()=>{l.close();l.batch=false;l.downloadSingle=true;const t=dq("#download-video");const e=await m();t.style.display=e?"flex":"none";if(!e){return}l.aid=c.aid;l.cid=c.cid;try{const t=new s(c.aid);await t.fetchInfo();l.coverUrl=t.coverUrl.replace("http:","https:")}catch(t){l.coverUrl=EmptyImageUrl}d=await h.getAvailableFormats();[p]=d;l.qualityModel={value:p.displayName,items:d.map(t=>t.displayName)};l.formatChange();await l.checkBatch()})}return{widget:{content:`\n`,condition:m,success:w}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/dpi-img.vue.min.js"] = (()=>{return(t,s)=>{const e=``;return{export:Object.assign({template:e},{props:["size","src","blur","root","rootMargin","threshold"],data(){return{srcset:null,actualSrc:null}},methods:{calcSrc(){if(!this.src||!this.size){return null}const t=this.src.substring(this.src.lastIndexOf(".")+1);this.srcset=getDpiSourceSet(this.src,this.size,t);this.actualSrc=this.src}},mounted(){const t={root:this.root,rootMargin:this.rootMargin||"200px",threshold:this.threshold};const s=new IntersectionObserver(t=>{t.forEach(t=>{if(t.isIntersecting){this.calcSrc();s.disconnect()}})},t);s.observe(this.$el)},computed:{width(){if(typeof this.size==="object"&&"width"in this.size){return this.size.width}return null},height(){if(typeof this.size==="object"&&"height"in this.size){return this.size.height}return null}}})}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/expand-danmaku.min.js"] = (()=>{return(e,a)=>{if(typeof isEmbeddedPlayer!=="undefined"&&isEmbeddedPlayer()){return}Observer.videoChange(async()=>{const e=await SpinQuery.select(".bui-collapse-wrap");if(e&&e.classList.contains("bui-collapse-wrap-folded")){const e=await SpinQuery.select(".bui-collapse-header");e.click()}})}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/expand-description.min.css"] = `.play-up-info .play-up-self,.video-desc .info{height:auto!important}.play-up-info .play-up-self-btn,.video-desc .btn{display:none!important}`; @@ -1207,7 +1208,7 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/v-dropdown.vue.min.js"] = (()=>{return(o,e)=>{const n=`
{{ value }}
`;e.applyStyleFromText(`.v-dropdown{--background-color:#eee;position:relative;background-color:var(--background-color);cursor:pointer;display:flex;align-items:center;justify-content:space-between;min-width:100px}body.dark .v-dropdown{--background-color:#333}.v-dropdown .dropdown-menu{transform-origin:top;transform:translateY(-4px) translateX(-50%);pointer-events:none;opacity:0;position:absolute;top:calc(100% + 2px);left:50%;background-color:var(--background-color);z-index:1;transition:.2s ease-out;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0}.v-dropdown .dropdown-menu.opened{transform:translateY(0) translateX(-50%);pointer-events:initial;opacity:1}.v-dropdown .dropdown-menu li{padding:4px 16px;white-space:nowrap;min-width:64px;text-align:center;cursor:pointer;color:inherit;background-color:transparent}.v-dropdown .dropdown-menu li:hover{background-color:rgba(0,0,0,.16)}.v-dropdown .mdi-chevron-down{font-size:16pt;line-height:1;transform:rotate(0)}.v-dropdown .dropdown-menu.opened~.mdi-chevron-down{transform:rotate(180deg)}.v-dropdown .selected{user-select:none;padding:4px 8px}.round-corner .v-dropdown,.round-corner .v-dropdown .dropdown-menu,.round-corner .v-dropdown .dropdown-menu li{border-radius:var(--corner-radius)}`,"v-dropdown-style");return{export:Object.assign({template:n},{props:["items","value"],data(){return{dropdownOpen:false}},methods:{toggleDropdown(){this.dropdownOpen=!this.dropdownOpen;if(this.dropdownOpen){document.addEventListener("click",o=>{const e=o.target;if(e===this.$el||this.$el.contains(e)){return}this.dropdownOpen=false},{once:true,capture:true})}},select(o){this.$emit("update:value",o);this.$emit("change",o)}}})}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-card-info.min.js"] = (()=>{return(r,e)=>{}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-card.vue.min.js"] = (()=>{return(e,i)=>{const t=`
{{durationText}}
{{watchlater ? '已添加' : '稍后再看'}}

{{title}}

{{description}}

{{upName}}
{{playCount}}
`;i.applyStyleFromText(`.video-card{display:grid;grid-template-columns:200px 1fr;grid-template-rows:1fr 1fr 1fr;grid-template-areas:"cover title" "cover description" "cover up";height:var(--card-height);width:var(--card-width);color:#000;background-color:#fff;border-radius:16px;box-shadow:0 4px 8px 0 #0001;margin-right:var(--card-margin);margin-bottom:var(--card-margin);position:relative}body.dark .video-card,body.dark .video-card:hover{background-color:#282828;color:#eee}.video-card:hover{color:#000}.video-card.vertical{grid-template-columns:auto auto;grid-template-rows:2fr 1fr 1fr;grid-template-areas:"cover cover" "title title" "up up"}.video-card.vertical .description,.video-card.vertical .topics{display:none}.video-card.vertical .cover-container{border-radius:16px 16px 0 0}.video-card.vertical .title{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;max-height:3em;word-break:break-all;white-space:normal;line-height:1.5;font-size:11pt}.video-card.vertical .up{align-self:start;white-space:nowrap}.video-card.vertical .up .name{text-overflow:ellipsis;overflow:hidden}.video-card.vertical .up:not(.no-face){margin-left:8px;max-width:calc(var(--card-width) - 16px)}.video-card.vertical .up.no-face{margin-top:8px;max-width:calc(var(--card-width) - 24px)}.video-card.vertical .stats{align-self:end;justify-self:start;margin-bottom:8px;margin-right:0}.video-card>*{justify-self:self-start;align-self:center}.video-card:hover .cover{transform:scale(1.05);transition:.1s cubic-bezier(.39,.58,.57,1)}.video-card:hover .duration,.video-card:hover .watchlater{opacity:1}.video-card .duration,.video-card .watchlater{opacity:0}.video-card .cover-container{grid-area:cover;border-radius:16px 0 0 16px;position:relative;width:100%;height:100%;overflow:hidden}.video-card .cover-container .cover{object-fit:cover;width:100%;height:100%}.video-card .cover-container>:not(.cover){position:absolute}.video-card .cover-container .duration,.video-card .cover-container .watchlater{bottom:6px;padding:4px 8px;background-color:#000a;color:#fff;border-radius:14px;height:24px}.video-card .cover-container .duration .mdi,.video-card .cover-container .watchlater .mdi{font-size:12pt;line-height:1;margin-right:4px}.video-card .cover-container .duration{left:6px}.video-card .cover-container .watchlater{right:6px;display:flex;align-items:center;padding-left:4px}.video-card .title{grid-area:title;font-size:12pt;font-weight:700;color:inherit;padding:0 12px;white-space:nowrap;overflow:hidden;justify-self:stretch;text-overflow:ellipsis}.video-card .topics{grid-area:description;display:flex;align-items:center;margin-left:12px}.video-card .topics .topic{color:inherit;padding:6px 8px;background-color:#8882;margin-right:8px;border-radius:14px;white-space:nowrap;max-width:120px;overflow:hidden;text-overflow:ellipsis}.video-card .topics .topic:hover{background-color:#8884;color:var(--theme-color)}.video-card .description{grid-area:description;color:inherit;overflow:hidden;align-self:stretch;justify-self:stretch;margin:0 12px;line-height:1.5;height:3em;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;scrollbar-width:none!important}.video-card .description::-webkit-scrollbar{width:0!important}.video-card .description.single-line{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.video-card .stats,.video-card .up{grid-area:up}.video-card .up{margin-left:12px;display:flex;align-items:center;padding:2px;background-color:#8882;border-radius:14px;color:inherit}.video-card .up.no-face{background-color:transparent;padding:0}.video-card .up.no-face .be-icon{font-size:14pt;opacity:.75}.video-card .up .face{border-radius:50%}.video-card .up .name{margin:0 8px}.video-card .up:not(.no-face):hover{background-color:#8884}.video-card .up:hover .be-icon,.video-card .up:hover .name{color:var(--theme-color)}.video-card .stats{justify-self:self-end;margin-right:12px;display:flex;align-items:center;opacity:.5}.video-card .stats .be-icon{font-size:12pt;margin:0 4px 0 12px}.video-card .stats .be-icon.be-iconfont-favorites-outline{font-size:14pt}.video-card .stats .be-icon.be-iconfont-coin-outline{font-size:11pt}`,"video-card-style");return{export:Object.assign({template:t},{props:["data","orientation"],components:{"dpi-img":()=>i.importAsync("dpi-img.vue"),Icon:()=>i.importAsync("icon.vue")},data(){return{upFaceUrl:"",danmakuCount:"",like:"",coins:"",favorites:"",dynamic:"",topics:[],upID:0,epID:0,...this.data}},computed:{vertical(){return this.orientation==="vertical"}},methods:{async toggleWatchlater(){try{this.watchlater=!this.watchlater;const{toggleWatchlater:e}=await i.importAsync("watchlater-api");e(this.aid.toString(),this.watchlater)}catch(e){this.watchlater=!this.watchlater;Toast.error(e.message,"稍后再看操作失败",3e3)}}}})}}})(); -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-dash.min.js"] = (()=>{return(t,a)=>{const d=t=>{return{url:t.downloadUrl,backupUrls:t.backupUrls,length:t.duration,size:Math.trunc(t.bandWidth*t.duration/8)}};const r=async(t,a)=>{const d=await Ajax.getJsonWithCredentials(t);const r=d.data||d.result||d;if(d.code!==0||!r.dash){throw new Error("DASH api failed")}const e=r.accept_quality;if(!e.includes(a)){throw new Error("没有找到请求的清晰度")}if(r.quality!==a){throw new Error("无法获取请求的清晰度, 请确认当前账号有相应的权限")}const o=r.accept_description;const n=o[e.indexOf(a)];const c=r.dash.duration;const i=r.dash.video.filter(t=>t.id===a).map(t=>{const d={quality:a,qualityText:n,width:t.width,height:t.height,codecs:t.codecs,codecId:t.codecid,bandWidth:t.bandwidth,frameRate:t.frameRate,backupUrls:t.backupUrl,downloadUrl:t.baseUrl,duration:c};return d});const s=r.dash.audio.map(t=>{return{bandWidth:t.bandwidth,codecs:t.codecs,codecId:t.codecid,backupUrls:t.backupUrl,downloadUrl:t.baseUrl,duration:c}});return{videoDashes:i,audioDashes:s}};return{export:{getDashInfo:r,dashToFragment:d}}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-dash.min.js"] = (()=>{return(t,a)=>{const r=t=>{return{url:t.downloadUrl,backupUrls:t.backupUrls,length:t.duration,size:Math.trunc(t.bandWidth*t.duration/8)}};const e=async(t,a)=>{const r=await Ajax.getJsonWithCredentials(t);const e=r.data||r.result||r;if(r.code!==0||!e.dash){throw new Error("DASH api failed")}const d=e.accept_quality;if(!d.includes(a)){throw new Error("没有找到请求的清晰度")}if(e.quality!==a){throw new Error("无法获取请求的清晰度, 请确认当前账号有相应的权限")}const c=e.accept_description;const o=c[d.indexOf(a)];const s=e.dash.duration;const n=e.dash.video.filter(t=>t.id===a).map(t=>{const r={quality:a,qualityText:o,width:t.width,height:t.height,codecs:t.codecs,codecId:t.codecid,bandWidth:t.bandwidth,frameRate:t.frameRate,backupUrls:(t.backupUrl||t.backup_url||"").replace("http:","https:"),downloadUrl:(t.baseUrl||t.base_url||"").replace("http:","https:"),duration:s};return r});const i=e.dash.audio.map(t=>{return{bandWidth:t.bandwidth,codecs:t.codecs,codecId:t.codecid,backupUrls:(t.backupUrl||t.backup_url||"").replace("http:","https:"),downloadUrl:(t.baseUrl||t.base_url||"").replace("http:","https:"),duration:s}});return{videoDashes:n,audioDashes:i}};return{export:{getDashInfo:e,dashToFragment:r}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-downloader-fragment.min.js"] = (()=>{return(r,e)=>{}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-info.min.js"] = (()=>{return(t,i)=>{class e{constructor(t){this.aid=t}async fetchInfo(){const t=JSON.parse(await Ajax.getText(`https://api.bilibili.com/x/web-interface/view?aid=${this.aid}`));if(t.code!==0){throw new Error(t.message)}const i=t.data;this.cid=i.cid;this.pageCount=i.videos;this.coverUrl=i.pic;this.tagId=i.tid;this.tagName=i.tname;this.title=i.title;this.description=i.desc;this.up={uid:i.owner.mid,name:i.owner.name,faceUrl:i.owner.face};this.pages=i.pages.map(t=>{return{cid:t.cid,title:t.part,pageNumber:t.page}});return this}async fetchDanmaku(){this.danmaku=new s(this.cid.toString());return this.danmaku.fetchInfo()}}class a{constructor(t,i){this.text=t;this.p=i}}class s{constructor(t){this.cid=t}async fetchInfo(){const t=await Ajax.getText(`https://api.bilibili.com/x/v1/dm/list.so?oid=${this.cid}`);this.rawXML=t;const i=(new DOMParser).parseFromString(t,"application/xml").documentElement;this.xml=i;this.danmakus=[...i.querySelectorAll("d[p]")].map(t=>{return new a(t.innerHTML,t.getAttribute("p"))})}}class n{constructor(t){this.ep=t;this.videos=[]}async fetchInfo(){const t=await Ajax.getText(`https://www.bilibili.com/bangumi/play/ep${this.ep}/`);const i=JSON.parse(t.match(/window\.__INITIAL_STATE__=(.*);\(function\(\){/)[1]);this.title=i.mediaInfo.title;this.cover=i.mediaInfo.cover;this.squareCover=i.mediaInfo.square_cover;this.aid=i.epInfo.aid;this.cid=i.epInfo.cid;this.videos=i.epList.map(async t=>{return{title:t.index_title,aid:t.aid,cid:t.cid,info:await new e(t.aid).fetchInfo()}});return this}}return{export:{VideoInfo:e,BangumiInfo:n,Danmaku:a,DanmakuInfo:s}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-list.vue.min.js"] = (()=>{return(i,a)=>{const t=`
加载中...
空空如也哦 = ̄ω ̄=
`;a.applyStyleFromText(`.minimal-home .video-list .empty,.minimal-home .video-list .loading{height:48px;display:flex;align-items:center;justify-content:center;font-size:11pt;color:#707070}.minimal-home .video-list .empty .mdi,.minimal-home .video-list .loading .mdi{margin-right:8px}body.dark .minimal-home .video-list .empty,body.dark .minimal-home .video-list .loading{color:#eee}.minimal-home .video-list .cards{display:flex;flex-wrap:wrap;align-items:flex-end}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1),.minimal-home .video-list .cards.show-rank .video-card:nth-child(17),.minimal-home .video-list .cards.show-rank .video-card:nth-child(9){margin-top:48px}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1)::before,.minimal-home .video-list .cards.show-rank .video-card:nth-child(17)::before,.minimal-home .video-list .cards.show-rank .video-card:nth-child(9)::before{position:absolute;top:-42px;left:0;font-size:14pt;font-weight:700}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1)::before{content:"昨日"}.minimal-home .video-list .cards.show-rank .video-card:nth-child(9)::before{content:"三日"}.minimal-home .video-list .cards.show-rank .video-card:nth-child(17)::before{content:"一周"}`,"video-list-style");return{export:Object.assign({template:t},{components:{VideoCard:()=>a.importAsync("video-card.vue")},props:["showRank"],data(){return{cards:[],loading:true}},methods:{async getRankList(){const{getTrendingVideos:i}=await a.importAsync("trending-videos");const{getWatchlaterList:t}=await a.importAsync("watchlater-api");const e=await t();const o=async a=>{const t=await i(a,e);this.cards.push(...t)};await Promise.all([1,3,7].map(o))},async getActivityVideos(){const i=await Ajax.getJsonWithCredentials(`https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new?uid=${getUID()}&type_list=8`);const{getWatchlaterList:t}=await a.importAsync("watchlater-api");const e=await t();if(i.code!==0){throw new Error(i.message)}this.cards=i.data.cards.map(i=>{const a=JSON.parse(i.card);const t=_.get(i,"display.topic_info.topic_details",[]).map(i=>{return{id:i.topic_id,name:i.topic_name}});return{id:i.desc.dynamic_id_str,aid:a.aid,title:a.title,upID:i.desc.user_profile.info.uid,upName:i.desc.user_profile.info.uname,upFaceUrl:i.desc.user_profile.info.face,coverUrl:a.pic,description:a.desc,timestamp:i.timestamp,time:new Date(i.timestamp*1e3),topics:t,dynamic:a.dynamic,like:formatCount(i.desc.like),duration:a.duration,durationText:formatDuration(a.duration,0),playCount:formatCount(a.stat.view),danmakuCount:formatCount(a.stat.danmaku),watchlater:e.includes(a.aid)}})}},async mounted(){try{if(this.showRank){await this.getRankList()}else{await this.getActivityVideos()}}catch(i){Toast.error(i.message,this.showRank?"热门视频":"视频动态",3e3)}finally{this.loading=false}}})}}})(); @@ -1637,13 +1638,17 @@ Resource.manifest = { useCache: '启用缓存' } }, + videoDownloadPackage: { + path: 'download-video-package.min.js', + }, downloadVideo: { path: 'download-video.min.js', html: true, style: 'instant', - dependencies: ['title', 'videoInfo'], + dependencies: ['title', 'videoInfo', 'videoDownloadPackage'], displayNames: { 'downloadVideo': '下载视频', + 'videoDownloadPackage': '下载视频打包器', 'batchDownload': '批量下载', 'aria2Rpc': 'aria2 RPC', } diff --git a/bilibili-evolved.preview.user.js b/bilibili-evolved.preview.user.js index e1dff764d..65d8fd025 100644 --- a/bilibili-evolved.preview.user.js +++ b/bilibili-evolved.preview.user.js @@ -364,6 +364,7 @@ const settings = { customNavbarSeasonLogo: false, selectableColumnText: true, downloadVideoFormat: 'flv', + downloadVideoFfmpegSupport: '无', enableDashDownload: false, watchlaterExpireWarnings: true, watchlaterExpireWarningDays: 14, @@ -1083,10 +1084,10 @@ onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/m onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/double-click-fullscreen.min.js"] = (()=>{return(i,e)=>{(async()=>{const e=["https://www.bilibili.com/bangumi/","https://www.bilibili.com/video/"];if(!e.some(i=>document.URL.startsWith(i))){return}if(i.touchVideoPlayer&&i.touchVideoPlayerDoubleTapControl){Toast.info("在开启了播放器触摸支持-启用双击控制后, 双击全屏功能将无效.","提示");i.doubleClickFullscreen=false;return}await SpinQuery.unsafeJquery();const l=await SpinQuery.condition(()=>dq(".bilibili-player-area"),i=>i!==null&&unsafeWindow.$(".bilibili-player-video").data("events"));if(l===null){return}const n="double-click-fullscreen";if(!l.classList.contains(n)){l.classList.add(n);const e=unsafeWindow.$(".bilibili-player-video");const t=i.doubleClickFullscreenPreventSingleClick?e.data("events").click[0].handler:()=>{};const c=new DoubleClickEvent(()=>dq(".bilibili-player-video-btn-fullscreen").click(),i=>t(i));if(i.doubleClickFullscreenPreventSingleClick){e.unbind("click")}c.bind(e[0])}})()}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/download-audio.min.js"] = (()=>{return(e,t)=>{class n{constructor(){this.sid=null;this.progress=null}async getDownloadUrl(){const e=`https://www.bilibili.com/audio/music-service-c/web/url?sid=${this.sid}&privilege=2&quality=2`;const t=await Ajax.getJsonWithCredentials(e);if(t.code===0){return t.data.cdns.shift()}else{logError("获取下载链接失败, 请确保当前账号有下载权限.","下载音频",1e4);return null}}async download(){const e=await this.getDownloadUrl();return new Promise((t,n)=>{const s=new XMLHttpRequest;s.open("GET",e);s.responseType="blob";s.addEventListener("load",()=>t(s.response));s.addEventListener("error",()=>n(s.status));s.addEventListener("progress",e=>this.progress&&this.progress(100*e.loaded/e.total));s.send()})}}const s="下载音频";return{export:n,widget:{content:`\n\n\n${s}\n\n`,condition:()=>document.URL.includes("bilibili.com/audio"),success:async()=>{await SpinQuery.select(()=>document.querySelector("#app"));const e=document.querySelector("#download-audio");const t=e.querySelector("span");const o=new n;o.progress=(e=>{t.innerHTML=`${Math.round(e)}%`});const i=document.querySelector("#download-audio-link");e.addEventListener("click",async e=>{if(o.sid===null||e.target===i){return}const n=await o.download();t.innerHTML=s;const r=i.getAttribute("href");if(r){URL.revokeObjectURL(r)}i.setAttribute("href",URL.createObjectURL(n));const d=(()=>{const e=document.querySelector(".song-title");if(e){return e.getAttribute("title")}else{return"神秘音频"}})();i.setAttribute("download",d+".m4a");i.click()});Observer.childList("#app",()=>{const t=document.URL.match(/bilibili\.com\/audio\/au([\d]+)/);if(t&&t[1]){e.disabled=false;o.sid=t[1]}else{e.disabled=true}})}}}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/download-danmaku.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:n}=e.import("title");const{DanmakuInfo:i}=e.import("video-info");const{DanmakuConverter:a}=e.import("danmaku-converter");async function o(t){const e=n();let i={title:e};try{await loadDanmakuSettingsPanel();const t=t=>{const e=parseFloat(dq(t).style.transform.replace(/translateX\(([\d\.]+)/,"$1"));const n={0:0,44:1,94:2,144:3,188:4}[e];return n};i.font=dq(".bilibili-player-video-danmaku-setting-right-font .bui-select-result").innerText;i.alpha=parseFloat(dq(".bilibili-player-setting-opacity .bui-bar").style.transform.replace(/scaleX\(([\d\.]+)\)/,"$1"));i.duration=(()=>{const e=[18,14,10,8,6][t(".bilibili-player-setting-speedplus .bui-thumb")];return t=>{switch(t.type){case 4:case 5:return 4;default:return e}}})();i.blockTypes=(()=>{let t=[];const e={".bilibili-player-block-filter-type[ftype=scroll]":[1,2,3],".bilibili-player-block-filter-type[ftype=top]":[5],".bilibili-player-block-filter-type[ftype=bottom]":[4],".bilibili-player-block-filter-type[ftype=color]":["color"]};for(const[n,i]of Object.entries(e)){if(dq(n).classList.contains("disabled")){t=t.concat(i)}}return t.concat(7,8)})();const e=[1.4,1.2,1,.8,.6][t(".bilibili-player-setting-fontsize .bui-thumb")];i.resolution={x:1920*e,y:1080*e};i.bottomMarginPercent=[.75,.5,.25,0,0][t(".bilibili-player-setting-area .bui-thumb")];if(i.bottomMarginPercent===0&&dq(".bilibili-player-video-danmaku-setting-left-preventshade input").checked){i.bottomMarginPercent=.15}i.bold=dq(".bilibili-player-video-danmaku-setting-right-font-bold input").checked}catch(t){i={font:"微软雅黑",alpha:.6,duration:t=>{switch(t.type){case 4:case 5:return 4;default:return 6}},blockTypes:[7,8],resolution:{x:1920,y:1080},bottomMarginPercent:.15,bold:false}}const o=new a(i);const l=o.convertToAssDocument(t);return l.generateAss()}async function l(t,e){const a=n();const l=new i((unsafeWindow||window).cid);await l.fetchInfo();const r=await(async()=>{if(t===true){return new Blob([await o(l.rawXML)],{type:"text/plain"})}else{return new Blob([l.rawXML],{type:"text/plain"})}})();const s=URL.createObjectURL(r);const c=dq("#danmaku-link");const d=c.getAttribute("href");if(d){URL.revokeObjectURL(d)}clearTimeout(e);dq("#download-danmaku>span").innerHTML="下载弹幕";c.setAttribute("download",`${a}.${t?"ass":"xml"}`);c.setAttribute("href",s);c.click()}return{export:{downloadDanmaku:l,convertToAss:o},widget:{content:`\n\n\n下载弹幕\n\n`,condition:async()=>{let t=await SpinQuery.select(()=>(unsafeWindow||window).cid);return Boolean(t)},success:()=>{const t=document.querySelector("#danmaku-link");dq("#download-danmaku").addEventListener("click",e=>{if(e.target!==t){const t=setTimeout(()=>dq("#download-danmaku>span").innerHTML="请稍侯...",200);l(e.shiftKey,t)}})}}}}})(); -onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/download-video-package.min.js"] = (()=>{return(e,t)=>{class n{constructor(e={}){this.config=e;this.entries=[]}download(e,t){const n=document.createElement("a");const i=URL.createObjectURL(t);n.setAttribute("href",i);n.setAttribute("download",e);document.body.appendChild(n);n.click();n.remove();URL.revokeObjectURL(i)}add(e,t){if(t===null||t===undefined){return}this.entries.push({name:e,data:t})}async emit(e){if(this.entries.length===0){return}if(!e||this.entries.length===1){e=this.entries[0].name}if(this.entries.length===1){const t=this.entries[0].data;this.download(e,typeof t==="string"?new Blob([t]):t);return}const t=new JSZip;this.entries.forEach(({name:e,data:n})=>{t.file(e,n)});const n=await t.generateAsync({type:"blob"});this.download(e,n)}static async single(e,t){const i=new n;i.add(e,t);await i.emit()}}return{export:{DownloadVideoPackage:n}}}})(); +onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/download-video-package.min.js"] = (()=>{return(e,t)=>{class n{constructor(e={}){this.config=e;this.entries=[]}download(e,t){const i=document.createElement("a");const a=URL.createObjectURL(t);if(n.lastPackageUrl){URL.revokeObjectURL(n.lastPackageUrl)}n.lastPackageUrl=a;i.setAttribute("href",a);i.setAttribute("download",e);document.body.appendChild(i);i.click();i.remove()}add(e,t){if(t===null||t===undefined){return}this.entries.push({name:e,data:t})}async preEmit(){const e=this.entries.filter(e=>[".flv",".mp4",".m4s"].some(t=>e.name.endsWith(t)));if(this.config.ffmpeg!==undefined&&e.length>=2){if(this.config.ffmpeg==="文件列表"||this.config.ffmpeg==="文件列表+脚本"){this.entries.push({name:"ffmpeg-files.txt",data:e.map(e=>`file '${e.name}'`).join("\n")})}if(this.config.ffmpeg==="文件列表+脚本"){const e=`ffmpeg -f concat -i ffmpeg-files.txt -c copy ""`;this.entries.push({name:"ffmpeg.bat",data:e},{name:"ffmpeg.sh",data:e.replace(/"/g,"'")})}}}async blob(){await this.preEmit();if(this.entries.length===0){return null}if(this.entries.length===1){const e=this.entries[0].data;return typeof e==="string"?new Blob([e]):e}const e=new JSZip;this.entries.forEach(({name:t,data:n})=>{e.file(t,n)});return await e.generateAsync({type:"blob"})}async emit(e){if(!e||this.entries.length===1){e=this.entries[0].name}const t=await this.blob();if(!t){return}return this.download(e,t)}static async single(e,t,i={}){const a=new n(i);a.add(e,t);return await a.emit()}}n.lastPackageUrl="";return{export:{DownloadVideoPackage:n}}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/download-video.min.css"] = `.download-video{--download-video-background:white;--download-video-foreground:black;position:absolute;top:64px;left:50%;transform:translateX(-50%) scale(.95);background:var(--download-video-background);color:var(--download-video-foreground);box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;z-index:10001;pointer-events:none;opacity:0;padding:16px;width:300px;display:flex;flex-direction:column;align-items:stretch;justify-content:space-between}.download-video,.download-video *{transition:.2s ease-out;-webkit-tap-highlight-color:transparent!important}.download-video.opened{pointer-events:initial;opacity:1;transform:translateX(-50%) scale(1)}body.dark .download-video{--download-video-background:#222;--download-video-foreground:#eee}.round-corner .download-video,.round-corner .download-video .episode-list .v-checkbox,.round-corner .download-video .rpc-settings{border-radius:var(--large-corner-radius)}.round-corner .download-video .button,.round-corner .download-video .cover,.round-corner .download-video .direct-download .progress .background,.round-corner .download-video .direct-download .progress .foreground,.round-corner .download-video .rpc-settings input[type=text],.round-corner .download-video .title,.round-corner .download-video button{border-radius:var(--corner-radius)}.download-video .cover{width:240px;min-height:135px;max-height:200px;object-fit:contain}.download-video .header{display:flex;justify-content:space-between;align-items:center}.download-video h1{font-size:16pt;font-weight:700;color:var(--download-video-foreground)}.download-video .header .mdi-close{font-size:16pt;color:var(--download-video-foreground);cursor:pointer}.download-video .header .mdi-close:hover{color:var(--theme-color)}.download-video .info{display:flex;flex-direction:column;align-items:center;margin-top:12px}.download-video .title{display:flex;flex-direction:column;justify-content:space-between;align-items:stretch;margin-top:12px}.download-video .title .bold{width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.download-video .title .size{font-size:10pt;color:var(--download-video-foreground);align-self:center;display:flex;align-items:center;height:24px}.download-video .bold{color:var(--download-video-foreground);font-weight:700;font-size:12pt}.download-video .option-item{display:flex;justify-content:space-between;align-items:center;padding-top:12px;font-size:10pt}.download-video .tabs{display:flex;padding-top:12px;font-size:10pt}.download-video .tabs .tab{padding:6px 12px;border-bottom:2px solid transparent;cursor:pointer}.download-video .tabs .tab.active{color:var(--theme-color);border-bottom-color:var(--theme-color)}.download-video .separator{height:1px;background:#8884;width:100%;margin:12px 0;flex-shrink:0}.download-video h2{font-size:12pt;font-weight:700;color:var(--download-video-foreground)}.download-video .direct-download{display:flex;flex-direction:column;align-items:start;justify-content:space-between}.download-video .button,.download-video button{border:none;outline:0!important;padding:6px 16px;font-size:10pt;cursor:pointer;background:#8884;color:var(--download-video-foreground)}.download-video .button:hover,.download-video button:hover{background:#8886}.download-video .primary{background:var(--theme-color);color:var(--foreground-color);align-self:center}.download-video .primary:hover{background:var(--theme-color-90)}.download-video .busy .button,.download-video .busy .primary,.download-video .busy button,.download-video button:disabled{background-color:#0001;color:#8884;cursor:not-allowed}.download-video .busy .button,.download-video .busy button{cursor:wait!important}.download-video .direct-download .progress{align-self:stretch;display:flex;align-items:center;margin-top:8px}.download-video .direct-download .progress .background{flex-grow:1;height:4px;background:#8884;margin-right:4px;position:relative}.download-video .direct-download .progress .background .foreground{position:absolute;top:0;left:0;height:4px;background:linear-gradient(to right,var(--theme-color),var(--theme-color-60))}.download-video .direct-download .progress .percent{width:50px;text-align:right}.download-video .actions{display:flex;flex-wrap:wrap;justify-content:space-between;margin:8px -4px 0}.download-video .actions>*{margin:4px;flex-grow:1;flex-basis:calc(50% - 16px);display:flex;justify-content:center;align-items:center}.download-video i.mdi-alert-circle{font-size:14pt;color:#ff9800}.download-video .size-warning{position:relative;padding:0 8px}.download-video .size-warning-tip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:var(--download-video-background);color:var(--download-video-foreground);border:1px dashed var(--theme-color);z-index:2;font-size:10pt;width:200px;padding:8px;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;pointer-events:none;opacity:0}.download-video .size-warning:hover .size-warning-tip{opacity:1}.download-video .episode-list .v-checkbox{padding:4px 8px;margin:4px 0;position:relative;background-color:transparent}.download-video .episode-list .v-checkbox.checked{background-color:#8882}.download-video .episode-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.download-video .episode-list{overflow:auto;max-height:320px}.download-video button.list-tool{padding:4px;line-height:1;font-size:12pt;margin:0 4px}.download-video .episode-header h2{flex-grow:1}.download-video .selected-count{width:64px;text-align:right}.download-video .aria2-rpc .mdi{margin-left:8px;font-size:14pt;line-height:1}.download-video .aria2-rpc{position:relative}.download-video .rpc-settings{position:absolute;display:flex;flex-direction:column;align-items:stretch;color:var(--download-video-foreground);background:#fff;bottom:120%;left:50%;cursor:initial;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;transform-origin:bottom;transform:translateX(-50%) scale(.9);opacity:0;pointer-events:none;padding:8px;z-index:3;transition:.3s cubic-bezier(.18,.89,.32,1.28);width:120%}body.dark .download-video .rpc-settings{background:#282828}.download-video .rpc-settings>*{margin:8px}.download-video .rpc-settings.show{opacity:1;transform:translateX(-50%) scale(1);pointer-events:initial}.download-video .rpc-settings input[type=text]{background:0 0;color:var(--download-video-foreground);border:1px solid #8884;padding:4px;margin-left:8px}.download-video .rpc-settings input[type=text]:focus{border-color:var(--theme-color)}.download-video .rpc-settings .operations{display:flex;align-items:center;justify-content:space-evenly}.download-video .final-dir{word-break:break-all}.download-video .rpc-settings-item{display:flex;align-items:center;justify-content:space-between;white-space:nowrap}.download-video .rpc-settings-item input[type=text]{flex-grow:1;margin-left:24px}.download-video button.cancel-download,.download-video button.start-download{margin-top:8px}.download-video .direct-download-header{align-self:stretch;display:flex;justify-content:space-between;align-items:center}body.dark .download-video .direct-download .progress .foreground{background:linear-gradient(to right,var(--theme-color-70),var(--theme-color))}`; -onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/download-video.min.html"] = `

下载视频

单个视频
批量导出
警告: 过大的视频大小会在直接下载时占用大量内存, 并可能导致浏览器标签页崩溃. 请考虑降低清晰度或使用导出选项.
预计大小: {{displaySize}}
格式
清晰度
弹幕

直接下载

{{speed}}
{{progressPercent}}%

选集

{{selectedEpisodeCount}}/{{episodeList.length}}

导出

{{showRpcSettings ? '取消' : 'aria2 RPC'}}

aria2 RPC

配置

主机
端口
密钥
限速
默认路径
路径
最终路径: {{rpcSettings.baseDir + rpcSettings.dir}}
方法
开始下载
{{saveRpcSettingsText}}
`; -onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/download-video.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:a}=e.import("title");const{VideoInfo:s,DanmakuInfo:i}=e.import("video-info");class o{async getDashUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json&fnver=0&fnval=16`}else{return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&otype=json&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&otype=json`}}}class n extends o{async getDashUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&qn=${t}&otype=json&fourk=1&fnval=16`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&otype=json&fourk=1&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=${r.aid}&cid=${r.cid}&qn=&otype=json`}}}const r={entity:new o,aid:"",cid:""};let l=[];let c=null;class d{constructor(t,e,a){this.quality=t;this.internalName=e;this.displayName=a}async downloadInfo(t=false){const e=new h(this);await e.fetchVideoInfo(t);return e}static parseFormats(t){const e=t.accept_quality;const a=t.accept_format.split(",");const s=t.accept_description;const i=e.map((t,e)=>{return new d(t,a[e],s[e])});return i}static async getAvailableDashFormats(){const t=await r.entity.getDashUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}return d.parseFormats(e.data||e.result||e)}static async getAvailableFormats(){const t=await r.entity.getUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}const a=e.data||e.result||e;return d.parseFormats(a)}}class h{constructor(t,e){this.fragmentSplitFactor=6*2;this.workingXhr=null;this.progressMap=new Map;this.format=t;this.fragments=e||[];this.videoSpeed=new p(this)}get totalSize(){return this.fragments.map(t=>t.size).reduce((t,e)=>t+e)}async fetchVideoInfo(t=false){if(!t){const t=await r.entity.getUrl(this.format.quality);const e=await Ajax.getTextWithCredentials(t);const a=JSON.parse(e.replace(/http:/g,"https:"));const s=a.data||a.result||a;if(s.quality!==this.format.quality){throw new Error("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const i=s.durl;this.fragments=i.map(t=>{return{length:t.length,size:t.size,url:t.url,backupUrls:t.backup_url}})}else{const{dashToFragment:t,getDashInfo:a}=await e.importAsync("video-dash");const s=await a(await r.entity.getDashUrl(this.format.quality),this.format.quality);const i=s.videoDashes.sort(ascendingSort(t=>t.bandWidth))[0];const o=s.audioDashes.sort(ascendingSort(t=>t.bandWidth))[0];this.fragments=[t(i),t(o)]}return this.fragments}updateProgress(){const t=this.progressMap?[...this.progressMap.values()].reduce((t,e)=>t+e,0)/this.totalSize:0;if(t>1||t<0){console.error(`[下载视频] 进度异常: ${t}`,this.progressMap.values())}this.progress&&this.progress(t)}cancelDownload(){this.videoSpeed.stopMeasure();if(this.workingXhr!==null){this.workingXhr.forEach(t=>t.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(t){const e=[];this.workingXhr=[];this.progressMap=new Map;this.updateProgress();let a;if(t.size<=96*1024*1024){a=t.size/this.fragmentSplitFactor}else{a=16*1024*1024}let s=0;const i=t=>[...this.progressMap.keys()].indexOf(t)+1;while(s{const s=new XMLHttpRequest;s.open("GET",t.url);s.responseType="arraybuffer";s.withCredentials=false;s.addEventListener("progress",t=>{console.log(`[下载视频] 视频片段${i(s)}下载进度: ${t.loaded}/${r} bytes loaded, ${n}`);this.progressMap.set(s,t.loaded);this.updateProgress()});s.addEventListener("load",()=>{if((""+s.status)[0]==="2"){console.log(`[下载视频] 视频片段${i(s)}下载完成`);e(s.response)}else{a(`视频片段${i(s)}请求失败, response = ${s.status}`)}});s.addEventListener("abort",()=>a("canceled"));s.addEventListener("error",()=>{console.error(`[下载视频] 视频片段${i(s)}下载失败: ${n}`);this.progressMap.set(s,0);this.updateProgress();s.open("GET",t.url);s.setRequestHeader("Range",n);s.send()});s.setRequestHeader("Range",n);this.progressMap.set(s,0);s.send();this.workingXhr.push(s)}));s=Math.round(s+a)+1}return Promise.all(e)}async copyUrl(){const t=this.fragments.map(t=>t.url).reduce((t,e)=>t+"\r\n"+e);GM.setClipboard(t,"text")}async showUrl(){const t=this.fragments.map(t=>`\n${t.url}\n`).reduce((t,e)=>t+"\r\n"+e);Toast.success(t+`复制全部`,"显示链接");const e=await SpinQuery.select("#copy-link");e.addEventListener("click",async()=>{await this.copyUrl()})}async exportData(t=false){const s=JSON.stringify([{fragments:this.fragments,title:a(),totalSize:this.fragments.map(t=>t.size).reduce((t,e)=>t+e),referer:document.URL.replace(window.location.search,"")}]);if(t){GM.setClipboard(s,"text")}else{const t=new Blob([s],{type:"text/json"});const i=await this.downloadDanmaku();const{DownloadVideoPackage:o}=await e.importAsync("download-video-package");const n=new o;n.add(`${a()}.json`,t);n.add(a()+"."+this.danmakuOption.toLowerCase(),i);await n.emit(`${a()}.zip`)}}async exportAria2(s=false){if(s){const s=await this.downloadDanmaku();if(s!==null){const{DownloadVideoPackage:t}=await e.importAsync("download-video-package");t.single(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,s)}const i=t.aria2RpcOption;const o=this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}const o=[];if(i.secretKey!==""){o.push(`token:${i.secretKey}`)}o.push([t.url]);o.push({referer:document.URL.replace(window.location.search,""),"user-agent":UserAgent,out:`${a()}${s}${this.extension(t)}`,split:this.fragmentSplitFactor,dir:i.baseDir+i.dir||undefined,"max-download-limit":i.maxDownloadLimit||undefined});const n=encodeURIComponent(`${a()}${s}`);return{params:o,id:n}});const{sendRpc:n}=await e.importAsync("aria2-rpc");await n(o)}else{const t=`\n# Generated by Bilibili Evolved Video Export\n# https://github.com/the1812/Bilibili-Evolved/\n${this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}return`\n${t.url}\n referer=${document.URL.replace(window.location.search,"")}\n user-agent=${UserAgent}\n out=${a()}${s}${this.extension(t)}\n split=${this.fragmentSplitFactor}\n`.trim()}).join("\n")}\n`.trim();const s=new Blob([t],{type:"text/plain"});const i=await this.downloadDanmaku();const{DownloadVideoPackage:o}=await e.importAsync("download-video-package");const n=new o;n.add(`${a()}.txt`,s);n.add(a()+"."+this.danmakuOption.toLowerCase(),i);await n.emit(`${a()}.zip`)}}extension(t){const e=t||this.fragments[0];const a=[".flv",".mp4",".m4s"].find(t=>e.url.includes(t));if(a){return a}else{console.warn("No extension detected.");return".flv"}}makeBlob(t,e){return new Blob(Array.isArray(t)?t:[t],{type:this.extension(e)===".flv"?"video/x-flv":"video/mp4"})}cleanUpOldBlobUrl(){const t=dq("a#video-complete").getAttribute("href");if(t&&!dq(`.link[href="${t}"]`)){URL.revokeObjectURL(t)}dqa(".toast-card-header").filter(t=>t.innerText.includes("下载视频")).forEach(t=>t.querySelector(".toast-card-dismiss").click())}async downloadDanmaku(){if(this.danmakuOption!=="无"){const t=new i(r.cid);await t.fetchInfo();if(this.danmakuOption==="XML"){return t.rawXML}else{const{convertToAss:a}=await e.importAsync("download-danmaku");return a(t.rawXML)}}else{return null}}async downloadSingle(t){const e=await this.downloadDanmaku();const[s]=t;if(e===null){const t=this.makeBlob(s);const e=a()+this.extension();return{blob:t,filename:e}}else{const t=new JSZip;t.file(a()+this.extension(),this.makeBlob(s));t.file(a()+"."+this.danmakuOption.toLowerCase(),e);const i=await t.generateAsync({type:"blob"});const o=a()+".zip";return{blob:i,filename:o}}}async downloadMultiple(t){const e=new JSZip;const s=a();if(t.length>1){t.forEach((t,a)=>{const i=this.fragments[a];e.file(`${s} - ${a+1}${this.extension(i)}`,this.makeBlob(t,i))})}else{const[a]=t;e.file(`${s}${this.extension()}`,this.makeBlob(a))}const i=await this.downloadDanmaku();if(i!==null){e.file(a()+"."+this.danmakuOption.toLowerCase(),i)}const o=await e.generateAsync({type:"blob"});const n=s+".zip";return{blob:o,filename:n}}async download(){const t=[];this.videoSpeed.startMeasure();for(const e of this.fragments){const a=await this.downloadFragment(e);t.push(a)}if(t.length<1){throw new Error("下载失败.")}let{blob:e,filename:a}=await(async()=>{if(t.length===1){return await this.downloadSingle(t)}else{return await this.downloadMultiple(t)}})();this.cleanUpOldBlobUrl();const s=URL.createObjectURL(e);this.progress&&this.progress(0);this.videoSpeed.stopMeasure();return{url:s,filename:a}}}class p{constructor(t){this.lastProgress=0;this.measureInterval=1e3;this.workingDownloader=t}startMeasure(){this.intervalTimer=setInterval(()=>{const t=this.workingDownloader.progressMap?[...this.workingDownloader.progressMap.values()].reduce((t,e)=>t+e,0):0;const e=t-this.lastProgress;if(this.speedUpdate!==undefined){this.speedUpdate(formatFileSize(e)+"/s")}this.lastProgress=t},this.measureInterval)}stopMeasure(){clearInterval(this.intervalTimer)}}async function u(){const t=await SpinQuery.select(()=>(unsafeWindow||window).aid);const e=await SpinQuery.select(()=>(unsafeWindow||window).cid);if(!(t&&e)){return false}r.aid=t;r.cid=e;if(document.URL.indexOf("bangumi")!==-1){r.entity=new n}else{r.entity=new o}try{l=await d.getAvailableFormats()}catch(t){return false}return true}async function f(){c=l[0];e.applyStyle("downloadVideoStyle");dq("#download-video").addEventListener("click",()=>{dq(".download-video").classList.toggle("opened");dq(".gui-settings-mask").click()});dq("#download-video").addEventListener("mouseover",()=>{document.body.insertAdjacentHTML("beforeend",e.import("downloadVideoHtml"));w()},{once:true})}async function w(){let o;const n=new Map;const h=new Vue({el:".download-video",components:{VDropdown:()=>e.importAsync("v-dropdown.vue"),VCheckbox:()=>e.importAsync("v-checkbox.vue"),RpcProfiles:()=>e.importAsync("aria2-rpc-profiles.vue")},data:{downloadSingle:true,coverUrl:EmptyImageUrl,aid:r.aid,cid:r.cid,dashModel:{value:t.downloadVideoFormat,items:["flv","dash"]},qualityModel:{value:c.displayName,items:l.map(t=>t.displayName)},danmakuModel:{value:t.downloadVideoDefaultDanmaku,items:["无","XML","ASS"]},progressPercent:0,size:"获取大小中",blobUrl:"",episodeList:[],downloading:false,speed:"",batch:false,rpcSettings:t.aria2RpcOption,showRpcSettings:false,busy:false,saveRpcSettingsText:"保存配置",enableDash:t.enableDashDownload},computed:{displaySize(){if(typeof this.size==="string"){return this.size}return formatFileSize(this.size)},sizeWarning(){if(typeof this.size==="string"){return false}return this.size>1073741824},selectedEpisodeCount(){return this.episodeList.filter(t=>t.checked).length},dash(){return this.dashModel.value==="dash"}},methods:{close(){this.$el.classList.remove("opened")},danmakuOptionChange(){t.downloadVideoDefaultDanmaku=this.danmakuModel.value},async dashChange(){const t=this.dashModel.value;let e=[];if(t==="flv"){e=await d.getAvailableFormats()}else{e=await d.getAvailableDashFormats()}l=e;[c]=t;this.qualityModel.items=e.map(t=>t.displayName);[this.qualityModel.value]=this.qualityModel.items;await this.formatChange()},async formatChange(){const t=this.getFormat();const e=n.get(t);if(e){this.size=e;return}try{this.size="获取大小中";const e=await t.downloadInfo(this.dash);this.size=e.totalSize;n.set(t,this.size)}catch(t){this.size="获取大小失败"}},getFormat(){const t=l.find(t=>t.displayName===this.qualityModel.value);if(!t){console.error(`No format found. model value = ${this.qualityModel.value}`);return null}return t},async exportData(t){if(this.busy===true){return}try{this.busy=true;if(!this.downloadSingle){await this.exportBatchData(t);return}const e=this.getFormat();const a=await e.downloadInfo(this.dash);a.danmakuOption=this.danmakuModel.value;switch(t){case"copyLink":await a.copyUrl();Toast.success("已复制链接到剪贴板.","下载视频",3e3);break;case"showLink":await a.showUrl();break;case"aria2":await a.exportAria2(false);break;case"aria2RPC":await a.exportAria2(true);break;case"copyVLD":await a.exportData(true);Toast.success("已复制VLD数据到剪贴板.","下载视频",3e3);break;case"exportVLD":await a.exportData(false);break;default:break}}catch(t){logError(t)}finally{this.busy=false}},async exportBatchData(t){const s=this.episodeList;if(s.every(t=>t.checked===false)){Toast.info("请至少选择1集或以上的数量!","批量导出",3e3);return}const o=t=>{const e=s.find(e=>e.cid===t.cid);if(e===undefined){return false}return e.checked};const n=this.getFormat();const{DownloadVideoPackage:r}=await e.importAsync("download-video-package");if(this.danmakuModel.value!=="无"){const t=Toast.info("下载弹幕中...","批量导出");const a=new r;try{if(this.danmakuModel.value==="XML"){for(const t of s.filter(o)){const e=new i(t.cid);await e.fetchInfo();a.add(t.title+".xml",e.rawXML)}}else{const{convertToAss:t}=await e.importAsync("download-danmaku");for(const e of s.filter(o)){const s=new i(e.cid);await s.fetchInfo();a.add(e.title+".ass",await t(s.rawXML))}}await a.emit(this.cid+".danmakus.zip")}catch(t){logError(`弹幕下载失败`)}finally{t.dismiss()}}const l=Toast.info("获取链接中...","批量导出");this.batchExtractor.itemFilter=o;let c;try{switch(t){case"aria2":c=await this.batchExtractor.collectAria2(n,l);await r.single(a(false)+".txt",new Blob([c],{type:"text/plain"}));return;case"aria2RPC":await this.batchExtractor.collectAria2(n,l,true);Toast.success(`成功发送了批量请求.`,"aria2 RPC",3e3);return;case"copyVLD":GM.setClipboard(await this.batchExtractor.collectData(n,l),{mimetype:"text/plain"});Toast.success("已复制批量vld数据到剪贴板.","批量导出",3e3);return;case"exportVLD":c=await this.batchExtractor.collectData(n,l);await r.single(a(false)+".json",new Blob([c],{type:"text/json"}));return;default:return}}catch(t){logError(t)}finally{l.dismiss()}},async checkBatch(){const t=["/www.bilibili.com/bangumi","/www.bilibili.com/video/av"];if(!t.some(t=>document.URL.includes(t))){this.batch=false;this.episodeList=[];return}const{BatchExtractor:a}=await e.importAsync("batch-download");if(await a.test()!==true){this.batch=false;this.episodeList=[];return}this.batchExtractor=new a;this.batch=true;this.episodeList=(await this.batchExtractor.getItemList()).map((t,e)=>{return{aid:t.aid,cid:t.cid,title:t.title,index:e,checked:true}})},cancelDownload(){if(o){o.cancelDownload()}},async startDownload(){const t=this.getFormat();try{this.downloading=true;const e=await t.downloadInfo(this.dash);e.videoSpeed.speedUpdate=(t=>this.speed=t);e.danmakuOption=this.danmakuModel.value;e.progress=(t=>{this.progressPercent=Math.trunc(t*100)});o=e;const a=await e.download();const s=document.getElementById("video-complete");s.setAttribute("href",a.url);s.setAttribute("download",a.filename);s.click();Toast.success(`下载完成: ${a.filename} 再次保存`,"下载视频")}catch(t){if(t!=="canceled"){logError(t)}this.progressPercent=0}finally{this.downloading=false;this.speed=""}},selectAllEpisodes(){this.episodeList.forEach(t=>t.checked=true)},unselectAllEpisodes(){this.episodeList.forEach(t=>t.checked=false)},inverseAllEpisodes(){this.episodeList.forEach(t=>t.checked=!t.checked)},toggleRpcSettings(){this.showRpcSettings=!this.showRpcSettings},saveRpcSettings(){if(this.rpcSettings.host===""){this.rpcSettings.host="127.0.0.1"}if(this.rpcSettings.port===""){this.rpcSettings.port="6800"}t.aria2RpcOption=this.rpcSettings;const e=t.aria2RpcOptionProfiles.find(e=>e.name===t.aria2RpcOptionSelectedProfile);if(e){Object.assign(e,this.rpcSettings);t.aria2RpcOptionProfiles=t.aria2RpcOptionProfiles}this.saveRpcSettingsText="已保存";setTimeout(()=>this.saveRpcSettingsText="保存配置",2e3)},updateProfile(e){t.aria2RpcOption=this.rpcSettings=_.omit(e,"name")}}});Observer.videoChange(async()=>{h.close();h.batch=false;h.downloadSingle=true;const t=dq("#download-video");const e=await u();t.style.display=e?"flex":"none";if(!e){return}h.aid=r.aid;h.cid=r.cid;const a=new s(r.aid);await a.fetchInfo();h.coverUrl=a.coverUrl.replace("http:","https:");l=await d.getAvailableFormats();[c]=l;h.qualityModel={value:c.displayName,items:l.map(t=>t.displayName)};h.formatChange();await h.checkBatch()})}return{widget:{content:`\n`,condition:u,success:f}}}})(); +onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/download-video.min.html"] = `

下载视频

单个视频
批量导出
警告: 过大的视频大小会在直接下载时占用大量内存, 并可能导致浏览器标签页崩溃. 请考虑降低清晰度或使用导出选项.
预计大小: {{displaySize}}
格式
清晰度
弹幕
ffmpeg支持

直接下载

{{speed}}
{{progressPercent}}%

选集

{{selectedEpisodeCount}}/{{episodeList.length}}

导出

{{showRpcSettings ? '取消' : 'aria2 RPC'}}

aria2 RPC

配置

主机
端口
密钥
限速
默认路径
路径
最终路径: {{rpcSettings.baseDir + rpcSettings.dir}}
方法
开始下载
{{saveRpcSettingsText}}
`; +onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/download-video.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:a}=e.import("title");const{VideoInfo:s,DanmakuInfo:i}=e.import("video-info");const{DownloadVideoPackage:n}=e.import("download-video-package");class o{async getDashUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&fnver=0&fnval=16`}else{return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&otype=json`}}}class r extends o{async getDashUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&qn=${t}&otype=json&fourk=1&fnval=16`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&otype=json&fourk=1&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=&otype=json`}}}class l extends o{constructor(t){super();this.ep=t}async getDashUrl(t){if(t){return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16`}else{return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&ep_id=${this.ep}`}else{return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&ep_id=${this.ep}`}}}const c={entity:new o,aid:"",cid:""};let d=[];let p=null;class h{constructor(t,e,a){this.quality=t;this.internalName=e;this.displayName=a}async downloadInfo(t=false){const e=new u(this);await e.fetchVideoInfo(t);return e}static parseFormats(t){const e=t.accept_quality;const a=t.accept_format.split(",");const s=t.accept_description;const i=e.map((t,e)=>{return new h(t,a[e],s[e])});return i}static async getAvailableDashFormats(){const t=await c.entity.getDashUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}return h.parseFormats(e.data||e.result||e)}static async getAvailableFormats(){const t=await c.entity.getUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}const a=e.data||e.result||e;return h.parseFormats(a)}}class u{constructor(t,e){this.fragmentSplitFactor=6*2;this.workingXhr=null;this.progressMap=new Map;this.danmakuOption="无";this.ffmpegOption="无";this.format=t;this.fragments=e||[];this.videoSpeed=new f(this)}get totalSize(){return this.fragments.map(t=>t.size).reduce((t,e)=>t+e)}async fetchVideoInfo(t=false){if(!t){const t=await c.entity.getUrl(this.format.quality);const e=await Ajax.getTextWithCredentials(t);const a=JSON.parse(e.replace(/http:/g,"https:"));const s=a.data||a.result||a;if(s.quality!==this.format.quality){throw new Error("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const i=s.durl;this.fragments=i.map(t=>{return{length:t.length,size:t.size,url:t.url,backupUrls:t.backup_url}})}else{const{dashToFragment:t,getDashInfo:a}=await e.importAsync("video-dash");const s=await a(await c.entity.getDashUrl(this.format.quality),this.format.quality);const i=s.videoDashes.sort(ascendingSort(t=>t.bandWidth))[0];const n=s.audioDashes.sort(ascendingSort(t=>t.bandWidth))[0];this.fragments=[t(i),t(n)]}return this.fragments}updateProgress(){const t=this.progressMap?[...this.progressMap.values()].reduce((t,e)=>t+e,0)/this.totalSize:0;if(t>1||t<0){console.error(`[下载视频] 进度异常: ${t}`,this.progressMap.values())}this.progress&&this.progress(t)}cancelDownload(){this.videoSpeed.stopMeasure();if(this.workingXhr!==null){this.workingXhr.forEach(t=>t.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(t){const e=[];this.workingXhr=[];this.progressMap=new Map;this.updateProgress();let a;if(t.size<=48*1024*1024){a=t.size/this.fragmentSplitFactor}else{a=4*1024*1024}let s=0;const i=t=>[...this.progressMap.keys()].indexOf(t)+1;while(s{const s=new XMLHttpRequest;s.open("GET",t.url);s.responseType="arraybuffer";s.withCredentials=false;s.addEventListener("progress",t=>{console.log(`[下载视频] 视频片段${i(s)}下载进度: ${t.loaded}/${r} bytes loaded, ${o}`);this.progressMap.set(s,t.loaded);this.updateProgress()});s.addEventListener("load",()=>{if((""+s.status)[0]==="2"){console.log(`[下载视频] 视频片段${i(s)}下载完成`);e(s.response)}else{a(`视频片段${i(s)}请求失败, response = ${s.status}`)}});s.addEventListener("abort",()=>a("canceled"));s.addEventListener("error",()=>{console.error(`[下载视频] 视频片段${i(s)}下载失败: ${o}`);this.progressMap.set(s,0);this.updateProgress();s.open("GET",t.url);s.setRequestHeader("Range",o);s.send()});s.setRequestHeader("Range",o);this.progressMap.set(s,0);s.send();this.workingXhr.push(s)}));s=Math.round(s+a)+1}return Promise.all(e)}async copyUrl(){const t=this.fragments.map(t=>t.url).reduce((t,e)=>t+"\r\n"+e);GM.setClipboard(t,"text")}async showUrl(){const t=this.fragments.map(t=>`\n${t.url}\n`).reduce((t,e)=>t+"\r\n"+e);Toast.success(t+`复制全部`,"显示链接");const e=await SpinQuery.select("#copy-link");e.addEventListener("click",async()=>{await this.copyUrl()})}async exportData(t=false){const e=JSON.stringify([{fragments:this.fragments,title:a(),totalSize:this.fragments.map(t=>t.size).reduce((t,e)=>t+e),referer:document.URL.replace(window.location.search,"")}]);if(t){GM.setClipboard(e,"text")}else{const t=new Blob([e],{type:"text/json"});const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.json`,t);i.add(a()+"."+this.danmakuOption.toLowerCase(),s);await i.emit(`${a()}.zip`)}}async exportAria2(s=false){if(s){const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,s);await i.emit();const o=t.aria2RpcOption;const r=this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}const i=[];if(o.secretKey!==""){i.push(`token:${o.secretKey}`)}i.push([t.url]);i.push({referer:document.URL.replace(window.location.search,""),"user-agent":UserAgent,out:`${a()}${s}${this.extension(t)}`,split:this.fragmentSplitFactor,dir:o.baseDir+o.dir||undefined,"max-download-limit":o.maxDownloadLimit||undefined});const n=encodeURIComponent(`${a()}${s}`);return{params:i,id:n}});const{sendRpc:l}=await e.importAsync("aria2-rpc");await l(r)}else{const t=`\n# Generated by Bilibili Evolved Video Export\n# https://github.com/the1812/Bilibili-Evolved/\n${this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}return`\n${t.url}\n referer=${document.URL.replace(window.location.search,"")}\n user-agent=${UserAgent}\n out=${a()}${s}${this.extension(t)}\n split=${this.fragmentSplitFactor}\n`.trim()}).join("\n")}\n`.trim();const e=new Blob([t],{type:"text/plain"});const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.txt`,e);i.add(a()+"."+this.danmakuOption.toLowerCase(),s);await i.emit(`${a()}.zip`)}}extension(t){const e=t||this.fragments[0];const a=[".flv",".mp4",".m4s"].find(t=>e.url.includes(t));if(a){return a}else{console.warn("No extension detected.");return".flv"}}async downloadDanmaku(){if(this.danmakuOption!=="无"){const t=new i(c.cid);await t.fetchInfo();if(this.danmakuOption==="XML"){return t.rawXML}else{const{convertToAss:a}=await e.importAsync("download-danmaku");return a(t.rawXML)}}else{return null}}async download(){const t=[];this.videoSpeed.startMeasure();for(const e of this.fragments){const a=await this.downloadFragment(e);t.push(a)}if(t.length<1){throw new Error("下载失败.")}const e=new n({ffmpeg:this.ffmpegOption});const s=a();t.forEach((a,i)=>{let n;const o=this.fragments[i];if(t.length>1){n=`${s} - ${i+1}${this.extension(o)}`}else{n=`${s}${this.extension(o)}`}e.add(n,new Blob(Array.isArray(a)?a:[a],{type:this.extension(o)===".flv"?"video/x-flv":"video/mp4"}))});const i=await this.downloadDanmaku();e.add(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,i);await e.emit(s+".zip");this.progress&&this.progress(0);this.videoSpeed.stopMeasure()}}class f{constructor(t){this.lastProgress=0;this.measureInterval=1e3;this.workingDownloader=t}startMeasure(){this.intervalTimer=setInterval(()=>{const t=this.workingDownloader.progressMap?[...this.workingDownloader.progressMap.values()].reduce((t,e)=>t+e,0):0;const e=t-this.lastProgress;if(this.speedUpdate!==undefined){this.speedUpdate(formatFileSize(e)+"/s")}this.lastProgress=t},this.measureInterval)}stopMeasure(){clearInterval(this.intervalTimer)}}async function m(){const t=await SpinQuery.select(()=>(unsafeWindow||window).aid);const e=await SpinQuery.select(()=>(unsafeWindow||window).cid);if(!(t&&e)){return false}c.aid=t;c.cid=e;if(document.URL.includes("bangumi")){c.entity=new r}else if(document.URL.includes("cheese")){const t=document.URL.match(/cheese\/play\/ep([\d]+)/);c.entity=new l(t[1])}else{c.entity=new o}try{d=await h.getAvailableFormats()}catch(t){return false}return true}async function w(){p=d[0];e.applyStyle("downloadVideoStyle");dq("#download-video").addEventListener("click",()=>{dq(".download-video").classList.toggle("opened");dq(".gui-settings-mask").click()});dq("#download-video").addEventListener("mouseover",()=>{document.body.insertAdjacentHTML("beforeend",e.import("downloadVideoHtml"));g()},{once:true})}async function g(){let o;const r=new Map;const l=new Vue({el:".download-video",components:{VDropdown:()=>e.importAsync("v-dropdown.vue"),VCheckbox:()=>e.importAsync("v-checkbox.vue"),RpcProfiles:()=>e.importAsync("aria2-rpc-profiles.vue")},data:{downloadSingle:true,coverUrl:EmptyImageUrl,aid:c.aid,cid:c.cid,dashModel:{value:t.downloadVideoFormat,items:["flv","dash"]},qualityModel:{value:p.displayName,items:d.map(t=>t.displayName)},danmakuModel:{value:t.downloadVideoDefaultDanmaku,items:["无","XML","ASS"]},ffmpegModel:{value:t.downloadVideoFfmpegSupport,items:["无","文件列表","文件列表+脚本"]},progressPercent:0,size:"获取大小中",blobUrl:"",episodeList:[],downloading:false,speed:"",batch:false,rpcSettings:t.aria2RpcOption,showRpcSettings:false,busy:false,saveRpcSettingsText:"保存配置",enableDash:t.enableDashDownload,lastDirectDownloadLink:""},computed:{displaySize(){if(typeof this.size==="string"){return this.size}return formatFileSize(this.size)},sizeWarning(){if(typeof this.size==="string"){return false}return this.size>1073741824},selectedEpisodeCount(){return this.episodeList.filter(t=>t.checked).length},dash(){return this.dashModel.value==="dash"}},methods:{close(){this.$el.classList.remove("opened")},danmakuOptionChange(){t.downloadVideoDefaultDanmaku=this.danmakuModel.value},async dashChange(){const t=this.dashModel.value;let e=[];if(t==="flv"){e=await h.getAvailableFormats()}else{e=await h.getAvailableDashFormats()}d=e;[p]=t;this.qualityModel.items=e.map(t=>t.displayName);[this.qualityModel.value]=this.qualityModel.items;await this.formatChange()},async formatChange(){const t=this.getFormat();const e=r.get(t);if(e){this.size=e;return}try{this.size="获取大小中";const e=await t.downloadInfo(this.dash);this.size=e.totalSize;r.set(t,this.size)}catch(t){this.size="获取大小失败"}},getFormat(){const t=d.find(t=>t.displayName===this.qualityModel.value);if(!t){console.error(`No format found. model value = ${this.qualityModel.value}`);return null}return t},async exportData(t){if(this.busy===true){return}try{this.busy=true;if(!this.downloadSingle){await this.exportBatchData(t);return}const e=this.getFormat();const a=await e.downloadInfo(this.dash);a.danmakuOption=this.danmakuModel.value;switch(t){case"copyLink":await a.copyUrl();Toast.success("已复制链接到剪贴板.","下载视频",3e3);break;case"showLink":await a.showUrl();break;case"aria2":await a.exportAria2(false);break;case"aria2RPC":await a.exportAria2(true);break;case"copyVLD":await a.exportData(true);Toast.success("已复制VLD数据到剪贴板.","下载视频",3e3);break;case"exportVLD":await a.exportData(false);break;default:break}}catch(t){logError(t)}finally{this.busy=false}},async exportBatchData(t){const s=this.episodeList;if(s.every(t=>t.checked===false)){Toast.info("请至少选择1集或以上的数量!","批量导出",3e3);return}const o=t=>{const e=s.find(e=>e.cid===t.cid);if(e===undefined){return false}return e.checked};const r=this.getFormat();if(this.danmakuModel.value!=="无"){const t=Toast.info("下载弹幕中...","批量导出");const a=new n;try{if(this.danmakuModel.value==="XML"){for(const t of s.filter(o)){const e=new i(t.cid);await e.fetchInfo();a.add(t.title+".xml",e.rawXML)}}else{const{convertToAss:t}=await e.importAsync("download-danmaku");for(const e of s.filter(o)){const s=new i(e.cid);await s.fetchInfo();a.add(e.title+".ass",await t(s.rawXML))}}await a.emit(this.cid+".danmakus.zip")}catch(t){logError(`弹幕下载失败`)}finally{t.dismiss()}}const l=Toast.info("获取链接中...","批量导出");this.batchExtractor.itemFilter=o;let c;try{switch(t){case"aria2":c=await this.batchExtractor.collectAria2(r,l);await n.single(a(false)+".txt",new Blob([c],{type:"text/plain"}),{ffmpeg:this.ffmpegOption});return;case"aria2RPC":await this.batchExtractor.collectAria2(r,l,true);Toast.success(`成功发送了批量请求.`,"aria2 RPC",3e3);return;case"copyVLD":GM.setClipboard(await this.batchExtractor.collectData(r,l),{mimetype:"text/plain"});Toast.success("已复制批量vld数据到剪贴板.","批量导出",3e3);return;case"exportVLD":c=await this.batchExtractor.collectData(r,l);await n.single(a(false)+".json",new Blob([c],{type:"text/json"}),{ffmpeg:this.ffmpegOption});return;default:return}}catch(t){logError(t)}finally{l.dismiss()}},async checkBatch(){const t=["/www.bilibili.com/bangumi","/www.bilibili.com/video/av"];if(!t.some(t=>document.URL.includes(t))){this.batch=false;this.episodeList=[];return}const{BatchExtractor:a}=await e.importAsync("batch-download");if(await a.test()!==true){this.batch=false;this.episodeList=[];return}this.batchExtractor=new a;this.batch=true;this.episodeList=(await this.batchExtractor.getItemList()).map((t,e)=>{return{aid:t.aid,cid:t.cid,title:t.title,index:e,checked:true}})},cancelDownload(){if(o){o.cancelDownload()}},async startDownload(){const t=this.getFormat();try{this.downloading=true;const e=await t.downloadInfo(this.dash);e.videoSpeed.speedUpdate=(t=>this.speed=t);e.danmakuOption=this.danmakuModel.value;e.ffmpegOption=this.ffmpegModel.value;e.progress=(t=>{this.progressPercent=Math.trunc(t*100)});o=e;await e.download();this.lastDirectDownloadLink=n.lastPackageUrl}catch(t){if(t!=="canceled"){logError(t)}this.progressPercent=0}finally{this.downloading=false;this.speed=""}},selectAllEpisodes(){this.episodeList.forEach(t=>t.checked=true)},unselectAllEpisodes(){this.episodeList.forEach(t=>t.checked=false)},inverseAllEpisodes(){this.episodeList.forEach(t=>t.checked=!t.checked)},toggleRpcSettings(){this.showRpcSettings=!this.showRpcSettings},saveRpcSettings(){if(this.rpcSettings.host===""){this.rpcSettings.host="127.0.0.1"}if(this.rpcSettings.port===""){this.rpcSettings.port="6800"}t.aria2RpcOption=this.rpcSettings;const e=t.aria2RpcOptionProfiles.find(e=>e.name===t.aria2RpcOptionSelectedProfile);if(e){Object.assign(e,this.rpcSettings);t.aria2RpcOptionProfiles=t.aria2RpcOptionProfiles}this.saveRpcSettingsText="已保存";setTimeout(()=>this.saveRpcSettingsText="保存配置",2e3)},updateProfile(e){t.aria2RpcOption=this.rpcSettings=_.omit(e,"name")}}});Observer.videoChange(async()=>{l.close();l.batch=false;l.downloadSingle=true;const t=dq("#download-video");const e=await m();t.style.display=e?"flex":"none";if(!e){return}l.aid=c.aid;l.cid=c.cid;try{const t=new s(c.aid);await t.fetchInfo();l.coverUrl=t.coverUrl.replace("http:","https:")}catch(t){l.coverUrl=EmptyImageUrl}d=await h.getAvailableFormats();[p]=d;l.qualityModel={value:p.displayName,items:d.map(t=>t.displayName)};l.formatChange();await l.checkBatch()})}return{widget:{content:`\n`,condition:m,success:w}}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/dpi-img.vue.min.js"] = (()=>{return(t,s)=>{const e=``;return{export:Object.assign({template:e},{props:["size","src","blur","root","rootMargin","threshold"],data(){return{srcset:null,actualSrc:null}},methods:{calcSrc(){if(!this.src||!this.size){return null}const t=this.src.substring(this.src.lastIndexOf(".")+1);this.srcset=getDpiSourceSet(this.src,this.size,t);this.actualSrc=this.src}},mounted(){const t={root:this.root,rootMargin:this.rootMargin||"200px",threshold:this.threshold};const s=new IntersectionObserver(t=>{t.forEach(t=>{if(t.isIntersecting){this.calcSrc();s.disconnect()}})},t);s.observe(this.$el)},computed:{width(){if(typeof this.size==="object"&&"width"in this.size){return this.size.width}return null},height(){if(typeof this.size==="object"&&"height"in this.size){return this.size.height}return null}}})}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/expand-danmaku.min.js"] = (()=>{return(e,a)=>{if(typeof isEmbeddedPlayer!=="undefined"&&isEmbeddedPlayer()){return}Observer.videoChange(async()=>{const e=await SpinQuery.select(".bui-collapse-wrap");if(e&&e.classList.contains("bui-collapse-wrap-folded")){const e=await SpinQuery.select(".bui-collapse-header");e.click()}})}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/expand-description.min.css"] = `.play-up-info .play-up-self,.video-desc .info{height:auto!important}.play-up-info .play-up-self-btn,.video-desc .btn{display:none!important}`; @@ -1206,7 +1207,7 @@ onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/m onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/v-dropdown.vue.min.js"] = (()=>{return(o,e)=>{const n=`
{{ value }}
`;e.applyStyleFromText(`.v-dropdown{--background-color:#eee;position:relative;background-color:var(--background-color);cursor:pointer;display:flex;align-items:center;justify-content:space-between;min-width:100px}body.dark .v-dropdown{--background-color:#333}.v-dropdown .dropdown-menu{transform-origin:top;transform:translateY(-4px) translateX(-50%);pointer-events:none;opacity:0;position:absolute;top:calc(100% + 2px);left:50%;background-color:var(--background-color);z-index:1;transition:.2s ease-out;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0}.v-dropdown .dropdown-menu.opened{transform:translateY(0) translateX(-50%);pointer-events:initial;opacity:1}.v-dropdown .dropdown-menu li{padding:4px 16px;white-space:nowrap;min-width:64px;text-align:center;cursor:pointer;color:inherit;background-color:transparent}.v-dropdown .dropdown-menu li:hover{background-color:rgba(0,0,0,.16)}.v-dropdown .mdi-chevron-down{font-size:16pt;line-height:1;transform:rotate(0)}.v-dropdown .dropdown-menu.opened~.mdi-chevron-down{transform:rotate(180deg)}.v-dropdown .selected{user-select:none;padding:4px 8px}.round-corner .v-dropdown,.round-corner .v-dropdown .dropdown-menu,.round-corner .v-dropdown .dropdown-menu li{border-radius:var(--corner-radius)}`,"v-dropdown-style");return{export:Object.assign({template:n},{props:["items","value"],data(){return{dropdownOpen:false}},methods:{toggleDropdown(){this.dropdownOpen=!this.dropdownOpen;if(this.dropdownOpen){document.addEventListener("click",o=>{const e=o.target;if(e===this.$el||this.$el.contains(e)){return}this.dropdownOpen=false},{once:true,capture:true})}},select(o){this.$emit("update:value",o);this.$emit("change",o)}}})}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/video-card-info.min.js"] = (()=>{return(r,e)=>{}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/video-card.vue.min.js"] = (()=>{return(e,i)=>{const t=`
{{durationText}}
{{watchlater ? '已添加' : '稍后再看'}}

{{title}}

{{description}}

{{upName}}
{{playCount}}
`;i.applyStyleFromText(`.video-card{display:grid;grid-template-columns:200px 1fr;grid-template-rows:1fr 1fr 1fr;grid-template-areas:"cover title" "cover description" "cover up";height:var(--card-height);width:var(--card-width);color:#000;background-color:#fff;border-radius:16px;box-shadow:0 4px 8px 0 #0001;margin-right:var(--card-margin);margin-bottom:var(--card-margin);position:relative}body.dark .video-card,body.dark .video-card:hover{background-color:#282828;color:#eee}.video-card:hover{color:#000}.video-card.vertical{grid-template-columns:auto auto;grid-template-rows:2fr 1fr 1fr;grid-template-areas:"cover cover" "title title" "up up"}.video-card.vertical .description,.video-card.vertical .topics{display:none}.video-card.vertical .cover-container{border-radius:16px 16px 0 0}.video-card.vertical .title{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;max-height:3em;word-break:break-all;white-space:normal;line-height:1.5;font-size:11pt}.video-card.vertical .up{align-self:start;white-space:nowrap}.video-card.vertical .up .name{text-overflow:ellipsis;overflow:hidden}.video-card.vertical .up:not(.no-face){margin-left:8px;max-width:calc(var(--card-width) - 16px)}.video-card.vertical .up.no-face{margin-top:8px;max-width:calc(var(--card-width) - 24px)}.video-card.vertical .stats{align-self:end;justify-self:start;margin-bottom:8px;margin-right:0}.video-card>*{justify-self:self-start;align-self:center}.video-card:hover .cover{transform:scale(1.05);transition:.1s cubic-bezier(.39,.58,.57,1)}.video-card:hover .duration,.video-card:hover .watchlater{opacity:1}.video-card .duration,.video-card .watchlater{opacity:0}.video-card .cover-container{grid-area:cover;border-radius:16px 0 0 16px;position:relative;width:100%;height:100%;overflow:hidden}.video-card .cover-container .cover{object-fit:cover;width:100%;height:100%}.video-card .cover-container>:not(.cover){position:absolute}.video-card .cover-container .duration,.video-card .cover-container .watchlater{bottom:6px;padding:4px 8px;background-color:#000a;color:#fff;border-radius:14px;height:24px}.video-card .cover-container .duration .mdi,.video-card .cover-container .watchlater .mdi{font-size:12pt;line-height:1;margin-right:4px}.video-card .cover-container .duration{left:6px}.video-card .cover-container .watchlater{right:6px;display:flex;align-items:center;padding-left:4px}.video-card .title{grid-area:title;font-size:12pt;font-weight:700;color:inherit;padding:0 12px;white-space:nowrap;overflow:hidden;justify-self:stretch;text-overflow:ellipsis}.video-card .topics{grid-area:description;display:flex;align-items:center;margin-left:12px}.video-card .topics .topic{color:inherit;padding:6px 8px;background-color:#8882;margin-right:8px;border-radius:14px;white-space:nowrap;max-width:120px;overflow:hidden;text-overflow:ellipsis}.video-card .topics .topic:hover{background-color:#8884;color:var(--theme-color)}.video-card .description{grid-area:description;color:inherit;overflow:hidden;align-self:stretch;justify-self:stretch;margin:0 12px;line-height:1.5;height:3em;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;scrollbar-width:none!important}.video-card .description::-webkit-scrollbar{width:0!important}.video-card .description.single-line{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.video-card .stats,.video-card .up{grid-area:up}.video-card .up{margin-left:12px;display:flex;align-items:center;padding:2px;background-color:#8882;border-radius:14px;color:inherit}.video-card .up.no-face{background-color:transparent;padding:0}.video-card .up.no-face .be-icon{font-size:14pt;opacity:.75}.video-card .up .face{border-radius:50%}.video-card .up .name{margin:0 8px}.video-card .up:not(.no-face):hover{background-color:#8884}.video-card .up:hover .be-icon,.video-card .up:hover .name{color:var(--theme-color)}.video-card .stats{justify-self:self-end;margin-right:12px;display:flex;align-items:center;opacity:.5}.video-card .stats .be-icon{font-size:12pt;margin:0 4px 0 12px}.video-card .stats .be-icon.be-iconfont-favorites-outline{font-size:14pt}.video-card .stats .be-icon.be-iconfont-coin-outline{font-size:11pt}`,"video-card-style");return{export:Object.assign({template:t},{props:["data","orientation"],components:{"dpi-img":()=>i.importAsync("dpi-img.vue"),Icon:()=>i.importAsync("icon.vue")},data(){return{upFaceUrl:"",danmakuCount:"",like:"",coins:"",favorites:"",dynamic:"",topics:[],upID:0,epID:0,...this.data}},computed:{vertical(){return this.orientation==="vertical"}},methods:{async toggleWatchlater(){try{this.watchlater=!this.watchlater;const{toggleWatchlater:e}=await i.importAsync("watchlater-api");e(this.aid.toString(),this.watchlater)}catch(e){this.watchlater=!this.watchlater;Toast.error(e.message,"稍后再看操作失败",3e3)}}}})}}})(); -onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/video-dash.min.js"] = (()=>{return(t,a)=>{const d=t=>{return{url:t.downloadUrl,backupUrls:t.backupUrls,length:t.duration,size:Math.trunc(t.bandWidth*t.duration/8)}};const r=async(t,a)=>{const d=await Ajax.getJsonWithCredentials(t);const r=d.data||d.result||d;if(d.code!==0||!r.dash){throw new Error("DASH api failed")}const e=r.accept_quality;if(!e.includes(a)){throw new Error("没有找到请求的清晰度")}if(r.quality!==a){throw new Error("无法获取请求的清晰度, 请确认当前账号有相应的权限")}const o=r.accept_description;const n=o[e.indexOf(a)];const c=r.dash.duration;const i=r.dash.video.filter(t=>t.id===a).map(t=>{const d={quality:a,qualityText:n,width:t.width,height:t.height,codecs:t.codecs,codecId:t.codecid,bandWidth:t.bandwidth,frameRate:t.frameRate,backupUrls:t.backupUrl,downloadUrl:t.baseUrl,duration:c};return d});const s=r.dash.audio.map(t=>{return{bandWidth:t.bandwidth,codecs:t.codecs,codecId:t.codecid,backupUrls:t.backupUrl,downloadUrl:t.baseUrl,duration:c}});return{videoDashes:i,audioDashes:s}};return{export:{getDashInfo:r,dashToFragment:d}}}})(); +onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/video-dash.min.js"] = (()=>{return(t,a)=>{const r=t=>{return{url:t.downloadUrl,backupUrls:t.backupUrls,length:t.duration,size:Math.trunc(t.bandWidth*t.duration/8)}};const e=async(t,a)=>{const r=await Ajax.getJsonWithCredentials(t);const e=r.data||r.result||r;if(r.code!==0||!e.dash){throw new Error("DASH api failed")}const d=e.accept_quality;if(!d.includes(a)){throw new Error("没有找到请求的清晰度")}if(e.quality!==a){throw new Error("无法获取请求的清晰度, 请确认当前账号有相应的权限")}const c=e.accept_description;const o=c[d.indexOf(a)];const s=e.dash.duration;const n=e.dash.video.filter(t=>t.id===a).map(t=>{const r={quality:a,qualityText:o,width:t.width,height:t.height,codecs:t.codecs,codecId:t.codecid,bandWidth:t.bandwidth,frameRate:t.frameRate,backupUrls:(t.backupUrl||t.backup_url||"").replace("http:","https:"),downloadUrl:(t.baseUrl||t.base_url||"").replace("http:","https:"),duration:s};return r});const i=e.dash.audio.map(t=>{return{bandWidth:t.bandwidth,codecs:t.codecs,codecId:t.codecid,backupUrls:(t.backupUrl||t.backup_url||"").replace("http:","https:"),downloadUrl:(t.baseUrl||t.base_url||"").replace("http:","https:"),duration:s}});return{videoDashes:n,audioDashes:i}};return{export:{getDashInfo:e,dashToFragment:r}}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/video-downloader-fragment.min.js"] = (()=>{return(r,e)=>{}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/video-info.min.js"] = (()=>{return(t,i)=>{class e{constructor(t){this.aid=t}async fetchInfo(){const t=JSON.parse(await Ajax.getText(`https://api.bilibili.com/x/web-interface/view?aid=${this.aid}`));if(t.code!==0){throw new Error(t.message)}const i=t.data;this.cid=i.cid;this.pageCount=i.videos;this.coverUrl=i.pic;this.tagId=i.tid;this.tagName=i.tname;this.title=i.title;this.description=i.desc;this.up={uid:i.owner.mid,name:i.owner.name,faceUrl:i.owner.face};this.pages=i.pages.map(t=>{return{cid:t.cid,title:t.part,pageNumber:t.page}});return this}async fetchDanmaku(){this.danmaku=new s(this.cid.toString());return this.danmaku.fetchInfo()}}class a{constructor(t,i){this.text=t;this.p=i}}class s{constructor(t){this.cid=t}async fetchInfo(){const t=await Ajax.getText(`https://api.bilibili.com/x/v1/dm/list.so?oid=${this.cid}`);this.rawXML=t;const i=(new DOMParser).parseFromString(t,"application/xml").documentElement;this.xml=i;this.danmakus=[...i.querySelectorAll("d[p]")].map(t=>{return new a(t.innerHTML,t.getAttribute("p"))})}}class n{constructor(t){this.ep=t;this.videos=[]}async fetchInfo(){const t=await Ajax.getText(`https://www.bilibili.com/bangumi/play/ep${this.ep}/`);const i=JSON.parse(t.match(/window\.__INITIAL_STATE__=(.*);\(function\(\){/)[1]);this.title=i.mediaInfo.title;this.cover=i.mediaInfo.cover;this.squareCover=i.mediaInfo.square_cover;this.aid=i.epInfo.aid;this.cid=i.epInfo.cid;this.videos=i.epList.map(async t=>{return{title:t.index_title,aid:t.aid,cid:t.cid,info:await new e(t.aid).fetchInfo()}});return this}}return{export:{VideoInfo:e,BangumiInfo:n,Danmaku:a,DanmakuInfo:s}}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/video-list.vue.min.js"] = (()=>{return(i,a)=>{const t=`
加载中...
空空如也哦 = ̄ω ̄=
`;a.applyStyleFromText(`.minimal-home .video-list .empty,.minimal-home .video-list .loading{height:48px;display:flex;align-items:center;justify-content:center;font-size:11pt;color:#707070}.minimal-home .video-list .empty .mdi,.minimal-home .video-list .loading .mdi{margin-right:8px}body.dark .minimal-home .video-list .empty,body.dark .minimal-home .video-list .loading{color:#eee}.minimal-home .video-list .cards{display:flex;flex-wrap:wrap;align-items:flex-end}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1),.minimal-home .video-list .cards.show-rank .video-card:nth-child(17),.minimal-home .video-list .cards.show-rank .video-card:nth-child(9){margin-top:48px}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1)::before,.minimal-home .video-list .cards.show-rank .video-card:nth-child(17)::before,.minimal-home .video-list .cards.show-rank .video-card:nth-child(9)::before{position:absolute;top:-42px;left:0;font-size:14pt;font-weight:700}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1)::before{content:"昨日"}.minimal-home .video-list .cards.show-rank .video-card:nth-child(9)::before{content:"三日"}.minimal-home .video-list .cards.show-rank .video-card:nth-child(17)::before{content:"一周"}`,"video-list-style");return{export:Object.assign({template:t},{components:{VideoCard:()=>a.importAsync("video-card.vue")},props:["showRank"],data(){return{cards:[],loading:true}},methods:{async getRankList(){const{getTrendingVideos:i}=await a.importAsync("trending-videos");const{getWatchlaterList:t}=await a.importAsync("watchlater-api");const e=await t();const o=async a=>{const t=await i(a,e);this.cards.push(...t)};await Promise.all([1,3,7].map(o))},async getActivityVideos(){const i=await Ajax.getJsonWithCredentials(`https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new?uid=${getUID()}&type_list=8`);const{getWatchlaterList:t}=await a.importAsync("watchlater-api");const e=await t();if(i.code!==0){throw new Error(i.message)}this.cards=i.data.cards.map(i=>{const a=JSON.parse(i.card);const t=_.get(i,"display.topic_info.topic_details",[]).map(i=>{return{id:i.topic_id,name:i.topic_name}});return{id:i.desc.dynamic_id_str,aid:a.aid,title:a.title,upID:i.desc.user_profile.info.uid,upName:i.desc.user_profile.info.uname,upFaceUrl:i.desc.user_profile.info.face,coverUrl:a.pic,description:a.desc,timestamp:i.timestamp,time:new Date(i.timestamp*1e3),topics:t,dynamic:a.dynamic,like:formatCount(i.desc.like),duration:a.duration,durationText:formatDuration(a.duration,0),playCount:formatCount(a.stat.view),danmakuCount:formatCount(a.stat.danmaku),watchlater:e.includes(a.aid)}})}},async mounted(){try{if(this.showRank){await this.getRankList()}else{await this.getActivityVideos()}}catch(i){Toast.error(i.message,this.showRank?"热门视频":"视频动态",3e3)}finally{this.loading=false}}})}}})(); @@ -1690,13 +1691,17 @@ Resource.manifest = { useCache: '启用缓存' } }, + videoDownloadPackage: { + path: 'download-video-package.min.js', + }, downloadVideo: { path: 'download-video.min.js', html: true, style: 'instant', - dependencies: ['title', 'videoInfo'], + dependencies: ['title', 'videoInfo', 'videoDownloadPackage'], displayNames: { 'downloadVideo': '下载视频', + 'videoDownloadPackage': '下载视频打包器', 'batchDownload': '批量下载', 'aria2Rpc': 'aria2 RPC', } diff --git a/bilibili-evolved.user.js b/bilibili-evolved.user.js index 51a89f45d..d68205863 100644 --- a/bilibili-evolved.user.js +++ b/bilibili-evolved.user.js @@ -364,6 +364,7 @@ const settings = { customNavbarSeasonLogo: false, selectableColumnText: true, downloadVideoFormat: 'flv', + downloadVideoFfmpegSupport: '无', enableDashDownload: false, watchlaterExpireWarnings: true, watchlaterExpireWarningDays: 14, @@ -1083,10 +1084,10 @@ onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/mi onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/double-click-fullscreen.min.js"] = (()=>{return(i,e)=>{(async()=>{const e=["https://www.bilibili.com/bangumi/","https://www.bilibili.com/video/"];if(!e.some(i=>document.URL.startsWith(i))){return}if(i.touchVideoPlayer&&i.touchVideoPlayerDoubleTapControl){Toast.info("在开启了播放器触摸支持-启用双击控制后, 双击全屏功能将无效.","提示");i.doubleClickFullscreen=false;return}await SpinQuery.unsafeJquery();const l=await SpinQuery.condition(()=>dq(".bilibili-player-area"),i=>i!==null&&unsafeWindow.$(".bilibili-player-video").data("events"));if(l===null){return}const n="double-click-fullscreen";if(!l.classList.contains(n)){l.classList.add(n);const e=unsafeWindow.$(".bilibili-player-video");const t=i.doubleClickFullscreenPreventSingleClick?e.data("events").click[0].handler:()=>{};const c=new DoubleClickEvent(()=>dq(".bilibili-player-video-btn-fullscreen").click(),i=>t(i));if(i.doubleClickFullscreenPreventSingleClick){e.unbind("click")}c.bind(e[0])}})()}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-audio.min.js"] = (()=>{return(e,t)=>{class n{constructor(){this.sid=null;this.progress=null}async getDownloadUrl(){const e=`https://www.bilibili.com/audio/music-service-c/web/url?sid=${this.sid}&privilege=2&quality=2`;const t=await Ajax.getJsonWithCredentials(e);if(t.code===0){return t.data.cdns.shift()}else{logError("获取下载链接失败, 请确保当前账号有下载权限.","下载音频",1e4);return null}}async download(){const e=await this.getDownloadUrl();return new Promise((t,n)=>{const s=new XMLHttpRequest;s.open("GET",e);s.responseType="blob";s.addEventListener("load",()=>t(s.response));s.addEventListener("error",()=>n(s.status));s.addEventListener("progress",e=>this.progress&&this.progress(100*e.loaded/e.total));s.send()})}}const s="下载音频";return{export:n,widget:{content:`\n\n\n${s}\n\n`,condition:()=>document.URL.includes("bilibili.com/audio"),success:async()=>{await SpinQuery.select(()=>document.querySelector("#app"));const e=document.querySelector("#download-audio");const t=e.querySelector("span");const o=new n;o.progress=(e=>{t.innerHTML=`${Math.round(e)}%`});const i=document.querySelector("#download-audio-link");e.addEventListener("click",async e=>{if(o.sid===null||e.target===i){return}const n=await o.download();t.innerHTML=s;const r=i.getAttribute("href");if(r){URL.revokeObjectURL(r)}i.setAttribute("href",URL.createObjectURL(n));const d=(()=>{const e=document.querySelector(".song-title");if(e){return e.getAttribute("title")}else{return"神秘音频"}})();i.setAttribute("download",d+".m4a");i.click()});Observer.childList("#app",()=>{const t=document.URL.match(/bilibili\.com\/audio\/au([\d]+)/);if(t&&t[1]){e.disabled=false;o.sid=t[1]}else{e.disabled=true}})}}}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-danmaku.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:n}=e.import("title");const{DanmakuInfo:i}=e.import("video-info");const{DanmakuConverter:a}=e.import("danmaku-converter");async function o(t){const e=n();let i={title:e};try{await loadDanmakuSettingsPanel();const t=t=>{const e=parseFloat(dq(t).style.transform.replace(/translateX\(([\d\.]+)/,"$1"));const n={0:0,44:1,94:2,144:3,188:4}[e];return n};i.font=dq(".bilibili-player-video-danmaku-setting-right-font .bui-select-result").innerText;i.alpha=parseFloat(dq(".bilibili-player-setting-opacity .bui-bar").style.transform.replace(/scaleX\(([\d\.]+)\)/,"$1"));i.duration=(()=>{const e=[18,14,10,8,6][t(".bilibili-player-setting-speedplus .bui-thumb")];return t=>{switch(t.type){case 4:case 5:return 4;default:return e}}})();i.blockTypes=(()=>{let t=[];const e={".bilibili-player-block-filter-type[ftype=scroll]":[1,2,3],".bilibili-player-block-filter-type[ftype=top]":[5],".bilibili-player-block-filter-type[ftype=bottom]":[4],".bilibili-player-block-filter-type[ftype=color]":["color"]};for(const[n,i]of Object.entries(e)){if(dq(n).classList.contains("disabled")){t=t.concat(i)}}return t.concat(7,8)})();const e=[1.4,1.2,1,.8,.6][t(".bilibili-player-setting-fontsize .bui-thumb")];i.resolution={x:1920*e,y:1080*e};i.bottomMarginPercent=[.75,.5,.25,0,0][t(".bilibili-player-setting-area .bui-thumb")];if(i.bottomMarginPercent===0&&dq(".bilibili-player-video-danmaku-setting-left-preventshade input").checked){i.bottomMarginPercent=.15}i.bold=dq(".bilibili-player-video-danmaku-setting-right-font-bold input").checked}catch(t){i={font:"微软雅黑",alpha:.6,duration:t=>{switch(t.type){case 4:case 5:return 4;default:return 6}},blockTypes:[7,8],resolution:{x:1920,y:1080},bottomMarginPercent:.15,bold:false}}const o=new a(i);const l=o.convertToAssDocument(t);return l.generateAss()}async function l(t,e){const a=n();const l=new i((unsafeWindow||window).cid);await l.fetchInfo();const r=await(async()=>{if(t===true){return new Blob([await o(l.rawXML)],{type:"text/plain"})}else{return new Blob([l.rawXML],{type:"text/plain"})}})();const s=URL.createObjectURL(r);const c=dq("#danmaku-link");const d=c.getAttribute("href");if(d){URL.revokeObjectURL(d)}clearTimeout(e);dq("#download-danmaku>span").innerHTML="下载弹幕";c.setAttribute("download",`${a}.${t?"ass":"xml"}`);c.setAttribute("href",s);c.click()}return{export:{downloadDanmaku:l,convertToAss:o},widget:{content:`\n\n\n下载弹幕\n\n`,condition:async()=>{let t=await SpinQuery.select(()=>(unsafeWindow||window).cid);return Boolean(t)},success:()=>{const t=document.querySelector("#danmaku-link");dq("#download-danmaku").addEventListener("click",e=>{if(e.target!==t){const t=setTimeout(()=>dq("#download-danmaku>span").innerHTML="请稍侯...",200);l(e.shiftKey,t)}})}}}}})(); -onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video-package.min.js"] = (()=>{return(e,t)=>{class n{constructor(e={}){this.config=e;this.entries=[]}download(e,t){const n=document.createElement("a");const i=URL.createObjectURL(t);n.setAttribute("href",i);n.setAttribute("download",e);document.body.appendChild(n);n.click();n.remove();URL.revokeObjectURL(i)}add(e,t){if(t===null||t===undefined){return}this.entries.push({name:e,data:t})}async emit(e){if(this.entries.length===0){return}if(!e||this.entries.length===1){e=this.entries[0].name}if(this.entries.length===1){const t=this.entries[0].data;this.download(e,typeof t==="string"?new Blob([t]):t);return}const t=new JSZip;this.entries.forEach(({name:e,data:n})=>{t.file(e,n)});const n=await t.generateAsync({type:"blob"});this.download(e,n)}static async single(e,t){const i=new n;i.add(e,t);await i.emit()}}return{export:{DownloadVideoPackage:n}}}})(); +onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video-package.min.js"] = (()=>{return(e,t)=>{class n{constructor(e={}){this.config=e;this.entries=[]}download(e,t){const i=document.createElement("a");const a=URL.createObjectURL(t);if(n.lastPackageUrl){URL.revokeObjectURL(n.lastPackageUrl)}n.lastPackageUrl=a;i.setAttribute("href",a);i.setAttribute("download",e);document.body.appendChild(i);i.click();i.remove()}add(e,t){if(t===null||t===undefined){return}this.entries.push({name:e,data:t})}async preEmit(){const e=this.entries.filter(e=>[".flv",".mp4",".m4s"].some(t=>e.name.endsWith(t)));if(this.config.ffmpeg!==undefined&&e.length>=2){if(this.config.ffmpeg==="文件列表"||this.config.ffmpeg==="文件列表+脚本"){this.entries.push({name:"ffmpeg-files.txt",data:e.map(e=>`file '${e.name}'`).join("\n")})}if(this.config.ffmpeg==="文件列表+脚本"){const e=`ffmpeg -f concat -i ffmpeg-files.txt -c copy ""`;this.entries.push({name:"ffmpeg.bat",data:e},{name:"ffmpeg.sh",data:e.replace(/"/g,"'")})}}}async blob(){await this.preEmit();if(this.entries.length===0){return null}if(this.entries.length===1){const e=this.entries[0].data;return typeof e==="string"?new Blob([e]):e}const e=new JSZip;this.entries.forEach(({name:t,data:n})=>{e.file(t,n)});return await e.generateAsync({type:"blob"})}async emit(e){if(!e||this.entries.length===1){e=this.entries[0].name}const t=await this.blob();if(!t){return}return this.download(e,t)}static async single(e,t,i={}){const a=new n(i);a.add(e,t);return await a.emit()}}n.lastPackageUrl="";return{export:{DownloadVideoPackage:n}}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.css"] = `.download-video{--download-video-background:white;--download-video-foreground:black;position:absolute;top:64px;left:50%;transform:translateX(-50%) scale(.95);background:var(--download-video-background);color:var(--download-video-foreground);box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;z-index:10001;pointer-events:none;opacity:0;padding:16px;width:300px;display:flex;flex-direction:column;align-items:stretch;justify-content:space-between}.download-video,.download-video *{transition:.2s ease-out;-webkit-tap-highlight-color:transparent!important}.download-video.opened{pointer-events:initial;opacity:1;transform:translateX(-50%) scale(1)}body.dark .download-video{--download-video-background:#222;--download-video-foreground:#eee}.round-corner .download-video,.round-corner .download-video .episode-list .v-checkbox,.round-corner .download-video .rpc-settings{border-radius:var(--large-corner-radius)}.round-corner .download-video .button,.round-corner .download-video .cover,.round-corner .download-video .direct-download .progress .background,.round-corner .download-video .direct-download .progress .foreground,.round-corner .download-video .rpc-settings input[type=text],.round-corner .download-video .title,.round-corner .download-video button{border-radius:var(--corner-radius)}.download-video .cover{width:240px;min-height:135px;max-height:200px;object-fit:contain}.download-video .header{display:flex;justify-content:space-between;align-items:center}.download-video h1{font-size:16pt;font-weight:700;color:var(--download-video-foreground)}.download-video .header .mdi-close{font-size:16pt;color:var(--download-video-foreground);cursor:pointer}.download-video .header .mdi-close:hover{color:var(--theme-color)}.download-video .info{display:flex;flex-direction:column;align-items:center;margin-top:12px}.download-video .title{display:flex;flex-direction:column;justify-content:space-between;align-items:stretch;margin-top:12px}.download-video .title .bold{width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.download-video .title .size{font-size:10pt;color:var(--download-video-foreground);align-self:center;display:flex;align-items:center;height:24px}.download-video .bold{color:var(--download-video-foreground);font-weight:700;font-size:12pt}.download-video .option-item{display:flex;justify-content:space-between;align-items:center;padding-top:12px;font-size:10pt}.download-video .tabs{display:flex;padding-top:12px;font-size:10pt}.download-video .tabs .tab{padding:6px 12px;border-bottom:2px solid transparent;cursor:pointer}.download-video .tabs .tab.active{color:var(--theme-color);border-bottom-color:var(--theme-color)}.download-video .separator{height:1px;background:#8884;width:100%;margin:12px 0;flex-shrink:0}.download-video h2{font-size:12pt;font-weight:700;color:var(--download-video-foreground)}.download-video .direct-download{display:flex;flex-direction:column;align-items:start;justify-content:space-between}.download-video .button,.download-video button{border:none;outline:0!important;padding:6px 16px;font-size:10pt;cursor:pointer;background:#8884;color:var(--download-video-foreground)}.download-video .button:hover,.download-video button:hover{background:#8886}.download-video .primary{background:var(--theme-color);color:var(--foreground-color);align-self:center}.download-video .primary:hover{background:var(--theme-color-90)}.download-video .busy .button,.download-video .busy .primary,.download-video .busy button,.download-video button:disabled{background-color:#0001;color:#8884;cursor:not-allowed}.download-video .busy .button,.download-video .busy button{cursor:wait!important}.download-video .direct-download .progress{align-self:stretch;display:flex;align-items:center;margin-top:8px}.download-video .direct-download .progress .background{flex-grow:1;height:4px;background:#8884;margin-right:4px;position:relative}.download-video .direct-download .progress .background .foreground{position:absolute;top:0;left:0;height:4px;background:linear-gradient(to right,var(--theme-color),var(--theme-color-60))}.download-video .direct-download .progress .percent{width:50px;text-align:right}.download-video .actions{display:flex;flex-wrap:wrap;justify-content:space-between;margin:8px -4px 0}.download-video .actions>*{margin:4px;flex-grow:1;flex-basis:calc(50% - 16px);display:flex;justify-content:center;align-items:center}.download-video i.mdi-alert-circle{font-size:14pt;color:#ff9800}.download-video .size-warning{position:relative;padding:0 8px}.download-video .size-warning-tip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:var(--download-video-background);color:var(--download-video-foreground);border:1px dashed var(--theme-color);z-index:2;font-size:10pt;width:200px;padding:8px;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;pointer-events:none;opacity:0}.download-video .size-warning:hover .size-warning-tip{opacity:1}.download-video .episode-list .v-checkbox{padding:4px 8px;margin:4px 0;position:relative;background-color:transparent}.download-video .episode-list .v-checkbox.checked{background-color:#8882}.download-video .episode-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.download-video .episode-list{overflow:auto;max-height:320px}.download-video button.list-tool{padding:4px;line-height:1;font-size:12pt;margin:0 4px}.download-video .episode-header h2{flex-grow:1}.download-video .selected-count{width:64px;text-align:right}.download-video .aria2-rpc .mdi{margin-left:8px;font-size:14pt;line-height:1}.download-video .aria2-rpc{position:relative}.download-video .rpc-settings{position:absolute;display:flex;flex-direction:column;align-items:stretch;color:var(--download-video-foreground);background:#fff;bottom:120%;left:50%;cursor:initial;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0;transform-origin:bottom;transform:translateX(-50%) scale(.9);opacity:0;pointer-events:none;padding:8px;z-index:3;transition:.3s cubic-bezier(.18,.89,.32,1.28);width:120%}body.dark .download-video .rpc-settings{background:#282828}.download-video .rpc-settings>*{margin:8px}.download-video .rpc-settings.show{opacity:1;transform:translateX(-50%) scale(1);pointer-events:initial}.download-video .rpc-settings input[type=text]{background:0 0;color:var(--download-video-foreground);border:1px solid #8884;padding:4px;margin-left:8px}.download-video .rpc-settings input[type=text]:focus{border-color:var(--theme-color)}.download-video .rpc-settings .operations{display:flex;align-items:center;justify-content:space-evenly}.download-video .final-dir{word-break:break-all}.download-video .rpc-settings-item{display:flex;align-items:center;justify-content:space-between;white-space:nowrap}.download-video .rpc-settings-item input[type=text]{flex-grow:1;margin-left:24px}.download-video button.cancel-download,.download-video button.start-download{margin-top:8px}.download-video .direct-download-header{align-self:stretch;display:flex;justify-content:space-between;align-items:center}body.dark .download-video .direct-download .progress .foreground{background:linear-gradient(to right,var(--theme-color-70),var(--theme-color))}`; -onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.html"] = `

下载视频

单个视频
批量导出
警告: 过大的视频大小会在直接下载时占用大量内存, 并可能导致浏览器标签页崩溃. 请考虑降低清晰度或使用导出选项.
预计大小: {{displaySize}}
格式
清晰度
弹幕

直接下载

{{speed}}
{{progressPercent}}%

选集

{{selectedEpisodeCount}}/{{episodeList.length}}

导出

{{showRpcSettings ? '取消' : 'aria2 RPC'}}

aria2 RPC

配置

主机
端口
密钥
限速
默认路径
路径
最终路径: {{rpcSettings.baseDir + rpcSettings.dir}}
方法
开始下载
{{saveRpcSettingsText}}
`; -onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:a}=e.import("title");const{VideoInfo:s,DanmakuInfo:i}=e.import("video-info");class o{async getDashUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json&fnver=0&fnval=16`}else{return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&otype=json&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&otype=json`}}}class n extends o{async getDashUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&qn=${t}&otype=json&fourk=1&fnval=16`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&otype=json&fourk=1&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=${r.aid}&cid=${r.cid}&qn=&otype=json`}}}const r={entity:new o,aid:"",cid:""};let l=[];let c=null;class d{constructor(t,e,a){this.quality=t;this.internalName=e;this.displayName=a}async downloadInfo(t=false){const e=new h(this);await e.fetchVideoInfo(t);return e}static parseFormats(t){const e=t.accept_quality;const a=t.accept_format.split(",");const s=t.accept_description;const i=e.map((t,e)=>{return new d(t,a[e],s[e])});return i}static async getAvailableDashFormats(){const t=await r.entity.getDashUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}return d.parseFormats(e.data||e.result||e)}static async getAvailableFormats(){const t=await r.entity.getUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}const a=e.data||e.result||e;return d.parseFormats(a)}}class h{constructor(t,e){this.fragmentSplitFactor=6*2;this.workingXhr=null;this.progressMap=new Map;this.format=t;this.fragments=e||[];this.videoSpeed=new p(this)}get totalSize(){return this.fragments.map(t=>t.size).reduce((t,e)=>t+e)}async fetchVideoInfo(t=false){if(!t){const t=await r.entity.getUrl(this.format.quality);const e=await Ajax.getTextWithCredentials(t);const a=JSON.parse(e.replace(/http:/g,"https:"));const s=a.data||a.result||a;if(s.quality!==this.format.quality){throw new Error("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const i=s.durl;this.fragments=i.map(t=>{return{length:t.length,size:t.size,url:t.url,backupUrls:t.backup_url}})}else{const{dashToFragment:t,getDashInfo:a}=await e.importAsync("video-dash");const s=await a(await r.entity.getDashUrl(this.format.quality),this.format.quality);const i=s.videoDashes.sort(ascendingSort(t=>t.bandWidth))[0];const o=s.audioDashes.sort(ascendingSort(t=>t.bandWidth))[0];this.fragments=[t(i),t(o)]}return this.fragments}updateProgress(){const t=this.progressMap?[...this.progressMap.values()].reduce((t,e)=>t+e,0)/this.totalSize:0;if(t>1||t<0){console.error(`[下载视频] 进度异常: ${t}`,this.progressMap.values())}this.progress&&this.progress(t)}cancelDownload(){this.videoSpeed.stopMeasure();if(this.workingXhr!==null){this.workingXhr.forEach(t=>t.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(t){const e=[];this.workingXhr=[];this.progressMap=new Map;this.updateProgress();let a;if(t.size<=96*1024*1024){a=t.size/this.fragmentSplitFactor}else{a=16*1024*1024}let s=0;const i=t=>[...this.progressMap.keys()].indexOf(t)+1;while(s{const s=new XMLHttpRequest;s.open("GET",t.url);s.responseType="arraybuffer";s.withCredentials=false;s.addEventListener("progress",t=>{console.log(`[下载视频] 视频片段${i(s)}下载进度: ${t.loaded}/${r} bytes loaded, ${n}`);this.progressMap.set(s,t.loaded);this.updateProgress()});s.addEventListener("load",()=>{if((""+s.status)[0]==="2"){console.log(`[下载视频] 视频片段${i(s)}下载完成`);e(s.response)}else{a(`视频片段${i(s)}请求失败, response = ${s.status}`)}});s.addEventListener("abort",()=>a("canceled"));s.addEventListener("error",()=>{console.error(`[下载视频] 视频片段${i(s)}下载失败: ${n}`);this.progressMap.set(s,0);this.updateProgress();s.open("GET",t.url);s.setRequestHeader("Range",n);s.send()});s.setRequestHeader("Range",n);this.progressMap.set(s,0);s.send();this.workingXhr.push(s)}));s=Math.round(s+a)+1}return Promise.all(e)}async copyUrl(){const t=this.fragments.map(t=>t.url).reduce((t,e)=>t+"\r\n"+e);GM.setClipboard(t,"text")}async showUrl(){const t=this.fragments.map(t=>`\n${t.url}\n`).reduce((t,e)=>t+"\r\n"+e);Toast.success(t+`复制全部`,"显示链接");const e=await SpinQuery.select("#copy-link");e.addEventListener("click",async()=>{await this.copyUrl()})}async exportData(t=false){const s=JSON.stringify([{fragments:this.fragments,title:a(),totalSize:this.fragments.map(t=>t.size).reduce((t,e)=>t+e),referer:document.URL.replace(window.location.search,"")}]);if(t){GM.setClipboard(s,"text")}else{const t=new Blob([s],{type:"text/json"});const i=await this.downloadDanmaku();const{DownloadVideoPackage:o}=await e.importAsync("download-video-package");const n=new o;n.add(`${a()}.json`,t);n.add(a()+"."+this.danmakuOption.toLowerCase(),i);await n.emit(`${a()}.zip`)}}async exportAria2(s=false){if(s){const s=await this.downloadDanmaku();if(s!==null){const{DownloadVideoPackage:t}=await e.importAsync("download-video-package");t.single(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,s)}const i=t.aria2RpcOption;const o=this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}const o=[];if(i.secretKey!==""){o.push(`token:${i.secretKey}`)}o.push([t.url]);o.push({referer:document.URL.replace(window.location.search,""),"user-agent":UserAgent,out:`${a()}${s}${this.extension(t)}`,split:this.fragmentSplitFactor,dir:i.baseDir+i.dir||undefined,"max-download-limit":i.maxDownloadLimit||undefined});const n=encodeURIComponent(`${a()}${s}`);return{params:o,id:n}});const{sendRpc:n}=await e.importAsync("aria2-rpc");await n(o)}else{const t=`\n# Generated by Bilibili Evolved Video Export\n# https://github.com/the1812/Bilibili-Evolved/\n${this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}return`\n${t.url}\n referer=${document.URL.replace(window.location.search,"")}\n user-agent=${UserAgent}\n out=${a()}${s}${this.extension(t)}\n split=${this.fragmentSplitFactor}\n`.trim()}).join("\n")}\n`.trim();const s=new Blob([t],{type:"text/plain"});const i=await this.downloadDanmaku();const{DownloadVideoPackage:o}=await e.importAsync("download-video-package");const n=new o;n.add(`${a()}.txt`,s);n.add(a()+"."+this.danmakuOption.toLowerCase(),i);await n.emit(`${a()}.zip`)}}extension(t){const e=t||this.fragments[0];const a=[".flv",".mp4",".m4s"].find(t=>e.url.includes(t));if(a){return a}else{console.warn("No extension detected.");return".flv"}}makeBlob(t,e){return new Blob(Array.isArray(t)?t:[t],{type:this.extension(e)===".flv"?"video/x-flv":"video/mp4"})}cleanUpOldBlobUrl(){const t=dq("a#video-complete").getAttribute("href");if(t&&!dq(`.link[href="${t}"]`)){URL.revokeObjectURL(t)}dqa(".toast-card-header").filter(t=>t.innerText.includes("下载视频")).forEach(t=>t.querySelector(".toast-card-dismiss").click())}async downloadDanmaku(){if(this.danmakuOption!=="无"){const t=new i(r.cid);await t.fetchInfo();if(this.danmakuOption==="XML"){return t.rawXML}else{const{convertToAss:a}=await e.importAsync("download-danmaku");return a(t.rawXML)}}else{return null}}async downloadSingle(t){const e=await this.downloadDanmaku();const[s]=t;if(e===null){const t=this.makeBlob(s);const e=a()+this.extension();return{blob:t,filename:e}}else{const t=new JSZip;t.file(a()+this.extension(),this.makeBlob(s));t.file(a()+"."+this.danmakuOption.toLowerCase(),e);const i=await t.generateAsync({type:"blob"});const o=a()+".zip";return{blob:i,filename:o}}}async downloadMultiple(t){const e=new JSZip;const s=a();if(t.length>1){t.forEach((t,a)=>{const i=this.fragments[a];e.file(`${s} - ${a+1}${this.extension(i)}`,this.makeBlob(t,i))})}else{const[a]=t;e.file(`${s}${this.extension()}`,this.makeBlob(a))}const i=await this.downloadDanmaku();if(i!==null){e.file(a()+"."+this.danmakuOption.toLowerCase(),i)}const o=await e.generateAsync({type:"blob"});const n=s+".zip";return{blob:o,filename:n}}async download(){const t=[];this.videoSpeed.startMeasure();for(const e of this.fragments){const a=await this.downloadFragment(e);t.push(a)}if(t.length<1){throw new Error("下载失败.")}let{blob:e,filename:a}=await(async()=>{if(t.length===1){return await this.downloadSingle(t)}else{return await this.downloadMultiple(t)}})();this.cleanUpOldBlobUrl();const s=URL.createObjectURL(e);this.progress&&this.progress(0);this.videoSpeed.stopMeasure();return{url:s,filename:a}}}class p{constructor(t){this.lastProgress=0;this.measureInterval=1e3;this.workingDownloader=t}startMeasure(){this.intervalTimer=setInterval(()=>{const t=this.workingDownloader.progressMap?[...this.workingDownloader.progressMap.values()].reduce((t,e)=>t+e,0):0;const e=t-this.lastProgress;if(this.speedUpdate!==undefined){this.speedUpdate(formatFileSize(e)+"/s")}this.lastProgress=t},this.measureInterval)}stopMeasure(){clearInterval(this.intervalTimer)}}async function u(){const t=await SpinQuery.select(()=>(unsafeWindow||window).aid);const e=await SpinQuery.select(()=>(unsafeWindow||window).cid);if(!(t&&e)){return false}r.aid=t;r.cid=e;if(document.URL.indexOf("bangumi")!==-1){r.entity=new n}else{r.entity=new o}try{l=await d.getAvailableFormats()}catch(t){return false}return true}async function f(){c=l[0];e.applyStyle("downloadVideoStyle");dq("#download-video").addEventListener("click",()=>{dq(".download-video").classList.toggle("opened");dq(".gui-settings-mask").click()});dq("#download-video").addEventListener("mouseover",()=>{document.body.insertAdjacentHTML("beforeend",e.import("downloadVideoHtml"));w()},{once:true})}async function w(){let o;const n=new Map;const h=new Vue({el:".download-video",components:{VDropdown:()=>e.importAsync("v-dropdown.vue"),VCheckbox:()=>e.importAsync("v-checkbox.vue"),RpcProfiles:()=>e.importAsync("aria2-rpc-profiles.vue")},data:{downloadSingle:true,coverUrl:EmptyImageUrl,aid:r.aid,cid:r.cid,dashModel:{value:t.downloadVideoFormat,items:["flv","dash"]},qualityModel:{value:c.displayName,items:l.map(t=>t.displayName)},danmakuModel:{value:t.downloadVideoDefaultDanmaku,items:["无","XML","ASS"]},progressPercent:0,size:"获取大小中",blobUrl:"",episodeList:[],downloading:false,speed:"",batch:false,rpcSettings:t.aria2RpcOption,showRpcSettings:false,busy:false,saveRpcSettingsText:"保存配置",enableDash:t.enableDashDownload},computed:{displaySize(){if(typeof this.size==="string"){return this.size}return formatFileSize(this.size)},sizeWarning(){if(typeof this.size==="string"){return false}return this.size>1073741824},selectedEpisodeCount(){return this.episodeList.filter(t=>t.checked).length},dash(){return this.dashModel.value==="dash"}},methods:{close(){this.$el.classList.remove("opened")},danmakuOptionChange(){t.downloadVideoDefaultDanmaku=this.danmakuModel.value},async dashChange(){const t=this.dashModel.value;let e=[];if(t==="flv"){e=await d.getAvailableFormats()}else{e=await d.getAvailableDashFormats()}l=e;[c]=t;this.qualityModel.items=e.map(t=>t.displayName);[this.qualityModel.value]=this.qualityModel.items;await this.formatChange()},async formatChange(){const t=this.getFormat();const e=n.get(t);if(e){this.size=e;return}try{this.size="获取大小中";const e=await t.downloadInfo(this.dash);this.size=e.totalSize;n.set(t,this.size)}catch(t){this.size="获取大小失败"}},getFormat(){const t=l.find(t=>t.displayName===this.qualityModel.value);if(!t){console.error(`No format found. model value = ${this.qualityModel.value}`);return null}return t},async exportData(t){if(this.busy===true){return}try{this.busy=true;if(!this.downloadSingle){await this.exportBatchData(t);return}const e=this.getFormat();const a=await e.downloadInfo(this.dash);a.danmakuOption=this.danmakuModel.value;switch(t){case"copyLink":await a.copyUrl();Toast.success("已复制链接到剪贴板.","下载视频",3e3);break;case"showLink":await a.showUrl();break;case"aria2":await a.exportAria2(false);break;case"aria2RPC":await a.exportAria2(true);break;case"copyVLD":await a.exportData(true);Toast.success("已复制VLD数据到剪贴板.","下载视频",3e3);break;case"exportVLD":await a.exportData(false);break;default:break}}catch(t){logError(t)}finally{this.busy=false}},async exportBatchData(t){const s=this.episodeList;if(s.every(t=>t.checked===false)){Toast.info("请至少选择1集或以上的数量!","批量导出",3e3);return}const o=t=>{const e=s.find(e=>e.cid===t.cid);if(e===undefined){return false}return e.checked};const n=this.getFormat();const{DownloadVideoPackage:r}=await e.importAsync("download-video-package");if(this.danmakuModel.value!=="无"){const t=Toast.info("下载弹幕中...","批量导出");const a=new r;try{if(this.danmakuModel.value==="XML"){for(const t of s.filter(o)){const e=new i(t.cid);await e.fetchInfo();a.add(t.title+".xml",e.rawXML)}}else{const{convertToAss:t}=await e.importAsync("download-danmaku");for(const e of s.filter(o)){const s=new i(e.cid);await s.fetchInfo();a.add(e.title+".ass",await t(s.rawXML))}}await a.emit(this.cid+".danmakus.zip")}catch(t){logError(`弹幕下载失败`)}finally{t.dismiss()}}const l=Toast.info("获取链接中...","批量导出");this.batchExtractor.itemFilter=o;let c;try{switch(t){case"aria2":c=await this.batchExtractor.collectAria2(n,l);await r.single(a(false)+".txt",new Blob([c],{type:"text/plain"}));return;case"aria2RPC":await this.batchExtractor.collectAria2(n,l,true);Toast.success(`成功发送了批量请求.`,"aria2 RPC",3e3);return;case"copyVLD":GM.setClipboard(await this.batchExtractor.collectData(n,l),{mimetype:"text/plain"});Toast.success("已复制批量vld数据到剪贴板.","批量导出",3e3);return;case"exportVLD":c=await this.batchExtractor.collectData(n,l);await r.single(a(false)+".json",new Blob([c],{type:"text/json"}));return;default:return}}catch(t){logError(t)}finally{l.dismiss()}},async checkBatch(){const t=["/www.bilibili.com/bangumi","/www.bilibili.com/video/av"];if(!t.some(t=>document.URL.includes(t))){this.batch=false;this.episodeList=[];return}const{BatchExtractor:a}=await e.importAsync("batch-download");if(await a.test()!==true){this.batch=false;this.episodeList=[];return}this.batchExtractor=new a;this.batch=true;this.episodeList=(await this.batchExtractor.getItemList()).map((t,e)=>{return{aid:t.aid,cid:t.cid,title:t.title,index:e,checked:true}})},cancelDownload(){if(o){o.cancelDownload()}},async startDownload(){const t=this.getFormat();try{this.downloading=true;const e=await t.downloadInfo(this.dash);e.videoSpeed.speedUpdate=(t=>this.speed=t);e.danmakuOption=this.danmakuModel.value;e.progress=(t=>{this.progressPercent=Math.trunc(t*100)});o=e;const a=await e.download();const s=document.getElementById("video-complete");s.setAttribute("href",a.url);s.setAttribute("download",a.filename);s.click();Toast.success(`下载完成: ${a.filename} 再次保存`,"下载视频")}catch(t){if(t!=="canceled"){logError(t)}this.progressPercent=0}finally{this.downloading=false;this.speed=""}},selectAllEpisodes(){this.episodeList.forEach(t=>t.checked=true)},unselectAllEpisodes(){this.episodeList.forEach(t=>t.checked=false)},inverseAllEpisodes(){this.episodeList.forEach(t=>t.checked=!t.checked)},toggleRpcSettings(){this.showRpcSettings=!this.showRpcSettings},saveRpcSettings(){if(this.rpcSettings.host===""){this.rpcSettings.host="127.0.0.1"}if(this.rpcSettings.port===""){this.rpcSettings.port="6800"}t.aria2RpcOption=this.rpcSettings;const e=t.aria2RpcOptionProfiles.find(e=>e.name===t.aria2RpcOptionSelectedProfile);if(e){Object.assign(e,this.rpcSettings);t.aria2RpcOptionProfiles=t.aria2RpcOptionProfiles}this.saveRpcSettingsText="已保存";setTimeout(()=>this.saveRpcSettingsText="保存配置",2e3)},updateProfile(e){t.aria2RpcOption=this.rpcSettings=_.omit(e,"name")}}});Observer.videoChange(async()=>{h.close();h.batch=false;h.downloadSingle=true;const t=dq("#download-video");const e=await u();t.style.display=e?"flex":"none";if(!e){return}h.aid=r.aid;h.cid=r.cid;const a=new s(r.aid);await a.fetchInfo();h.coverUrl=a.coverUrl.replace("http:","https:");l=await d.getAvailableFormats();[c]=l;h.qualityModel={value:c.displayName,items:l.map(t=>t.displayName)};h.formatChange();await h.checkBatch()})}return{widget:{content:`\n`,condition:u,success:f}}}})(); +onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.html"] = `

下载视频

单个视频
批量导出
警告: 过大的视频大小会在直接下载时占用大量内存, 并可能导致浏览器标签页崩溃. 请考虑降低清晰度或使用导出选项.
预计大小: {{displaySize}}
格式
清晰度
弹幕
ffmpeg支持

直接下载

{{speed}}
{{progressPercent}}%

选集

{{selectedEpisodeCount}}/{{episodeList.length}}

导出

{{showRpcSettings ? '取消' : 'aria2 RPC'}}

aria2 RPC

配置

主机
端口
密钥
限速
默认路径
路径
最终路径: {{rpcSettings.baseDir + rpcSettings.dir}}
方法
开始下载
{{saveRpcSettingsText}}
`; +onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.js"] = (()=>{return(t,e)=>{const{getFriendlyTitle:a}=e.import("title");const{VideoInfo:s,DanmakuInfo:i}=e.import("video-info");const{DownloadVideoPackage:n}=e.import("download-video-package");class o{async getDashUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&fnver=0&fnval=16`}else{return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&otype=json`}}}class r extends o{async getDashUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&qn=${t}&otype=json&fourk=1&fnval=16`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&otype=json&fourk=1&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=&otype=json`}}}class l extends o{constructor(t){super();this.ep=t}async getDashUrl(t){if(t){return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16`}else{return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&ep_id=${this.ep}`}else{return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&ep_id=${this.ep}`}}}const c={entity:new o,aid:"",cid:""};let d=[];let p=null;class h{constructor(t,e,a){this.quality=t;this.internalName=e;this.displayName=a}async downloadInfo(t=false){const e=new u(this);await e.fetchVideoInfo(t);return e}static parseFormats(t){const e=t.accept_quality;const a=t.accept_format.split(",");const s=t.accept_description;const i=e.map((t,e)=>{return new h(t,a[e],s[e])});return i}static async getAvailableDashFormats(){const t=await c.entity.getDashUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}return h.parseFormats(e.data||e.result||e)}static async getAvailableFormats(){const t=await c.entity.getUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}const a=e.data||e.result||e;return h.parseFormats(a)}}class u{constructor(t,e){this.fragmentSplitFactor=6*2;this.workingXhr=null;this.progressMap=new Map;this.danmakuOption="无";this.ffmpegOption="无";this.format=t;this.fragments=e||[];this.videoSpeed=new f(this)}get totalSize(){return this.fragments.map(t=>t.size).reduce((t,e)=>t+e)}async fetchVideoInfo(t=false){if(!t){const t=await c.entity.getUrl(this.format.quality);const e=await Ajax.getTextWithCredentials(t);const a=JSON.parse(e.replace(/http:/g,"https:"));const s=a.data||a.result||a;if(s.quality!==this.format.quality){throw new Error("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const i=s.durl;this.fragments=i.map(t=>{return{length:t.length,size:t.size,url:t.url,backupUrls:t.backup_url}})}else{const{dashToFragment:t,getDashInfo:a}=await e.importAsync("video-dash");const s=await a(await c.entity.getDashUrl(this.format.quality),this.format.quality);const i=s.videoDashes.sort(ascendingSort(t=>t.bandWidth))[0];const n=s.audioDashes.sort(ascendingSort(t=>t.bandWidth))[0];this.fragments=[t(i),t(n)]}return this.fragments}updateProgress(){const t=this.progressMap?[...this.progressMap.values()].reduce((t,e)=>t+e,0)/this.totalSize:0;if(t>1||t<0){console.error(`[下载视频] 进度异常: ${t}`,this.progressMap.values())}this.progress&&this.progress(t)}cancelDownload(){this.videoSpeed.stopMeasure();if(this.workingXhr!==null){this.workingXhr.forEach(t=>t.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(t){const e=[];this.workingXhr=[];this.progressMap=new Map;this.updateProgress();let a;if(t.size<=48*1024*1024){a=t.size/this.fragmentSplitFactor}else{a=4*1024*1024}let s=0;const i=t=>[...this.progressMap.keys()].indexOf(t)+1;while(s{const s=new XMLHttpRequest;s.open("GET",t.url);s.responseType="arraybuffer";s.withCredentials=false;s.addEventListener("progress",t=>{console.log(`[下载视频] 视频片段${i(s)}下载进度: ${t.loaded}/${r} bytes loaded, ${o}`);this.progressMap.set(s,t.loaded);this.updateProgress()});s.addEventListener("load",()=>{if((""+s.status)[0]==="2"){console.log(`[下载视频] 视频片段${i(s)}下载完成`);e(s.response)}else{a(`视频片段${i(s)}请求失败, response = ${s.status}`)}});s.addEventListener("abort",()=>a("canceled"));s.addEventListener("error",()=>{console.error(`[下载视频] 视频片段${i(s)}下载失败: ${o}`);this.progressMap.set(s,0);this.updateProgress();s.open("GET",t.url);s.setRequestHeader("Range",o);s.send()});s.setRequestHeader("Range",o);this.progressMap.set(s,0);s.send();this.workingXhr.push(s)}));s=Math.round(s+a)+1}return Promise.all(e)}async copyUrl(){const t=this.fragments.map(t=>t.url).reduce((t,e)=>t+"\r\n"+e);GM.setClipboard(t,"text")}async showUrl(){const t=this.fragments.map(t=>`\n${t.url}\n`).reduce((t,e)=>t+"\r\n"+e);Toast.success(t+`复制全部`,"显示链接");const e=await SpinQuery.select("#copy-link");e.addEventListener("click",async()=>{await this.copyUrl()})}async exportData(t=false){const e=JSON.stringify([{fragments:this.fragments,title:a(),totalSize:this.fragments.map(t=>t.size).reduce((t,e)=>t+e),referer:document.URL.replace(window.location.search,"")}]);if(t){GM.setClipboard(e,"text")}else{const t=new Blob([e],{type:"text/json"});const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.json`,t);i.add(a()+"."+this.danmakuOption.toLowerCase(),s);await i.emit(`${a()}.zip`)}}async exportAria2(s=false){if(s){const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,s);await i.emit();const o=t.aria2RpcOption;const r=this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}const i=[];if(o.secretKey!==""){i.push(`token:${o.secretKey}`)}i.push([t.url]);i.push({referer:document.URL.replace(window.location.search,""),"user-agent":UserAgent,out:`${a()}${s}${this.extension(t)}`,split:this.fragmentSplitFactor,dir:o.baseDir+o.dir||undefined,"max-download-limit":o.maxDownloadLimit||undefined});const n=encodeURIComponent(`${a()}${s}`);return{params:i,id:n}});const{sendRpc:l}=await e.importAsync("aria2-rpc");await l(r)}else{const t=`\n# Generated by Bilibili Evolved Video Export\n# https://github.com/the1812/Bilibili-Evolved/\n${this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}return`\n${t.url}\n referer=${document.URL.replace(window.location.search,"")}\n user-agent=${UserAgent}\n out=${a()}${s}${this.extension(t)}\n split=${this.fragmentSplitFactor}\n`.trim()}).join("\n")}\n`.trim();const e=new Blob([t],{type:"text/plain"});const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.txt`,e);i.add(a()+"."+this.danmakuOption.toLowerCase(),s);await i.emit(`${a()}.zip`)}}extension(t){const e=t||this.fragments[0];const a=[".flv",".mp4",".m4s"].find(t=>e.url.includes(t));if(a){return a}else{console.warn("No extension detected.");return".flv"}}async downloadDanmaku(){if(this.danmakuOption!=="无"){const t=new i(c.cid);await t.fetchInfo();if(this.danmakuOption==="XML"){return t.rawXML}else{const{convertToAss:a}=await e.importAsync("download-danmaku");return a(t.rawXML)}}else{return null}}async download(){const t=[];this.videoSpeed.startMeasure();for(const e of this.fragments){const a=await this.downloadFragment(e);t.push(a)}if(t.length<1){throw new Error("下载失败.")}const e=new n({ffmpeg:this.ffmpegOption});const s=a();t.forEach((a,i)=>{let n;const o=this.fragments[i];if(t.length>1){n=`${s} - ${i+1}${this.extension(o)}`}else{n=`${s}${this.extension(o)}`}e.add(n,new Blob(Array.isArray(a)?a:[a],{type:this.extension(o)===".flv"?"video/x-flv":"video/mp4"}))});const i=await this.downloadDanmaku();e.add(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,i);await e.emit(s+".zip");this.progress&&this.progress(0);this.videoSpeed.stopMeasure()}}class f{constructor(t){this.lastProgress=0;this.measureInterval=1e3;this.workingDownloader=t}startMeasure(){this.intervalTimer=setInterval(()=>{const t=this.workingDownloader.progressMap?[...this.workingDownloader.progressMap.values()].reduce((t,e)=>t+e,0):0;const e=t-this.lastProgress;if(this.speedUpdate!==undefined){this.speedUpdate(formatFileSize(e)+"/s")}this.lastProgress=t},this.measureInterval)}stopMeasure(){clearInterval(this.intervalTimer)}}async function m(){const t=await SpinQuery.select(()=>(unsafeWindow||window).aid);const e=await SpinQuery.select(()=>(unsafeWindow||window).cid);if(!(t&&e)){return false}c.aid=t;c.cid=e;if(document.URL.includes("bangumi")){c.entity=new r}else if(document.URL.includes("cheese")){const t=document.URL.match(/cheese\/play\/ep([\d]+)/);c.entity=new l(t[1])}else{c.entity=new o}try{d=await h.getAvailableFormats()}catch(t){return false}return true}async function w(){p=d[0];e.applyStyle("downloadVideoStyle");dq("#download-video").addEventListener("click",()=>{dq(".download-video").classList.toggle("opened");dq(".gui-settings-mask").click()});dq("#download-video").addEventListener("mouseover",()=>{document.body.insertAdjacentHTML("beforeend",e.import("downloadVideoHtml"));g()},{once:true})}async function g(){let o;const r=new Map;const l=new Vue({el:".download-video",components:{VDropdown:()=>e.importAsync("v-dropdown.vue"),VCheckbox:()=>e.importAsync("v-checkbox.vue"),RpcProfiles:()=>e.importAsync("aria2-rpc-profiles.vue")},data:{downloadSingle:true,coverUrl:EmptyImageUrl,aid:c.aid,cid:c.cid,dashModel:{value:t.downloadVideoFormat,items:["flv","dash"]},qualityModel:{value:p.displayName,items:d.map(t=>t.displayName)},danmakuModel:{value:t.downloadVideoDefaultDanmaku,items:["无","XML","ASS"]},ffmpegModel:{value:t.downloadVideoFfmpegSupport,items:["无","文件列表","文件列表+脚本"]},progressPercent:0,size:"获取大小中",blobUrl:"",episodeList:[],downloading:false,speed:"",batch:false,rpcSettings:t.aria2RpcOption,showRpcSettings:false,busy:false,saveRpcSettingsText:"保存配置",enableDash:t.enableDashDownload,lastDirectDownloadLink:""},computed:{displaySize(){if(typeof this.size==="string"){return this.size}return formatFileSize(this.size)},sizeWarning(){if(typeof this.size==="string"){return false}return this.size>1073741824},selectedEpisodeCount(){return this.episodeList.filter(t=>t.checked).length},dash(){return this.dashModel.value==="dash"}},methods:{close(){this.$el.classList.remove("opened")},danmakuOptionChange(){t.downloadVideoDefaultDanmaku=this.danmakuModel.value},async dashChange(){const t=this.dashModel.value;let e=[];if(t==="flv"){e=await h.getAvailableFormats()}else{e=await h.getAvailableDashFormats()}d=e;[p]=t;this.qualityModel.items=e.map(t=>t.displayName);[this.qualityModel.value]=this.qualityModel.items;await this.formatChange()},async formatChange(){const t=this.getFormat();const e=r.get(t);if(e){this.size=e;return}try{this.size="获取大小中";const e=await t.downloadInfo(this.dash);this.size=e.totalSize;r.set(t,this.size)}catch(t){this.size="获取大小失败"}},getFormat(){const t=d.find(t=>t.displayName===this.qualityModel.value);if(!t){console.error(`No format found. model value = ${this.qualityModel.value}`);return null}return t},async exportData(t){if(this.busy===true){return}try{this.busy=true;if(!this.downloadSingle){await this.exportBatchData(t);return}const e=this.getFormat();const a=await e.downloadInfo(this.dash);a.danmakuOption=this.danmakuModel.value;switch(t){case"copyLink":await a.copyUrl();Toast.success("已复制链接到剪贴板.","下载视频",3e3);break;case"showLink":await a.showUrl();break;case"aria2":await a.exportAria2(false);break;case"aria2RPC":await a.exportAria2(true);break;case"copyVLD":await a.exportData(true);Toast.success("已复制VLD数据到剪贴板.","下载视频",3e3);break;case"exportVLD":await a.exportData(false);break;default:break}}catch(t){logError(t)}finally{this.busy=false}},async exportBatchData(t){const s=this.episodeList;if(s.every(t=>t.checked===false)){Toast.info("请至少选择1集或以上的数量!","批量导出",3e3);return}const o=t=>{const e=s.find(e=>e.cid===t.cid);if(e===undefined){return false}return e.checked};const r=this.getFormat();if(this.danmakuModel.value!=="无"){const t=Toast.info("下载弹幕中...","批量导出");const a=new n;try{if(this.danmakuModel.value==="XML"){for(const t of s.filter(o)){const e=new i(t.cid);await e.fetchInfo();a.add(t.title+".xml",e.rawXML)}}else{const{convertToAss:t}=await e.importAsync("download-danmaku");for(const e of s.filter(o)){const s=new i(e.cid);await s.fetchInfo();a.add(e.title+".ass",await t(s.rawXML))}}await a.emit(this.cid+".danmakus.zip")}catch(t){logError(`弹幕下载失败`)}finally{t.dismiss()}}const l=Toast.info("获取链接中...","批量导出");this.batchExtractor.itemFilter=o;let c;try{switch(t){case"aria2":c=await this.batchExtractor.collectAria2(r,l);await n.single(a(false)+".txt",new Blob([c],{type:"text/plain"}),{ffmpeg:this.ffmpegOption});return;case"aria2RPC":await this.batchExtractor.collectAria2(r,l,true);Toast.success(`成功发送了批量请求.`,"aria2 RPC",3e3);return;case"copyVLD":GM.setClipboard(await this.batchExtractor.collectData(r,l),{mimetype:"text/plain"});Toast.success("已复制批量vld数据到剪贴板.","批量导出",3e3);return;case"exportVLD":c=await this.batchExtractor.collectData(r,l);await n.single(a(false)+".json",new Blob([c],{type:"text/json"}),{ffmpeg:this.ffmpegOption});return;default:return}}catch(t){logError(t)}finally{l.dismiss()}},async checkBatch(){const t=["/www.bilibili.com/bangumi","/www.bilibili.com/video/av"];if(!t.some(t=>document.URL.includes(t))){this.batch=false;this.episodeList=[];return}const{BatchExtractor:a}=await e.importAsync("batch-download");if(await a.test()!==true){this.batch=false;this.episodeList=[];return}this.batchExtractor=new a;this.batch=true;this.episodeList=(await this.batchExtractor.getItemList()).map((t,e)=>{return{aid:t.aid,cid:t.cid,title:t.title,index:e,checked:true}})},cancelDownload(){if(o){o.cancelDownload()}},async startDownload(){const t=this.getFormat();try{this.downloading=true;const e=await t.downloadInfo(this.dash);e.videoSpeed.speedUpdate=(t=>this.speed=t);e.danmakuOption=this.danmakuModel.value;e.ffmpegOption=this.ffmpegModel.value;e.progress=(t=>{this.progressPercent=Math.trunc(t*100)});o=e;await e.download();this.lastDirectDownloadLink=n.lastPackageUrl}catch(t){if(t!=="canceled"){logError(t)}this.progressPercent=0}finally{this.downloading=false;this.speed=""}},selectAllEpisodes(){this.episodeList.forEach(t=>t.checked=true)},unselectAllEpisodes(){this.episodeList.forEach(t=>t.checked=false)},inverseAllEpisodes(){this.episodeList.forEach(t=>t.checked=!t.checked)},toggleRpcSettings(){this.showRpcSettings=!this.showRpcSettings},saveRpcSettings(){if(this.rpcSettings.host===""){this.rpcSettings.host="127.0.0.1"}if(this.rpcSettings.port===""){this.rpcSettings.port="6800"}t.aria2RpcOption=this.rpcSettings;const e=t.aria2RpcOptionProfiles.find(e=>e.name===t.aria2RpcOptionSelectedProfile);if(e){Object.assign(e,this.rpcSettings);t.aria2RpcOptionProfiles=t.aria2RpcOptionProfiles}this.saveRpcSettingsText="已保存";setTimeout(()=>this.saveRpcSettingsText="保存配置",2e3)},updateProfile(e){t.aria2RpcOption=this.rpcSettings=_.omit(e,"name")}}});Observer.videoChange(async()=>{l.close();l.batch=false;l.downloadSingle=true;const t=dq("#download-video");const e=await m();t.style.display=e?"flex":"none";if(!e){return}l.aid=c.aid;l.cid=c.cid;try{const t=new s(c.aid);await t.fetchInfo();l.coverUrl=t.coverUrl.replace("http:","https:")}catch(t){l.coverUrl=EmptyImageUrl}d=await h.getAvailableFormats();[p]=d;l.qualityModel={value:p.displayName,items:d.map(t=>t.displayName)};l.formatChange();await l.checkBatch()})}return{widget:{content:`\n`,condition:m,success:w}}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/dpi-img.vue.min.js"] = (()=>{return(t,s)=>{const e=``;return{export:Object.assign({template:e},{props:["size","src","blur","root","rootMargin","threshold"],data(){return{srcset:null,actualSrc:null}},methods:{calcSrc(){if(!this.src||!this.size){return null}const t=this.src.substring(this.src.lastIndexOf(".")+1);this.srcset=getDpiSourceSet(this.src,this.size,t);this.actualSrc=this.src}},mounted(){const t={root:this.root,rootMargin:this.rootMargin||"200px",threshold:this.threshold};const s=new IntersectionObserver(t=>{t.forEach(t=>{if(t.isIntersecting){this.calcSrc();s.disconnect()}})},t);s.observe(this.$el)},computed:{width(){if(typeof this.size==="object"&&"width"in this.size){return this.size.width}return null},height(){if(typeof this.size==="object"&&"height"in this.size){return this.size.height}return null}}})}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/expand-danmaku.min.js"] = (()=>{return(e,a)=>{if(typeof isEmbeddedPlayer!=="undefined"&&isEmbeddedPlayer()){return}Observer.videoChange(async()=>{const e=await SpinQuery.select(".bui-collapse-wrap");if(e&&e.classList.contains("bui-collapse-wrap-folded")){const e=await SpinQuery.select(".bui-collapse-header");e.click()}})}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/expand-description.min.css"] = `.play-up-info .play-up-self,.video-desc .info{height:auto!important}.play-up-info .play-up-self-btn,.video-desc .btn{display:none!important}`; @@ -1206,7 +1207,7 @@ onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/mi onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/v-dropdown.vue.min.js"] = (()=>{return(o,e)=>{const n=`
{{ value }}
`;e.applyStyleFromText(`.v-dropdown{--background-color:#eee;position:relative;background-color:var(--background-color);cursor:pointer;display:flex;align-items:center;justify-content:space-between;min-width:100px}body.dark .v-dropdown{--background-color:#333}.v-dropdown .dropdown-menu{transform-origin:top;transform:translateY(-4px) translateX(-50%);pointer-events:none;opacity:0;position:absolute;top:calc(100% + 2px);left:50%;background-color:var(--background-color);z-index:1;transition:.2s ease-out;box-shadow:rgba(0,0,0,.2) 0 4px 8px 0}.v-dropdown .dropdown-menu.opened{transform:translateY(0) translateX(-50%);pointer-events:initial;opacity:1}.v-dropdown .dropdown-menu li{padding:4px 16px;white-space:nowrap;min-width:64px;text-align:center;cursor:pointer;color:inherit;background-color:transparent}.v-dropdown .dropdown-menu li:hover{background-color:rgba(0,0,0,.16)}.v-dropdown .mdi-chevron-down{font-size:16pt;line-height:1;transform:rotate(0)}.v-dropdown .dropdown-menu.opened~.mdi-chevron-down{transform:rotate(180deg)}.v-dropdown .selected{user-select:none;padding:4px 8px}.round-corner .v-dropdown,.round-corner .v-dropdown .dropdown-menu,.round-corner .v-dropdown .dropdown-menu li{border-radius:var(--corner-radius)}`,"v-dropdown-style");return{export:Object.assign({template:n},{props:["items","value"],data(){return{dropdownOpen:false}},methods:{toggleDropdown(){this.dropdownOpen=!this.dropdownOpen;if(this.dropdownOpen){document.addEventListener("click",o=>{const e=o.target;if(e===this.$el||this.$el.contains(e)){return}this.dropdownOpen=false},{once:true,capture:true})}},select(o){this.$emit("update:value",o);this.$emit("change",o)}}})}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-card-info.min.js"] = (()=>{return(r,e)=>{}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-card.vue.min.js"] = (()=>{return(e,i)=>{const t=`
{{durationText}}
{{watchlater ? '已添加' : '稍后再看'}}

{{title}}

{{description}}

{{upName}}
{{playCount}}
`;i.applyStyleFromText(`.video-card{display:grid;grid-template-columns:200px 1fr;grid-template-rows:1fr 1fr 1fr;grid-template-areas:"cover title" "cover description" "cover up";height:var(--card-height);width:var(--card-width);color:#000;background-color:#fff;border-radius:16px;box-shadow:0 4px 8px 0 #0001;margin-right:var(--card-margin);margin-bottom:var(--card-margin);position:relative}body.dark .video-card,body.dark .video-card:hover{background-color:#282828;color:#eee}.video-card:hover{color:#000}.video-card.vertical{grid-template-columns:auto auto;grid-template-rows:2fr 1fr 1fr;grid-template-areas:"cover cover" "title title" "up up"}.video-card.vertical .description,.video-card.vertical .topics{display:none}.video-card.vertical .cover-container{border-radius:16px 16px 0 0}.video-card.vertical .title{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;max-height:3em;word-break:break-all;white-space:normal;line-height:1.5;font-size:11pt}.video-card.vertical .up{align-self:start;white-space:nowrap}.video-card.vertical .up .name{text-overflow:ellipsis;overflow:hidden}.video-card.vertical .up:not(.no-face){margin-left:8px;max-width:calc(var(--card-width) - 16px)}.video-card.vertical .up.no-face{margin-top:8px;max-width:calc(var(--card-width) - 24px)}.video-card.vertical .stats{align-self:end;justify-self:start;margin-bottom:8px;margin-right:0}.video-card>*{justify-self:self-start;align-self:center}.video-card:hover .cover{transform:scale(1.05);transition:.1s cubic-bezier(.39,.58,.57,1)}.video-card:hover .duration,.video-card:hover .watchlater{opacity:1}.video-card .duration,.video-card .watchlater{opacity:0}.video-card .cover-container{grid-area:cover;border-radius:16px 0 0 16px;position:relative;width:100%;height:100%;overflow:hidden}.video-card .cover-container .cover{object-fit:cover;width:100%;height:100%}.video-card .cover-container>:not(.cover){position:absolute}.video-card .cover-container .duration,.video-card .cover-container .watchlater{bottom:6px;padding:4px 8px;background-color:#000a;color:#fff;border-radius:14px;height:24px}.video-card .cover-container .duration .mdi,.video-card .cover-container .watchlater .mdi{font-size:12pt;line-height:1;margin-right:4px}.video-card .cover-container .duration{left:6px}.video-card .cover-container .watchlater{right:6px;display:flex;align-items:center;padding-left:4px}.video-card .title{grid-area:title;font-size:12pt;font-weight:700;color:inherit;padding:0 12px;white-space:nowrap;overflow:hidden;justify-self:stretch;text-overflow:ellipsis}.video-card .topics{grid-area:description;display:flex;align-items:center;margin-left:12px}.video-card .topics .topic{color:inherit;padding:6px 8px;background-color:#8882;margin-right:8px;border-radius:14px;white-space:nowrap;max-width:120px;overflow:hidden;text-overflow:ellipsis}.video-card .topics .topic:hover{background-color:#8884;color:var(--theme-color)}.video-card .description{grid-area:description;color:inherit;overflow:hidden;align-self:stretch;justify-self:stretch;margin:0 12px;line-height:1.5;height:3em;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;scrollbar-width:none!important}.video-card .description::-webkit-scrollbar{width:0!important}.video-card .description.single-line{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.video-card .stats,.video-card .up{grid-area:up}.video-card .up{margin-left:12px;display:flex;align-items:center;padding:2px;background-color:#8882;border-radius:14px;color:inherit}.video-card .up.no-face{background-color:transparent;padding:0}.video-card .up.no-face .be-icon{font-size:14pt;opacity:.75}.video-card .up .face{border-radius:50%}.video-card .up .name{margin:0 8px}.video-card .up:not(.no-face):hover{background-color:#8884}.video-card .up:hover .be-icon,.video-card .up:hover .name{color:var(--theme-color)}.video-card .stats{justify-self:self-end;margin-right:12px;display:flex;align-items:center;opacity:.5}.video-card .stats .be-icon{font-size:12pt;margin:0 4px 0 12px}.video-card .stats .be-icon.be-iconfont-favorites-outline{font-size:14pt}.video-card .stats .be-icon.be-iconfont-coin-outline{font-size:11pt}`,"video-card-style");return{export:Object.assign({template:t},{props:["data","orientation"],components:{"dpi-img":()=>i.importAsync("dpi-img.vue"),Icon:()=>i.importAsync("icon.vue")},data(){return{upFaceUrl:"",danmakuCount:"",like:"",coins:"",favorites:"",dynamic:"",topics:[],upID:0,epID:0,...this.data}},computed:{vertical(){return this.orientation==="vertical"}},methods:{async toggleWatchlater(){try{this.watchlater=!this.watchlater;const{toggleWatchlater:e}=await i.importAsync("watchlater-api");e(this.aid.toString(),this.watchlater)}catch(e){this.watchlater=!this.watchlater;Toast.error(e.message,"稍后再看操作失败",3e3)}}}})}}})(); -onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-dash.min.js"] = (()=>{return(t,a)=>{const d=t=>{return{url:t.downloadUrl,backupUrls:t.backupUrls,length:t.duration,size:Math.trunc(t.bandWidth*t.duration/8)}};const r=async(t,a)=>{const d=await Ajax.getJsonWithCredentials(t);const r=d.data||d.result||d;if(d.code!==0||!r.dash){throw new Error("DASH api failed")}const e=r.accept_quality;if(!e.includes(a)){throw new Error("没有找到请求的清晰度")}if(r.quality!==a){throw new Error("无法获取请求的清晰度, 请确认当前账号有相应的权限")}const o=r.accept_description;const n=o[e.indexOf(a)];const c=r.dash.duration;const i=r.dash.video.filter(t=>t.id===a).map(t=>{const d={quality:a,qualityText:n,width:t.width,height:t.height,codecs:t.codecs,codecId:t.codecid,bandWidth:t.bandwidth,frameRate:t.frameRate,backupUrls:t.backupUrl,downloadUrl:t.baseUrl,duration:c};return d});const s=r.dash.audio.map(t=>{return{bandWidth:t.bandwidth,codecs:t.codecs,codecId:t.codecid,backupUrls:t.backupUrl,downloadUrl:t.baseUrl,duration:c}});return{videoDashes:i,audioDashes:s}};return{export:{getDashInfo:r,dashToFragment:d}}}})(); +onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-dash.min.js"] = (()=>{return(t,a)=>{const r=t=>{return{url:t.downloadUrl,backupUrls:t.backupUrls,length:t.duration,size:Math.trunc(t.bandWidth*t.duration/8)}};const e=async(t,a)=>{const r=await Ajax.getJsonWithCredentials(t);const e=r.data||r.result||r;if(r.code!==0||!e.dash){throw new Error("DASH api failed")}const d=e.accept_quality;if(!d.includes(a)){throw new Error("没有找到请求的清晰度")}if(e.quality!==a){throw new Error("无法获取请求的清晰度, 请确认当前账号有相应的权限")}const c=e.accept_description;const o=c[d.indexOf(a)];const s=e.dash.duration;const n=e.dash.video.filter(t=>t.id===a).map(t=>{const r={quality:a,qualityText:o,width:t.width,height:t.height,codecs:t.codecs,codecId:t.codecid,bandWidth:t.bandwidth,frameRate:t.frameRate,backupUrls:(t.backupUrl||t.backup_url||"").replace("http:","https:"),downloadUrl:(t.baseUrl||t.base_url||"").replace("http:","https:"),duration:s};return r});const i=e.dash.audio.map(t=>{return{bandWidth:t.bandwidth,codecs:t.codecs,codecId:t.codecid,backupUrls:(t.backupUrl||t.backup_url||"").replace("http:","https:"),downloadUrl:(t.baseUrl||t.base_url||"").replace("http:","https:"),duration:s}});return{videoDashes:n,audioDashes:i}};return{export:{getDashInfo:e,dashToFragment:r}}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-downloader-fragment.min.js"] = (()=>{return(r,e)=>{}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-info.min.js"] = (()=>{return(t,i)=>{class e{constructor(t){this.aid=t}async fetchInfo(){const t=JSON.parse(await Ajax.getText(`https://api.bilibili.com/x/web-interface/view?aid=${this.aid}`));if(t.code!==0){throw new Error(t.message)}const i=t.data;this.cid=i.cid;this.pageCount=i.videos;this.coverUrl=i.pic;this.tagId=i.tid;this.tagName=i.tname;this.title=i.title;this.description=i.desc;this.up={uid:i.owner.mid,name:i.owner.name,faceUrl:i.owner.face};this.pages=i.pages.map(t=>{return{cid:t.cid,title:t.part,pageNumber:t.page}});return this}async fetchDanmaku(){this.danmaku=new s(this.cid.toString());return this.danmaku.fetchInfo()}}class a{constructor(t,i){this.text=t;this.p=i}}class s{constructor(t){this.cid=t}async fetchInfo(){const t=await Ajax.getText(`https://api.bilibili.com/x/v1/dm/list.so?oid=${this.cid}`);this.rawXML=t;const i=(new DOMParser).parseFromString(t,"application/xml").documentElement;this.xml=i;this.danmakus=[...i.querySelectorAll("d[p]")].map(t=>{return new a(t.innerHTML,t.getAttribute("p"))})}}class n{constructor(t){this.ep=t;this.videos=[]}async fetchInfo(){const t=await Ajax.getText(`https://www.bilibili.com/bangumi/play/ep${this.ep}/`);const i=JSON.parse(t.match(/window\.__INITIAL_STATE__=(.*);\(function\(\){/)[1]);this.title=i.mediaInfo.title;this.cover=i.mediaInfo.cover;this.squareCover=i.mediaInfo.square_cover;this.aid=i.epInfo.aid;this.cid=i.epInfo.cid;this.videos=i.epList.map(async t=>{return{title:t.index_title,aid:t.aid,cid:t.cid,info:await new e(t.aid).fetchInfo()}});return this}}return{export:{VideoInfo:e,BangumiInfo:n,Danmaku:a,DanmakuInfo:s}}}})(); onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-list.vue.min.js"] = (()=>{return(i,a)=>{const t=`
加载中...
空空如也哦 = ̄ω ̄=
`;a.applyStyleFromText(`.minimal-home .video-list .empty,.minimal-home .video-list .loading{height:48px;display:flex;align-items:center;justify-content:center;font-size:11pt;color:#707070}.minimal-home .video-list .empty .mdi,.minimal-home .video-list .loading .mdi{margin-right:8px}body.dark .minimal-home .video-list .empty,body.dark .minimal-home .video-list .loading{color:#eee}.minimal-home .video-list .cards{display:flex;flex-wrap:wrap;align-items:flex-end}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1),.minimal-home .video-list .cards.show-rank .video-card:nth-child(17),.minimal-home .video-list .cards.show-rank .video-card:nth-child(9){margin-top:48px}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1)::before,.minimal-home .video-list .cards.show-rank .video-card:nth-child(17)::before,.minimal-home .video-list .cards.show-rank .video-card:nth-child(9)::before{position:absolute;top:-42px;left:0;font-size:14pt;font-weight:700}.minimal-home .video-list .cards.show-rank .video-card:nth-child(1)::before{content:"昨日"}.minimal-home .video-list .cards.show-rank .video-card:nth-child(9)::before{content:"三日"}.minimal-home .video-list .cards.show-rank .video-card:nth-child(17)::before{content:"一周"}`,"video-list-style");return{export:Object.assign({template:t},{components:{VideoCard:()=>a.importAsync("video-card.vue")},props:["showRank"],data(){return{cards:[],loading:true}},methods:{async getRankList(){const{getTrendingVideos:i}=await a.importAsync("trending-videos");const{getWatchlaterList:t}=await a.importAsync("watchlater-api");const e=await t();const o=async a=>{const t=await i(a,e);this.cards.push(...t)};await Promise.all([1,3,7].map(o))},async getActivityVideos(){const i=await Ajax.getJsonWithCredentials(`https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new?uid=${getUID()}&type_list=8`);const{getWatchlaterList:t}=await a.importAsync("watchlater-api");const e=await t();if(i.code!==0){throw new Error(i.message)}this.cards=i.data.cards.map(i=>{const a=JSON.parse(i.card);const t=_.get(i,"display.topic_info.topic_details",[]).map(i=>{return{id:i.topic_id,name:i.topic_name}});return{id:i.desc.dynamic_id_str,aid:a.aid,title:a.title,upID:i.desc.user_profile.info.uid,upName:i.desc.user_profile.info.uname,upFaceUrl:i.desc.user_profile.info.face,coverUrl:a.pic,description:a.desc,timestamp:i.timestamp,time:new Date(i.timestamp*1e3),topics:t,dynamic:a.dynamic,like:formatCount(i.desc.like),duration:a.duration,durationText:formatDuration(a.duration,0),playCount:formatCount(a.stat.view),danmakuCount:formatCount(a.stat.danmaku),watchlater:e.includes(a.aid)}})}},async mounted(){try{if(this.showRank){await this.getRankList()}else{await this.getActivityVideos()}}catch(i){Toast.error(i.message,this.showRank?"热门视频":"视频动态",3e3)}finally{this.loading=false}}})}}})(); @@ -1690,13 +1691,17 @@ Resource.manifest = { useCache: '启用缓存' } }, + videoDownloadPackage: { + path: 'download-video-package.min.js', + }, downloadVideo: { path: 'download-video.min.js', html: true, style: 'instant', - dependencies: ['title', 'videoInfo'], + dependencies: ['title', 'videoInfo', 'videoDownloadPackage'], displayNames: { 'downloadVideo': '下载视频', + 'videoDownloadPackage': '下载视频打包器', 'batchDownload': '批量下载', 'aria2Rpc': 'aria2 RPC', } diff --git a/min/bundle.json b/min/bundle.json index 15287b077..6ca5d1ac5 100644 --- a/min/bundle.json +++ b/min/bundle.json @@ -44,10 +44,10 @@ "double-click-fullscreen.min.js": "09C035FC7E281ABB042A4200F69757AB093079DBCC9939BE8C53C23EE2EDE41C", "download-audio.min.js": "1F4536DE4FF302BFD026CA17E028AF8EB037FB6D0CB355692549DECAEAE0E8C9", "download-danmaku.min.js": "B254644525ABF064DB770FE986D2AB88063406783EC0538004EFBE0E2B2ACD62", - "download-video-package.min.js": "13FE4E54C20669A6726DAFDA4D9433D8AE495530494E5C8A989FB6EDC28D7F85", + "download-video-package.min.js": "9460B7FC79E4F7A2CCC35F5CC9B01A5D7476BAC9833BAD15917C6806C488E17E", "download-video.min.css": "B570412DD5A8AA9C10020600084CE5EB520E92CDDA03B78450E6480B6A60DB3C", - "download-video.min.html": "4311ABAF2886EB02B1003EA864DD605B113CDB05FF04C3A6882AD931F320D216", - "download-video.min.js": "91131BF338135AC256B8F743A33DE586A87EBC461D436A0E59107607C14424A5", + "download-video.min.html": "08F44F7F2A6C7680D89F229CA9A99FFBCDBE2CC79C912AD6432750FC631E667E", + "download-video.min.js": "6CAC0A0EFB6B3C196027D8338B50334A1BE1D02B953536BC16D7AEE9C507DB4B", "dpi-img.vue.min.js": "3D9D93079365DCABA8DC8970F051AD1A7F25C3EFFF850CD1000C4312E9B910DD", "expand-danmaku.min.js": "B21658C40085AEA8DC49652AE62EB8610BB2EBEAF7A9C9AF69EF3B11E08EEC8D", "expand-description.min.css": "58C7710A50521B80F7D872BDC4C652610D84C4FABC6874BA66DA37B4F8759224", @@ -167,7 +167,7 @@ "v-dropdown.vue.min.js": "D26B4A74515F53A34A3CB0590FC9683476D99FBBBB9647FDFCBF33E265C3F662", "video-card-info.min.js": "13B755C0EE0CA018AE65251E168BAF3395FEA2EB4FAD6949AADD752F61B8819B", "video-card.vue.min.js": "340436CDE3B102F467F671411D4373E0DBF59C5A72867D18BDF45BA6C66156C2", - "video-dash.min.js": "AB61CB28867B75A472CA6450046F6F10862BD1D8D8D206A3AAB143CDCE27B8A0", + "video-dash.min.js": "57EEF7B547E9BD2A84338F89869D4F5DAF8A08C9F372C915E8F68E4A2B51CF43", "video-downloader-fragment.min.js": "13B755C0EE0CA018AE65251E168BAF3395FEA2EB4FAD6949AADD752F61B8819B", "video-info.min.js": "7234A74CA28A772A31E41BBD4925FC2B22C6701419ADFD511402C6A9D6D9E5FA", "video-list.vue.min.js": "BC1DB652C4CD8E98AC620E74ED306AACE0CD99359EE472BFD2A846ADCA37AD0B", diff --git a/min/bundle.zip b/min/bundle.zip index 4237ceaff69fe6f0ecd12e8b49ec919c1d024ab7..d04c62b66001688f58c4b2ba01021988e337e793 100644 GIT binary patch delta 6120 zcmcIodw3L8mhVS^z9hsv`i2l*ohF-fL#IM`NfHVYNg@dH&>(6^NTs`y6sfN2R8blkI1W0yDh#@(s=7&nq z=KF4L-FweH_ndRj`JHon_ok&EytwqVb@6K*-r=AY(^Vxv)Q1no@A~6%991lJIG*IyVE@gZaC*kg$>`irrQNL zFeGzC3g`8g1!YOqJRA$@7hUcw&0i)o`6Nct|T5 zOn|m$DYbL3?NK@k=3I7-&JvI(6BLDDtIzmS_^{l;`{41*uBEFY3SSi#G@n0e$-%Q) zi=Z;Rq$vWgGEIW0@rsXUXV!X|Cb7dC@G{}Z6tkP6dg~Zf4)Z>Zoyjv27v^zaNL?yu zEk4cfH#IT2A?qfgnQ3YYNBHJkmTi|pe3KyYq5Q^to)LMeS!;eynzs>aiu&H z<|2lE4aSP6ATMfZq8BvynH91i`Mk>{uV44;KTEd0V-x0VFb@tidkUL8I2YtJPodzs zUK&qf5LY8z92HOO#6NY4)nAvP}>Tz_C*Hk_J37F{oWvtaE6 zl70O`dLhZNE3rT!;qBM2;ikH~1|G`b;d*|X#OBL}&#)_0S!&RAJ&2H|dPEPuQZrD( zBU^~0vxUrCwIoq2%;A4i2yzXp6x%7NKvfR`)zDYOK zot_j)>?!(dvh~UJ~ zCxkdD%(b>JjA()^A&kNXuVr7$1N+azJCn$CdlL+sOjg^2v9*)QB|9=*J(b++l311D z+Cu`IoJxwIWEvT6mtu>jktq(xlztHmyq$JWwxQQOXF4aLRBx! zi%NP!Jkcqv6bqG*B)eS(`wTKNwx*PH#|J^2<7W_`U5-6AgVa0hJbW>e9K`OWS;T|g z=~-kHTq-AH;qAF(5bF`*5gfJDDK)*IziJ3Jf*INkc~Q>i*BR3r5g;&6>g9wPs$%S$ zxF`TujRAYSoK&04$Nzlh&{jdF4Nvfi14dk38D6Tu>rmim1zB>7U|cOin9Qhr5P@bM z--YSWi&;uwBJFC6uR)Vrd8srn+K)nSz~o~s*J@0=BG#ew>vO8>;P6ePB3Z@^q4Jf2 zGC^Lyq52=tgwtk|JFvodbT(d-2==_pEZ8%fWI9Ek5<4@SJZncwMyiOv&yq8KzOufA zB{7FK1o)pY{_X6S}38-v>wl$Q-wl5&B*_~mZ9~y>ddZ6dH zD+$&vA{sGqhSkb~Fl;dy0bhQWk)DRB&8Xc3t;>uIWqrzIVA8VnMt?p5a ztnsoUtQfkM74Z>Y?Xpna1b-3MqWw3EKCQO6&Tm<3z>2JEN>?-#PtPq7UQFgd+U+FC z8DT@Qy^G0YyS*9ybQ|&HHe=yo+?d=K{+M%bf`&Uu7Q9kJ7A6wqo*FW0X0=&L-rgQD@?SvE_^?`9Yrd&vRvE7y<_l75sn;9(dpAYZUoPPHm}{l`yBN zh$kVIFRP8z;Vrtc25EtFhu)`mbA%z5ZDeJKRkE-8n+UM~JNQ7}cUt)dpMG zCJrO9OoV$|NrgQOhgwPTV$mpJSkobp&ZuO9#(&dHiMr4TOVwx6Bus@s!6VDLQj=^R z5X3i*f=?$_gL09K3+PyRBZ^?1flL!?RpE%%H8*TMvhXr3J<*{>l06EqHG~qhwR0lI z)2(ud7ujeBC${sY1H99zqXwr$l7(RVnMgiK4hPisV31eU($0r^!vxz<9O5z4OziH?<)I-=CuXDPG8{@7 z(U!+GG;8Y+YzfoZm>@2Osq750Jk(1xXR^!&YeS5H@3xf-n-Ko$;^C_zmk>q-6KYqm z;FhKMyo4KHlqi#Gxw!wy*Pc1i z4k5(L25j(ZsT45EsKiKsx(FSU$>U2&ZK;u~6|Omq=v}JlFczU7+-GQ7?9~W8F~j%) zBDQ)f9pX$K_+taW%e2<1V8DVw-~Y^OKm4t$Q-Y{T*Ah`zthk;I_QhM~{Xl-z-j z44aMi5#rZ3g#>!WBLHvNOjBUPb~?s!T!x%o&oiquSY9uYIk7-EBQ?*5RO8(aZHH(UoZC#?!}|E0c!9uoo5>h>?+8lx(RMuXi5E#)N*_hXR$z9} z3Wu@{+IG-#$Dx;vJ`-;I6-|YAcF-}-^*d0@R}j5ZcGB_AMZ3+B8*bf68E0@0fwiw+ zv%pTYK;0qe*-7U(o_PZn?m~$?yJ(@K<*+fh$?>0uVf`*zDz4+ip50b$?=kmkO8MZY_9v(R`onMwxnk5B5Ejbu6fd@;!9AE2}fv zWMk2}?@M-P_gVPzYHN|Xr=_rFDJ(uthr{>>lGE@tocK$52uUyi;mi?SykRez@%hK0 zXfG{s)b_%Py>zzY&%cFBdr`VOdgu-CKWCHO{qFF+_l&g)!hDQu3=lHRM`6)E55lSgboS6KkYSTJMUgu}dYO)d z^9PXE(O<%l9<$$6^q^YLZh+%GbguL34H@8hE+Ypf9;D+PjW58mgD7mx z)(o30hG20Ib;FK>$mfMU@XkS6?Kt@kj5%WV1&a_Jz zzJK<%hFx;yF(g zgXb+e*KtQJv|?}11N%`lz_GXJjn0p@WWx7bkjaRnh$v@%Wsb5A#`b zmd{?oeUAI9jhRYkXt5jCEkwGzdQcqwH^}l^Ybwh^p3RHh?tTIC=&D7RWh|h~)Yool< z^0pzT@zkdIP;eRp?baGtaT@vkYYl8WO~-i#)H+!2r1xDJevOmh(rLrLRG4^%&UdU+ z;UCYS%-?oVXzRovwlMz;9&r4@CwtLDZI3{CFYZ_iu&NicllByaFMxVscMNagQZG_! R&q4Zs&~bxr+-#(}{{_?_csl?9 delta 5703 zcmb7I4RjP$mhPXB^dk@;>6ef|LZ<_v8#)~#0@6(-Cj4kXXh42OVGtI!@OfT|BH(~%-E8!^}v>lEhTob zhei31j0TPO4c+?k#z)Nt18cbk15DdR^ETYH^#NZKNrq)HYY*u2wIvO<+_XFbEhHnS z7jJiZ{j#KLHj#sV-&(A>n$s(}RY5D)G)0^r)&z&WP7!MDE)icq^e4;cB8e^W2SxuP z2YXV4dbvTs$JsNVz(Iq&Nbt>HDEKuTJ486~lVvVc-m#>@#M_oZ#wg6VV;KVrZ(Hn7 zYn)ams%}BTqXe~TM72A>YrI#V49JaAQ04;;!KF2a1i99xaU5q?ajCSxUM2~Rwu+!U z-%+JiJ3XkhB4}YnipGu6;Noq|&|!j$$@552Cs!KL+_hp*Kyi{Y+G(`J@r}Hw*)-rY zGxBENe=x38HC_|_HePL({5BPj)mM`GBsf(;Js4x`ldCb2y{XSn+>b zW)4hy3H?*H{izkN^fMS<=@(l&fb8!P`zfEK^h(>locGN;_Fu82@diWEcl>6t(N07PB?gHE>C|W2pIJt$YEY(D# zQGbwERhtw$Jc0nzQ(PTA_YQ~URINCjiY{?0@L%gC2lVqiy*Hj0Ou*F5x zf&2)W52mr?A!7(ejU_9LN^I{~@>e5n-R>pJj4})#N2VI(So1jYu*o!bH2kiVj53vs zhAXAyS$sXAj10?_xSILRnxG<%YP4u@M2^-Zc&~7B?8P#YWHd^#b&nFj95eNL%O$Olk ze;tyMX|#iH7tMsrZjv-a2TtM`abyf1Mx2_#5gxhX*1h6lAqZ!t5O+_Exj3C9*g1(* z4Hau0YCfl9oM2#NLLyG)hyg*K&ifbf3k0|^B%^=g%v6kU%^hbhobr)}3sh$!N<>a` z^NPqnG&AJ)g)~u?5}3&F>SJW~WSMytj}$Q<_%Xhw2+er7-R_LY?oe2*bJS=U>yl@1 zq|1tEjWe2fU8T9hO0e4LmBITs*_DQ?92f;?^pV1mNJ@d1W`}&i0NXWN2|79xfyM zU#<^fI0$wpgx;dm#!%D>3-fVJjXNkxi>g>oac&c_re_GD z+nu;xRwnZPI>&~-87RZ&(VbvxnM6J!#`QSYgwwcnHR+;%s!31FK> ztZ;i0>9e#-t>!dlgMcZR1^7Ly^^|!RMnpQE7X=RaJUpJ=n>0aEkz80I;s{6PBX}Oo z#qzPl*9#sY8Wn=7kjSZ;9vYLMd|C`4b8%6z;CPTU*ZpTRqBEIrehL|uE_CW5c1`kw zm&&?ocK35)$lgsM@t#65X2y8R?<_-8!$D0%pE~XV)J4s>(JGUyyV{M0Ezs&pOPmo@ zDd7r-=Hi_ktSK;Af*5+N^3^K*f_f}}Y87AY72*X7bAcMQ71=N)3@?cyL-Z1P7evt+ zt+~%~4Qn&jv@RH;ICNM-AmsT-X68R`<8c$b?ju7oSd8CIEAd@AhN*a1+%%bkygQb` z@O)-QN`b_w!yka3d=Ebf4ooEn$}j}tz83Di;-hhQICOj+tTMCUNFav%Ld-e?F@GA# z$h=F;xP4vU4ejEUXw-?|>tOvul)~{JEQ8EQ2v~pBk_)4!6Wd+aV}|mmUDfL>J)zjV z>Ew*j9CkQidUl2lT2ES%VA=*c5agNUXGE{9h_V75GfDPi0inrP>#)z~r3K-7(e6Y% zi#psHQYWf(ecWV9S%_@swJYSGZv8#*<{Ev7!-6gDWCSe!-(D zVF5iI=VonK^0TaM!vzsmedR>-#f!^SK9m^OL0~rd!K!QQ!b^ZhVOIgX9I18i{Twn7 zUYJ8ljDA=zkql!H`c;ukxH5nsDMLwIfcy(~9Rc!o_eCoNGB);!K>C}(DiSZe zS55l&L{=oi6N+!9XOFPopQ63$1Mj;$D_%~o%I>_`OL;vwS+>Hd&J60E#WJ;94g39q zsyb@oN%%_3ny*){^RNKEyD4fL$J_KP4QFTh-)`$H0QxaeyR9?Pu%d8pAKs@!LEbNn zbQIf*7r5+&i^Haaotx0VlRp04RdxKYAdVk zeqM+5SM%3#wLB(UZyijoC*{U4tf?m@Q|s7OlhYZ3>)4G`=STuNUZ=0>(BF4D1+^4V zT%}Yi>%#r`6`){E3WGim#J{^RHUcp(ny>vfen|Z6o5^pWT?Ug^zV`- zO9JQ)6$=4Au{0lW`_Tjp^bt#z71AZGpSrMJk^2<6`>k%>S1h+@2`# zdWcOx0|eD0y7+KFloKNrj4I7bSM=mFOP-V{fSy3CM5TWl$3Ajnh40c7b6WQgTJY|o zRi?eSVAC!-7^b(-q=EOorVNHGL)YKO{UQH-N?~OS?Q84)b!9Nnt}6|13}Z{nQ$MRG zhCoOx66+U0NgKsXr4nn#y`}FgCI+D?#7od`7gm5R?KBBay-#yYX(|-&rr9s=rbVU; z`t!tIl^QYB@(r>gY62|ZPV?dQ-MBQr0S@e@TvB)yF~Fd0gu z&4H#Eu6*P7kiQp=e^Nb_6A@Ya=Oebt|6q5?k=j zVQAS)$D5kkSf2?w9W)JWJ5a{~`%uTLZSed)+8=!TP<+D?Hkgny{3tOj2#av)U7D*q z2d=ZVOMisq4`{jR5D%3f&@$6u1%AnTL4#8t(8nzK;hu&%yfDM}ZFB&Hj^Y_(_tTu- zbq(?PBCMtoEIx_Wg!iLrIgPM!Kg#=|5iaegkD3-XLC%LbUfT@StpD?Ku;oKqk#;MB z`{jC}NatbPpD71Wz?h%I&;yh+o&7n~VsGjArl&zHc|?NzlQbLJaf#*GXHpYW`>7S~ zuw8{=$U8{Kn0hXUxd(CAz<`W{MM85uAA&EpB1@Ki zh!*sG~_6pYL z!dd20a~sVwzp*kM-d&a6pD}HiY41j;Yr}n)0Cu#Y+*`kf>#X1V3OJ7-C0aIvbc9x# z&99|H-`CS~VDfIX=JF9VRN4A+JFX1ufU|fgVG1a<9Q$*4u8tJD&)?Y01XJmMLg7cafBlc?u=ysMqtkiqN4R9bP59kMwA56Y0yjQF4ZqI; z_i^m!41{{tSLVXb<7o4(L2%g?XpZ)IB4uU>sx3 zfY@nTWd8fZ`iR1<({z~GG{y>j##*!E`D5A{lw|c-A%7eSf8h)+*f2pKWx<&<=nu^Y z3MtaEkTSGa>C`%pf~vQbXdNh@atl zpxe6LAn+D}f8=%fjSRxZk5Q$KAqsO;O!>hWs$}{D&FlSLs8g6I)xwDPk;2K((XIf` zY6Sidv^=eFW#>v&lNB&-M?~6DM6YLFU@wG5{AZydo)FC!(b#W)1qBzeDs%va^}nWe Wc;O-%*YPUszDNs_H@wMe-TwexQrlPn diff --git a/min/download-video-package.min.js b/min/download-video-package.min.js index 35a6a8d9e..35d1904eb 100644 --- a/min/download-video-package.min.js +++ b/min/download-video-package.min.js @@ -1 +1 @@ -(()=>{return(e,t)=>{class n{constructor(e={}){this.config=e;this.entries=[]}download(e,t){const n=document.createElement("a");const i=URL.createObjectURL(t);n.setAttribute("href",i);n.setAttribute("download",e);document.body.appendChild(n);n.click();n.remove();URL.revokeObjectURL(i)}add(e,t){if(t===null||t===undefined){return}this.entries.push({name:e,data:t})}async emit(e){if(this.entries.length===0){return}if(!e||this.entries.length===1){e=this.entries[0].name}if(this.entries.length===1){const t=this.entries[0].data;this.download(e,typeof t==="string"?new Blob([t]):t);return}const t=new JSZip;this.entries.forEach(({name:e,data:n})=>{t.file(e,n)});const n=await t.generateAsync({type:"blob"});this.download(e,n)}static async single(e,t){const i=new n;i.add(e,t);await i.emit()}}return{export:{DownloadVideoPackage:n}}}})(); \ No newline at end of file +(()=>{return(e,t)=>{class n{constructor(e={}){this.config=e;this.entries=[]}download(e,t){const i=document.createElement("a");const a=URL.createObjectURL(t);if(n.lastPackageUrl){URL.revokeObjectURL(n.lastPackageUrl)}n.lastPackageUrl=a;i.setAttribute("href",a);i.setAttribute("download",e);document.body.appendChild(i);i.click();i.remove()}add(e,t){if(t===null||t===undefined){return}this.entries.push({name:e,data:t})}async preEmit(){const e=this.entries.filter(e=>[".flv",".mp4",".m4s"].some(t=>e.name.endsWith(t)));if(this.config.ffmpeg!==undefined&&e.length>=2){if(this.config.ffmpeg==="文件列表"||this.config.ffmpeg==="文件列表+脚本"){this.entries.push({name:"ffmpeg-files.txt",data:e.map(e=>`file '${e.name}'`).join("\n")})}if(this.config.ffmpeg==="文件列表+脚本"){const e=`ffmpeg -f concat -i ffmpeg-files.txt -c copy ""`;this.entries.push({name:"ffmpeg.bat",data:e},{name:"ffmpeg.sh",data:e.replace(/"/g,"'")})}}}async blob(){await this.preEmit();if(this.entries.length===0){return null}if(this.entries.length===1){const e=this.entries[0].data;return typeof e==="string"?new Blob([e]):e}const e=new JSZip;this.entries.forEach(({name:t,data:n})=>{e.file(t,n)});return await e.generateAsync({type:"blob"})}async emit(e){if(!e||this.entries.length===1){e=this.entries[0].name}const t=await this.blob();if(!t){return}return this.download(e,t)}static async single(e,t,i={}){const a=new n(i);a.add(e,t);return await a.emit()}}n.lastPackageUrl="";return{export:{DownloadVideoPackage:n}}}})(); \ No newline at end of file diff --git a/min/download-video.min.html b/min/download-video.min.html index 7152231a6..ec27307c1 100644 --- a/min/download-video.min.html +++ b/min/download-video.min.html @@ -1 +1 @@ -

下载视频

单个视频
批量导出
警告: 过大的视频大小会在直接下载时占用大量内存, 并可能导致浏览器标签页崩溃. 请考虑降低清晰度或使用导出选项.
预计大小: {{displaySize}}
格式
清晰度
弹幕

直接下载

{{speed}}
{{progressPercent}}%

选集

{{selectedEpisodeCount}}/{{episodeList.length}}

导出

{{showRpcSettings ? '取消' : 'aria2 RPC'}}

aria2 RPC

配置

主机
端口
密钥
限速
默认路径
路径
最终路径: {{rpcSettings.baseDir + rpcSettings.dir}}
方法
开始下载
{{saveRpcSettingsText}}
\ No newline at end of file +

下载视频

单个视频
批量导出
警告: 过大的视频大小会在直接下载时占用大量内存, 并可能导致浏览器标签页崩溃. 请考虑降低清晰度或使用导出选项.
预计大小: {{displaySize}}
格式
清晰度
弹幕
ffmpeg支持

直接下载

{{speed}}
{{progressPercent}}%

选集

{{selectedEpisodeCount}}/{{episodeList.length}}

导出

{{showRpcSettings ? '取消' : 'aria2 RPC'}}

aria2 RPC

配置

主机
端口
密钥
限速
默认路径
路径
最终路径: {{rpcSettings.baseDir + rpcSettings.dir}}
方法
开始下载
{{saveRpcSettingsText}}
\ No newline at end of file diff --git a/min/download-video.min.js b/min/download-video.min.js index 82e52b031..7bbab8c09 100644 --- a/min/download-video.min.js +++ b/min/download-video.min.js @@ -1 +1 @@ -(()=>{return(t,e)=>{const{getFriendlyTitle:a}=e.import("title");const{VideoInfo:s,DanmakuInfo:i}=e.import("video-info");class o{async getDashUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json&fnver=0&fnval=16`}else{return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&otype=json&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/x/player/playurl?avid=${r.aid}&cid=${r.cid}&otype=json`}}}class n extends o{async getDashUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&qn=${t}&otype=json&fourk=1&fnval=16`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&otype=json&fourk=1&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=${r.aid}&cid=${r.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=${r.aid}&cid=${r.cid}&qn=&otype=json`}}}const r={entity:new o,aid:"",cid:""};let l=[];let c=null;class d{constructor(t,e,a){this.quality=t;this.internalName=e;this.displayName=a}async downloadInfo(t=false){const e=new h(this);await e.fetchVideoInfo(t);return e}static parseFormats(t){const e=t.accept_quality;const a=t.accept_format.split(",");const s=t.accept_description;const i=e.map((t,e)=>{return new d(t,a[e],s[e])});return i}static async getAvailableDashFormats(){const t=await r.entity.getDashUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}return d.parseFormats(e.data||e.result||e)}static async getAvailableFormats(){const t=await r.entity.getUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}const a=e.data||e.result||e;return d.parseFormats(a)}}class h{constructor(t,e){this.fragmentSplitFactor=6*2;this.workingXhr=null;this.progressMap=new Map;this.format=t;this.fragments=e||[];this.videoSpeed=new p(this)}get totalSize(){return this.fragments.map(t=>t.size).reduce((t,e)=>t+e)}async fetchVideoInfo(t=false){if(!t){const t=await r.entity.getUrl(this.format.quality);const e=await Ajax.getTextWithCredentials(t);const a=JSON.parse(e.replace(/http:/g,"https:"));const s=a.data||a.result||a;if(s.quality!==this.format.quality){throw new Error("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const i=s.durl;this.fragments=i.map(t=>{return{length:t.length,size:t.size,url:t.url,backupUrls:t.backup_url}})}else{const{dashToFragment:t,getDashInfo:a}=await e.importAsync("video-dash");const s=await a(await r.entity.getDashUrl(this.format.quality),this.format.quality);const i=s.videoDashes.sort(ascendingSort(t=>t.bandWidth))[0];const o=s.audioDashes.sort(ascendingSort(t=>t.bandWidth))[0];this.fragments=[t(i),t(o)]}return this.fragments}updateProgress(){const t=this.progressMap?[...this.progressMap.values()].reduce((t,e)=>t+e,0)/this.totalSize:0;if(t>1||t<0){console.error(`[下载视频] 进度异常: ${t}`,this.progressMap.values())}this.progress&&this.progress(t)}cancelDownload(){this.videoSpeed.stopMeasure();if(this.workingXhr!==null){this.workingXhr.forEach(t=>t.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(t){const e=[];this.workingXhr=[];this.progressMap=new Map;this.updateProgress();let a;if(t.size<=96*1024*1024){a=t.size/this.fragmentSplitFactor}else{a=16*1024*1024}let s=0;const i=t=>[...this.progressMap.keys()].indexOf(t)+1;while(s{const s=new XMLHttpRequest;s.open("GET",t.url);s.responseType="arraybuffer";s.withCredentials=false;s.addEventListener("progress",t=>{console.log(`[下载视频] 视频片段${i(s)}下载进度: ${t.loaded}/${r} bytes loaded, ${n}`);this.progressMap.set(s,t.loaded);this.updateProgress()});s.addEventListener("load",()=>{if((""+s.status)[0]==="2"){console.log(`[下载视频] 视频片段${i(s)}下载完成`);e(s.response)}else{a(`视频片段${i(s)}请求失败, response = ${s.status}`)}});s.addEventListener("abort",()=>a("canceled"));s.addEventListener("error",()=>{console.error(`[下载视频] 视频片段${i(s)}下载失败: ${n}`);this.progressMap.set(s,0);this.updateProgress();s.open("GET",t.url);s.setRequestHeader("Range",n);s.send()});s.setRequestHeader("Range",n);this.progressMap.set(s,0);s.send();this.workingXhr.push(s)}));s=Math.round(s+a)+1}return Promise.all(e)}async copyUrl(){const t=this.fragments.map(t=>t.url).reduce((t,e)=>t+"\r\n"+e);GM.setClipboard(t,"text")}async showUrl(){const t=this.fragments.map(t=>`\n${t.url}\n`).reduce((t,e)=>t+"\r\n"+e);Toast.success(t+`复制全部`,"显示链接");const e=await SpinQuery.select("#copy-link");e.addEventListener("click",async()=>{await this.copyUrl()})}async exportData(t=false){const s=JSON.stringify([{fragments:this.fragments,title:a(),totalSize:this.fragments.map(t=>t.size).reduce((t,e)=>t+e),referer:document.URL.replace(window.location.search,"")}]);if(t){GM.setClipboard(s,"text")}else{const t=new Blob([s],{type:"text/json"});const i=await this.downloadDanmaku();const{DownloadVideoPackage:o}=await e.importAsync("download-video-package");const n=new o;n.add(`${a()}.json`,t);n.add(a()+"."+this.danmakuOption.toLowerCase(),i);await n.emit(`${a()}.zip`)}}async exportAria2(s=false){if(s){const s=await this.downloadDanmaku();if(s!==null){const{DownloadVideoPackage:t}=await e.importAsync("download-video-package");t.single(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,s)}const i=t.aria2RpcOption;const o=this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}const o=[];if(i.secretKey!==""){o.push(`token:${i.secretKey}`)}o.push([t.url]);o.push({referer:document.URL.replace(window.location.search,""),"user-agent":UserAgent,out:`${a()}${s}${this.extension(t)}`,split:this.fragmentSplitFactor,dir:i.baseDir+i.dir||undefined,"max-download-limit":i.maxDownloadLimit||undefined});const n=encodeURIComponent(`${a()}${s}`);return{params:o,id:n}});const{sendRpc:n}=await e.importAsync("aria2-rpc");await n(o)}else{const t=`\n# Generated by Bilibili Evolved Video Export\n# https://github.com/the1812/Bilibili-Evolved/\n${this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}return`\n${t.url}\n referer=${document.URL.replace(window.location.search,"")}\n user-agent=${UserAgent}\n out=${a()}${s}${this.extension(t)}\n split=${this.fragmentSplitFactor}\n`.trim()}).join("\n")}\n`.trim();const s=new Blob([t],{type:"text/plain"});const i=await this.downloadDanmaku();const{DownloadVideoPackage:o}=await e.importAsync("download-video-package");const n=new o;n.add(`${a()}.txt`,s);n.add(a()+"."+this.danmakuOption.toLowerCase(),i);await n.emit(`${a()}.zip`)}}extension(t){const e=t||this.fragments[0];const a=[".flv",".mp4",".m4s"].find(t=>e.url.includes(t));if(a){return a}else{console.warn("No extension detected.");return".flv"}}makeBlob(t,e){return new Blob(Array.isArray(t)?t:[t],{type:this.extension(e)===".flv"?"video/x-flv":"video/mp4"})}cleanUpOldBlobUrl(){const t=dq("a#video-complete").getAttribute("href");if(t&&!dq(`.link[href="${t}"]`)){URL.revokeObjectURL(t)}dqa(".toast-card-header").filter(t=>t.innerText.includes("下载视频")).forEach(t=>t.querySelector(".toast-card-dismiss").click())}async downloadDanmaku(){if(this.danmakuOption!=="无"){const t=new i(r.cid);await t.fetchInfo();if(this.danmakuOption==="XML"){return t.rawXML}else{const{convertToAss:a}=await e.importAsync("download-danmaku");return a(t.rawXML)}}else{return null}}async downloadSingle(t){const e=await this.downloadDanmaku();const[s]=t;if(e===null){const t=this.makeBlob(s);const e=a()+this.extension();return{blob:t,filename:e}}else{const t=new JSZip;t.file(a()+this.extension(),this.makeBlob(s));t.file(a()+"."+this.danmakuOption.toLowerCase(),e);const i=await t.generateAsync({type:"blob"});const o=a()+".zip";return{blob:i,filename:o}}}async downloadMultiple(t){const e=new JSZip;const s=a();if(t.length>1){t.forEach((t,a)=>{const i=this.fragments[a];e.file(`${s} - ${a+1}${this.extension(i)}`,this.makeBlob(t,i))})}else{const[a]=t;e.file(`${s}${this.extension()}`,this.makeBlob(a))}const i=await this.downloadDanmaku();if(i!==null){e.file(a()+"."+this.danmakuOption.toLowerCase(),i)}const o=await e.generateAsync({type:"blob"});const n=s+".zip";return{blob:o,filename:n}}async download(){const t=[];this.videoSpeed.startMeasure();for(const e of this.fragments){const a=await this.downloadFragment(e);t.push(a)}if(t.length<1){throw new Error("下载失败.")}let{blob:e,filename:a}=await(async()=>{if(t.length===1){return await this.downloadSingle(t)}else{return await this.downloadMultiple(t)}})();this.cleanUpOldBlobUrl();const s=URL.createObjectURL(e);this.progress&&this.progress(0);this.videoSpeed.stopMeasure();return{url:s,filename:a}}}class p{constructor(t){this.lastProgress=0;this.measureInterval=1e3;this.workingDownloader=t}startMeasure(){this.intervalTimer=setInterval(()=>{const t=this.workingDownloader.progressMap?[...this.workingDownloader.progressMap.values()].reduce((t,e)=>t+e,0):0;const e=t-this.lastProgress;if(this.speedUpdate!==undefined){this.speedUpdate(formatFileSize(e)+"/s")}this.lastProgress=t},this.measureInterval)}stopMeasure(){clearInterval(this.intervalTimer)}}async function u(){const t=await SpinQuery.select(()=>(unsafeWindow||window).aid);const e=await SpinQuery.select(()=>(unsafeWindow||window).cid);if(!(t&&e)){return false}r.aid=t;r.cid=e;if(document.URL.indexOf("bangumi")!==-1){r.entity=new n}else{r.entity=new o}try{l=await d.getAvailableFormats()}catch(t){return false}return true}async function f(){c=l[0];e.applyStyle("downloadVideoStyle");dq("#download-video").addEventListener("click",()=>{dq(".download-video").classList.toggle("opened");dq(".gui-settings-mask").click()});dq("#download-video").addEventListener("mouseover",()=>{document.body.insertAdjacentHTML("beforeend",e.import("downloadVideoHtml"));w()},{once:true})}async function w(){let o;const n=new Map;const h=new Vue({el:".download-video",components:{VDropdown:()=>e.importAsync("v-dropdown.vue"),VCheckbox:()=>e.importAsync("v-checkbox.vue"),RpcProfiles:()=>e.importAsync("aria2-rpc-profiles.vue")},data:{downloadSingle:true,coverUrl:EmptyImageUrl,aid:r.aid,cid:r.cid,dashModel:{value:t.downloadVideoFormat,items:["flv","dash"]},qualityModel:{value:c.displayName,items:l.map(t=>t.displayName)},danmakuModel:{value:t.downloadVideoDefaultDanmaku,items:["无","XML","ASS"]},progressPercent:0,size:"获取大小中",blobUrl:"",episodeList:[],downloading:false,speed:"",batch:false,rpcSettings:t.aria2RpcOption,showRpcSettings:false,busy:false,saveRpcSettingsText:"保存配置",enableDash:t.enableDashDownload},computed:{displaySize(){if(typeof this.size==="string"){return this.size}return formatFileSize(this.size)},sizeWarning(){if(typeof this.size==="string"){return false}return this.size>1073741824},selectedEpisodeCount(){return this.episodeList.filter(t=>t.checked).length},dash(){return this.dashModel.value==="dash"}},methods:{close(){this.$el.classList.remove("opened")},danmakuOptionChange(){t.downloadVideoDefaultDanmaku=this.danmakuModel.value},async dashChange(){const t=this.dashModel.value;let e=[];if(t==="flv"){e=await d.getAvailableFormats()}else{e=await d.getAvailableDashFormats()}l=e;[c]=t;this.qualityModel.items=e.map(t=>t.displayName);[this.qualityModel.value]=this.qualityModel.items;await this.formatChange()},async formatChange(){const t=this.getFormat();const e=n.get(t);if(e){this.size=e;return}try{this.size="获取大小中";const e=await t.downloadInfo(this.dash);this.size=e.totalSize;n.set(t,this.size)}catch(t){this.size="获取大小失败"}},getFormat(){const t=l.find(t=>t.displayName===this.qualityModel.value);if(!t){console.error(`No format found. model value = ${this.qualityModel.value}`);return null}return t},async exportData(t){if(this.busy===true){return}try{this.busy=true;if(!this.downloadSingle){await this.exportBatchData(t);return}const e=this.getFormat();const a=await e.downloadInfo(this.dash);a.danmakuOption=this.danmakuModel.value;switch(t){case"copyLink":await a.copyUrl();Toast.success("已复制链接到剪贴板.","下载视频",3e3);break;case"showLink":await a.showUrl();break;case"aria2":await a.exportAria2(false);break;case"aria2RPC":await a.exportAria2(true);break;case"copyVLD":await a.exportData(true);Toast.success("已复制VLD数据到剪贴板.","下载视频",3e3);break;case"exportVLD":await a.exportData(false);break;default:break}}catch(t){logError(t)}finally{this.busy=false}},async exportBatchData(t){const s=this.episodeList;if(s.every(t=>t.checked===false)){Toast.info("请至少选择1集或以上的数量!","批量导出",3e3);return}const o=t=>{const e=s.find(e=>e.cid===t.cid);if(e===undefined){return false}return e.checked};const n=this.getFormat();const{DownloadVideoPackage:r}=await e.importAsync("download-video-package");if(this.danmakuModel.value!=="无"){const t=Toast.info("下载弹幕中...","批量导出");const a=new r;try{if(this.danmakuModel.value==="XML"){for(const t of s.filter(o)){const e=new i(t.cid);await e.fetchInfo();a.add(t.title+".xml",e.rawXML)}}else{const{convertToAss:t}=await e.importAsync("download-danmaku");for(const e of s.filter(o)){const s=new i(e.cid);await s.fetchInfo();a.add(e.title+".ass",await t(s.rawXML))}}await a.emit(this.cid+".danmakus.zip")}catch(t){logError(`弹幕下载失败`)}finally{t.dismiss()}}const l=Toast.info("获取链接中...","批量导出");this.batchExtractor.itemFilter=o;let c;try{switch(t){case"aria2":c=await this.batchExtractor.collectAria2(n,l);await r.single(a(false)+".txt",new Blob([c],{type:"text/plain"}));return;case"aria2RPC":await this.batchExtractor.collectAria2(n,l,true);Toast.success(`成功发送了批量请求.`,"aria2 RPC",3e3);return;case"copyVLD":GM.setClipboard(await this.batchExtractor.collectData(n,l),{mimetype:"text/plain"});Toast.success("已复制批量vld数据到剪贴板.","批量导出",3e3);return;case"exportVLD":c=await this.batchExtractor.collectData(n,l);await r.single(a(false)+".json",new Blob([c],{type:"text/json"}));return;default:return}}catch(t){logError(t)}finally{l.dismiss()}},async checkBatch(){const t=["/www.bilibili.com/bangumi","/www.bilibili.com/video/av"];if(!t.some(t=>document.URL.includes(t))){this.batch=false;this.episodeList=[];return}const{BatchExtractor:a}=await e.importAsync("batch-download");if(await a.test()!==true){this.batch=false;this.episodeList=[];return}this.batchExtractor=new a;this.batch=true;this.episodeList=(await this.batchExtractor.getItemList()).map((t,e)=>{return{aid:t.aid,cid:t.cid,title:t.title,index:e,checked:true}})},cancelDownload(){if(o){o.cancelDownload()}},async startDownload(){const t=this.getFormat();try{this.downloading=true;const e=await t.downloadInfo(this.dash);e.videoSpeed.speedUpdate=(t=>this.speed=t);e.danmakuOption=this.danmakuModel.value;e.progress=(t=>{this.progressPercent=Math.trunc(t*100)});o=e;const a=await e.download();const s=document.getElementById("video-complete");s.setAttribute("href",a.url);s.setAttribute("download",a.filename);s.click();Toast.success(`下载完成: ${a.filename} 再次保存`,"下载视频")}catch(t){if(t!=="canceled"){logError(t)}this.progressPercent=0}finally{this.downloading=false;this.speed=""}},selectAllEpisodes(){this.episodeList.forEach(t=>t.checked=true)},unselectAllEpisodes(){this.episodeList.forEach(t=>t.checked=false)},inverseAllEpisodes(){this.episodeList.forEach(t=>t.checked=!t.checked)},toggleRpcSettings(){this.showRpcSettings=!this.showRpcSettings},saveRpcSettings(){if(this.rpcSettings.host===""){this.rpcSettings.host="127.0.0.1"}if(this.rpcSettings.port===""){this.rpcSettings.port="6800"}t.aria2RpcOption=this.rpcSettings;const e=t.aria2RpcOptionProfiles.find(e=>e.name===t.aria2RpcOptionSelectedProfile);if(e){Object.assign(e,this.rpcSettings);t.aria2RpcOptionProfiles=t.aria2RpcOptionProfiles}this.saveRpcSettingsText="已保存";setTimeout(()=>this.saveRpcSettingsText="保存配置",2e3)},updateProfile(e){t.aria2RpcOption=this.rpcSettings=_.omit(e,"name")}}});Observer.videoChange(async()=>{h.close();h.batch=false;h.downloadSingle=true;const t=dq("#download-video");const e=await u();t.style.display=e?"flex":"none";if(!e){return}h.aid=r.aid;h.cid=r.cid;const a=new s(r.aid);await a.fetchInfo();h.coverUrl=a.coverUrl.replace("http:","https:");l=await d.getAvailableFormats();[c]=l;h.qualityModel={value:c.displayName,items:l.map(t=>t.displayName)};h.formatChange();await h.checkBatch()})}return{widget:{content:`\n`,condition:u,success:f}}}})(); \ No newline at end of file +(()=>{return(t,e)=>{const{getFriendlyTitle:a}=e.import("title");const{VideoInfo:s,DanmakuInfo:i}=e.import("video-info");const{DownloadVideoPackage:n}=e.import("download-video-package");class o{async getDashUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&fnver=0&fnval=16`}else{return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/x/player/playurl?avid=${c.aid}&cid=${c.cid}&otype=json`}}}class r extends o{async getDashUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&qn=${t}&otype=json&fourk=1&fnval=16`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=56995872&cid=99547543&otype=json&fourk=1&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pgc/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json`}else{return`https://api.bilibili.com/pgc/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=&otype=json`}}}class l extends o{constructor(t){super();this.ep=t}async getDashUrl(t){if(t){return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16`}else{return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16`}}async getUrl(t){if(t){return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&qn=${t}&otype=json&ep_id=${this.ep}`}else{return`https://api.bilibili.com/pugv/player/web/playurl?avid=${c.aid}&cid=${c.cid}&otype=json&ep_id=${this.ep}`}}}const c={entity:new o,aid:"",cid:""};let d=[];let p=null;class h{constructor(t,e,a){this.quality=t;this.internalName=e;this.displayName=a}async downloadInfo(t=false){const e=new u(this);await e.fetchVideoInfo(t);return e}static parseFormats(t){const e=t.accept_quality;const a=t.accept_format.split(",");const s=t.accept_description;const i=e.map((t,e)=>{return new h(t,a[e],s[e])});return i}static async getAvailableDashFormats(){const t=await c.entity.getDashUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}return h.parseFormats(e.data||e.result||e)}static async getAvailableFormats(){const t=await c.entity.getUrl();const e=await Ajax.getJsonWithCredentials(t);if(e.code!==0){throw new Error("获取清晰度信息失败.")}const a=e.data||e.result||e;return h.parseFormats(a)}}class u{constructor(t,e){this.fragmentSplitFactor=6*2;this.workingXhr=null;this.progressMap=new Map;this.danmakuOption="无";this.ffmpegOption="无";this.format=t;this.fragments=e||[];this.videoSpeed=new f(this)}get totalSize(){return this.fragments.map(t=>t.size).reduce((t,e)=>t+e)}async fetchVideoInfo(t=false){if(!t){const t=await c.entity.getUrl(this.format.quality);const e=await Ajax.getTextWithCredentials(t);const a=JSON.parse(e.replace(/http:/g,"https:"));const s=a.data||a.result||a;if(s.quality!==this.format.quality){throw new Error("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const i=s.durl;this.fragments=i.map(t=>{return{length:t.length,size:t.size,url:t.url,backupUrls:t.backup_url}})}else{const{dashToFragment:t,getDashInfo:a}=await e.importAsync("video-dash");const s=await a(await c.entity.getDashUrl(this.format.quality),this.format.quality);const i=s.videoDashes.sort(ascendingSort(t=>t.bandWidth))[0];const n=s.audioDashes.sort(ascendingSort(t=>t.bandWidth))[0];this.fragments=[t(i),t(n)]}return this.fragments}updateProgress(){const t=this.progressMap?[...this.progressMap.values()].reduce((t,e)=>t+e,0)/this.totalSize:0;if(t>1||t<0){console.error(`[下载视频] 进度异常: ${t}`,this.progressMap.values())}this.progress&&this.progress(t)}cancelDownload(){this.videoSpeed.stopMeasure();if(this.workingXhr!==null){this.workingXhr.forEach(t=>t.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(t){const e=[];this.workingXhr=[];this.progressMap=new Map;this.updateProgress();let a;if(t.size<=48*1024*1024){a=t.size/this.fragmentSplitFactor}else{a=4*1024*1024}let s=0;const i=t=>[...this.progressMap.keys()].indexOf(t)+1;while(s{const s=new XMLHttpRequest;s.open("GET",t.url);s.responseType="arraybuffer";s.withCredentials=false;s.addEventListener("progress",t=>{console.log(`[下载视频] 视频片段${i(s)}下载进度: ${t.loaded}/${r} bytes loaded, ${o}`);this.progressMap.set(s,t.loaded);this.updateProgress()});s.addEventListener("load",()=>{if((""+s.status)[0]==="2"){console.log(`[下载视频] 视频片段${i(s)}下载完成`);e(s.response)}else{a(`视频片段${i(s)}请求失败, response = ${s.status}`)}});s.addEventListener("abort",()=>a("canceled"));s.addEventListener("error",()=>{console.error(`[下载视频] 视频片段${i(s)}下载失败: ${o}`);this.progressMap.set(s,0);this.updateProgress();s.open("GET",t.url);s.setRequestHeader("Range",o);s.send()});s.setRequestHeader("Range",o);this.progressMap.set(s,0);s.send();this.workingXhr.push(s)}));s=Math.round(s+a)+1}return Promise.all(e)}async copyUrl(){const t=this.fragments.map(t=>t.url).reduce((t,e)=>t+"\r\n"+e);GM.setClipboard(t,"text")}async showUrl(){const t=this.fragments.map(t=>`\n${t.url}\n`).reduce((t,e)=>t+"\r\n"+e);Toast.success(t+`复制全部`,"显示链接");const e=await SpinQuery.select("#copy-link");e.addEventListener("click",async()=>{await this.copyUrl()})}async exportData(t=false){const e=JSON.stringify([{fragments:this.fragments,title:a(),totalSize:this.fragments.map(t=>t.size).reduce((t,e)=>t+e),referer:document.URL.replace(window.location.search,"")}]);if(t){GM.setClipboard(e,"text")}else{const t=new Blob([e],{type:"text/json"});const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.json`,t);i.add(a()+"."+this.danmakuOption.toLowerCase(),s);await i.emit(`${a()}.zip`)}}async exportAria2(s=false){if(s){const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,s);await i.emit();const o=t.aria2RpcOption;const r=this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}const i=[];if(o.secretKey!==""){i.push(`token:${o.secretKey}`)}i.push([t.url]);i.push({referer:document.URL.replace(window.location.search,""),"user-agent":UserAgent,out:`${a()}${s}${this.extension(t)}`,split:this.fragmentSplitFactor,dir:o.baseDir+o.dir||undefined,"max-download-limit":o.maxDownloadLimit||undefined});const n=encodeURIComponent(`${a()}${s}`);return{params:i,id:n}});const{sendRpc:l}=await e.importAsync("aria2-rpc");await l(r)}else{const t=`\n# Generated by Bilibili Evolved Video Export\n# https://github.com/the1812/Bilibili-Evolved/\n${this.fragments.map((t,e)=>{let s="";if(this.fragments.length>1){s=" - "+(e+1)}return`\n${t.url}\n referer=${document.URL.replace(window.location.search,"")}\n user-agent=${UserAgent}\n out=${a()}${s}${this.extension(t)}\n split=${this.fragmentSplitFactor}\n`.trim()}).join("\n")}\n`.trim();const e=new Blob([t],{type:"text/plain"});const s=await this.downloadDanmaku();const i=new n({ffmpeg:this.ffmpegOption});i.add(`${a()}.txt`,e);i.add(a()+"."+this.danmakuOption.toLowerCase(),s);await i.emit(`${a()}.zip`)}}extension(t){const e=t||this.fragments[0];const a=[".flv",".mp4",".m4s"].find(t=>e.url.includes(t));if(a){return a}else{console.warn("No extension detected.");return".flv"}}async downloadDanmaku(){if(this.danmakuOption!=="无"){const t=new i(c.cid);await t.fetchInfo();if(this.danmakuOption==="XML"){return t.rawXML}else{const{convertToAss:a}=await e.importAsync("download-danmaku");return a(t.rawXML)}}else{return null}}async download(){const t=[];this.videoSpeed.startMeasure();for(const e of this.fragments){const a=await this.downloadFragment(e);t.push(a)}if(t.length<1){throw new Error("下载失败.")}const e=new n({ffmpeg:this.ffmpegOption});const s=a();t.forEach((a,i)=>{let n;const o=this.fragments[i];if(t.length>1){n=`${s} - ${i+1}${this.extension(o)}`}else{n=`${s}${this.extension(o)}`}e.add(n,new Blob(Array.isArray(a)?a:[a],{type:this.extension(o)===".flv"?"video/x-flv":"video/mp4"}))});const i=await this.downloadDanmaku();e.add(`${a()}.${this.danmakuOption==="ASS"?"ass":"xml"}`,i);await e.emit(s+".zip");this.progress&&this.progress(0);this.videoSpeed.stopMeasure()}}class f{constructor(t){this.lastProgress=0;this.measureInterval=1e3;this.workingDownloader=t}startMeasure(){this.intervalTimer=setInterval(()=>{const t=this.workingDownloader.progressMap?[...this.workingDownloader.progressMap.values()].reduce((t,e)=>t+e,0):0;const e=t-this.lastProgress;if(this.speedUpdate!==undefined){this.speedUpdate(formatFileSize(e)+"/s")}this.lastProgress=t},this.measureInterval)}stopMeasure(){clearInterval(this.intervalTimer)}}async function m(){const t=await SpinQuery.select(()=>(unsafeWindow||window).aid);const e=await SpinQuery.select(()=>(unsafeWindow||window).cid);if(!(t&&e)){return false}c.aid=t;c.cid=e;if(document.URL.includes("bangumi")){c.entity=new r}else if(document.URL.includes("cheese")){const t=document.URL.match(/cheese\/play\/ep([\d]+)/);c.entity=new l(t[1])}else{c.entity=new o}try{d=await h.getAvailableFormats()}catch(t){return false}return true}async function w(){p=d[0];e.applyStyle("downloadVideoStyle");dq("#download-video").addEventListener("click",()=>{dq(".download-video").classList.toggle("opened");dq(".gui-settings-mask").click()});dq("#download-video").addEventListener("mouseover",()=>{document.body.insertAdjacentHTML("beforeend",e.import("downloadVideoHtml"));g()},{once:true})}async function g(){let o;const r=new Map;const l=new Vue({el:".download-video",components:{VDropdown:()=>e.importAsync("v-dropdown.vue"),VCheckbox:()=>e.importAsync("v-checkbox.vue"),RpcProfiles:()=>e.importAsync("aria2-rpc-profiles.vue")},data:{downloadSingle:true,coverUrl:EmptyImageUrl,aid:c.aid,cid:c.cid,dashModel:{value:t.downloadVideoFormat,items:["flv","dash"]},qualityModel:{value:p.displayName,items:d.map(t=>t.displayName)},danmakuModel:{value:t.downloadVideoDefaultDanmaku,items:["无","XML","ASS"]},ffmpegModel:{value:t.downloadVideoFfmpegSupport,items:["无","文件列表","文件列表+脚本"]},progressPercent:0,size:"获取大小中",blobUrl:"",episodeList:[],downloading:false,speed:"",batch:false,rpcSettings:t.aria2RpcOption,showRpcSettings:false,busy:false,saveRpcSettingsText:"保存配置",enableDash:t.enableDashDownload,lastDirectDownloadLink:""},computed:{displaySize(){if(typeof this.size==="string"){return this.size}return formatFileSize(this.size)},sizeWarning(){if(typeof this.size==="string"){return false}return this.size>1073741824},selectedEpisodeCount(){return this.episodeList.filter(t=>t.checked).length},dash(){return this.dashModel.value==="dash"}},methods:{close(){this.$el.classList.remove("opened")},danmakuOptionChange(){t.downloadVideoDefaultDanmaku=this.danmakuModel.value},async dashChange(){const t=this.dashModel.value;let e=[];if(t==="flv"){e=await h.getAvailableFormats()}else{e=await h.getAvailableDashFormats()}d=e;[p]=t;this.qualityModel.items=e.map(t=>t.displayName);[this.qualityModel.value]=this.qualityModel.items;await this.formatChange()},async formatChange(){const t=this.getFormat();const e=r.get(t);if(e){this.size=e;return}try{this.size="获取大小中";const e=await t.downloadInfo(this.dash);this.size=e.totalSize;r.set(t,this.size)}catch(t){this.size="获取大小失败"}},getFormat(){const t=d.find(t=>t.displayName===this.qualityModel.value);if(!t){console.error(`No format found. model value = ${this.qualityModel.value}`);return null}return t},async exportData(t){if(this.busy===true){return}try{this.busy=true;if(!this.downloadSingle){await this.exportBatchData(t);return}const e=this.getFormat();const a=await e.downloadInfo(this.dash);a.danmakuOption=this.danmakuModel.value;switch(t){case"copyLink":await a.copyUrl();Toast.success("已复制链接到剪贴板.","下载视频",3e3);break;case"showLink":await a.showUrl();break;case"aria2":await a.exportAria2(false);break;case"aria2RPC":await a.exportAria2(true);break;case"copyVLD":await a.exportData(true);Toast.success("已复制VLD数据到剪贴板.","下载视频",3e3);break;case"exportVLD":await a.exportData(false);break;default:break}}catch(t){logError(t)}finally{this.busy=false}},async exportBatchData(t){const s=this.episodeList;if(s.every(t=>t.checked===false)){Toast.info("请至少选择1集或以上的数量!","批量导出",3e3);return}const o=t=>{const e=s.find(e=>e.cid===t.cid);if(e===undefined){return false}return e.checked};const r=this.getFormat();if(this.danmakuModel.value!=="无"){const t=Toast.info("下载弹幕中...","批量导出");const a=new n;try{if(this.danmakuModel.value==="XML"){for(const t of s.filter(o)){const e=new i(t.cid);await e.fetchInfo();a.add(t.title+".xml",e.rawXML)}}else{const{convertToAss:t}=await e.importAsync("download-danmaku");for(const e of s.filter(o)){const s=new i(e.cid);await s.fetchInfo();a.add(e.title+".ass",await t(s.rawXML))}}await a.emit(this.cid+".danmakus.zip")}catch(t){logError(`弹幕下载失败`)}finally{t.dismiss()}}const l=Toast.info("获取链接中...","批量导出");this.batchExtractor.itemFilter=o;let c;try{switch(t){case"aria2":c=await this.batchExtractor.collectAria2(r,l);await n.single(a(false)+".txt",new Blob([c],{type:"text/plain"}),{ffmpeg:this.ffmpegOption});return;case"aria2RPC":await this.batchExtractor.collectAria2(r,l,true);Toast.success(`成功发送了批量请求.`,"aria2 RPC",3e3);return;case"copyVLD":GM.setClipboard(await this.batchExtractor.collectData(r,l),{mimetype:"text/plain"});Toast.success("已复制批量vld数据到剪贴板.","批量导出",3e3);return;case"exportVLD":c=await this.batchExtractor.collectData(r,l);await n.single(a(false)+".json",new Blob([c],{type:"text/json"}),{ffmpeg:this.ffmpegOption});return;default:return}}catch(t){logError(t)}finally{l.dismiss()}},async checkBatch(){const t=["/www.bilibili.com/bangumi","/www.bilibili.com/video/av"];if(!t.some(t=>document.URL.includes(t))){this.batch=false;this.episodeList=[];return}const{BatchExtractor:a}=await e.importAsync("batch-download");if(await a.test()!==true){this.batch=false;this.episodeList=[];return}this.batchExtractor=new a;this.batch=true;this.episodeList=(await this.batchExtractor.getItemList()).map((t,e)=>{return{aid:t.aid,cid:t.cid,title:t.title,index:e,checked:true}})},cancelDownload(){if(o){o.cancelDownload()}},async startDownload(){const t=this.getFormat();try{this.downloading=true;const e=await t.downloadInfo(this.dash);e.videoSpeed.speedUpdate=(t=>this.speed=t);e.danmakuOption=this.danmakuModel.value;e.ffmpegOption=this.ffmpegModel.value;e.progress=(t=>{this.progressPercent=Math.trunc(t*100)});o=e;await e.download();this.lastDirectDownloadLink=n.lastPackageUrl}catch(t){if(t!=="canceled"){logError(t)}this.progressPercent=0}finally{this.downloading=false;this.speed=""}},selectAllEpisodes(){this.episodeList.forEach(t=>t.checked=true)},unselectAllEpisodes(){this.episodeList.forEach(t=>t.checked=false)},inverseAllEpisodes(){this.episodeList.forEach(t=>t.checked=!t.checked)},toggleRpcSettings(){this.showRpcSettings=!this.showRpcSettings},saveRpcSettings(){if(this.rpcSettings.host===""){this.rpcSettings.host="127.0.0.1"}if(this.rpcSettings.port===""){this.rpcSettings.port="6800"}t.aria2RpcOption=this.rpcSettings;const e=t.aria2RpcOptionProfiles.find(e=>e.name===t.aria2RpcOptionSelectedProfile);if(e){Object.assign(e,this.rpcSettings);t.aria2RpcOptionProfiles=t.aria2RpcOptionProfiles}this.saveRpcSettingsText="已保存";setTimeout(()=>this.saveRpcSettingsText="保存配置",2e3)},updateProfile(e){t.aria2RpcOption=this.rpcSettings=_.omit(e,"name")}}});Observer.videoChange(async()=>{l.close();l.batch=false;l.downloadSingle=true;const t=dq("#download-video");const e=await m();t.style.display=e?"flex":"none";if(!e){return}l.aid=c.aid;l.cid=c.cid;try{const t=new s(c.aid);await t.fetchInfo();l.coverUrl=t.coverUrl.replace("http:","https:")}catch(t){l.coverUrl=EmptyImageUrl}d=await h.getAvailableFormats();[p]=d;l.qualityModel={value:p.displayName,items:d.map(t=>t.displayName)};l.formatChange();await l.checkBatch()})}return{widget:{content:`\n`,condition:m,success:w}}}})(); \ No newline at end of file diff --git a/min/video-dash.min.js b/min/video-dash.min.js index 9ab3d33fa..e915c8551 100644 --- a/min/video-dash.min.js +++ b/min/video-dash.min.js @@ -1 +1 @@ -(()=>{return(t,a)=>{const d=t=>{return{url:t.downloadUrl,backupUrls:t.backupUrls,length:t.duration,size:Math.trunc(t.bandWidth*t.duration/8)}};const r=async(t,a)=>{const d=await Ajax.getJsonWithCredentials(t);const r=d.data||d.result||d;if(d.code!==0||!r.dash){throw new Error("DASH api failed")}const e=r.accept_quality;if(!e.includes(a)){throw new Error("没有找到请求的清晰度")}if(r.quality!==a){throw new Error("无法获取请求的清晰度, 请确认当前账号有相应的权限")}const o=r.accept_description;const n=o[e.indexOf(a)];const c=r.dash.duration;const i=r.dash.video.filter(t=>t.id===a).map(t=>{const d={quality:a,qualityText:n,width:t.width,height:t.height,codecs:t.codecs,codecId:t.codecid,bandWidth:t.bandwidth,frameRate:t.frameRate,backupUrls:t.backupUrl,downloadUrl:t.baseUrl,duration:c};return d});const s=r.dash.audio.map(t=>{return{bandWidth:t.bandwidth,codecs:t.codecs,codecId:t.codecid,backupUrls:t.backupUrl,downloadUrl:t.baseUrl,duration:c}});return{videoDashes:i,audioDashes:s}};return{export:{getDashInfo:r,dashToFragment:d}}}})(); \ No newline at end of file +(()=>{return(t,a)=>{const r=t=>{return{url:t.downloadUrl,backupUrls:t.backupUrls,length:t.duration,size:Math.trunc(t.bandWidth*t.duration/8)}};const e=async(t,a)=>{const r=await Ajax.getJsonWithCredentials(t);const e=r.data||r.result||r;if(r.code!==0||!e.dash){throw new Error("DASH api failed")}const d=e.accept_quality;if(!d.includes(a)){throw new Error("没有找到请求的清晰度")}if(e.quality!==a){throw new Error("无法获取请求的清晰度, 请确认当前账号有相应的权限")}const c=e.accept_description;const o=c[d.indexOf(a)];const s=e.dash.duration;const n=e.dash.video.filter(t=>t.id===a).map(t=>{const r={quality:a,qualityText:o,width:t.width,height:t.height,codecs:t.codecs,codecId:t.codecid,bandWidth:t.bandwidth,frameRate:t.frameRate,backupUrls:(t.backupUrl||t.backup_url||"").replace("http:","https:"),downloadUrl:(t.baseUrl||t.base_url||"").replace("http:","https:"),duration:s};return r});const i=e.dash.audio.map(t=>{return{bandWidth:t.bandwidth,codecs:t.codecs,codecId:t.codecid,backupUrls:(t.backupUrl||t.backup_url||"").replace("http:","https:"),downloadUrl:(t.baseUrl||t.base_url||"").replace("http:","https:"),duration:s}});return{videoDashes:n,audioDashes:i}};return{export:{getDashInfo:e,dashToFragment:r}}}})(); \ No newline at end of file diff --git a/src/client/resource-manifest.js b/src/client/resource-manifest.js index 8e6cabe8d..537ba817c 100644 --- a/src/client/resource-manifest.js +++ b/src/client/resource-manifest.js @@ -286,13 +286,17 @@ Resource.manifest = { useCache: '启用缓存' } }, + videoDownloadPackage: { + path: 'download-video-package.min.js', + }, downloadVideo: { path: 'download-video.min.js', html: true, style: 'instant', - dependencies: ['title', 'videoInfo'], + dependencies: ['title', 'videoInfo', 'videoDownloadPackage'], displayNames: { 'downloadVideo': '下载视频', + 'videoDownloadPackage': '下载视频打包器', 'batchDownload': '批量下载', 'aria2Rpc': 'aria2 RPC', } diff --git a/src/client/settings.js b/src/client/settings.js index 5878ce7ae..e3a0dacfb 100644 --- a/src/client/settings.js +++ b/src/client/settings.js @@ -163,6 +163,7 @@ export const settings = { customNavbarSeasonLogo: false, selectableColumnText: true, downloadVideoFormat: 'flv', + downloadVideoFfmpegSupport: '无', enableDashDownload: false, watchlaterExpireWarnings: true, watchlaterExpireWarningDays: 14, diff --git a/src/video/download-video/download-video-package.ts b/src/video/download-video/download-video-package.ts index d15e164b2..6846517b0 100644 --- a/src/video/download-video/download-video-package.ts +++ b/src/video/download-video/download-video-package.ts @@ -1,49 +1,85 @@ export interface DownloadVideoPackageConfig { - ffmpeg?: boolean + ffmpeg?: FfmpegOption } export class DownloadVideoPackage { - entries: {name: string; data: Blob | string}[] = [] + static lastPackageUrl: string = '' + entries: { name: string; data: Blob | string }[] = [] constructor(private config: DownloadVideoPackageConfig = {}) { } private download(filename: string, blob: Blob) { const a = document.createElement('a') const url = URL.createObjectURL(blob) + if (DownloadVideoPackage.lastPackageUrl) { + URL.revokeObjectURL(DownloadVideoPackage.lastPackageUrl) + } + DownloadVideoPackage.lastPackageUrl = url a.setAttribute('href', url) a.setAttribute('download', filename) document.body.appendChild(a) a.click() a.remove() - URL.revokeObjectURL(url) } add(name: string, data: string | Blob | null | undefined) { if (data === null || data === undefined) { return } - this.entries.push({name, data}) + this.entries.push({ name, data }) } - async emit(filename?: string) { - if (this.entries.length === 0) { - return + private async preEmit() { + const videoFiles = this.entries + .filter(it => ['.flv', '.mp4', '.m4s'] + .some(ext => it.name.endsWith(ext))) + if (this.config.ffmpeg !== undefined && videoFiles.length >= 2) { + if (this.config.ffmpeg === '文件列表' || this.config.ffmpeg === '文件列表+脚本') { + this.entries.push({ + name: 'ffmpeg-files.txt', + data: videoFiles.map(it => `file '${it.name}'`).join('\n'), + }) + } + if (this.config.ffmpeg === '文件列表+脚本') { + const command = `ffmpeg -f concat -i ffmpeg-files.txt -c copy ""` + this.entries.push( + { + name: 'ffmpeg.bat', + data: command, + }, + { + name: 'ffmpeg.sh', + data: command.replace(/"/g, "'"), + } + ) + } } - if (!filename || this.entries.length === 1) { - filename = this.entries[0].name + } + async blob(): Promise { + await this.preEmit() + if (this.entries.length === 0) { + return null } if (this.entries.length === 1) { const data = this.entries[0].data - this.download(filename, typeof data === 'string' ? new Blob([data]) : data) - return + return typeof data === 'string' ? new Blob([data]) : data } const zip = new JSZip() - this.entries.forEach(({name, data}) => { + this.entries.forEach(({ name, data }) => { zip.file(name, data) }) - const blob = await zip.generateAsync({type: 'blob'}) - this.download(filename, blob) + return await zip.generateAsync({ type: 'blob' }) } - static async single(filename: string, data: string | Blob) { - const pack = new DownloadVideoPackage() + async emit(filename?: string) { + if (!filename || this.entries.length === 1) { + filename = this.entries[0].name + } + const blob = await this.blob() + if (!blob) { + return + } + return this.download(filename, blob) + } + static async single(filename: string, data: string | Blob, config: DownloadVideoPackageConfig = {}) { + const pack = new DownloadVideoPackage(config) pack.add(filename, data) - await pack.emit() + return await pack.emit() } } export default { diff --git a/src/video/download-video/download-video.html b/src/video/download-video/download-video.html index 5e72e0ca1..cfc75b376 100644 --- a/src/video/download-video/download-video.html +++ b/src/video/download-video/download-video.html @@ -41,6 +41,11 @@ 弹幕 +
+ ffmpeg支持 + +
diff --git a/src/video/download-video/download-video.ts b/src/video/download-video/download-video.ts index a170e2e0f..3cd5c55ae 100644 --- a/src/video/download-video/download-video.ts +++ b/src/video/download-video/download-video.ts @@ -1,6 +1,7 @@ import { getFriendlyTitle, formatTitle } from '../title' import { VideoInfo, DanmakuInfo } from '../video-info' -import { VideoDownloaderFragment } from './video-downloader-fragment'; +import { VideoDownloaderFragment } from './video-downloader-fragment' +import { DownloadVideoPackage } from './download-video-package' interface PageData { entity: Video @@ -39,6 +40,24 @@ class Bangumi extends Video { } } } +// 课程, 不知道为什么b站给它起名cheese +class Cheese extends Video { + constructor(public ep: number | string) { super() } + async getDashUrl(quality?: number) { + if (quality) { + return `https://api.bilibili.com/pugv/player/web/playurl?avid=${pageData.aid}&cid=${pageData.cid}&qn=${quality}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16` + } else { + return `https://api.bilibili.com/pugv/player/web/playurl?avid=${pageData.aid}&cid=${pageData.cid}&otype=json&ep_id=${this.ep}&fnver=0&fnval=16` + } + } + async getUrl(quality?: number) { + if (quality) { + return `https://api.bilibili.com/pugv/player/web/playurl?avid=${pageData.aid}&cid=${pageData.cid}&qn=${quality}&otype=json&ep_id=${this.ep}` + } else { + return `https://api.bilibili.com/pugv/player/web/playurl?avid=${pageData.aid}&cid=${pageData.cid}&otype=json&ep_id=${this.ep}` + } + } +} const pageData: PageData = { entity: new Video(), @@ -108,7 +127,8 @@ class VideoDownloader { workingXhr: XMLHttpRequest[] | null = null progress: (progress: number) => void progressMap: Map = new Map() - danmakuOption: DanmakuOption + danmakuOption: DanmakuOption = '无' + ffmpegOption: FfmpegOption = '无' videoSpeed: VideoSpeed constructor(format: VideoFormat, fragments?: VideoDownloaderFragment[]) { @@ -167,17 +187,17 @@ class VideoDownloader { } } downloadFragment(fragment: VideoDownloaderFragment) { - const promises: Promise[] = [] + const promises: Promise[] = [] this.workingXhr = [] this.progressMap = new Map() this.updateProgress() // const partialLength = Math.round(fragment.size / this.fragmentSplitFactor) // 按一定大小分段或许对大视频更好 let partialLength: number - if (fragment.size <= 96 * 1024 * 1024) { // 小于等于96MB时, 均分为12段 (this.fragmentSplitFactor) + if (fragment.size <= 48 * 1024 * 1024) { // 小于等于48MB时, 均分为12段 (this.fragmentSplitFactor) partialLength = fragment.size / this.fragmentSplitFactor - } else { // 大于96MB时, 每16MB为一段 - partialLength = 16 * 1024 * 1024 // 16MB + } else { // 大于48MB时, 每4MB为一段 + partialLength = 4 * 1024 * 1024 // 4MB } let startByte = 0 const getPartNumber = (xhr: XMLHttpRequest) => [...this.progressMap.keys()].indexOf(xhr) + 1 @@ -185,7 +205,7 @@ class VideoDownloader { const endByte = Math.min(fragment.size - 1, Math.round(startByte + partialLength)) const range = `bytes=${startByte}-${endByte}` const rangeLength = endByte - startByte + 1 - promises.push(new Promise((resolve, reject) => { + promises.push(new Promise((resolve, reject) => { const xhr = new XMLHttpRequest() xhr.open('GET', fragment.url) xhr.responseType = 'arraybuffer' @@ -262,8 +282,7 @@ class VideoDownloader { } else { const blob = new Blob([data], { type: 'text/json' }) const danmaku = await this.downloadDanmaku() - const { DownloadVideoPackage } = await import('./download-video-package') - const pack = new DownloadVideoPackage() + const pack = new DownloadVideoPackage({ ffmpeg: this.ffmpegOption }) pack.add(`${getFriendlyTitle()}.json`, blob) pack.add(getFriendlyTitle() + '.' + this.danmakuOption.toLowerCase(), danmaku) await pack.emit(`${getFriendlyTitle()}.zip`) @@ -272,13 +291,12 @@ class VideoDownloader { async exportAria2(rpc = false) { if (rpc) { // https://aria2.github.io/manual/en/html/aria2c.html#json-rpc-using-http-get const danmaku = await this.downloadDanmaku() - if (danmaku !== null) { - const { DownloadVideoPackage } = await import('./download-video-package') - DownloadVideoPackage.single( - `${getFriendlyTitle()}.${this.danmakuOption === 'ASS' ? 'ass' : 'xml'}`, - danmaku - ) - } + const pack = new DownloadVideoPackage({ ffmpeg: this.ffmpegOption }) + pack.add( + `${getFriendlyTitle()}.${this.danmakuOption === 'ASS' ? 'ass' : 'xml'}`, + danmaku + ) + await pack.emit() const option = settings.aria2RpcOption const params = this.fragments.map((fragment, index) => { let indexNumber = '' @@ -326,8 +344,7 @@ ${it.url} `.trim() const blob = new Blob([input], { type: 'text/plain' }) const danmaku = await this.downloadDanmaku() - const { DownloadVideoPackage } = await import('./download-video-package') - const pack = new DownloadVideoPackage() + const pack = new DownloadVideoPackage({ ffmpeg: this.ffmpegOption }) pack.add(`${getFriendlyTitle()}.txt`, blob) pack.add(getFriendlyTitle() + '.' + this.danmakuOption.toLowerCase(), danmaku) await pack.emit(`${getFriendlyTitle()}.zip`) @@ -347,20 +364,20 @@ ${it.url} return '.flv' } } - makeBlob(data: any, fragment?: VideoDownloaderFragment) { - return new Blob(Array.isArray(data) ? data : [data], { - type: this.extension(fragment) === '.flv' ? 'video/x-flv' : 'video/mp4' - }) - } - cleanUpOldBlobUrl() { - const oldBlobUrl = dq('a#video-complete')!.getAttribute('href') - if (oldBlobUrl && !dq(`.link[href="${oldBlobUrl}"]`)) { - URL.revokeObjectURL(oldBlobUrl) - } - dqa('.toast-card-header') - .filter((it: HTMLElement) => it.innerText.includes('下载视频')) - .forEach((it: HTMLElement) => (it.querySelector('.toast-card-dismiss') as HTMLElement).click()) - } + // makeBlob(data: any, fragment?: VideoDownloaderFragment) { + // return new Blob(Array.isArray(data) ? data : [data], { + // type: this.extension(fragment) === '.flv' ? 'video/x-flv' : 'video/mp4' + // }) + // } + // cleanUpOldBlobUrl() { + // const oldBlobUrl = dq('a#video-complete')!.getAttribute('href') + // if (oldBlobUrl && !dq(`.link[href="${oldBlobUrl}"]`)) { + // URL.revokeObjectURL(oldBlobUrl) + // } + // dqa('.toast-card-header') + // .filter((it: HTMLElement) => it.innerText.includes('下载视频')) + // .forEach((it: HTMLElement) => (it.querySelector('.toast-card-dismiss') as HTMLElement).click()) + // } async downloadDanmaku() { if (this.danmakuOption !== '无') { const danmakuInfo = new DanmakuInfo(pageData.cid) @@ -375,44 +392,51 @@ ${it.url} return null } } - async downloadSingle(downloadedData: any[]) { - const danmaku = await this.downloadDanmaku() - const [data] = downloadedData - if (danmaku === null) { - const blob = this.makeBlob(data) - const filename = getFriendlyTitle() + this.extension() - return { blob, filename } - } else { - const zip = new JSZip() - zip.file(getFriendlyTitle() + this.extension(), this.makeBlob(data)) - zip.file(getFriendlyTitle() + '.' + this.danmakuOption.toLowerCase(), danmaku) - const blob = await zip.generateAsync({ type: 'blob' }) - const filename = getFriendlyTitle() + '.zip' - return { blob, filename } - } - } - async downloadMultiple(downloadedData: any[]) { - const zip = new JSZip() - const title = getFriendlyTitle() - if (downloadedData.length > 1) { - downloadedData.forEach((data, index) => { - const fragment = this.fragments[index] - zip.file(`${title} - ${index + 1}${this.extension(fragment)}`, this.makeBlob(data, fragment)) - }) - } else { - const [data] = downloadedData - zip.file(`${title}${this.extension()}`, this.makeBlob(data)) - } - const danmaku = await this.downloadDanmaku() - if (danmaku !== null) { - zip.file(getFriendlyTitle() + '.' + this.danmakuOption.toLowerCase(), danmaku) - } - const blob = await zip.generateAsync({ type: 'blob' }) - const filename = title + '.zip' - return { blob, filename } - } + // async downloadSingle(downloadedData: any[]) { + // const danmaku = await this.downloadDanmaku() + // const [data] = downloadedData + // const pack = new DownloadVideoPackage({ ffmpeg: this.ffmpegOption }) + // pack.add(getFriendlyTitle() + this.extension(), this.makeBlob(data)) + // pack.add(getFriendlyTitle() + '.' + this.danmakuOption.toLowerCase(), danmaku) + // return { + // blob: await pack.blob(), + // filename: getFriendlyTitle() + '.zip' + // } + // // if (danmaku === null) { + // // const blob = this.makeBlob(data) + // // const filename = getFriendlyTitle() + this.extension() + // // return { blob, filename } + // // } else { + // // const zip = new JSZip() + // // zip.file(getFriendlyTitle() + this.extension(), this.makeBlob(data)) + // // zip.file(getFriendlyTitle() + '.' + this.danmakuOption.toLowerCase(), danmaku) + // // const blob = await zip.generateAsync({ type: 'blob' }) + // // const filename = getFriendlyTitle() + '.zip' + // // return { blob, filename } + // // } + // } + // async downloadMultiple(downloadedData: any[]) { + // const zip = new JSZip() + // const title = getFriendlyTitle() + // if (downloadedData.length > 1) { + // downloadedData.forEach((data, index) => { + // const fragment = this.fragments[index] + // zip.file(`${title} - ${index + 1}${this.extension(fragment)}`, this.makeBlob(data, fragment)) + // }) + // } else { + // const [data] = downloadedData + // zip.file(`${title}${this.extension()}`, this.makeBlob(data)) + // } + // const danmaku = await this.downloadDanmaku() + // if (danmaku !== null) { + // zip.file(getFriendlyTitle() + '.' + this.danmakuOption.toLowerCase(), danmaku) + // } + // const blob = await zip.generateAsync({ type: 'blob' }) + // const filename = title + '.zip' + // return { blob, filename } + // } async download() { - const downloadedData = [] + const downloadedData: ArrayBuffer[][] = [] this.videoSpeed.startMeasure() for (const fragment of this.fragments) { const data = await this.downloadFragment(fragment) @@ -422,21 +446,41 @@ ${it.url} throw new Error('下载失败.') } - let { blob, filename } = await (async () => { - if (downloadedData.length === 1) { - return await this.downloadSingle(downloadedData) + // let { blob, filename } = await (async () => { + // if (downloadedData.length === 1) { + // return await this.downloadSingle(downloadedData) + // } else { + // return await this.downloadMultiple(downloadedData) + // } + // })() + // this.cleanUpOldBlobUrl() + // const blobUrl = URL.createObjectURL(blob) + const pack = new DownloadVideoPackage({ffmpeg: this.ffmpegOption}) + const title = getFriendlyTitle() + downloadedData.forEach((data, index) => { + let filename: string + const fragment = this.fragments[index] + if (downloadedData.length > 1) { + filename = `${title} - ${index + 1}${this.extension(fragment)}` } else { - return await this.downloadMultiple(downloadedData) + filename = `${title}${this.extension(fragment)}` } - })() - this.cleanUpOldBlobUrl() - const blobUrl = URL.createObjectURL(blob) + pack.add(filename, new Blob(Array.isArray(data) ? data : [data], { + type: this.extension(fragment) === '.flv' ? 'video/x-flv' : 'video/mp4' + })) + }) + const danmaku = await this.downloadDanmaku() + pack.add( + `${getFriendlyTitle()}.${this.danmakuOption === 'ASS' ? 'ass' : 'xml'}`, + danmaku + ) + await pack.emit(title + '.zip') this.progress && this.progress(0) this.videoSpeed.stopMeasure() - return { - url: blobUrl, - filename: filename - } + // return { + // url: blobUrl, + // filename: filename + // } } } class VideoSpeed { @@ -471,8 +515,11 @@ async function loadPageData() { } pageData.aid = aid pageData.cid = cid - if (document.URL.indexOf('bangumi') !== -1) { + if (document.URL.includes('bangumi')) { pageData.entity = new Bangumi() + } else if (document.URL.includes('cheese')) { + const match = document.URL.match(/cheese\/play\/ep([\d]+)/)! + pageData.entity = new Cheese(match[1]) } else { pageData.entity = new Video() } @@ -530,6 +577,10 @@ async function loadPanel() { value: settings.downloadVideoDefaultDanmaku as DanmakuOption, items: ['无', 'XML', 'ASS'] as DanmakuOption[] }, + ffmpegModel: { + value: settings.downloadVideoFfmpegSupport, + items: ['无', '文件列表', '文件列表+脚本'] + }, progressPercent: 0, size: '获取大小中' as number | string, blobUrl: '', @@ -542,6 +593,7 @@ async function loadPanel() { busy: false, saveRpcSettingsText: '保存配置', enableDash: settings.enableDashDownload, + lastDirectDownloadLink: '', }, computed: { displaySize() { @@ -665,7 +717,6 @@ async function loadPanel() { return match.checked } const format = this.getFormat() - const { DownloadVideoPackage } = await import('./download-video-package') if (this.danmakuModel.value !== '无') { const danmakuToast = Toast.info('下载弹幕中...', '批量导出') const pack = new DownloadVideoPackage() @@ -700,7 +751,8 @@ async function loadPanel() { result = await this.batchExtractor.collectAria2(format, toast) await DownloadVideoPackage.single( getFriendlyTitle(false) + '.txt', - new Blob([result], { type: 'text/plain' }) + new Blob([result], { type: 'text/plain' }), + { ffmpeg: this.ffmpegOption } ) return case 'aria2RPC': @@ -715,7 +767,8 @@ async function loadPanel() { result = await this.batchExtractor.collectData(format, toast) await DownloadVideoPackage.single( getFriendlyTitle(false) + '.json', - new Blob([result], { type: 'text/json' }) + new Blob([result], { type: 'text/json' }), + { ffmpeg: this.ffmpegOption } ) return default: @@ -767,16 +820,13 @@ async function loadPanel() { const videoDownloader = await format.downloadInfo(this.dash) videoDownloader.videoSpeed.speedUpdate = speed => this.speed = speed videoDownloader.danmakuOption = this.danmakuModel.value + videoDownloader.ffmpegOption = this.ffmpegModel.value videoDownloader.progress = percent => { this.progressPercent = Math.trunc(percent * 100) } workingDownloader = videoDownloader - const result = await videoDownloader.download() - const completeLink = document.getElementById('video-complete') as HTMLAnchorElement - completeLink.setAttribute('href', result.url) - completeLink.setAttribute('download', result.filename) - completeLink.click() - Toast.success(/*html*/`下载完成: ${result.filename} 再次保存`, '下载视频') + await videoDownloader.download() + this.lastDirectDownloadLink = DownloadVideoPackage.lastPackageUrl } catch (error) { if (error !== 'canceled') { @@ -836,9 +886,13 @@ async function loadPanel() { panel.aid = pageData.aid panel.cid = pageData.cid - const videoInfo = new VideoInfo(pageData.aid) - await videoInfo.fetchInfo() - panel.coverUrl = videoInfo.coverUrl.replace('http:', 'https:') + try { + const videoInfo = new VideoInfo(pageData.aid) + await videoInfo.fetchInfo() + panel.coverUrl = videoInfo.coverUrl.replace('http:', 'https:') + } catch (error) { + panel.coverUrl = EmptyImageUrl + } formats = await VideoFormat.getAvailableFormats(); [selectedFormat] = formats diff --git a/src/video/download-video/video-dash.ts b/src/video/download-video/video-dash.ts index 245b99942..3f9cfc53c 100644 --- a/src/video/download-video/video-dash.ts +++ b/src/video/download-video/video-dash.ts @@ -51,8 +51,8 @@ export const getDashInfo = async (api: string, quality: number) => { codecId: d.codecid, bandWidth: d.bandwidth, frameRate: d.frameRate, - backupUrls: d.backupUrl, - downloadUrl: d.baseUrl, + backupUrls: (d.backupUrl || d.backup_url || '').replace('http:', 'https:'), + downloadUrl: (d.baseUrl || d.base_url || '').replace('http:', 'https:'), duration, } return dash @@ -62,8 +62,8 @@ export const getDashInfo = async (api: string, quality: number) => { bandWidth: d.bandwidth, codecs: d.codecs, codecId: d.codecid, - backupUrls: d.backupUrl, - downloadUrl: d.baseUrl, + backupUrls: (d.backupUrl || d.backup_url || '').replace('http:', 'https:'), + downloadUrl: (d.baseUrl || d.base_url || '').replace('http:', 'https:'), duration, } })