feat: 更换哔哩哔哩下载方式:性能、稳定、轻量

This commit is contained in:
zhiyu1998 2024-08-10 00:19:13 +08:00
parent e97ff79210
commit 0a0a813514
5 changed files with 112 additions and 23 deletions

View File

@ -301,6 +301,21 @@ aiApiKey: '' # 用于识图的api keykimi接口申请https://platform.moon
- Linux教程https://pwa.sspai.com/post/83345
- Windows教程https://github.com/nilaoda/BBDown/issues/305
### 📺 关于使用 哔哩哔哩 下载方式
- 轻量
```shell
apt install wget
apt install axel
```
- 稳定(无须安装任何东西)
- 性能
```shell
apt install aria2
```
## 🤺 R插件交流群
<img src="./img/qq.webp" width="30%" height="30%">

View File

@ -210,7 +210,7 @@ export class tools extends plugin {
// 加载 BBDown 的CDN配置
this.biliCDN = this.toolsConfig.biliCDN;
// 加载哔哩哔哩是否使用Aria2
this.biliUseAria2 = this.toolsConfig.biliUseAria2;
this.biliDownloadMethod = this.toolsConfig.biliDownloadMethod;
// 加载抖音Cookie
this.douyinCookie = this.toolsConfig.douyinCookie;
// 加载抖音是否压缩
@ -629,7 +629,7 @@ export class tools extends plugin {
// 下载视频
await startBBDown(url, path, {
biliSessData: this.biliSessData,
biliUseAria2: this.biliUseAria2,
biliUseAria2: this.biliDownloadMethod === 1,
biliCDN: BILI_CDN_SELECT_LIST.find(item => item.value === this.biliCDN)?.sign,
});
// 发送视频
@ -1768,7 +1768,7 @@ export class tools extends plugin {
}),
1000,
),
this.biliUseAria2,
this.biliDownloadMethod,
this.videoDownloadConcurrency
),
downloadBFile(
@ -1781,7 +1781,7 @@ export class tools extends plugin {
}),
1000,
),
this.biliUseAria2,
this.biliDownloadMethod,
this.videoDownloadConcurrency
),
]).then(data => {

View File

@ -127,3 +127,9 @@ export const BILI_CDN_SELECT_LIST = Object.freeze([
{ label: '阿卡迈(海外)', value: 4 , sign: BILI_CDN_TEMPLATE.replace('{}', 'akamai')},
{ 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 }
]);

View File

@ -1,7 +1,7 @@
import path from "path";
import model from "./model/index.js";
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";
export function supportGuoba() {
@ -140,12 +140,14 @@ export function supportGuoba() {
}
},
{
field: "tools.biliUseAria2",
label: "使用Aria2下载",
field: "tools.biliDownloadMethod",
label: "bili下载方式",
bottomHelpMessage:
"【默认不开启】如果不爱折腾就使用默认下载方式如果喜欢折腾就开启开启后更加强劲宽带直接拉满Debian和Ubuntu用户直接使用命令安装apt-get install aria2",
component: "Switch",
required: false,
"哔哩哔哩的下载方式默认使用原生稳定的下载方式如果你在乎内存可以使用轻量的wget和axel下载方式如果在乎性能可以使用Aria2下载",
component: "Select",
componentProps: {
options: BILI_DOWNLOAD_METHOD,
}
},
{
field: "tools.douyinCookie",

View File

@ -2,6 +2,7 @@ import fs from "node:fs";
import axios from 'axios'
import child_process from 'node:child_process'
import util from "util";
import path from "path";
import {
BILI_BVID_TO_CID,
BILI_DYNAMIC,
@ -11,7 +12,7 @@ import {
BILI_VIDEO_INFO
} from "../constants/tools.js";
import { mkdirIfNotExists } from "./file.js";
import { spawn } from 'child_process';
import { exec, spawn } from 'child_process';
import qrcode from "qrcode"
const biliHeaders = {
@ -25,15 +26,21 @@ const biliHeaders = {
* @param url 下载链接
* @param fullFileName 文件名
* @param progressCallback 下载进度
* @param isAria2 是否使用aria2
* @param biliDownloadMethod 下载方式 {BILI_DOWNLOAD_METHOD}
* @param videoDownloadConcurrency 视频下载并发
* @returns {Promise<any>}
*/
export async function downloadBFile(url, fullFileName, progressCallback, isAria2 = false, videoDownloadConcurrency = 1) {
if (isAria2) {
export async function downloadBFile(url, fullFileName, progressCallback, biliDownloadMethod = 0, videoDownloadConcurrency = 1) {
if (biliDownloadMethod === 0) {
// 原生
return normalDownloadBFile(url, fullFileName, progressCallback);
}
if (biliDownloadMethod === 1) {
// 性能 Aria2
return aria2DownloadBFile(url, fullFileName, progressCallback, videoDownloadConcurrency);
} 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 fullFileName
* @param progressCallback
* @returns {Promise<any>}
* @returns {Promise<{fullFileName: string, totalLen: number}>}
*/
async function normalDownloadBFile(url, fullFileName, progressCallback) {
return axios
@ -80,7 +87,7 @@ async function normalDownloadBFile(url, fullFileName, progressCallback) {
* @param fullFileName
* @param progressCallback
* @param videoDownloadConcurrency
* @returns {Promise<void>}
* @returns {Promise<{fullFileName: string, totalLen: number}>}
*/
async function aria2DownloadBFile(url, fullFileName, progressCallback, videoDownloadConcurrency) {
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
@ -362,7 +427,8 @@ export async function getDynamic(dynamicId, SESSDATA) {
* refresh_token
* }>}
*/
export async function getScanCodeData(qrcodeSavePath = 'qrcode.png', detectTime = 10, hook = () => {}) {
export async function getScanCodeData(qrcodeSavePath = 'qrcode.png', detectTime = 10, hook = () => {
}) {
try {
const resp = await axios.get(BILI_SCAN_CODE_GENERATE, { ...biliHeaders });
// 保存扫码的地址、扫码登录秘钥