mirror of
https://github.com/Jerryplusy/rc-plugin.git
synced 2025-10-14 16:19:18 +00:00
🎈 pref: 优化直播切片,兼容 icqq 和 llo
This commit is contained in:
parent
44e3027f6c
commit
7ed883f18d
@ -85,6 +85,7 @@ import {
|
||||
truncateString,
|
||||
urlTransformShortLink
|
||||
} from "../utils/common.js";
|
||||
import { convertFlvToMp4 } from "../utils/ffmpeg-util.js";
|
||||
import { checkAndRemoveFile, deleteFolderRecursive, getMediaFilesAndOthers, mkdirIfNotExists } from "../utils/file.js";
|
||||
import GeneralLinkAdapter from "../utils/general-link-adapter.js";
|
||||
import { LagrangeAdapter } from "../utils/lagrange-adapter.js";
|
||||
@ -260,6 +261,8 @@ export class tools extends plugin {
|
||||
this.douyinCompression = this.toolsConfig.douyinCompression;
|
||||
// 加载抖音是否开启评论
|
||||
this.douyinComments = this.toolsConfig.douyinComments;
|
||||
// 加载抖音的是否开启兼容模式
|
||||
this.douyinStreamCompatibility = this.toolsConfig.douyinStreamCompatibility;
|
||||
// 加载小红书Cookie
|
||||
this.xiaohongshuCookie = this.toolsConfig.xiaohongshuCookie;
|
||||
// 翻译引擎
|
||||
@ -352,7 +355,6 @@ export class tools extends plugin {
|
||||
const webcastResp = await fetch(dyApi);
|
||||
const webcastData = await webcastResp.json();
|
||||
const item = webcastData.data.room;
|
||||
logger.info(item);
|
||||
const { title, cover, user_count, stream_url } = item;
|
||||
const dySendContent = `${ this.identifyPrefix }识别:抖音直播,${ title }`
|
||||
e.reply([segment.image(cover?.url_list?.[0]), dySendContent, `\n🏄♂️在线人数:${ user_count }人正在观看`]);
|
||||
@ -481,8 +483,13 @@ export class tools extends plugin {
|
||||
* @param second
|
||||
*/
|
||||
async sendStreamSegment(e, stream_url, second = this.streamDuration) {
|
||||
const outputFilePath = `${ this.getCurDownloadPath(e) }/stream_${second}s.flv`;
|
||||
let outputFilePath = `${ this.getCurDownloadPath(e) }/stream_${second}s.flv`;
|
||||
// 删除临时文件
|
||||
if (this.douyinStreamCompatibility) {
|
||||
await checkAndRemoveFile(outputFilePath.replace("flv", "mp4"));
|
||||
} else {
|
||||
await checkAndRemoveFile(outputFilePath);
|
||||
}
|
||||
|
||||
// 创建一个取消令牌
|
||||
const CancelToken = axios.CancelToken;
|
||||
@ -502,9 +509,17 @@ export class tools extends plugin {
|
||||
setTimeout(async () => {
|
||||
logger.info(`[R插件][发送直播流] 直播下载 ${ second } 秒钟到,停止下载!`);
|
||||
// 取消请求
|
||||
source.cancel('下载时间到,停止请求');
|
||||
source.cancel('[R插件][发送直播流] 下载时间到,停止请求');
|
||||
response.data.unpipe(file); // 取消管道连接
|
||||
file.end(); // 结束写入
|
||||
// 这里判断是否开启兼容模式
|
||||
if (this.douyinStreamCompatibility) {
|
||||
logger.info(`[R插件][发送直播流] 开启兼容模式,开始转换mp4格式...`);
|
||||
const resolvedOutputPath = await convertFlvToMp4(outputFilePath, outputFilePath.replace(".flv", ".mp4"));
|
||||
fs.unlinkSync(outputFilePath);
|
||||
outputFilePath = resolvedOutputPath;
|
||||
logger.info(`[R插件][发送直播流] 转换完成,开始发送视频...`);
|
||||
}
|
||||
await this.sendVideoToUpload(e, outputFilePath);
|
||||
}, second * 1000);
|
||||
|
||||
|
@ -26,6 +26,7 @@ YouTubeGraphicsOptions: 720 #YouTobe的下载画质,0为原画,1080,720,
|
||||
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-不压缩;是否使用压缩视频格式的抖音(默认使用),使用后加速视频发送
|
||||
douyinComments: false # true-开启评论,false-关闭评论
|
||||
douyinStreamCompatibility: false # 兼容模式,NCQQ不用开,其他ICQQ、LLO需要开启
|
||||
|
||||
xiaohongshuCookie: '' # 2024-8-2后反馈必须使用ck,不然无法解析
|
||||
|
||||
|
@ -245,6 +245,12 @@ export function supportGuoba() {
|
||||
component: "Switch",
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
field: "tools.douyinStreamCompatibility",
|
||||
label: "抖音直播是否开启兼容模式",
|
||||
component: "Switch",
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
field: "tools.xiaohongshuCookie",
|
||||
label: "小红书的Cookie",
|
||||
|
@ -1,5 +1,6 @@
|
||||
import path from 'path';
|
||||
import { exec } from 'child_process';
|
||||
import fs from "fs";
|
||||
|
||||
/**
|
||||
* 提取关键帧
|
||||
@ -34,22 +35,32 @@ export async function extractKeyframes(inputFilePath, outputFolderPath, frameCou
|
||||
* @param {string} outputFilePath - 输出的 MP4 文件路径
|
||||
* @returns {Promise<string>} - 返回一个 Promise,成功时返回输出文件路径,失败时返回错误信息
|
||||
*/
|
||||
function convertFlvToMp4(inputFilePath, outputFilePath) {
|
||||
export function convertFlvToMp4(inputFilePath, outputFilePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const command = `ffmpeg -i ${inputFilePath} ${outputFilePath}`;
|
||||
const resolvedInputPath = path.resolve(inputFilePath);
|
||||
const resolvedOutputPath = path.resolve(outputFilePath);
|
||||
|
||||
// 检查文件是否存在
|
||||
fs.access(resolvedInputPath, fs.constants.F_OK, (err) => {
|
||||
if (err) {
|
||||
reject(`[R插件][ffmpeg工具]输入文件不存在: ${resolvedInputPath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const command = `ffmpeg -y -i "${resolvedInputPath}" "${resolvedOutputPath}"`;
|
||||
logger.info(`[R插件][ffmpeg工具]执行命令:${command}`);
|
||||
|
||||
// 执行 ffmpeg 转换
|
||||
exec(command, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(`执行 ffmpeg 命令时出错: ${error.message}`);
|
||||
reject(`[R插件][ffmpeg工具]执行 ffmpeg 命令时出错: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
if (stderr) {
|
||||
reject(`ffmpeg 标准错误输出: ${stderr}`);
|
||||
return;
|
||||
logger.warn(`[R插件][ffmpeg工具]ffmpeg 标准错误输出: ${stderr}`);
|
||||
}
|
||||
resolve(outputFilePath);
|
||||
resolve(resolvedOutputPath);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user