mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
1 line
2.9 KiB
JavaScript
1 line
2.9 KiB
JavaScript
(()=>{return(e,o)=>{const s=(unsafeWindow||window).aid;const t=(unsafeWindow||window).cid;if(s===undefined||t===undefined){console.error(`unable to get aid or cid. aid=${s}, cid=${t}`)}class r{constructor(e,o,s){this.quality=e;this.internalName=o;this.displayName=s}async download(){const e=new n(this);await e.fetchVideoInfo().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});e.progress=(e=>{$(".download-progress-value").text(`${fixed(e*100)}%`);$(".download-progress-foreground").css("transform",`scaleX(${e})`)});return e.download()}static get availableFormats(){return new Promise((e,o)=>{const a=`https://api.bilibili.com/x/player/playurl?avid=${s}&cid=${t}&otype=json`;downloadText(a,o=>{const s=JSON.parse(o).data;const t=s.accept_quality;const a=s.accept_format.split(",");const n=s.accept_description;const i=[];while(t.length>0){const e=new r(t.pop(),a.pop(),n.pop());i.push(e)}e(i)},e=>o(`获取清晰度信息失败: ${e}`))})}}class a{constructor(e,o,s,t){this.length=e;this.size=o;this.url=s;this.backupUrls=t}}class n{constructor(e,o){this.format=e;this.fragments=o||[];this.progress=null}async fetchVideoInfo(){const e=`https://api.bilibili.com/x/player/playurl?avid=${s}&cid=${t}&qn=${this.format.quality}&otype=json`;downloadText(e,e=>{const o=JSON.parse(e).data;if(o.quality!==this.format.quality){throw new Error("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const s=o.durl;this.fragments=s.map(e=>new a(e.length,e.size,e.url,e.backup_url));if(this.fragments.length>1){throw new Error("暂不支持分段视频的下载.")}Promise.resolve()})}async download(){const[e]=this.fragments;const o=new XMLHttpRequest;o.open("GET",e.url);o.responseType="arraybuffer";o.withCredentials=true;o.addEventListener("progress",o=>{this.progress&&this.progress(o.loaded/e.size)});o.addEventListener("load",()=>{if(o.status===200){const e=new Blob([o.response],{type:"video/x-flv"});const s=URL.createObjectURL(e);open(s);Promise.resolve(s)}else{throw new Error(`请求失败. ${o.status}`)}});o.addEventListener("error",e=>{throw new Error(`下载失败. ${e}`)});o.send()}}return{settingsWidget:{after:()=>$("span.settings-category").filter((e,o)=>o.innerHTML==="视频与直播").parent(),content:o.data.downloadVideoDom.text,success:()=>{r.availableFormats.then(e=>{e.forEach(e=>{async function o(){$(".download-video-panel").removeClass("quality").addClass("progress");await e.download();$(".download-video-panel").removeClass("progress").addClass("quality")}$(`<li>${e.displayName}</li>`).on("click",o).prependTo("ol.video-quality")});o.applyStyle("downloadVideoStyle");$("#download-video").on("click",()=>{$(".download-video-panel").toggleClass("opened")}).parent().removeClass("hidden")});$(".video-error").on("click",()=>{$(".video-error").text("");$(".download-video-panel").removeClass("error").removeClass("progress").addClass("quality")})}}}}})(); |