mirror of
https://github.com/Jerryplusy/rc-plugin.git
synced 2025-10-14 08:09:19 +00:00
✨ feat: 更换哔哩哔哩下载方式:性能、稳定、轻量
This commit is contained in:
parent
e97ff79210
commit
0a0a813514
15
README.md
15
README.md
@ -301,6 +301,21 @@ aiApiKey: '' # 用于识图的api key,kimi接口申请:https://platform.moon
|
|||||||
- Linux教程:https://pwa.sspai.com/post/83345
|
- Linux教程:https://pwa.sspai.com/post/83345
|
||||||
- Windows教程:https://github.com/nilaoda/BBDown/issues/305
|
- Windows教程:https://github.com/nilaoda/BBDown/issues/305
|
||||||
|
|
||||||
|
### 📺 关于使用 哔哩哔哩 下载方式
|
||||||
|
|
||||||
|
- 轻量
|
||||||
|
|
||||||
|
```shell
|
||||||
|
apt install wget
|
||||||
|
apt install axel
|
||||||
|
```
|
||||||
|
|
||||||
|
- 稳定(无须安装任何东西)
|
||||||
|
|
||||||
|
- 性能
|
||||||
|
```shell
|
||||||
|
apt install aria2
|
||||||
|
```
|
||||||
|
|
||||||
## 🤺 R插件交流群
|
## 🤺 R插件交流群
|
||||||
<img src="./img/qq.webp" width="30%" height="30%">
|
<img src="./img/qq.webp" width="30%" height="30%">
|
||||||
|
@ -210,7 +210,7 @@ export class tools extends plugin {
|
|||||||
// 加载 BBDown 的CDN配置
|
// 加载 BBDown 的CDN配置
|
||||||
this.biliCDN = this.toolsConfig.biliCDN;
|
this.biliCDN = this.toolsConfig.biliCDN;
|
||||||
// 加载哔哩哔哩是否使用Aria2
|
// 加载哔哩哔哩是否使用Aria2
|
||||||
this.biliUseAria2 = this.toolsConfig.biliUseAria2;
|
this.biliDownloadMethod = this.toolsConfig.biliDownloadMethod;
|
||||||
// 加载抖音Cookie
|
// 加载抖音Cookie
|
||||||
this.douyinCookie = this.toolsConfig.douyinCookie;
|
this.douyinCookie = this.toolsConfig.douyinCookie;
|
||||||
// 加载抖音是否压缩
|
// 加载抖音是否压缩
|
||||||
@ -629,7 +629,7 @@ export class tools extends plugin {
|
|||||||
// 下载视频
|
// 下载视频
|
||||||
await startBBDown(url, path, {
|
await startBBDown(url, path, {
|
||||||
biliSessData: this.biliSessData,
|
biliSessData: this.biliSessData,
|
||||||
biliUseAria2: this.biliUseAria2,
|
biliUseAria2: this.biliDownloadMethod === 1,
|
||||||
biliCDN: BILI_CDN_SELECT_LIST.find(item => item.value === this.biliCDN)?.sign,
|
biliCDN: BILI_CDN_SELECT_LIST.find(item => item.value === this.biliCDN)?.sign,
|
||||||
});
|
});
|
||||||
// 发送视频
|
// 发送视频
|
||||||
@ -1768,7 +1768,7 @@ export class tools extends plugin {
|
|||||||
}),
|
}),
|
||||||
1000,
|
1000,
|
||||||
),
|
),
|
||||||
this.biliUseAria2,
|
this.biliDownloadMethod,
|
||||||
this.videoDownloadConcurrency
|
this.videoDownloadConcurrency
|
||||||
),
|
),
|
||||||
downloadBFile(
|
downloadBFile(
|
||||||
@ -1781,7 +1781,7 @@ export class tools extends plugin {
|
|||||||
}),
|
}),
|
||||||
1000,
|
1000,
|
||||||
),
|
),
|
||||||
this.biliUseAria2,
|
this.biliDownloadMethod,
|
||||||
this.videoDownloadConcurrency
|
this.videoDownloadConcurrency
|
||||||
),
|
),
|
||||||
]).then(data => {
|
]).then(data => {
|
||||||
|
@ -127,3 +127,9 @@ export const BILI_CDN_SELECT_LIST = Object.freeze([
|
|||||||
{ label: '阿卡迈(海外)', value: 4 , sign: BILI_CDN_TEMPLATE.replace('{}', 'akamai')},
|
{ label: '阿卡迈(海外)', value: 4 , sign: BILI_CDN_TEMPLATE.replace('{}', 'akamai')},
|
||||||
{ label: 'HK-CDN', value: 5, sign: BILI_CDN_TEMPLATE.replace('{}', 'aliov') }
|
{ label: 'HK-CDN', value: 5, sign: BILI_CDN_TEMPLATE.replace('{}', 'aliov') }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
export const BILI_DOWNLOAD_METHOD = Object.freeze([
|
||||||
|
{ label: '稳定(原生)', value: 0 },
|
||||||
|
{ label: '性能(Aria2)', value: 1 },
|
||||||
|
{ label: '轻量(axel/wget)', value: 2 }
|
||||||
|
]);
|
@ -1,7 +1,7 @@
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import model from "./model/index.js";
|
import model from "./model/index.js";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { BILI_CDN_SELECT_LIST } from "./constants/constant.js";
|
import { BILI_CDN_SELECT_LIST, BILI_DOWNLOAD_METHOD } from "./constants/constant.js";
|
||||||
|
|
||||||
const _path = process.cwd() + "/plugins/rconsole-plugin";
|
const _path = process.cwd() + "/plugins/rconsole-plugin";
|
||||||
export function supportGuoba() {
|
export function supportGuoba() {
|
||||||
@ -140,12 +140,14 @@ export function supportGuoba() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: "tools.biliUseAria2",
|
field: "tools.biliDownloadMethod",
|
||||||
label: "使用Aria2下载",
|
label: "bili下载方式",
|
||||||
bottomHelpMessage:
|
bottomHelpMessage:
|
||||||
"【默认不开启】如果不爱折腾就使用默认下载方式,如果喜欢折腾就开启,开启后更加强劲,宽带直接拉满,Debian和Ubuntu用户直接使用命令安装:apt-get install aria2",
|
"哔哩哔哩的下载方式:默认使用原生稳定的下载方式,如果你在乎内存可以使用轻量的wget和axel下载方式,如果在乎性能可以使用Aria2下载",
|
||||||
component: "Switch",
|
component: "Select",
|
||||||
required: false,
|
componentProps: {
|
||||||
|
options: BILI_DOWNLOAD_METHOD,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: "tools.douyinCookie",
|
field: "tools.douyinCookie",
|
||||||
|
@ -2,6 +2,7 @@ import fs from "node:fs";
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import child_process from 'node:child_process'
|
import child_process from 'node:child_process'
|
||||||
import util from "util";
|
import util from "util";
|
||||||
|
import path from "path";
|
||||||
import {
|
import {
|
||||||
BILI_BVID_TO_CID,
|
BILI_BVID_TO_CID,
|
||||||
BILI_DYNAMIC,
|
BILI_DYNAMIC,
|
||||||
@ -11,7 +12,7 @@ import {
|
|||||||
BILI_VIDEO_INFO
|
BILI_VIDEO_INFO
|
||||||
} from "../constants/tools.js";
|
} from "../constants/tools.js";
|
||||||
import { mkdirIfNotExists } from "./file.js";
|
import { mkdirIfNotExists } from "./file.js";
|
||||||
import { spawn } from 'child_process';
|
import { exec, spawn } from 'child_process';
|
||||||
import qrcode from "qrcode"
|
import qrcode from "qrcode"
|
||||||
|
|
||||||
const biliHeaders = {
|
const biliHeaders = {
|
||||||
@ -25,15 +26,21 @@ const biliHeaders = {
|
|||||||
* @param url 下载链接
|
* @param url 下载链接
|
||||||
* @param fullFileName 文件名
|
* @param fullFileName 文件名
|
||||||
* @param progressCallback 下载进度
|
* @param progressCallback 下载进度
|
||||||
* @param isAria2 是否使用aria2
|
* @param biliDownloadMethod 下载方式 {BILI_DOWNLOAD_METHOD}
|
||||||
* @param videoDownloadConcurrency 视频下载并发
|
* @param videoDownloadConcurrency 视频下载并发
|
||||||
* @returns {Promise<any>}
|
* @returns {Promise<any>}
|
||||||
*/
|
*/
|
||||||
export async function downloadBFile(url, fullFileName, progressCallback, isAria2 = false, videoDownloadConcurrency = 1) {
|
export async function downloadBFile(url, fullFileName, progressCallback, biliDownloadMethod = 0, videoDownloadConcurrency = 1) {
|
||||||
if (isAria2) {
|
if (biliDownloadMethod === 0) {
|
||||||
|
// 原生
|
||||||
|
return normalDownloadBFile(url, fullFileName, progressCallback);
|
||||||
|
}
|
||||||
|
if (biliDownloadMethod === 1) {
|
||||||
|
// 性能 Aria2
|
||||||
return aria2DownloadBFile(url, fullFileName, progressCallback, videoDownloadConcurrency);
|
return aria2DownloadBFile(url, fullFileName, progressCallback, videoDownloadConcurrency);
|
||||||
} else {
|
} else {
|
||||||
return normalDownloadBFile(url, fullFileName, progressCallback);
|
// 轻量
|
||||||
|
return axelDownloadBFile(url, fullFileName, progressCallback, videoDownloadConcurrency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +49,7 @@ export async function downloadBFile(url, fullFileName, progressCallback, isAria2
|
|||||||
* @param url
|
* @param url
|
||||||
* @param fullFileName
|
* @param fullFileName
|
||||||
* @param progressCallback
|
* @param progressCallback
|
||||||
* @returns {Promise<any>}
|
* @returns {Promise<{fullFileName: string, totalLen: number}>}
|
||||||
*/
|
*/
|
||||||
async function normalDownloadBFile(url, fullFileName, progressCallback) {
|
async function normalDownloadBFile(url, fullFileName, progressCallback) {
|
||||||
return axios
|
return axios
|
||||||
@ -80,7 +87,7 @@ async function normalDownloadBFile(url, fullFileName, progressCallback) {
|
|||||||
* @param fullFileName
|
* @param fullFileName
|
||||||
* @param progressCallback
|
* @param progressCallback
|
||||||
* @param videoDownloadConcurrency
|
* @param videoDownloadConcurrency
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<{fullFileName: string, totalLen: number}>}
|
||||||
*/
|
*/
|
||||||
async function aria2DownloadBFile(url, fullFileName, progressCallback, videoDownloadConcurrency) {
|
async function aria2DownloadBFile(url, fullFileName, progressCallback, videoDownloadConcurrency) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -131,6 +138,64 @@ async function aria2DownloadBFile(url, fullFileName, progressCallback, videoDown
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 C 语言写的轻量级下载工具 Axel 进行下载
|
||||||
|
* @param url
|
||||||
|
* @param fullFileName
|
||||||
|
* @param progressCallback
|
||||||
|
* @param videoDownloadConcurrency
|
||||||
|
* @returns {Promise<{fullFileName: string, totalLen: number}>}
|
||||||
|
*/
|
||||||
|
async function axelDownloadBFile(url, fullFileName, progressCallback, videoDownloadConcurrency) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// 构建路径
|
||||||
|
fullFileName = path.resolve(fullFileName);
|
||||||
|
|
||||||
|
// 构建 -H 参数
|
||||||
|
const headerParams = Object.entries(biliHeaders).map(
|
||||||
|
([key, value]) => `--header="${ key }: ${ value }"`
|
||||||
|
).join(' ');
|
||||||
|
|
||||||
|
let command = '';
|
||||||
|
let downloadTool = 'wget';
|
||||||
|
if (videoDownloadConcurrency === 1) {
|
||||||
|
// wget 命令
|
||||||
|
command = `${ downloadTool } -O ${ fullFileName } ${ headerParams } '${ url }'`;
|
||||||
|
} else {
|
||||||
|
// AXEL 命令行
|
||||||
|
downloadTool = 'axel';
|
||||||
|
command = `${ downloadTool } -n ${ videoDownloadConcurrency } -o ${ fullFileName } ${ headerParams } '${ url }'`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行命令
|
||||||
|
const axel = exec(command);
|
||||||
|
logger.info(`[R插件][axel/wget] 执行命令:${ downloadTool } 下载方式为:${ downloadTool === 'wget' ? '单线程' : '多线程' }`);
|
||||||
|
|
||||||
|
axel.stdout.on('data', (data) => {
|
||||||
|
const match = data.match(/(\d+)%/);
|
||||||
|
if (match) {
|
||||||
|
const progress = parseInt(match[1], 10) / 100;
|
||||||
|
progressCallback?.(progress);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
axel.stderr.on('data', (data) => {
|
||||||
|
logger.info(`[R插件][${ downloadTool }]: ${ data }`);
|
||||||
|
});
|
||||||
|
|
||||||
|
axel.on('close', (code) => {
|
||||||
|
if (code === 0) {
|
||||||
|
resolve({
|
||||||
|
fullFileName,
|
||||||
|
totalLen: fs.statSync(fullFileName).size,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
reject(new Error(`[R插件][${ downloadTool }] 错误:${ code }`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取下载链接
|
* 获取下载链接
|
||||||
* @param url
|
* @param url
|
||||||
@ -362,7 +427,8 @@ export async function getDynamic(dynamicId, SESSDATA) {
|
|||||||
* refresh_token
|
* refresh_token
|
||||||
* }>}
|
* }>}
|
||||||
*/
|
*/
|
||||||
export async function getScanCodeData(qrcodeSavePath = 'qrcode.png', detectTime = 10, hook = () => {}) {
|
export async function getScanCodeData(qrcodeSavePath = 'qrcode.png', detectTime = 10, hook = () => {
|
||||||
|
}) {
|
||||||
try {
|
try {
|
||||||
const resp = await axios.get(BILI_SCAN_CODE_GENERATE, { ...biliHeaders });
|
const resp = await axios.get(BILI_SCAN_CODE_GENERATE, { ...biliHeaders });
|
||||||
// 保存扫码的地址、扫码登录秘钥
|
// 保存扫码的地址、扫码登录秘钥
|
||||||
|
Loading…
x
Reference in New Issue
Block a user