feat: 增加YouTuBe限制解析时长/🎈pref:优化解析成功显示

This commit is contained in:
秋刀鱼 2024-10-17 16:50:53 +08:00
parent 6a463afded
commit 14d8df8532
4 changed files with 78 additions and 11 deletions

View File

@ -101,7 +101,7 @@ import { saveTDL, startTDL } from "../utils/tdl-util.js";
import { genVerifyFp } from "../utils/tiktok.js";
import Translate from "../utils/trans-strategy.js";
import { mid2id } from "../utils/weibo.js";
import { ytDlpGetTilt, ytDlpHelper } from "../utils/yt-dlp-util.js";
import { ytDlpGetTilt, ytDlpHelper, ytDlpGetThumbnail, ytDlpGetDuration } from "../utils/yt-dlp-util.js";
import { textArrayToMakeForward } from "../utils/yunzai-util.js";
import puppeteer from "../../../lib/puppeteer/puppeteer.js";
@ -283,6 +283,8 @@ export class tools extends plugin {
this.biliDownloadMethod = this.toolsConfig.biliDownloadMethod;
// 加载哔哩哔哩最高分辨率
this.biliResolution = this.toolsConfig.biliResolution;
// 加载youtube的限制时长
this.youtubeDuration = this.toolsConfig.youtubeDuration
// 加载油管下载画质选项
this.YouTubeGraphicsOptions = this.toolsConfig.YouTubeGraphicsOptions
// 加载抖音Cookie
@ -1910,6 +1912,19 @@ export class tools extends plugin {
// 油管解析
async sy2b(e) {
function formatTime(seconds) {
// 计算小时、分钟和秒
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = seconds % 60;
// 将小时、分钟和秒格式化为两位数
const formattedHours = String(hours).padStart(2, '0');
const formattedMinutes = String(minutes).padStart(2, '0');
const formattedSeconds = String(secs).padStart(2, '0');
// 构造时间范围字符串
return `00:00:00-${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
}
const timeRange = await formatTime(this.youtubeDuration)
const isOversea = await this.isOverseasServer();
if (!isOversea && !(await testProxy(this.proxyAddr, this.proxyPort))) {
e.reply("检测到没有梯子,无法解析油管");
@ -1941,9 +1956,25 @@ export class tools extends plugin {
}
const path = this.getCurDownloadPath(e);
await checkAndRemoveFile(path + "/temp.mp4")
const title = await ytDlpGetTilt(url, isOversea, this.myProxy);
e.reply(`${ this.identifyPrefix }识别:油管,视频下载中请耐心等待 \n${ title }`);
await ytDlpHelper(path, url, isOversea, this.myProxy, true, graphics);
await checkAndRemoveFile(path + "/Thumbnail.png")
await ytDlpGetThumbnail(path, url, isOversea, this.myProxy)
const Duration = await ytDlpGetDuration(url, isOversea, this.myProxy).toString().replace(/\n/g, '')
// logger.info('时长------',Duration)
const title = await ytDlpGetTilt(url, isOversea, this.myProxy).toString().replace(/\n/g, '');
// logger.info('标题------',title)
function convertToSeconds(timeStr) {
const [minutes, seconds] = timeStr.split(':').map(Number); // 拆分并转换为数字
return minutes * 60 + seconds; // 分钟转化为秒并加上秒数
}
if(await convertToSeconds(Duration) > this.youtubeDuration){
e.reply([
segment.image(`${path}/Thumbnail.png`),
`${this.identifyPrefix}识别:油管,视频下载中请耐心等待 \n视频标题:${title}${DIVIDING_LINE.replace('{}', '限制说明')}\n视频时长:${Duration}分钟\n大于管理员限定时长:${(this.youtubeDuration / 60).toFixed(2).replace(/\.00$/, '')} 分钟\n将截取限定时间部分`
]);
} else {
e.reply([segment.image(`${ path }/Thumbnail.png`),`${ this.identifyPrefix }识别:油管,视频下载中请耐心等待 \n视频标题:${ title }\n视频时长:${Duration} 分钟`]);
}
await ytDlpHelper(path, url, isOversea, this.myProxy, true, graphics, timeRange);
this.sendVideoToUpload(e, `${ path }/temp.mp4`);
} catch (error) {
logger.error(error);

View File

@ -22,12 +22,13 @@ biliCDN: 0 # 哔哩哔哩 CDN默认为0表示不使用
biliDownloadMethod: 0 # 哔哩哔哩的下载方式0默认使用原生稳定的下载方式如果你在乎内存可以使用轻量的wget和axel下载方式如果在乎性能可以使用Aria2下载
biliResolution: 1 # 哔哩哔哩的下载画质0为原画1为清晰画2为流畅画默认为0
useLocalNeteaseAPI: false #是否使用网易云解析自建API
neteaseCookie: '' #网易云ck
neteaseCloudAPIServer: '' #网易云自建服务器地址
neteaseCloudAudioQuality: exhigh #网易云解析最高音质 默认exhigh(极高) 分类standard => 标准,higher => 较高, exhigh=>极高, lossless=>无损, hires=>Hi-Res, jyeffect => 高清环绕声, sky => 沉浸环绕声, dolby => 杜比全景声, jymaster => 超清母带
useLocalNeteaseAPI: false # 是否使用网易云解析自建API
neteaseCookie: '' # 网易云ck
neteaseCloudAPIServer: '' # 网易云自建服务器地址
neteaseCloudAudioQuality: exhigh # 网易云解析最高音质 默认exhigh(极高) 分类standard => 标准,higher => 较高, exhigh=>极高, lossless=>无损, hires=>Hi-Res, jyeffect => 高清环绕声, sky => 沉浸环绕声, dolby => 杜比全景声, jymaster => 超清母带
YouTubeGraphicsOptions: 720 #YouTobe的下载画质0为原画1080720480自定义画面高度默认为720
YouTubeGraphicsOptions: 720 # YouTobe的下载画质0为原画1080720480自定义画面高度默认为720
youtubeDuration: 300 # YouTobe限制的最大视频时长默认5分钟单位
douyinCookie: '' # douyin's cookie, 格式odin_tt=xxx;passport_fe_beating_status=xxx;sid_guard=xxx;uid_tt=xxx;uid_tt_ss=xxx;sid_tt=xxx;sessionid=xxx;sessionid_ss=xxx;sid_ucp_v1=xxx;ssid_ucp_v1=xxx;passport_assist_user=xxx;ttwid=xxx;
douyinCompression: true # true-压缩false-不压缩;是否使用压缩视频格式的抖音(默认使用),使用后加速视频发送

View File

@ -220,6 +220,17 @@ export function supportGuoba() {
options: BILI_RESOLUTION_LIST,
}
},
{
field: "tools.youtubeDuration",
label: "YouTuBe最大时长",
bottomHelpMessage:
"超过时长会截取指定时间单位保护魔法的流量计算公式5分钟 x 60秒 = 300秒",
component: "InputNumber",
required: false,
componentProps: {
placeholder: "请输入YouTuBe视频最大时长限制默认5分钟",
},
},
{
field: "tools.YouTubeGraphicsOptions",
label: "YouTube最高分辨率",

View File

@ -10,6 +10,18 @@ function constructProxyParam(isOversea, proxy) {
return isOversea ? "" : `--proxy ${proxy}`;
}
/**
* 获取时长
* @param url
* @param isOversea
* @param proxy
* @returns string
*/
export function ytDlpGetDuration(url, isOversea, proxy) {
return execSync(`yt-dlp --get-duration ${constructProxyParam(isOversea, proxy)} ${url}`);
}
/**
* 获取标题
* @param url
@ -21,6 +33,17 @@ export function ytDlpGetTilt(url, isOversea, proxy) {
return execSync(`yt-dlp --get-title ${constructProxyParam(isOversea, proxy)} ${url} --encoding utf8`);
}
/**
* 获取封面
* @param path
* @param url
* @param isOversea
* @param proxy
*/
export function ytDlpGetThumbnail(path, url, isOversea, proxy) {
return execSync(`yt-dlp --write-thumbnail --convert-thumbnails png --skip-download ${constructProxyParam(isOversea, proxy)} ${url} -P ${path} -o "thumbnail.%(ext)s"`);
}
/**
* yt-dlp 工具类
* @returns {Promise<void>}
@ -30,12 +53,13 @@ export function ytDlpGetTilt(url, isOversea, proxy) {
* @param proxy 代理地址
* @param merge 是否合并输出为 mp4 格式 (仅适用于视频合并需求)
* @param graphics YouTube画质参数
* @param timeRange 截取时间段
*/
export async function ytDlpHelper(path, url, isOversea, proxy, merge = false, graphics) {
export async function ytDlpHelper(path, url, isOversea, proxy, merge = false, graphics, timeRange) {
return new Promise((resolve, reject) => {
const mergeOption = merge ? '--merge-output-format "mp4"' : '';
const fParam = url.includes("youtu") ? `-f "bv${graphics}[ext=mp4]+ba[ext=m4a]"` : "";
const fParam = url.includes("youtu") ? `--download-sections "*${timeRange}" -f "bv${graphics}[ext=mp4]+ba[ext=m4a]"` : "";
const command = `yt-dlp ${fParam} ${constructProxyParam(isOversea, proxy)} -P ${path} -o "temp.%(ext)s" ${url}`;