mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Use zip if video is split
This commit is contained in:
parent
65685f5345
commit
f5d7666619
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Bilibili Evolved (Preview)
|
// @name Bilibili Evolved (Preview)
|
||||||
// @version 1.5.15
|
// @version 1.5.16
|
||||||
// @description 增强哔哩哔哩Web端体验.(预览版分支)
|
// @description 增强哔哩哔哩Web端体验.(预览版分支)
|
||||||
// @author Grant Howard, Coulomb-G
|
// @author Grant Howard, Coulomb-G
|
||||||
// @copyright 2018, Grant Howrad (https://github.com/the1812)
|
// @copyright 2018, Grant Howrad (https://github.com/the1812)
|
||||||
@ -17,6 +17,7 @@
|
|||||||
// @grant GM_setValue
|
// @grant GM_setValue
|
||||||
// @grant GM_addValueChangeListener
|
// @grant GM_addValueChangeListener
|
||||||
// @require https://code.jquery.com/jquery-3.2.1.min.js
|
// @require https://code.jquery.com/jquery-3.2.1.min.js
|
||||||
|
// @require https://cdn.bootcss.com/jszip/3.1.5/jszip.min.js
|
||||||
// @icon https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/logo.png
|
// @icon https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/logo.png
|
||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
(self$ =>
|
(self$ =>
|
||||||
@ -60,7 +61,7 @@
|
|||||||
fixFullscreen: false,
|
fixFullscreen: false,
|
||||||
downloadVideo: true,
|
downloadVideo: true,
|
||||||
latestVersionLink: "https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview.user.js",
|
latestVersionLink: "https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview.user.js",
|
||||||
currentVersion: "1.5.15"
|
currentVersion: "1.5.16"
|
||||||
};
|
};
|
||||||
function loadSettings()
|
function loadSettings()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Bilibili Evolved
|
// @name Bilibili Evolved
|
||||||
// @version 1.5.15
|
// @version 1.5.16
|
||||||
// @description 增强哔哩哔哩Web端体验.
|
// @description 增强哔哩哔哩Web端体验.
|
||||||
// @author Grant Howard, Coulomb-G
|
// @author Grant Howard, Coulomb-G
|
||||||
// @copyright 2018, Grant Howrad (https://github.com/the1812)
|
// @copyright 2018, Grant Howrad (https://github.com/the1812)
|
||||||
@ -17,6 +17,7 @@
|
|||||||
// @grant GM_setValue
|
// @grant GM_setValue
|
||||||
// @grant GM_addValueChangeListener
|
// @grant GM_addValueChangeListener
|
||||||
// @require https://code.jquery.com/jquery-3.2.1.min.js
|
// @require https://code.jquery.com/jquery-3.2.1.min.js
|
||||||
|
// @require https://cdn.bootcss.com/jszip/3.1.5/jszip.min.js
|
||||||
// @icon https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/images/logo.png
|
// @icon https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/images/logo.png
|
||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
(self$ =>
|
(self$ =>
|
||||||
@ -60,7 +61,7 @@
|
|||||||
fixFullscreen: false,
|
fixFullscreen: false,
|
||||||
downloadVideo: true,
|
downloadVideo: true,
|
||||||
latestVersionLink: "https://github.com/the1812/Bilibili-Evolved/raw/master/bilibili-evolved.user.js",
|
latestVersionLink: "https://github.com/the1812/Bilibili-Evolved/raw/master/bilibili-evolved.user.js",
|
||||||
currentVersion: "1.5.15"
|
currentVersion: "1.5.16"
|
||||||
};
|
};
|
||||||
function loadSettings()
|
function loadSettings()
|
||||||
{
|
{
|
||||||
|
|||||||
2
min/download-video.min.js
vendored
2
min/download-video.min.js
vendored
@ -1 +1 @@
|
|||||||
(()=>{return(e,t)=>{const s=(unsafeWindow||window).aid;const o=(unsafeWindow||window).cid;if(s===undefined||o===undefined){return}class n{constructor(e,t,s){this.quality=e;this.internalName=t;this.displayName=s}async download(){const e=new r(this);await e.fetchVideoInfo();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,t)=>{const a=`https://api.bilibili.com/x/player/playurl?avid=${s}&cid=${o}&otype=json`;const r=new XMLHttpRequest;r.addEventListener("load",()=>{const t=JSON.parse(r.responseText).data;const s=t.accept_quality;const o=t.accept_format.split(",");const a=t.accept_description;const i=[];while(s.length>0){const e=new n(s.pop(),o.pop(),a.pop());i.push(e)}e(i)});r.addEventListener("error",()=>t(`获取清晰度信息失败.`));r.withCredentials=true;r.open("GET",a);r.send()})}}class a{constructor(e,t,s,o){this.length=e;this.size=t;this.url=s;this.backupUrls=o}}class r{constructor(e,t){this.format=e;this.fragments=t||[];this.progress=null}fetchVideoInfo(){return new Promise((e,t)=>{const n=`https://api.bilibili.com/x/player/playurl?avid=${s}&cid=${o}&qn=${this.format.quality}&otype=json`;const r=new XMLHttpRequest;r.addEventListener("load",()=>{const s=JSON.parse(r.responseText.replace("http:","https:")).data;if(s.quality!==this.format.quality){t("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const o=s.durl;this.fragments=o.map(e=>new a(e.length,e.size,e.url,e.backup_url));if(this.fragments.length>1){t("暂不支持分段视频的下载.")}e(this.fragments)});r.withCredentials=true;r.open("GET",n);r.send()})}download(){return new Promise((e,t)=>{const[s]=this.fragments;const o=new XMLHttpRequest;o.open("GET",s.url);o.responseType="arraybuffer";o.withCredentials=false;o.addEventListener("progress",e=>{this.progress&&this.progress(e.loaded/s.size)});o.addEventListener("load",()=>{if(o.status===200){const t=new Blob([o.response],{type:"video/x-flv"});const n=URL.createObjectURL(t);const a=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","");const r=s.url.indexOf(".flv")!==-1?".flv":".mp4";const i=$("a#video-complete").attr("href");if(i){URL.revokeObjectURL(i)}$("a#video-complete").attr("href",n).attr("download",a+r);this.progress&&this.progress(0);document.getElementById("video-complete").click();e(n)}else{t(`请求失败.`)}});o.addEventListener("error",()=>{t(`下载失败.`)});o.send()})}}return{settingsWidget:{category:"视频与直播",content:t.data.downloadVideoDom.text,success:()=>{n.availableFormats.then(e=>{e.forEach(e=>{async function t(){$(".download-video-panel").removeClass("quality").addClass("progress");await e.download().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});$(".download-video-panel").removeClass("progress").addClass("quality")}$(`<li>${e.displayName}</li>`).on("click",t).prependTo("ol.video-quality")});t.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")})}}}}})();
|
(()=>{return(e,t)=>{const s=(unsafeWindow||window).aid;const o=(unsafeWindow||window).cid;if(s===undefined||o===undefined){return}class a{constructor(e,t,s){this.quality=e;this.internalName=t;this.displayName=s}async download(){const e=new r(this);await e.fetchVideoInfo();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,t)=>{const n=`https://api.bilibili.com/x/player/playurl?avid=${s}&cid=${o}&otype=json`;const r=new XMLHttpRequest;r.addEventListener("load",()=>{const t=JSON.parse(r.responseText).data;const s=t.accept_quality;const o=t.accept_format.split(",");const n=t.accept_description;const i=[];while(s.length>0){const e=new a(s.pop(),o.pop(),n.pop());i.push(e)}e(i)});r.addEventListener("error",()=>t(`获取清晰度信息失败.`));r.withCredentials=true;r.open("GET",n);r.send()})}}class n{constructor(e,t,s,o){this.length=e;this.size=t;this.url=s;this.backupUrls=o}}class r{constructor(e,t){this.format=e;this.fragments=t||[];this.progress=null;this.loaded=0;this.totalSize=null}fetchVideoInfo(){return new Promise((e,t)=>{const a=`https://api.bilibili.com/x/player/playurl?avid=${s}&cid=${o}&qn=${this.format.quality}&otype=json`;const r=new XMLHttpRequest;r.addEventListener("load",()=>{const s=JSON.parse(r.responseText.replace("http:","https:")).data;if(s.quality!==this.format.quality){t("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const o=s.durl;this.fragments=o.map(e=>new n(e.length,e.size,e.url,e.backup_url));e(this.fragments)});r.withCredentials=true;r.open("GET",a);r.send()})}downloadUrl(e){return new Promise((e,t)=>{const s=new XMLHttpRequest;s.open("GET",fragment.url);s.responseType="arraybuffer";s.withCredentials=false;s.addEventListener("progress",e=>{this.progress&&this.progress((this.loaded+e.loaded)/this.totalSize)});s.addEventListener("load",()=>{if(s.status===200){e(s.response)}else{t(`请求失败.`)}});s.addEventListener("error",()=>{t(`下载失败.`)});s.send()})}async download(){const e=[];this.loaded=0;this.totalSize=this.fragments.map(e=>e.size).reduce((e,t)=>e+t);for(const t of this.fragments){const s=await this.downloadUrl(t.url);this.loaded+=t.size;e.push(s)}if(e.length<1){throw new Error("下载失败.")}let t=null;const s=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","");const o=fragment.url.indexOf(".flv")!==-1?".flv":".mp4";if(e.length===1){const[s]=e;t=new Blob([s],{type:"video/x-flv"})}else{const a=new JSZip;e.forEach((e,t)=>{a.file(`${s} - ${t}${o}`,e)});t=await a.generateAsync({type:"blob"})}const a=URL.createObjectURL(t);const n=$("a#video-complete").attr("href");if(n){URL.revokeObjectURL(n)}$("a#video-complete").attr("href",a).attr("download",s+o);this.progress&&this.progress(0);document.getElementById("video-complete").click();return a}}return{settingsWidget:{category:"视频与直播",content:t.data.downloadVideoDom.text,success:()=>{a.availableFormats.then(e=>{e.forEach(e=>{async function t(){$(".download-video-panel").removeClass("quality").addClass("progress");await e.download().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});$(".download-video-panel").removeClass("progress").addClass("quality")}$(`<li>${e.displayName}</li>`).on("click",t).prependTo("ol.video-quality")});t.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")})}}}}})();
|
||||||
@ -1 +1 @@
|
|||||||
1.5.15
|
1.5.16
|
||||||
@ -75,6 +75,8 @@
|
|||||||
this.format = format;
|
this.format = format;
|
||||||
this.fragments = fragments || [];
|
this.fragments = fragments || [];
|
||||||
this.progress = null;
|
this.progress = null;
|
||||||
|
this.loaded = 0;
|
||||||
|
this.totalSize = null;
|
||||||
}
|
}
|
||||||
fetchVideoInfo()
|
fetchVideoInfo()
|
||||||
{
|
{
|
||||||
@ -95,10 +97,10 @@
|
|||||||
it.url,
|
it.url,
|
||||||
it.backup_url
|
it.backup_url
|
||||||
));
|
));
|
||||||
if (this.fragments.length > 1)
|
// if (this.fragments.length > 1)
|
||||||
{
|
// {
|
||||||
reject("暂不支持分段视频的下载.");
|
// reject("暂不支持分段视频的下载.");
|
||||||
}
|
// }
|
||||||
resolve(this.fragments);
|
resolve(this.fragments);
|
||||||
});
|
});
|
||||||
xhr.withCredentials = true;
|
xhr.withCredentials = true;
|
||||||
@ -106,40 +108,23 @@
|
|||||||
xhr.send();
|
xhr.send();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
download()
|
downloadUrl(url)
|
||||||
{
|
{
|
||||||
return new Promise((resolve, reject) =>
|
return new Promise((resolve, reject) =>
|
||||||
{
|
{
|
||||||
const [fragment] = this.fragments;
|
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.open("GET", fragment.url);
|
xhr.open("GET", fragment.url);
|
||||||
xhr.responseType = "arraybuffer";
|
xhr.responseType = "arraybuffer";
|
||||||
xhr.withCredentials = false;
|
xhr.withCredentials = false;
|
||||||
xhr.addEventListener("progress", (e) =>
|
xhr.addEventListener("progress", (e) =>
|
||||||
{
|
{
|
||||||
this.progress && this.progress(e.loaded / fragment.size);
|
this.progress && this.progress((this.loaded + e.loaded) / this.totalSize);
|
||||||
});
|
});
|
||||||
xhr.addEventListener("load", () =>
|
xhr.addEventListener("load", () =>
|
||||||
{
|
{
|
||||||
if (xhr.status === 200)
|
if (xhr.status === 200)
|
||||||
{
|
{
|
||||||
const blob = new Blob([xhr.response], {
|
resolve(xhr.response);
|
||||||
type: "video/x-flv"
|
|
||||||
});
|
|
||||||
const blobUrl = URL.createObjectURL(blob);
|
|
||||||
const title = document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili", "");
|
|
||||||
const extension = fragment.url.indexOf(".flv") !== -1 ? ".flv" : ".mp4";
|
|
||||||
const oldBlobUrl = $("a#video-complete").attr("href");
|
|
||||||
if (oldBlobUrl)
|
|
||||||
{
|
|
||||||
URL.revokeObjectURL(oldBlobUrl);
|
|
||||||
}
|
|
||||||
$("a#video-complete")
|
|
||||||
.attr("href", blobUrl)
|
|
||||||
.attr("download", title + extension);
|
|
||||||
this.progress && this.progress(0);
|
|
||||||
document.getElementById("video-complete").click();
|
|
||||||
resolve(blobUrl);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -153,6 +138,55 @@
|
|||||||
xhr.send();
|
xhr.send();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
async download()
|
||||||
|
{
|
||||||
|
const downloadedData = [];
|
||||||
|
this.loaded = 0;
|
||||||
|
this.totalSize = this.fragments.map(it => it.size).reduce((acc, it) => acc + it);
|
||||||
|
for (const fragment of this.fragments)
|
||||||
|
{
|
||||||
|
const data = await this.downloadUrl(fragment.url);
|
||||||
|
this.loaded += fragment.size;
|
||||||
|
downloadedData.push(data);
|
||||||
|
}
|
||||||
|
if (downloadedData.length < 1)
|
||||||
|
{
|
||||||
|
throw new Error("下载失败.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let blob = null;
|
||||||
|
const title = document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili", "");
|
||||||
|
const extension = fragment.url.indexOf(".flv") !== -1 ? ".flv" : ".mp4";
|
||||||
|
if (downloadedData.length === 1)
|
||||||
|
{
|
||||||
|
const [data] = downloadedData;
|
||||||
|
blob = new Blob([data], {
|
||||||
|
type: "video/x-flv"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const zip = new JSZip();
|
||||||
|
downloadedData.forEach((data, index) =>
|
||||||
|
{
|
||||||
|
zip.file(`${title} - ${index}${extension}`, data);
|
||||||
|
});
|
||||||
|
blob = await zip.generateAsync({ type: "blob" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
|
const oldBlobUrl = $("a#video-complete").attr("href");
|
||||||
|
if (oldBlobUrl)
|
||||||
|
{
|
||||||
|
URL.revokeObjectURL(oldBlobUrl);
|
||||||
|
}
|
||||||
|
$("a#video-complete")
|
||||||
|
.attr("href", blobUrl)
|
||||||
|
.attr("download", title + extension);
|
||||||
|
this.progress && this.progress(0);
|
||||||
|
document.getElementById("video-complete").click();
|
||||||
|
return blobUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
settingsWidget: {
|
settingsWidget: {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user