🌟 feat: V1.3.0 新增油管解析

1. 新增油管解析
2. 修复tiktok在海外服务器无法解析问题
3. 更换翻译引擎为全局引擎,并初次使用在油管解析中
This commit is contained in:
zhiyu 2024-02-02 15:37:37 +08:00
parent ef75e7c12c
commit 083b4ea613
8 changed files with 237 additions and 31 deletions

View File

@ -38,7 +38,7 @@ utils -- 工具类
git clone https://gitee.com/kyrzy0416/rconsole-plugin.git ./plugins/rconsole-plugin/ git clone https://gitee.com/kyrzy0416/rconsole-plugin.git ./plugins/rconsole-plugin/
``` ```
2.【必要】在`Yunzai-Bot`目录下安装axios(0.27.2)、魔法工具tunnel、哔哩哔哩总结(chatgpt-api)依赖 2.【必要】在`Yunzai-Bot`目录下安装axios(0.27.2)、魔法工具tunnel
```shell ```shell
@ -53,6 +53,19 @@ sudo apt-get install ffmpeg
# 其他linux参考群友推荐https://gitee.com/baihu433/ffmpeg # 其他linux参考群友推荐https://gitee.com/baihu433/ffmpeg
# Windows 参考https://www.jianshu.com/p/5015a477de3c # Windows 参考https://www.jianshu.com/p/5015a477de3c
```` ````
油管解析需要 yt-dlp 的依赖才能完成解析(三选一):
```shell
# 三选一
# ubuntu (国内 or 国外且安装了snap
snap install yt-dlp
# debian 海外
curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o ~/.local/bin/yt-dlp
chmod a+rx ~/.local/bin/yt-dlp
# debian 国内
curl -L https://ghproxy.net/https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o ~/.local/bin/yt-dlp
chmod a+rx ~/.local/bin/yt-dlp
```
4. 【可选】小程序解析适配了: 4. 【可选】小程序解析适配了:
* 喵崽:[Yoimiya / Miao-Yunzai](https://gitee.com/yoimiya-kokomi/Miao-Yunzai) * 喵崽:[Yoimiya / Miao-Yunzai](https://gitee.com/yoimiya-kokomi/Miao-Yunzai)
* TRSS[时雨◎星空 / Yunzai](https://gitee.com/TimeRainStarSky/Yunzai) * TRSS[时雨◎星空 / Yunzai](https://gitee.com/TimeRainStarSky/Yunzai)
@ -118,7 +131,7 @@ sudo apt-get install ffmpeg
![help](./img/help.webp) ![help](./img/help.webp)
## 📝 计划功能 ## 📝 计划功能
- [ ] YouTube解析这个可能要🕊一久 - [x] YouTube解析这个可能要🕊一久
- [ ] Instagram解析修复 - [ ] Instagram解析修复
- [ ] 单张图片解析 - [ ] 单张图片解析
- [ ] 视频解析 - [ ] 视频解析
@ -142,6 +155,9 @@ sudo apt-get install ffmpeg
* [一杯凉](https://gitee.com/yibeiliang) 提供小程序解析冲突解决方案 * [一杯凉](https://gitee.com/yibeiliang) 提供小程序解析冲突解决方案
* [x0rz4](https://gitee.com/x0rz4) 提供依赖掉包解决方案 * [x0rz4](https://gitee.com/x0rz4) 提供依赖掉包解决方案
感谢以下框架的开源:
YouTube解析参考了[yt-dlp:A youtube-dl fork with additional features and fixes](https://github.com/yt-dlp/yt-dlp)
## ☕ 请我喝一杯瑞幸咖啡 ## ☕ 请我喝一杯瑞幸咖啡
如果你觉得插件能帮助到你增进好友关系,那么你可以在有条件的情况下[请我喝一杯瑞幸咖啡](https://afdian.net/a/zhiyu1998),这是我开源这个插件的最大动力! 如果你觉得插件能帮助到你增进好友关系,那么你可以在有条件的情况下[请我喝一杯瑞幸咖啡](https://afdian.net/a/zhiyu1998),这是我开源这个插件的最大动力!
感谢以下朋友的支持!(排名不分多少) 感谢以下朋友的支持!(排名不分多少)

View File

@ -12,9 +12,10 @@ import { parseUrl, parseM3u8, downloadM3u8Videos, mergeAcFileToMp4 } from "../ut
import { import {
transMap, transMap,
douyinTypeMap, douyinTypeMap,
RESTRICTION_DESCRIPTION, XHS_NO_WATERMARK_HEADER, DIVIDING_LINE,
XHS_NO_WATERMARK_HEADER, REDIS_YUNZAI_ISOVERSEA,
} from "../constants/constant.js"; } from "../constants/constant.js";
import { formatBiliInfo, getIdVideo, secondsToTime } from "../utils/common.js"; import {containsChinese, formatBiliInfo, getIdVideo, secondsToTime} from "../utils/common.js";
import config from "../model/index.js"; import config from "../model/index.js";
import Translate from "../utils/trans-strategy.js"; import Translate from "../utils/trans-strategy.js";
import * as xBogus from "../utils/x-bogus.cjs"; import * as xBogus from "../utils/x-bogus.cjs";
@ -26,6 +27,8 @@ import TokenBucket from "../utils/token-bucket.js";
import { getWbi } from "../utils/biliWbi.js"; import { getWbi } from "../utils/biliWbi.js";
import { BILI_SUMMARY } from "../constants/bili.js"; import { BILI_SUMMARY } from "../constants/bili.js";
import { XHS_VIDEO } from "../constants/xhs.js"; import { XHS_VIDEO } from "../constants/xhs.js";
import child_process from 'node:child_process'
import { getAudio, getVideo } from "../utils/y2b.js";
export class tools extends plugin { export class tools extends plugin {
constructor() { constructor() {
@ -80,6 +83,11 @@ export class tools extends plugin {
fnc: "clearTrash", fnc: "clearTrash",
permission: "master", permission: "master",
}, },
{
reg: "^#设置海外解析$",
fnc: "setOversea",
permission: "master",
},
{ {
reg: "(h5app.kuwo.cn)", reg: "(h5app.kuwo.cn)",
fnc: "bodianMusic", fnc: "bodianMusic",
@ -88,6 +96,10 @@ export class tools extends plugin {
reg: "(kuaishou.com)", reg: "(kuaishou.com)",
fnc: "kuaishou", fnc: "kuaishou",
}, },
{
reg: "(youtube.com)",
fnc: "y2b"
}
], ],
}); });
// 配置文件 // 配置文件
@ -104,6 +116,12 @@ export class tools extends plugin {
this.biliDuration = this.toolsConfig.biliDuration; this.biliDuration = this.toolsConfig.biliDuration;
// 加载抖音Cookie // 加载抖音Cookie
this.douyinCookie = this.toolsConfig.douyinCookie; this.douyinCookie = this.toolsConfig.douyinCookie;
// 翻译引擎
this.translateEngine = new Translate({
translateAppId: this.toolsConfig.translateAppId,
translateSecret: this.toolsConfig.translateSecret,
proxy: this.myProxy,
});
} }
// 翻译插件 // 翻译插件
@ -118,13 +136,8 @@ export class tools extends plugin {
return; return;
} }
const place = msg.slice(1 + language[1].length) const place = msg.slice(1 + language[1].length)
const translateEngine = new Translate({
translateAppId: this.toolsConfig.translateAppId,
translateSecret: this.toolsConfig.translateSecret,
proxy: this.myProxy,
});
// 如果没有百度那就Google // 如果没有百度那就Google
const translateResult = await translateEngine.translate(place, language[1]); const translateResult = await this.translateEngine.translate(place, language[1]);
e.reply(translateResult.trim(), true); e.reply(translateResult.trim(), true);
return true; return true;
} }
@ -216,6 +229,8 @@ export class tools extends plugin {
const urlShortRex = /(http:|https:)\/\/vt.tiktok.com\/[A-Za-z\d._?%&+\-=\/#]*/g; const urlShortRex = /(http:|https:)\/\/vt.tiktok.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
const urlShortRex2 = /(http:|https:)\/\/vm.tiktok.com\/[A-Za-z\d._?%&+\-=\/#]*/g; const urlShortRex2 = /(http:|https:)\/\/vm.tiktok.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
let url = e.msg.trim(); let url = e.msg.trim();
// 判断是否是海外服务器
const isOversea = await this.isOverseasServer();
// 短号处理 // 短号处理
if (url.includes("vt.tiktok")) { if (url.includes("vt.tiktok")) {
const temp_url = urlShortRex.exec(url)[0]; const temp_url = urlShortRex.exec(url)[0];
@ -223,7 +238,7 @@ export class tools extends plugin {
redirect: "follow", redirect: "follow",
follow: 10, follow: 10,
timeout: 10000, timeout: 10000,
agent: new HttpProxyAgent(this.myProxy), agent: isOversea ? '' : new HttpProxyAgent(this.myProxy),
}).then(resp => { }).then(resp => {
url = resp.url; url = resp.url;
}); });
@ -234,7 +249,7 @@ export class tools extends plugin {
redirect: "follow", redirect: "follow",
follow: 10, follow: 10,
timeout: 10000, timeout: 10000,
agent: new HttpProxyAgent(this.myProxy), agent: isOversea ? '' : new HttpProxyAgent(this.myProxy),
}).then(resp => { }).then(resp => {
url = resp.url; url = resp.url;
}); });
@ -255,13 +270,13 @@ export class tools extends plugin {
// redirect: "follow", // redirect: "follow",
follow: 10, follow: 10,
timeout: 10000, timeout: 10000,
agent: new HttpsProxyAgent(this.myProxy), agent: isOversea ? '' : new HttpProxyAgent(this.myProxy),
}) })
.then(async resp => { .then(async resp => {
const respJson = await resp.json(); const respJson = await resp.json();
const data = respJson.aweme_list[0]; const data = respJson.aweme_list[0];
e.reply(`识别tiktok, ${ data.desc }`); e.reply(`识别tiktok, ${ data.desc }`);
this.downloadVideo(data.video.play_addr.url_list[0], true).then(video => { this.downloadVideo(data.video.play_addr.url_list[0], !isOversea).then(video => {
e.reply( e.reply(
segment.video( segment.video(
`${ this.defaultPath }${ this.e.group_id || this.e.user_id }/temp.mp4`, `${ this.defaultPath }${ this.e.group_id || this.e.user_id }/temp.mp4`,
@ -343,7 +358,7 @@ export class tools extends plugin {
biliInfo.unshift(segment.image(pic)) biliInfo.unshift(segment.image(pic))
// 限制视频解析 // 限制视频解析
const durationInMinutes = (curDuration / 60).toFixed(0); const durationInMinutes = (curDuration / 60).toFixed(0);
biliInfo.push(`${ RESTRICTION_DESCRIPTION }\n当前视频时长约:${ durationInMinutes }分钟,\n大于管理员设置的最大时长 ${ this.biliDuration / 60 } 分钟!`) biliInfo.push(`${ DIVIDING_LINE.replace('{}', '限制说明') }\n当前视频时长约:${ durationInMinutes }分钟,\n大于管理员设置的最大时长 ${ this.biliDuration / 60 } 分钟!`)
summary && biliInfo.push(`\n${ summary }`); summary && biliInfo.push(`\n${ summary }`);
e.reply(biliInfo); e.reply(biliInfo);
return true; return true;
@ -889,6 +904,102 @@ export class tools extends plugin {
}); });
} }
/**
* youtube解析
* @param e
* @returns {Promise<void>}
*/
async y2b(e) {
const urlRex = /(?:https?:\/\/)?www\.youtube\.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
let url = urlRex.exec(e.msg)[0];
// 获取url查询参数
const query = querystring.parse(url.split("?")[1]);
let p = query?.p || '0';
let v = query?.v;
// 判断是否是海外服务器默认为false
const isProxy = !(await this.isOverseasServer());
let audios = [], videos = [];
let bestAudio = {}, bestVideo = {};
let rs = { title: '', thumbnail: '', formats: [] };
try {
let cmd = `yt-dlp --print-json --skip-download ${this.y2bCk !== undefined ? `--cookies ${this.y2bCk}` : ''} '${url}' ${isProxy ? '--proxy http://127.0.0.1:7890' : ''} 2> /dev/null`
console.log('解析视频, 命令:', cmd);
rs = child_process.execSync(cmd).toString();
try {
rs = JSON.parse(rs);
} catch (error) {
let cmd = `yt-dlp --print-json --skip-download ${this.y2bCk !== undefined ? `--cookies ${this.y2bCk}` : ''} '${url}?p=1' ${isProxy ? '--proxy http://127.0.0.1:7890' : ''} 2> /dev/null`;
logger.mark('尝试分P, 命令:', cmd);
rs = child_process.execSync(cmd).toString();
rs = JSON.parse(rs);
p = '1';
// url = `${msg.url}?p=1`;
}
if (!containsChinese(rs.title)) {
// 启用翻译引擎翻译不是中文的标题
const transedTitle = await this.translateEngine.translate(rs.title, '中');
// const transedDescription = await this.translateEngine.translate(rs.description, '中');
e.reply(`识别:油管,
${rs.title.trim()}\n
${DIVIDING_LINE.replace("{}", "R插件翻译引擎服务")}\n
${transedTitle}\n
${rs.description}
`);
} else {
e.reply(`识别:油管,${rs.title}`);
}
} catch (error) {
logger.error(error.toString());
e.reply("解析失败")
return;
}
// 格式化
rs.formats.forEach(it => {
let length = (it.filesize_approx ? '≈' : '') + ((it.filesize || it.filesize_approx || 0) / 1024 / 1024).toFixed(2);
if (it.audio_ext != 'none') {
audios.push(getAudio(it.format_id, it.ext, (it.abr || 0).toFixed(0), it.format_note || it.format || '', length));
} else if (it.video_ext != 'none') {
videos.push(getVideo(it.format_id, it.ext, it.resolution, it.height, (it.vbr || 0).toFixed(0), it.format_note || it.format || '', length));
}
});
// 寻找最佳的分辨率
// bestAudio = Array.from(audios).sort((a, b) => a.rate - b.rate)[audios.length - 1];
// bestVideo = Array.from(videos).sort((a, b) => a.rate - b.rate)[videos.length - 1];
// 较为有性能的分辨率
logger.info(videos)
bestVideo = Array.from(videos).filter(item => item.scale.includes("720"))[0];
bestAudio = Array.from(audios).filter(item => item.format === 'm4a')[0];
logger.info({
bestVideo,
bestAudio
})
// 格式化yt-dlp的请求
const format = `${bestVideo.id}x${bestAudio.id}`
// 下载地址格式化
const path = `${v}${ p ? `/p${p}` : '' }`;
const fullpath = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }/${path}`;
// yt-dlp下载
let cmd = //`cd '${__dirname}' && (cd tmp > /dev/null || (mkdir tmp && cd tmp)) &&` +
`yt-dlp ${this.y2bCk !== undefined ? `--cookies ${this.y2bCk}` : ''} https://youtu.be/${v} -f ${format.replace('x', '+')} ` +
`-o '${fullpath}/${v}.%(ext)s' ${isProxy ? '--proxy http://127.0.0.1:7890' : ''} -k --write-info-json`;
try {
await child_process.execSync(cmd);
e.reply(segment.video(`${fullpath}/${v}.mp4`))
// 清理文件
await deleteFolderRecursive(fullpath);
} catch (error) {
logger.error(error.toString());
e.reply("y2b下载失败");
return;
}
}
/** /**
* 哔哩哔哩下载 * 哔哩哔哩下载
* @param title * @param title
@ -1054,15 +1165,33 @@ export class tools extends plugin {
} }
} }
async setOversea(e) {
// 查看当前设置
let os;
if ((await redis.exists(REDIS_YUNZAI_ISOVERSEA))) {
os = JSON.parse(await redis.get(REDIS_YUNZAI_ISOVERSEA)).os;
}
// 设置
os = ~os
await redis.set(
REDIS_YUNZAI_ISOVERSEA,
JSON.stringify({
os: os,
}),
);
e.reply(`当前服务器:${os ? '海外服务器' : '国内服务器'}`)
return true;
}
/** /**
* 判断是否是海外服务器 * 判断是否是海外服务器
* @return {Promise<Boolean>} * @return {Promise<Boolean>}
*/ */
async isOverseasServer() { async isOverseasServer() {
const isOS = "Yz:rconsole:tools:oversea";
// 如果第一次使用没有值就设置 // 如果第一次使用没有值就设置
if (!(await redis.exists(isOS))) { if (!(await redis.exists(REDIS_YUNZAI_ISOVERSEA))) {
await redis.set( await redis.set(
REDIS_YUNZAI_ISOVERSEA,
JSON.stringify({ JSON.stringify({
os: false, os: false,
}), }),
@ -1070,7 +1199,7 @@ export class tools extends plugin {
return true; return true;
} }
// 如果有就取出来 // 如果有就取出来
return JSON.parse(redis.get(isOS)).os; return JSON.parse((await redis.get(REDIS_YUNZAI_ISOVERSEA))).os;
} }
/** /**

View File

@ -41,6 +41,9 @@
- icon: bilimusic - icon: bilimusic
title: "bili音乐+链接" title: "bili音乐+链接"
desc: 哔哩哔哩音乐分享实时下载 desc: 哔哩哔哩音乐分享实时下载
- icon: youtube
title: "youtube.com"
desc: 油管学习版分享实时下载
- icon: 推特 - icon: 推特
title: "小蓝鸟" title: "小蓝鸟"
desc: 推特学习版分享实时下载 desc: 推特学习版分享实时下载

View File

@ -1,10 +1,10 @@
- { - {
version: 1.2.3, version: 1.3.0,
data: data:
[ [
新增<span class="cmd">油管解析</span>功能,
新增<span class="cmd">小红书无水印下载</span>功能, 新增<span class="cmd">小红书无水印下载</span>功能,
新增<span class="cmd">哔哩哔哩官方AI总结</span>功能, 新增<span class="cmd">哔哩哔哩官方AI总结</span>功能,
新增<span class="cmd">哔哩哔哩音乐提取</span>功能,
新增<span class="cmd">快手解析</span>功能, 新增<span class="cmd">快手解析</span>功能,
支持<span class="cmd">锅巴</span>插件,方便查看和修改配置, 支持<span class="cmd">锅巴</span>插件,方便查看和修改配置,
添加<span class="cmd">#R帮助</span>获取插件帮助, 添加<span class="cmd">#R帮助</span>获取插件帮助,

View File

@ -59,4 +59,10 @@ export const XHS_NO_WATERMARK_HEADER = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4098.3 Safari/537.36', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4098.3 Safari/537.36',
} }
export const RESTRICTION_DESCRIPTION = "\n-----------------------限制说明-----------------------" /**
* 分割线
* @type {string}
*/
export const DIVIDING_LINE = "\n-----------------------{}-----------------------"
export const REDIS_YUNZAI_ISOVERSEA = "Yz:rconsole:tools:oversea";

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -9,7 +9,7 @@ import {TEN_THOUSAND} from "../constants/constant.js";
/** /**
* 请求模板 * 请求模板
*/ */
class jFeatch { export class jFetch {
async get(url) { async get(url) {
const r = await fetch(url); const r = await fetch(url);
return await r.json(); return await r.json();
@ -26,7 +26,7 @@ class jFeatch {
* @param time cron * @param time cron
* @param isAutoPush 是否推送开关 * @param isAutoPush 是否推送开关
*/ */
function autoTask(func, time, groupList, isAutoPush = false) { export function autoTask(func, time, groupList, isAutoPush = false) {
if (isAutoPush) { if (isAutoPush) {
schedule.scheduleJob(time, () => { schedule.scheduleJob(time, () => {
// 正常传输 // 正常传输
@ -55,7 +55,7 @@ function autoTask(func, time, groupList, isAutoPush = false) {
* @param delay * @param delay
* @returns {Promise<unknown>} * @returns {Promise<unknown>}
*/ */
function retry(func, maxRetries = 3, delay = 1000) { export function retry(func, maxRetries = 3, delay = 1000) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const attempt = (remainingTries) => { const attempt = (remainingTries) => {
func() func()
@ -79,7 +79,7 @@ function retry(func, maxRetries = 3, delay = 1000) {
* @param filename * @param filename
* @returns {Promise<unknown>} * @returns {Promise<unknown>}
*/ */
function downloadPDF (url, filename) { export function downloadPDF (url, filename) {
return axios({ return axios({
url: url, url: url,
responseType: "stream", responseType: "stream",
@ -102,7 +102,7 @@ function downloadPDF (url, filename) {
* @param url * @param url
* @returns {Promise<string|string|null>} * @returns {Promise<string|string|null>}
*/ */
async function getIdVideo(url) { export async function getIdVideo(url) {
const matching = url.includes("/video/"); const matching = url.includes("/video/");
if (!matching) { if (!matching) {
this.e.reply("没找到,正在获取随机视频!"); this.e.reply("没找到,正在获取随机视频!");
@ -112,7 +112,7 @@ async function getIdVideo(url) {
return idVideo.length > 19 ? idVideo.substring(0, idVideo.indexOf("?")) : idVideo; return idVideo.length > 19 ? idVideo.substring(0, idVideo.indexOf("?")) : idVideo;
} }
function generateRandomStr(randomlength = 16){ export function generateRandomStr(randomlength = 16){
const base_str = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789=' const base_str = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789='
let random_str = '' let random_str = ''
for (let i = 0; i < randomlength; i++) { for (let i = 0; i < randomlength; i++) {
@ -128,7 +128,7 @@ function generateRandomStr(randomlength = 16){
* @param redirect 是否要重定向 * @param redirect 是否要重定向
* @returns {Promise<unknown>} * @returns {Promise<unknown>}
*/ */
async function downloadMp3(mp3Url, path, redirect = "manual") { export async function downloadMp3(mp3Url, path, redirect = "manual") {
return fetch(mp3Url, { return fetch(mp3Url, {
headers: { headers: {
"User-Agent": "User-Agent":
@ -178,7 +178,7 @@ const dataProcessing = data => {
* @param data * @param data
* @return {string} * @return {string}
*/ */
function formatBiliInfo(data) { export function formatBiliInfo(data) {
return Object.keys(data).map(key => `${key}${dataProcessing(data[key])}`).join(' | '); return Object.keys(data).map(key => `${key}${dataProcessing(data[key])}`).join(' | ');
} }
@ -187,7 +187,7 @@ function formatBiliInfo(data) {
* @param seconds * @param seconds
* @return {string} * @return {string}
*/ */
function secondsToTime(seconds) { export function secondsToTime(seconds) {
const pad = (num, size) => num.toString().padStart(size, '0'); const pad = (num, size) => num.toString().padStart(size, '0');
let hours = Math.floor(seconds / 3600); let hours = Math.floor(seconds / 3600);
@ -201,4 +201,29 @@ function secondsToTime(seconds) {
return `${pad(hours, 2)}:${pad(minutes, 2)}:${pad(secs, 2)}`; return `${pad(hours, 2)}:${pad(minutes, 2)}:${pad(secs, 2)}`;
} }
export { jFeatch, autoTask, retry, getIdVideo, generateRandomStr, downloadMp3, dataProcessing, formatBiliInfo, secondsToTime }; /**
* 判断字符串是否是中文全局判断
* @param str
* @returns {boolean}
*/
export function isChinese(str) {
return /^[\u4e00-\u9fff]+$/.test(str);
}
/**
* 判断字符串是否包含中文
* @param str
* @returns {boolean}
*/
export function containsChinese(str) {
return /[\u4e00-\u9fff]/.test(str);
}
/**
* 判断字符串是否包含中文 && 检测标点符号
* @param str
* @returns {boolean}
*/
export function containsChineseOrPunctuation(str) {
return /[\u4e00-\u9fff\uff00-\uffef]/.test(str);
}

27
utils/y2b.js Normal file
View File

@ -0,0 +1,27 @@
/**
* y2b 音频信息
* @param id
* @param format
* @param rate
* @param info
* @param size
* @returns {{size: (string|*), rate: (string|*), format, id, info}}
*/
export function getAudio(id, format, rate, info, size) {
return { id, format, rate: rate == 0 ? '未知' : rate, info, size: size == 0 ? '未知' : size };
}
/**
* y2b 视频信息
* @param id
* @param format
* @param scale
* @param frame
* @param rate
* @param info
* @param size
* @returns {{size: (string|*), rate: (string|*), format, scale, id, frame, info}}
*/
export function getVideo(id, format, scale, frame, rate, info, size) {
return { id, format, scale, frame, rate: rate == 0 ? '未知' : rate, info, size: size == 0 ? '未知' : size };
}