karin-plugin-kkk 2.24.0 → 2.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/config/default_config/app.yaml +4 -0
- package/lib/apps/admin.js +1 -1
- package/lib/apps/help.js +1 -1
- package/lib/apps/push.js +1 -1
- package/lib/apps/qrlogin.js +1 -1
- package/lib/apps/statistics.js +1 -1
- package/lib/apps/tools.js +1 -1
- package/lib/apps/update.js +1 -1
- package/lib/build-metadata.json +5 -5
- package/lib/core_chunk/{main-1eljaHiz.js → main-BY6eDfoV.js} +381 -53
- package/lib/index.js +1 -1
- package/lib/root.js +1 -1
- package/lib/web.config.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [2.25.1](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.25.0...v2.25.1) (2026-03-11)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### 🧰 其他更新
|
|
9
|
+
|
|
10
|
+
* 注释 ([d78adef](https://github.com/ikenxuan/karin-plugin-kkk/commit/d78adef61be62a7486a84a4be18e8b3f40ae1b7f))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### ⚙️ 配置变更
|
|
14
|
+
|
|
15
|
+
* 添加 Live Photo 静态图兼容系统配置 ([a8c5137](https://github.com/ikenxuan/karin-plugin-kkk/commit/a8c51374a697c111a0813e9f0eb939cdb9285597))
|
|
16
|
+
|
|
17
|
+
## [2.25.0](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.24.0...v2.25.0) (2026-03-11)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### ✨ 新功能
|
|
21
|
+
|
|
22
|
+
* **core:** 解析动图作品时,实验性将合并转发消息中的静态图片魔改成 Google Motion 标准的 Live Photo ([5e789e3](https://github.com/ikenxuan/karin-plugin-kkk/commit/5e789e351eebfaca84e26c326ddf7c16e253a20f))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### 🐛 错误修复
|
|
26
|
+
|
|
27
|
+
* 取消注释 ([921bf95](https://github.com/ikenxuan/karin-plugin-kkk/commit/921bf95ad05d8ac17a2540ac9aa3014beed3b6e5))
|
|
28
|
+
|
|
5
29
|
## [2.24.0](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.23.2...v2.24.0) (2026-03-10)
|
|
6
30
|
|
|
7
31
|
|
|
@@ -47,6 +47,10 @@ multiPageRender: true
|
|
|
47
47
|
# 分页渲染时,每页的高度,经测试最佳每页高度为12000px,默认12000px
|
|
48
48
|
multiPageHeight: 12000
|
|
49
49
|
|
|
50
|
+
# 当解析到作品/动态包含 Live Photo 时,合并转发消息里发送的 Live Photo 静态图兼容系统
|
|
51
|
+
# 可选值:'google'、'xiaomi'、'oppo'、'huawei_honor'
|
|
52
|
+
livePhotoSystem: google
|
|
53
|
+
|
|
50
54
|
# 扫码登录时使用的地址类型,可选值:'lan'(局域网IP)、'external'(外部地址)
|
|
51
55
|
qrLoginAddrType: lan
|
|
52
56
|
|
package/lib/apps/admin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
|
|
2
|
-
import { C as biLogin, E as task, T as removeOldFiles, w as dylogin } from "../core_chunk/main-
|
|
2
|
+
import { C as biLogin, E as task, T as removeOldFiles, w as dylogin } from "../core_chunk/main-BY6eDfoV.js";
|
|
3
3
|
import "../core_chunk/vendor-DxfKHvj-.js";
|
|
4
4
|
import "../core_chunk/template-DekmxKd7.js";
|
|
5
5
|
export { biLogin, dylogin, removeOldFiles, task };
|
package/lib/apps/help.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
|
|
2
|
-
import { S as version, x as help } from "../core_chunk/main-
|
|
2
|
+
import { S as version, x as help } from "../core_chunk/main-BY6eDfoV.js";
|
|
3
3
|
import "../core_chunk/vendor-DxfKHvj-.js";
|
|
4
4
|
import "../core_chunk/template-DekmxKd7.js";
|
|
5
5
|
export { help, version };
|
package/lib/apps/push.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
|
|
2
|
-
import { _ as forcePush, b as testDouyinPush, f as bilibiliPush, g as douyinPushList, h as douyinPush, m as changeBotID, p as bilibiliPushList, v as setbiliPush, y as setdyPush } from "../core_chunk/main-
|
|
2
|
+
import { _ as forcePush, b as testDouyinPush, f as bilibiliPush, g as douyinPushList, h as douyinPush, m as changeBotID, p as bilibiliPushList, v as setbiliPush, y as setdyPush } from "../core_chunk/main-BY6eDfoV.js";
|
|
3
3
|
import "../core_chunk/vendor-DxfKHvj-.js";
|
|
4
4
|
import "../core_chunk/template-DekmxKd7.js";
|
|
5
5
|
export { bilibiliPush, bilibiliPushList, changeBotID, douyinPush, douyinPushList, forcePush, setbiliPush, setdyPush, testDouyinPush };
|
package/lib/apps/qrlogin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
|
|
2
|
-
import { d as qrLogin } from "../core_chunk/main-
|
|
2
|
+
import { d as qrLogin } from "../core_chunk/main-BY6eDfoV.js";
|
|
3
3
|
import "../core_chunk/vendor-DxfKHvj-.js";
|
|
4
4
|
import "../core_chunk/template-DekmxKd7.js";
|
|
5
5
|
export { qrLogin };
|
package/lib/apps/statistics.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
|
|
2
|
-
import { l as globalStatistics, u as groupStatistics } from "../core_chunk/main-
|
|
2
|
+
import { l as globalStatistics, u as groupStatistics } from "../core_chunk/main-BY6eDfoV.js";
|
|
3
3
|
import "../core_chunk/vendor-DxfKHvj-.js";
|
|
4
4
|
import "../core_chunk/template-DekmxKd7.js";
|
|
5
5
|
export { globalStatistics, groupStatistics };
|
package/lib/apps/tools.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
|
|
2
|
-
import { a as douyinAPP, c as xiaohongshuAPP, i as bilibiliAPP, o as kuaishouAPP, s as prefix } from "../core_chunk/main-
|
|
2
|
+
import { a as douyinAPP, c as xiaohongshuAPP, i as bilibiliAPP, o as kuaishouAPP, s as prefix } from "../core_chunk/main-BY6eDfoV.js";
|
|
3
3
|
import "../core_chunk/vendor-DxfKHvj-.js";
|
|
4
4
|
import "../core_chunk/template-DekmxKd7.js";
|
|
5
5
|
export { bilibiliAPP, douyinAPP, kuaishouAPP, prefix, xiaohongshuAPP };
|
package/lib/apps/update.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../core_chunk/rolldown-runtime-BMXAG3ag.js";
|
|
2
|
-
import { n as kkkUpdateCommand, r as update, t as kkkUpdate } from "../core_chunk/main-
|
|
2
|
+
import { n as kkkUpdateCommand, r as update, t as kkkUpdate } from "../core_chunk/main-BY6eDfoV.js";
|
|
3
3
|
import "../core_chunk/vendor-DxfKHvj-.js";
|
|
4
4
|
import "../core_chunk/template-DekmxKd7.js";
|
|
5
5
|
export { kkkUpdate, kkkUpdateCommand, update };
|
package/lib/build-metadata.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
3
|
-
"buildTime": "2026-03-
|
|
4
|
-
"buildTimestamp":
|
|
2
|
+
"version": "2.25.1",
|
|
3
|
+
"buildTime": "2026-03-11T02:39:23.980Z",
|
|
4
|
+
"buildTimestamp": 1773196763981,
|
|
5
5
|
"name": "karin-plugin-kkk",
|
|
6
6
|
"description": "Karin 的「抖音」「B 站」视频解析/动态推送插件",
|
|
7
7
|
"homepage": "https://github.com/ikenxuan/karin-plugin-kkk",
|
|
8
|
-
"commitHash": "
|
|
9
|
-
"shortCommitHash": "
|
|
8
|
+
"commitHash": "81f623e7cf8c1ee0af14ba3c417709705d54512c",
|
|
9
|
+
"shortCommitHash": "81f623e7"
|
|
10
10
|
}
|
|
@@ -7111,6 +7111,124 @@ var init_EmojiReaction = __esmMin(() => {
|
|
|
7111
7111
|
}
|
|
7112
7112
|
};
|
|
7113
7113
|
});
|
|
7114
|
+
var xmpHeaderBuffer, oppoExifHex, xiaomiExifHex, huaweiHonorLiveIdFallback, isJpegBuffer, getJpegDimensions, hasExifApp1, buildExifSegment, getSystemExifHex, resolveMotionPhotoSystem, buildMotionPhotoXmp, injectXmpToJpeg, readOrConvertToJpeg, buildGoogleMotionPhoto;
|
|
7115
|
+
var init_MotionPhoto = __esmMin(async () => {
|
|
7116
|
+
await init_Common();
|
|
7117
|
+
await init_Config();
|
|
7118
|
+
xmpHeaderBuffer = Buffer.from("http://ns.adobe.com/xap/1.0/\0", "utf8");
|
|
7119
|
+
oppoExifHex = "FFE100724578696600004D4D002A0000000800040100000400000001000005A001010004000000010000043C87690004000000010000003E011200030000000100000000000000000002928600020000000E0000005C920800040000000100000000000000006F706C75735F3833383836303800";
|
|
7120
|
+
xiaomiExifHex = "FFE1007E4578696600004D4D002A0000000800040100000400000001000005A001010004000000010000043C01120003000000010000000087690004000000010000003E000000000003889700010000000101000000920800040000000100000000928600020000000E00000068000000006F706C75735F3833383836303800";
|
|
7121
|
+
huaweiHonorLiveIdFallback = 1915884;
|
|
7122
|
+
isJpegBuffer = (fileBuffer) => fileBuffer.length > 2 && fileBuffer[0] === 255 && fileBuffer[1] === 216;
|
|
7123
|
+
getJpegDimensions = (jpegBuffer) => {
|
|
7124
|
+
let offset = 2;
|
|
7125
|
+
while (offset + 9 < jpegBuffer.length) {
|
|
7126
|
+
if (jpegBuffer[offset] !== 255) {
|
|
7127
|
+
offset += 1;
|
|
7128
|
+
continue;
|
|
7129
|
+
}
|
|
7130
|
+
const marker = jpegBuffer[offset + 1];
|
|
7131
|
+
if (marker === 216 || marker === 217 || marker === 1 || marker >= 208 && marker <= 215) {
|
|
7132
|
+
offset += 2;
|
|
7133
|
+
continue;
|
|
7134
|
+
}
|
|
7135
|
+
if (offset + 3 >= jpegBuffer.length) return null;
|
|
7136
|
+
const segmentLength = jpegBuffer.readUInt16BE(offset + 2);
|
|
7137
|
+
if (segmentLength < 2 || offset + 2 + segmentLength > jpegBuffer.length) return null;
|
|
7138
|
+
if ((marker >= 192 && marker <= 195 || marker >= 197 && marker <= 199 || marker >= 201 && marker <= 203 || marker >= 205 && marker <= 207) && segmentLength >= 7) {
|
|
7139
|
+
const height = jpegBuffer.readUInt16BE(offset + 5);
|
|
7140
|
+
const width = jpegBuffer.readUInt16BE(offset + 7);
|
|
7141
|
+
if (width > 0 && height > 0) return {
|
|
7142
|
+
width,
|
|
7143
|
+
height
|
|
7144
|
+
};
|
|
7145
|
+
return null;
|
|
7146
|
+
}
|
|
7147
|
+
offset += 2 + segmentLength;
|
|
7148
|
+
}
|
|
7149
|
+
return null;
|
|
7150
|
+
};
|
|
7151
|
+
hasExifApp1 = (jpegBuffer) => jpegBuffer.includes(Buffer.from("Exif\0\0", "binary"));
|
|
7152
|
+
buildExifSegment = (hex, width, height) => {
|
|
7153
|
+
const exifBuffer = Buffer.from(hex, "hex");
|
|
7154
|
+
exifBuffer[28] = width >> 24 & 255;
|
|
7155
|
+
exifBuffer[29] = width >> 16 & 255;
|
|
7156
|
+
exifBuffer[30] = width >> 8 & 255;
|
|
7157
|
+
exifBuffer[31] = width & 255;
|
|
7158
|
+
exifBuffer[40] = height >> 24 & 255;
|
|
7159
|
+
exifBuffer[41] = height >> 16 & 255;
|
|
7160
|
+
exifBuffer[42] = height >> 8 & 255;
|
|
7161
|
+
exifBuffer[43] = height & 255;
|
|
7162
|
+
return exifBuffer;
|
|
7163
|
+
};
|
|
7164
|
+
getSystemExifHex = (system) => {
|
|
7165
|
+
if (system === "oppo") return oppoExifHex;
|
|
7166
|
+
if (system === "xiaomi") return xiaomiExifHex;
|
|
7167
|
+
return null;
|
|
7168
|
+
};
|
|
7169
|
+
resolveMotionPhotoSystem = () => {
|
|
7170
|
+
const system = Config.app.livePhotoSystem;
|
|
7171
|
+
if (system === "google" || system === "xiaomi" || system === "oppo" || system === "huawei_honor") return system;
|
|
7172
|
+
return "google";
|
|
7173
|
+
};
|
|
7174
|
+
buildMotionPhotoXmp = (videoLength, presentationTimestampUs, system) => {
|
|
7175
|
+
if (system === "oppo") return `<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.1.0-jc003"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:hdrgm="http://ns.adobe.com/hdr-gain-map/1.0/" xmlns:GCamera="http://ns.google.com/photos/1.0/camera/" xmlns:OpCamera="http://ns.oplus.com/photos/1.0/camera/" xmlns:Container="http://ns.google.com/photos/1.0/container/" xmlns:Item="http://ns.google.com/photos/1.0/container/item/" hdrgm:Version="1.0" GCamera:MotionPhoto="1" GCamera:MotionPhotoVersion="1" GCamera:MotionPhotoPresentationTimestampUs="${presentationTimestampUs}" OpCamera:MotionPhotoPrimaryPresentationTimestampUs="${presentationTimestampUs}" OpCamera:MotionPhotoOwner="oplus" OpCamera:OLivePhotoVersion="2" OpCamera:VideoLength="${videoLength}"><Container:Directory><rdf:Seq><rdf:li rdf:parseType="Resource"><Container:Item Item:Mime="image/jpeg" Item:Semantic="Primary" Item:Length="0" Item:Padding="0" /></rdf:li><rdf:li rdf:parseType="Resource"><Container:Item Item:Mime="video/mp4" Item:Semantic="MotionPhoto" Item:Length="${videoLength}" /></rdf:li></rdf:Seq></Container:Directory></rdf:Description></rdf:RDF></x:xmpmeta>`;
|
|
7176
|
+
if (system === "xiaomi") return `<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.1.0-jc003"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:GCamera="http://ns.google.com/photos/1.0/camera/" xmlns:MiCamera="http://ns.xiaomi.com/photos/1.0/camera/" xmlns:Container="http://ns.google.com/photos/1.0/container/" xmlns:Item="http://ns.google.com/photos/1.0/container/item/" GCamera:MotionPhoto="1" GCamera:MotionPhotoVersion="1" GCamera:MotionPhotoPresentationTimestampUs="${presentationTimestampUs}" GCamera:MicroVideo="1" GCamera:MicroVideoVersion="1" GCamera:MicroVideoOffset="${videoLength}" GCamera:MicroVideoPresentationTimestampUs="${presentationTimestampUs}" MiCamera:XMPMeta="<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>"><Container:Directory><rdf:Seq><rdf:li rdf:parseType="Resource"><Container:Item Item:Mime="image/jpeg" Item:Semantic="Primary" Item:Length="0" Item:Padding="0" /></rdf:li><rdf:li rdf:parseType="Resource"><Container:Item Item:Mime="video/mp4" Item:Semantic="MotionPhoto" Item:Length="${videoLength}" Item:Padding="0" /></rdf:li></rdf:Seq></Container:Directory></rdf:Description></rdf:RDF></x:xmpmeta>`;
|
|
7177
|
+
return `<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.1.0-jc003"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:GCamera="http://ns.google.com/photos/1.0/camera/" xmlns:Container="http://ns.google.com/photos/1.0/container/" xmlns:Item="http://ns.google.com/photos/1.0/container/item/" GCamera:MotionPhoto="1" GCamera:MotionPhotoVersion="1" GCamera:MotionPhotoPresentationTimestampUs="${presentationTimestampUs}"><Container:Directory><rdf:Seq><rdf:li rdf:parseType="Resource"><Container:Item Item:Mime="image/jpeg" Item:Semantic="Primary" Item:Length="0" Item:Padding="0" /></rdf:li><rdf:li rdf:parseType="Resource"><Container:Item Item:Mime="video/mp4" Item:Semantic="MotionPhoto" Item:Length="${videoLength}" Item:Padding="0" /></rdf:li></rdf:Seq></Container:Directory></rdf:Description></rdf:RDF></x:xmpmeta>`;
|
|
7178
|
+
};
|
|
7179
|
+
injectXmpToJpeg = (jpegBuffer, xmpPacket, system) => {
|
|
7180
|
+
if (!isJpegBuffer(jpegBuffer)) throw new Error("输入图片不是 JPEG 格式");
|
|
7181
|
+
const xmpPayload = Buffer.concat([xmpHeaderBuffer, Buffer.from(xmpPacket, "utf8")]);
|
|
7182
|
+
const app1Length = xmpPayload.length + 2;
|
|
7183
|
+
if (app1Length > 65535) throw new Error("XMP 数据过大,无法写入 JPEG APP1");
|
|
7184
|
+
const app1Segment = Buffer.alloc(4);
|
|
7185
|
+
app1Segment[0] = 255;
|
|
7186
|
+
app1Segment[1] = 225;
|
|
7187
|
+
app1Segment.writeUInt16BE(app1Length, 2);
|
|
7188
|
+
const dimensions = getJpegDimensions(jpegBuffer);
|
|
7189
|
+
const exifHex = getSystemExifHex(system);
|
|
7190
|
+
const exifSegment = !hasExifApp1(jpegBuffer) && dimensions !== null && exifHex !== null ? buildExifSegment(exifHex, dimensions.width, dimensions.height) : null;
|
|
7191
|
+
return Buffer.concat([
|
|
7192
|
+
jpegBuffer.subarray(0, 2),
|
|
7193
|
+
...exifSegment ? [exifSegment] : [],
|
|
7194
|
+
app1Segment,
|
|
7195
|
+
xmpPayload,
|
|
7196
|
+
jpegBuffer.subarray(2)
|
|
7197
|
+
]);
|
|
7198
|
+
};
|
|
7199
|
+
readOrConvertToJpeg = async (imagePath) => {
|
|
7200
|
+
const sourceBuffer = fs.readFileSync(imagePath);
|
|
7201
|
+
if (isJpegBuffer(sourceBuffer)) return sourceBuffer;
|
|
7202
|
+
const tempJpegPath = path.join(Common.tempDri.images, `MotionPhoto_${Date.now()}_${Math.random().toString(36).slice(2)}.jpg`);
|
|
7203
|
+
if (!(await ffmpeg(`-y -i "${imagePath}" -frames:v 1 -q:v 2 "${tempJpegPath}"`)).status) throw new Error(`图片转换 JPEG 失败: ${imagePath}`);
|
|
7204
|
+
try {
|
|
7205
|
+
return fs.readFileSync(tempJpegPath);
|
|
7206
|
+
} finally {
|
|
7207
|
+
fs.rmSync(tempJpegPath, { force: true });
|
|
7208
|
+
}
|
|
7209
|
+
};
|
|
7210
|
+
buildGoogleMotionPhoto = async (options) => {
|
|
7211
|
+
const { imagePath, videoPath, outputPath, presentationTimestampUs } = options;
|
|
7212
|
+
try {
|
|
7213
|
+
const system = resolveMotionPhotoSystem();
|
|
7214
|
+
const imageBuffer = await readOrConvertToJpeg(imagePath);
|
|
7215
|
+
const videoBuffer = fs.readFileSync(videoPath);
|
|
7216
|
+
const resolvedPresentationTimestampUs = presentationTimestampUs === void 0 || presentationTimestampUs < 0 ? 0 : presentationTimestampUs;
|
|
7217
|
+
const huaweiHonorFooter = Buffer.from(`v2_f35 409:1000 LIVE_${resolvedPresentationTimestampUs > 0 ? Math.floor(resolvedPresentationTimestampUs) : huaweiHonorLiveIdFallback}`, "utf8");
|
|
7218
|
+
const outputBuffer = system === "huawei_honor" ? Buffer.concat([imageBuffer, huaweiHonorFooter]) : (() => {
|
|
7219
|
+
const jpegWithXmp = injectXmpToJpeg(imageBuffer, buildMotionPhotoXmp(videoBuffer.length, resolvedPresentationTimestampUs, system), system);
|
|
7220
|
+
return Buffer.concat([jpegWithXmp, videoBuffer]);
|
|
7221
|
+
})();
|
|
7222
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
7223
|
+
fs.writeFileSync(outputPath, outputBuffer);
|
|
7224
|
+
logger.debug(`Motion Photo 封面生成成功(${system}): ${outputPath}`);
|
|
7225
|
+
return true;
|
|
7226
|
+
} catch (error) {
|
|
7227
|
+
logger.error("Motion Photo 封面生成失败", error);
|
|
7228
|
+
return false;
|
|
7229
|
+
}
|
|
7230
|
+
};
|
|
7231
|
+
});
|
|
7114
7232
|
async function fixM4sFile(inputPath, outputPath) {
|
|
7115
7233
|
const result = await ffmpeg(`-y -i "${inputPath}" -c copy -movflags +faststart "${outputPath}"`);
|
|
7116
7234
|
if (result.status) logger.debug(`m4s 文件修复成功: ${outputPath}`);
|
|
@@ -7123,7 +7241,7 @@ async function getMediaDuration(path$1) {
|
|
|
7123
7241
|
}
|
|
7124
7242
|
async function mergeVideoAudio(videoPath, audioPath, resultPath) {
|
|
7125
7243
|
const result = await ffmpeg(`-y -i "${videoPath}" -i "${audioPath}" -c copy "${resultPath}"`);
|
|
7126
|
-
if (result.status) logger.
|
|
7244
|
+
if (result.status) logger.debug(`视频合成成功: ${resultPath}`);
|
|
7127
7245
|
else logger.error("视频合成失败", result);
|
|
7128
7246
|
return result.status;
|
|
7129
7247
|
}
|
|
@@ -7131,7 +7249,7 @@ async function compressVideo(options) {
|
|
|
7131
7249
|
const { inputPath, outputPath, targetBitrate, maxRate = targetBitrate * 1.5, bufSize = targetBitrate * 2, crf = 35, removeSource = true } = options;
|
|
7132
7250
|
const result = await ffmpeg(`-y -i "${inputPath}" -b:v ${targetBitrate}k -maxrate ${maxRate}k -bufsize ${bufSize}k -crf ${crf} -preset medium -c:v libx264 -vf "scale='if(gte(iw/ih,16/9),1280,-1)':'if(gte(iw/ih,16/9),-1,720)',scale=ceil(iw/2)*2:ceil(ih/2)*2" "${outputPath}"`);
|
|
7133
7251
|
if (result.status) {
|
|
7134
|
-
logger.
|
|
7252
|
+
logger.debug(`视频压缩成功: ${outputPath}`);
|
|
7135
7253
|
if (removeSource) Common.removeFile(inputPath);
|
|
7136
7254
|
} else logger.error(`视频压缩失败: ${inputPath}`, result);
|
|
7137
7255
|
return result.status;
|
|
@@ -7139,6 +7257,7 @@ async function compressVideo(options) {
|
|
|
7139
7257
|
var getMediaFrameRate, loopVideoWithTransition;
|
|
7140
7258
|
var init_FFmpeg = __esmMin(async () => {
|
|
7141
7259
|
await init_utils$1();
|
|
7260
|
+
await init_MotionPhoto();
|
|
7142
7261
|
getMediaFrameRate = async (path$1) => {
|
|
7143
7262
|
const { stdout } = await ffprobe(`-v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=noprint_wrappers=1:nokey=1 "${path$1}"`);
|
|
7144
7263
|
const rate = stdout.trim();
|
|
@@ -7214,7 +7333,7 @@ var init_FFmpeg = __esmMin(async () => {
|
|
|
7214
7333
|
else bgmInputArgs = `-stream_loop ${Math.ceil(totalDuration / baseContext.bgmDuration) + 1} -ss ${bgmStartTime} -i "${bgmPath}"`;
|
|
7215
7334
|
} else if (bgmNeedLoop) bgmInputArgs = `-stream_loop ${Math.max(0, Math.ceil(totalDuration / baseContext.bgmDuration) - 1)} -i "${bgmPath}"`;
|
|
7216
7335
|
const result$1 = await ffmpeg(`-y ${inputArgs} ${bgmInputArgs} -filter_complex "${filterComplex};[0:a][${bgmInputIndex}:a]amix=inputs=2:duration=longest:dropout_transition=3[aout]" -map "[outv]" -map "[aout]" -c:v libx264 -c:a aac -b:a 192k -pix_fmt yuv420p -shortest "${outputPath}"`);
|
|
7217
|
-
if (result$1.status) logger.
|
|
7336
|
+
if (result$1.status) logger.debug(`Live Photo 效果视频重放成功: ${outputPath}`);
|
|
7218
7337
|
else logger.error("Live Photo 效果视频重放失败", result$1);
|
|
7219
7338
|
if (mergeMode === "continuous") {
|
|
7220
7339
|
const outputDuration = result$1.status ? await getMediaDuration(outputPath) : totalDuration;
|
|
@@ -7230,7 +7349,7 @@ var init_FFmpeg = __esmMin(async () => {
|
|
|
7230
7349
|
};
|
|
7231
7350
|
}
|
|
7232
7351
|
const result = await ffmpeg(`-y ${inputArgs} -filter_complex "${filterComplex}" -map "[outv]" -c:v libx264 -pix_fmt yuv420p "${outputPath}"`);
|
|
7233
|
-
if (result.status) logger.
|
|
7352
|
+
if (result.status) logger.debug(`Live Photo 效果视频重放成功: ${outputPath}`);
|
|
7234
7353
|
else logger.error("Live Photo 效果视频重放失败", result);
|
|
7235
7354
|
return { success: result.status };
|
|
7236
7355
|
};
|
|
@@ -8158,6 +8277,7 @@ var init_utils$1 = __esmMin(async () => {
|
|
|
8158
8277
|
init_EmojiReaction();
|
|
8159
8278
|
init_FFmpeg();
|
|
8160
8279
|
init_ImageHelper();
|
|
8280
|
+
init_MotionPhoto();
|
|
8161
8281
|
init_Networks();
|
|
8162
8282
|
init_QRCodeScanner();
|
|
8163
8283
|
init_Render();
|
|
@@ -11051,6 +11171,35 @@ var init_app_schema = __esmMin(() => {
|
|
|
11051
11171
|
error: "请输入一个范围在 1000 到 20000 之间的数字"
|
|
11052
11172
|
}]
|
|
11053
11173
|
},
|
|
11174
|
+
{
|
|
11175
|
+
type: "divider",
|
|
11176
|
+
title: "Live Photo 兼容设置"
|
|
11177
|
+
},
|
|
11178
|
+
{
|
|
11179
|
+
key: "livePhotoSystem",
|
|
11180
|
+
type: "radio",
|
|
11181
|
+
label: "Live Photo 静态图兼容系统",
|
|
11182
|
+
description: "当解析到作品/动态包含 Live Photo 时,合并转发里发送的 Live Photo 静态图按所选系统生成",
|
|
11183
|
+
orientation: "horizontal",
|
|
11184
|
+
options: [
|
|
11185
|
+
{
|
|
11186
|
+
label: "Google",
|
|
11187
|
+
value: "google"
|
|
11188
|
+
},
|
|
11189
|
+
{
|
|
11190
|
+
label: "小米(HyperOS)",
|
|
11191
|
+
value: "xiaomi"
|
|
11192
|
+
},
|
|
11193
|
+
{
|
|
11194
|
+
label: "OPPO(ColorOS)",
|
|
11195
|
+
value: "oppo"
|
|
11196
|
+
},
|
|
11197
|
+
{
|
|
11198
|
+
label: "华为/荣耀(HarmonyOS/MagicOS)",
|
|
11199
|
+
value: "huawei_honor"
|
|
11200
|
+
}
|
|
11201
|
+
]
|
|
11202
|
+
},
|
|
11054
11203
|
{
|
|
11055
11204
|
type: "divider",
|
|
11056
11205
|
title: "API服务配置"
|
|
@@ -14431,6 +14580,34 @@ const webConfig = defineConfig({
|
|
|
14431
14580
|
error: "请输入一个范围在 1000 到 20000 之间的数字"
|
|
14432
14581
|
}]
|
|
14433
14582
|
}),
|
|
14583
|
+
components.divider.create("divider-app-live-photo", {
|
|
14584
|
+
description: "Live Photo 兼容设置",
|
|
14585
|
+
descPosition: 20
|
|
14586
|
+
}),
|
|
14587
|
+
components.radio.group("livePhotoSystem", {
|
|
14588
|
+
label: "Live Photo 静态图兼容系统",
|
|
14589
|
+
description: "当解析到作品/动态包含 Live Photo 时,合并转发里发送的 Live Photo 静态图按所选系统生成",
|
|
14590
|
+
orientation: "horizontal",
|
|
14591
|
+
defaultValue: all.app.livePhotoSystem || "google",
|
|
14592
|
+
radio: [
|
|
14593
|
+
components.radio.create("livePhotoSystem-google", {
|
|
14594
|
+
label: "Google",
|
|
14595
|
+
value: "google"
|
|
14596
|
+
}),
|
|
14597
|
+
components.radio.create("livePhotoSystem-xiaomi", {
|
|
14598
|
+
label: "小米(HyperOS)",
|
|
14599
|
+
value: "xiaomi"
|
|
14600
|
+
}),
|
|
14601
|
+
components.radio.create("livePhotoSystem-oppo", {
|
|
14602
|
+
label: "OPPO(ColorOS)",
|
|
14603
|
+
value: "oppo"
|
|
14604
|
+
}),
|
|
14605
|
+
components.radio.create("livePhotoSystem-huawei-honor", {
|
|
14606
|
+
label: "华为/荣耀(HarmonyOS/MagicOS)",
|
|
14607
|
+
value: "huawei_honor"
|
|
14608
|
+
})
|
|
14609
|
+
]
|
|
14610
|
+
}),
|
|
14434
14611
|
components.divider.create("divider-app-api", {
|
|
14435
14612
|
description: "API服务配置",
|
|
14436
14613
|
descPosition: 20
|
|
@@ -15792,6 +15969,10 @@ var Bilibili = class extends Base {
|
|
|
15792
15969
|
headers: BASE_HEADERS,
|
|
15793
15970
|
filepath: Common.tempDri.images + `Bilibili_static_${Date.now()}_${index}.jpg`
|
|
15794
15971
|
});
|
|
15972
|
+
if (staticImg.filepath) temp.push({
|
|
15973
|
+
filepath: staticImg.filepath,
|
|
15974
|
+
totalBytes: 0
|
|
15975
|
+
});
|
|
15795
15976
|
const loopCount = 3;
|
|
15796
15977
|
if (!staticImg.filepath) {
|
|
15797
15978
|
await Common.removeFile(livePhoto.filepath, true);
|
|
@@ -15808,16 +15989,35 @@ var Bilibili = class extends Base {
|
|
|
15808
15989
|
const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
|
|
15809
15990
|
fs.renameSync(outputPath, filePath);
|
|
15810
15991
|
logger.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
|
|
15811
|
-
logger.mark("正在尝试删除缓存文件");
|
|
15812
|
-
await Common.removeFile(livePhoto.filepath, true);
|
|
15813
15992
|
temp.push({
|
|
15814
15993
|
filepath: filePath,
|
|
15815
15994
|
totalBytes: 0
|
|
15816
15995
|
});
|
|
15817
15996
|
const videoPath = Config.upload.videoSendMode === "base64" ? `base64://${fs.readFileSync(filePath).toString("base64")}` : `file://${filePath}`;
|
|
15818
15997
|
imgArray.push(segment.video(videoPath));
|
|
15819
|
-
|
|
15820
|
-
|
|
15998
|
+
let hasPushedMotionPhotoCover = false;
|
|
15999
|
+
if (staticImg.filepath) {
|
|
16000
|
+
const motionPhotoCoverPath = Common.tempDri.images + `MVIMG_${format(/* @__PURE__ */ new Date(), "yyyyMMdd_HHmmss_SSS")}_${index}.jpg`;
|
|
16001
|
+
if (await buildGoogleMotionPhoto({
|
|
16002
|
+
imagePath: staticImg.filepath,
|
|
16003
|
+
videoPath: livePhoto.filepath,
|
|
16004
|
+
outputPath: motionPhotoCoverPath
|
|
16005
|
+
})) {
|
|
16006
|
+
temp.push({
|
|
16007
|
+
filepath: motionPhotoCoverPath,
|
|
16008
|
+
totalBytes: 0
|
|
16009
|
+
});
|
|
16010
|
+
const motionPhotoCover = Config.upload.imageSendMode === "base64" ? `base64://${fs.readFileSync(motionPhotoCoverPath).toString("base64")}` : `file://${motionPhotoCoverPath}`;
|
|
16011
|
+
imgArray.push(segment.image(motionPhotoCover));
|
|
16012
|
+
hasPushedMotionPhotoCover = true;
|
|
16013
|
+
}
|
|
16014
|
+
}
|
|
16015
|
+
if (!hasPushedMotionPhotoCover) {
|
|
16016
|
+
const imageUrl = await processImageUrl(img$2.url, title, index);
|
|
16017
|
+
imgArray.push(segment.image(imageUrl));
|
|
16018
|
+
}
|
|
16019
|
+
logger.mark("正在尝试删除缓存文件");
|
|
16020
|
+
await Common.removeFile(livePhoto.filepath, true);
|
|
15821
16021
|
} else await Common.removeFile(livePhoto.filepath, true);
|
|
15822
16022
|
}
|
|
15823
16023
|
} else {
|
|
@@ -17602,6 +17802,10 @@ var Bilibilipush = class extends Base {
|
|
|
17602
17802
|
headers: bilibiliBaseHeaders,
|
|
17603
17803
|
filepath: Common.tempDri.images + `Bilibili_static_${Date.now()}_${index}.jpg`
|
|
17604
17804
|
});
|
|
17805
|
+
if (staticImg.filepath) temp.push({
|
|
17806
|
+
filepath: staticImg.filepath,
|
|
17807
|
+
totalBytes: 0
|
|
17808
|
+
});
|
|
17605
17809
|
const loopCount = 3;
|
|
17606
17810
|
if (!staticImg.filepath) {
|
|
17607
17811
|
await Common.removeFile(livePhoto.filepath, true);
|
|
@@ -17617,16 +17821,35 @@ var Bilibilipush = class extends Base {
|
|
|
17617
17821
|
const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
|
|
17618
17822
|
fs.renameSync(outputPath, filePath);
|
|
17619
17823
|
logger.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
|
|
17620
|
-
logger.mark("正在尝试删除缓存文件");
|
|
17621
|
-
await Common.removeFile(staticImg.filepath, true);
|
|
17622
17824
|
temp.push({
|
|
17623
17825
|
filepath: filePath,
|
|
17624
17826
|
totalBytes: 0
|
|
17625
17827
|
});
|
|
17626
17828
|
const videoPath = Config.upload.videoSendMode === "base64" ? `base64://${fs.readFileSync(filePath).toString("base64")}` : `file://${filePath}`;
|
|
17627
17829
|
imgArray.push(segment.video(videoPath));
|
|
17628
|
-
|
|
17629
|
-
|
|
17830
|
+
let hasPushedMotionPhotoCover = false;
|
|
17831
|
+
if (staticImg.filepath) {
|
|
17832
|
+
const motionPhotoCoverPath = Common.tempDri.images + `MVIMG_${Date.now()}_${index}.jpg`;
|
|
17833
|
+
if (await buildGoogleMotionPhoto({
|
|
17834
|
+
imagePath: staticImg.filepath,
|
|
17835
|
+
videoPath: livePhoto.filepath,
|
|
17836
|
+
outputPath: motionPhotoCoverPath
|
|
17837
|
+
})) {
|
|
17838
|
+
temp.push({
|
|
17839
|
+
filepath: motionPhotoCoverPath,
|
|
17840
|
+
totalBytes: 0
|
|
17841
|
+
});
|
|
17842
|
+
const motionPhotoCover = Config.upload.imageSendMode === "base64" ? `base64://${fs.readFileSync(motionPhotoCoverPath).toString("base64")}` : `file://${motionPhotoCoverPath}`;
|
|
17843
|
+
imgArray.push(segment.image(motionPhotoCover));
|
|
17844
|
+
hasPushedMotionPhotoCover = true;
|
|
17845
|
+
}
|
|
17846
|
+
}
|
|
17847
|
+
if (!hasPushedMotionPhotoCover) {
|
|
17848
|
+
const imageUrl = await processImageUrl(imageSrc, title, index);
|
|
17849
|
+
imgArray.push(segment.image(imageUrl));
|
|
17850
|
+
}
|
|
17851
|
+
logger.mark("正在尝试删除缓存文件");
|
|
17852
|
+
await Common.removeFile(livePhoto.filepath, true);
|
|
17630
17853
|
continue;
|
|
17631
17854
|
}
|
|
17632
17855
|
await Common.removeFile(livePhoto.filepath, true);
|
|
@@ -18498,11 +18721,18 @@ var DouYin = class extends Base {
|
|
|
18498
18721
|
const outputPath = Common.tempDri.video + `Douyin_Result_${Date.now()}.mp4`;
|
|
18499
18722
|
const loopCount = imageItem.clip_type === 4 ? 1 : 3;
|
|
18500
18723
|
let staticImgPath = "";
|
|
18501
|
-
if (imageItem.url_list?.[0])
|
|
18502
|
-
|
|
18503
|
-
|
|
18504
|
-
|
|
18505
|
-
|
|
18724
|
+
if (imageItem.url_list?.[0]) {
|
|
18725
|
+
const staticImg = await downloadFile(imageItem.url_list[0], {
|
|
18726
|
+
title: `Douyin_static_${Date.now()}_${index}.jpg`,
|
|
18727
|
+
headers: this.headers,
|
|
18728
|
+
filepath: Common.tempDri.images + `Douyin_static_${Date.now()}_${index}.jpg`
|
|
18729
|
+
});
|
|
18730
|
+
temp.push({
|
|
18731
|
+
filepath: staticImg.filepath,
|
|
18732
|
+
totalBytes: 0
|
|
18733
|
+
});
|
|
18734
|
+
staticImgPath = staticImg.filepath ?? "";
|
|
18735
|
+
}
|
|
18506
18736
|
const transitionEnabled = loopCount > 1 && Boolean(staticImgPath);
|
|
18507
18737
|
const safeStaticPath = staticImgPath || liveimg.filepath;
|
|
18508
18738
|
const result = await loopVideoWithTransition({
|
|
@@ -18521,8 +18751,6 @@ var DouYin = class extends Base {
|
|
|
18521
18751
|
const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
|
|
18522
18752
|
fs.renameSync(outputPath, filePath);
|
|
18523
18753
|
logger.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
|
|
18524
|
-
logger.mark("正在尝试删除缓存文件");
|
|
18525
|
-
await Common.removeFile(liveimg.filepath, true);
|
|
18526
18754
|
temp.push({
|
|
18527
18755
|
filepath: filePath,
|
|
18528
18756
|
totalBytes: 0
|
|
@@ -18530,9 +18758,30 @@ var DouYin = class extends Base {
|
|
|
18530
18758
|
const videoPath = Config.upload.videoSendMode === "base64" ? `base64://${fs.readFileSync(filePath).toString("base64")}` : `file://${filePath}`;
|
|
18531
18759
|
processedImages.push(segment.video(videoPath));
|
|
18532
18760
|
if (imageItem.clip_type === 5 && imageItem.url_list?.[0]) {
|
|
18533
|
-
|
|
18534
|
-
|
|
18761
|
+
let hasPushedMotionPhotoCover = false;
|
|
18762
|
+
if (staticImgPath) {
|
|
18763
|
+
const motionPhotoCoverPath = Common.tempDri.images + `MVIMG_${format(/* @__PURE__ */ new Date(), "yyyyMMdd_HHmmss_SSS")}_${index}.jpg`;
|
|
18764
|
+
if (await buildGoogleMotionPhoto({
|
|
18765
|
+
imagePath: staticImgPath,
|
|
18766
|
+
videoPath: liveimg.filepath,
|
|
18767
|
+
outputPath: motionPhotoCoverPath
|
|
18768
|
+
})) {
|
|
18769
|
+
temp.push({
|
|
18770
|
+
filepath: motionPhotoCoverPath,
|
|
18771
|
+
totalBytes: 0
|
|
18772
|
+
});
|
|
18773
|
+
const motionPhotoCover = Config.upload.imageSendMode === "base64" ? `base64://${fs.readFileSync(motionPhotoCoverPath).toString("base64")}` : `file://${motionPhotoCoverPath}`;
|
|
18774
|
+
processedImages.push(segment.image(motionPhotoCover));
|
|
18775
|
+
hasPushedMotionPhotoCover = true;
|
|
18776
|
+
}
|
|
18777
|
+
}
|
|
18778
|
+
if (!hasPushedMotionPhotoCover) {
|
|
18779
|
+
const imageUrl = await processImageUrl(imageItem.url_list[0], g_title, index);
|
|
18780
|
+
processedImages.push(segment.image(imageUrl));
|
|
18781
|
+
}
|
|
18535
18782
|
}
|
|
18783
|
+
logger.mark("正在尝试删除缓存文件");
|
|
18784
|
+
await Common.removeFile(liveimg.filepath, true);
|
|
18536
18785
|
} else await Common.removeFile(liveimg.filepath, true);
|
|
18537
18786
|
}
|
|
18538
18787
|
}
|
|
@@ -18612,11 +18861,18 @@ var DouYin = class extends Base {
|
|
|
18612
18861
|
const outputPath = Common.tempDri.video + `Douyin_Result_${Date.now()}.mp4`;
|
|
18613
18862
|
const loopCount = item.clip_type === 4 ? 1 : 3;
|
|
18614
18863
|
let staticImgPath = "";
|
|
18615
|
-
if (item.url_list?.[0])
|
|
18616
|
-
|
|
18617
|
-
|
|
18618
|
-
|
|
18619
|
-
|
|
18864
|
+
if (item.url_list?.[0]) {
|
|
18865
|
+
const staticImg = await downloadFile(item.url_list[0], {
|
|
18866
|
+
title: `Douyin_static_${Date.now()}_${index}.jpg`,
|
|
18867
|
+
headers: this.headers,
|
|
18868
|
+
filepath: Common.tempDri.images + `Douyin_static_${Date.now()}_${index}.jpg`
|
|
18869
|
+
});
|
|
18870
|
+
temp.push({
|
|
18871
|
+
filepath: staticImg.filepath,
|
|
18872
|
+
totalBytes: 0
|
|
18873
|
+
});
|
|
18874
|
+
staticImgPath = staticImg.filepath ?? "";
|
|
18875
|
+
}
|
|
18620
18876
|
const transitionEnabled = loopCount > 1 && Boolean(staticImgPath);
|
|
18621
18877
|
const safeStaticPath = staticImgPath || livePhoto.filepath;
|
|
18622
18878
|
const result = await loopVideoWithTransition({
|
|
@@ -18635,8 +18891,6 @@ var DouYin = class extends Base {
|
|
|
18635
18891
|
const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
|
|
18636
18892
|
fs.renameSync(outputPath, filePath);
|
|
18637
18893
|
logger.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
|
|
18638
|
-
logger.mark("正在尝试删除缓存文件");
|
|
18639
|
-
await Common.removeFile(livePhoto.filepath, true);
|
|
18640
18894
|
temp.push({
|
|
18641
18895
|
filepath: filePath,
|
|
18642
18896
|
totalBytes: 0
|
|
@@ -18644,9 +18898,30 @@ var DouYin = class extends Base {
|
|
|
18644
18898
|
const videoPath = Config.upload.videoSendMode === "base64" ? `base64://${fs.readFileSync(filePath).toString("base64")}` : `file://${filePath}`;
|
|
18645
18899
|
images.push(segment.video(videoPath));
|
|
18646
18900
|
if (item.clip_type === 5 && item.url_list?.[0]) {
|
|
18647
|
-
|
|
18648
|
-
|
|
18901
|
+
let hasPushedMotionPhotoCover = false;
|
|
18902
|
+
if (staticImgPath) {
|
|
18903
|
+
const motionPhotoCoverPath = Common.tempDri.images + `MVIMG_${format(/* @__PURE__ */ new Date(), "yyyyMMdd_HHmmss_SSS")}_${index}.jpg`;
|
|
18904
|
+
if (await buildGoogleMotionPhoto({
|
|
18905
|
+
imagePath: staticImgPath,
|
|
18906
|
+
videoPath: livePhoto.filepath,
|
|
18907
|
+
outputPath: motionPhotoCoverPath
|
|
18908
|
+
})) {
|
|
18909
|
+
temp.push({
|
|
18910
|
+
filepath: motionPhotoCoverPath,
|
|
18911
|
+
totalBytes: 0
|
|
18912
|
+
});
|
|
18913
|
+
const motionPhotoCover = Config.upload.imageSendMode === "base64" ? `base64://${fs.readFileSync(motionPhotoCoverPath).toString("base64")}` : `file://${motionPhotoCoverPath}`;
|
|
18914
|
+
images.push(segment.image(motionPhotoCover));
|
|
18915
|
+
hasPushedMotionPhotoCover = true;
|
|
18916
|
+
}
|
|
18917
|
+
}
|
|
18918
|
+
if (!hasPushedMotionPhotoCover) {
|
|
18919
|
+
const imageUrl = await processImageUrl(item.url_list[0], g_title, index);
|
|
18920
|
+
images.push(segment.image(imageUrl));
|
|
18921
|
+
}
|
|
18649
18922
|
}
|
|
18923
|
+
logger.mark("正在尝试删除缓存文件");
|
|
18924
|
+
await Common.removeFile(livePhoto.filepath, true);
|
|
18650
18925
|
} else await Common.removeFile(livePhoto.filepath, true);
|
|
18651
18926
|
}
|
|
18652
18927
|
}
|
|
@@ -18670,11 +18945,12 @@ var DouYin = class extends Base {
|
|
|
18670
18945
|
if (music.play_url.uri === "") music_url = JSON.parse(music.extra).original_song_url;
|
|
18671
18946
|
else music_url = music.play_url.uri;
|
|
18672
18947
|
if (!isVideo && Config.app.removeCache === false && music_url !== void 0) try {
|
|
18673
|
-
const
|
|
18674
|
-
|
|
18675
|
-
|
|
18676
|
-
|
|
18677
|
-
|
|
18948
|
+
const title = g_title ?? VideoData.data.aweme_detail.preview_title.substring(0, 50).replace(/[\\/:*?"<>|\r\n]/g, " ");
|
|
18949
|
+
const path$1 = Common.tempDri.images + `${title}.mp3`;
|
|
18950
|
+
await downloadFile(music_url, {
|
|
18951
|
+
title,
|
|
18952
|
+
filepath: path$1
|
|
18953
|
+
});
|
|
18678
18954
|
} catch (error) {
|
|
18679
18955
|
console.log(error);
|
|
18680
18956
|
}
|
|
@@ -19739,11 +20015,18 @@ var DouYinpush = class extends Base {
|
|
|
19739
20015
|
const outputPath = Common.tempDri.video + `Douyin_Result_${Date.now()}.mp4`;
|
|
19740
20016
|
const loopCount = item.clip_type === 4 ? 1 : 3;
|
|
19741
20017
|
let staticImgPath = "";
|
|
19742
|
-
if (item.url_list?.[0])
|
|
19743
|
-
|
|
19744
|
-
|
|
19745
|
-
|
|
19746
|
-
|
|
20018
|
+
if (item.url_list?.[0]) {
|
|
20019
|
+
const staticImg = await downloadFile(item.url_list[0], {
|
|
20020
|
+
title: `Douyin_static_${Date.now()}_${index}.jpg`,
|
|
20021
|
+
headers: douyinBaseHeaders,
|
|
20022
|
+
filepath: Common.tempDri.images + `Douyin_static_${Date.now()}_${index}.jpg`
|
|
20023
|
+
});
|
|
20024
|
+
if (staticImg.filepath) temp.push({
|
|
20025
|
+
filepath: staticImg.filepath,
|
|
20026
|
+
totalBytes: 0
|
|
20027
|
+
});
|
|
20028
|
+
staticImgPath = staticImg.filepath ?? "";
|
|
20029
|
+
}
|
|
19747
20030
|
const transitionEnabled = loopCount > 1 && Boolean(staticImgPath);
|
|
19748
20031
|
const safeStaticPath = staticImgPath || liveimg.filepath;
|
|
19749
20032
|
const result = await loopVideoWithTransition({
|
|
@@ -19762,8 +20045,6 @@ var DouYinpush = class extends Base {
|
|
|
19762
20045
|
const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
|
|
19763
20046
|
fs.renameSync(outputPath, filePath);
|
|
19764
20047
|
logger.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
|
|
19765
|
-
logger.mark("正在尝试删除缓存文件");
|
|
19766
|
-
await Common.removeFile(liveimg.filepath, true);
|
|
19767
20048
|
temp.push({
|
|
19768
20049
|
filepath: filePath,
|
|
19769
20050
|
totalBytes: 0
|
|
@@ -19771,9 +20052,30 @@ var DouYinpush = class extends Base {
|
|
|
19771
20052
|
const videoPath = Config.upload.videoSendMode === "base64" ? `base64://${fs.readFileSync(filePath).toString("base64")}` : `file://${filePath}`;
|
|
19772
20053
|
images.push(segment.video(videoPath));
|
|
19773
20054
|
if (item.clip_type === 5 && item.url_list?.[0]) {
|
|
19774
|
-
|
|
19775
|
-
|
|
20055
|
+
let hasPushedMotionPhotoCover = false;
|
|
20056
|
+
if (staticImgPath) {
|
|
20057
|
+
const motionPhotoCoverPath = Common.tempDri.images + `MVIMG_${format(/* @__PURE__ */ new Date(), "yyyyMMdd_HHmmss_SSS")}_${index}.jpg`;
|
|
20058
|
+
if (await buildGoogleMotionPhoto({
|
|
20059
|
+
imagePath: staticImgPath,
|
|
20060
|
+
videoPath: liveimg.filepath,
|
|
20061
|
+
outputPath: motionPhotoCoverPath
|
|
20062
|
+
})) {
|
|
20063
|
+
temp.push({
|
|
20064
|
+
filepath: motionPhotoCoverPath,
|
|
20065
|
+
totalBytes: 0
|
|
20066
|
+
});
|
|
20067
|
+
const motionPhotoCover = Config.upload.imageSendMode === "base64" ? `base64://${fs.readFileSync(motionPhotoCoverPath).toString("base64")}` : `file://${motionPhotoCoverPath}`;
|
|
20068
|
+
images.push(segment.image(motionPhotoCover));
|
|
20069
|
+
hasPushedMotionPhotoCover = true;
|
|
20070
|
+
}
|
|
20071
|
+
}
|
|
20072
|
+
if (!hasPushedMotionPhotoCover) {
|
|
20073
|
+
const imageUrl = await processImageUrl(item.url_list[0], Detail_Data.desc, index);
|
|
20074
|
+
images.push(segment.image(imageUrl));
|
|
20075
|
+
}
|
|
19776
20076
|
}
|
|
20077
|
+
logger.mark("正在尝试删除缓存文件");
|
|
20078
|
+
await Common.removeFile(liveimg.filepath, true);
|
|
19777
20079
|
} else await Common.removeFile(liveimg.filepath, true);
|
|
19778
20080
|
}
|
|
19779
20081
|
}
|
|
@@ -19821,11 +20123,18 @@ var DouYinpush = class extends Base {
|
|
|
19821
20123
|
const outputPath = Common.tempDri.video + `Douyin_Result_${Date.now()}.mp4`;
|
|
19822
20124
|
const loopCount = item.clip_type === 4 ? 1 : 3;
|
|
19823
20125
|
let staticImgPath = "";
|
|
19824
|
-
if (item.url_list?.[0])
|
|
19825
|
-
|
|
19826
|
-
|
|
19827
|
-
|
|
19828
|
-
|
|
20126
|
+
if (item.url_list?.[0]) {
|
|
20127
|
+
const staticImg = await downloadFile(item.url_list[0], {
|
|
20128
|
+
title: `Douyin_static_${Date.now()}_${index}.jpg`,
|
|
20129
|
+
headers: douyinBaseHeaders,
|
|
20130
|
+
filepath: Common.tempDri.images + `Douyin_static_${Date.now()}_${index}.jpg`
|
|
20131
|
+
});
|
|
20132
|
+
if (staticImg.filepath) temp.push({
|
|
20133
|
+
filepath: staticImg.filepath,
|
|
20134
|
+
totalBytes: 0
|
|
20135
|
+
});
|
|
20136
|
+
staticImgPath = staticImg.filepath ?? "";
|
|
20137
|
+
}
|
|
19829
20138
|
const transitionEnabled = loopCount > 1 && Boolean(staticImgPath);
|
|
19830
20139
|
const safeStaticPath = staticImgPath || liveimg.filepath;
|
|
19831
20140
|
const result = await loopVideoWithTransition({
|
|
@@ -19844,8 +20153,6 @@ var DouYinpush = class extends Base {
|
|
|
19844
20153
|
const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
|
|
19845
20154
|
fs.renameSync(outputPath, filePath);
|
|
19846
20155
|
logger.mark(`视频文件重命名完成: ${outputPath.split("/").pop()} -> ${filePath.split("/").pop()}`);
|
|
19847
|
-
logger.mark("正在尝试删除缓存文件");
|
|
19848
|
-
await Common.removeFile(liveimg.filepath, true);
|
|
19849
20156
|
temp.push({
|
|
19850
20157
|
filepath: filePath,
|
|
19851
20158
|
totalBytes: 0
|
|
@@ -19853,9 +20160,30 @@ var DouYinpush = class extends Base {
|
|
|
19853
20160
|
const videoPath = Config.upload.videoSendMode === "base64" ? `base64://${fs.readFileSync(filePath).toString("base64")}` : `file://${filePath}`;
|
|
19854
20161
|
processedImages.push(segment.video(videoPath));
|
|
19855
20162
|
if (item.clip_type === 5 && item.url_list?.[0]) {
|
|
19856
|
-
|
|
19857
|
-
|
|
20163
|
+
let hasPushedMotionPhotoCover = false;
|
|
20164
|
+
if (staticImgPath) {
|
|
20165
|
+
const motionPhotoCoverPath = Common.tempDri.images + `MVIMG_${format(/* @__PURE__ */ new Date(), "yyyyMMdd_HHmmss_SSS")}_${index}.jpg`;
|
|
20166
|
+
if (await buildGoogleMotionPhoto({
|
|
20167
|
+
imagePath: staticImgPath,
|
|
20168
|
+
videoPath: liveimg.filepath,
|
|
20169
|
+
outputPath: motionPhotoCoverPath
|
|
20170
|
+
})) {
|
|
20171
|
+
temp.push({
|
|
20172
|
+
filepath: motionPhotoCoverPath,
|
|
20173
|
+
totalBytes: 0
|
|
20174
|
+
});
|
|
20175
|
+
const motionPhotoCover = Config.upload.imageSendMode === "base64" ? `base64://${fs.readFileSync(motionPhotoCoverPath).toString("base64")}` : `file://${motionPhotoCoverPath}`;
|
|
20176
|
+
processedImages.push(segment.image(motionPhotoCover));
|
|
20177
|
+
hasPushedMotionPhotoCover = true;
|
|
20178
|
+
}
|
|
20179
|
+
}
|
|
20180
|
+
if (!hasPushedMotionPhotoCover) {
|
|
20181
|
+
const imageUrl = await processImageUrl(item.url_list[0], Detail_Data.desc, index);
|
|
20182
|
+
processedImages.push(segment.image(imageUrl));
|
|
20183
|
+
}
|
|
19858
20184
|
}
|
|
20185
|
+
logger.mark("正在尝试删除缓存文件");
|
|
20186
|
+
await Common.removeFile(liveimg.filepath, true);
|
|
19859
20187
|
} else await Common.removeFile(liveimg.filepath, true);
|
|
19860
20188
|
}
|
|
19861
20189
|
}
|
package/lib/index.js
CHANGED
package/lib/root.js
CHANGED
package/lib/web.config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./core_chunk/rolldown-runtime-BMXAG3ag.js";
|
|
2
|
-
import { D as webConfig, O as web_config_default } from "./core_chunk/main-
|
|
2
|
+
import { D as webConfig, O as web_config_default } from "./core_chunk/main-BY6eDfoV.js";
|
|
3
3
|
import "./core_chunk/vendor-DxfKHvj-.js";
|
|
4
4
|
import "./core_chunk/template-DekmxKd7.js";
|
|
5
5
|
export { web_config_default as default, webConfig };
|