frostpv 1.0.12 → 1.0.14
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/index.js +62 -96
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const path = require("path");
|
|
|
4
4
|
const os = require("os");
|
|
5
5
|
const FormData = require("form-data");
|
|
6
6
|
const crypto = require("crypto");
|
|
7
|
-
const { igdl, ttdl, fbdown, mediafire, capcut, gdrive, pinterest } = require("btch-downloader");
|
|
7
|
+
const { igdl, ttdl, fbdown, mediafire, capcut, gdrive, pinterest, twitter } = require("btch-downloader");
|
|
8
8
|
const { TwitterDL } = require("twitter-downloader");
|
|
9
9
|
const btch = require("btch-downloader");
|
|
10
10
|
const btchOld = require("btch-downloader-old");
|
|
@@ -47,6 +47,7 @@ const videoPlatforms = [
|
|
|
47
47
|
"https://www.fb.watch",
|
|
48
48
|
"https://fb.com",
|
|
49
49
|
"https://www.fb.com",
|
|
50
|
+
"https://web.facebook.com",
|
|
50
51
|
"https://www.mediafire.com",
|
|
51
52
|
"https://mediafire.com",
|
|
52
53
|
"https://www.capcut.com",
|
|
@@ -886,25 +887,16 @@ const MediaDownloader = async (url, options = {}) => {
|
|
|
886
887
|
// Function to process downloaded file
|
|
887
888
|
async function processDownloadedFile(fileName, config, platform = null) {
|
|
888
889
|
let processedFile = path.resolve(fileName);
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
}
|
|
899
|
-
if (config.autocrop) {
|
|
900
|
-
processedFile = await autoCrop(processedFile);
|
|
901
|
-
}
|
|
902
|
-
processedFile = await checkAndCompressVideo(processedFile, config.limitSizeMB, platform);
|
|
903
|
-
if (config.outputFormat) {
|
|
904
|
-
processedFile = await convertVideoFormat(processedFile, String(config.outputFormat).toLowerCase());
|
|
905
|
-
}
|
|
890
|
+
if (config.rotation) {
|
|
891
|
+
processedFile = await rotateVideo(processedFile, config.rotation);
|
|
892
|
+
}
|
|
893
|
+
if (config.autocrop) {
|
|
894
|
+
processedFile = await autoCrop(processedFile);
|
|
895
|
+
}
|
|
896
|
+
processedFile = await checkAndCompressVideo(processedFile, config.limitSizeMB, platform);
|
|
897
|
+
if (config.outputFormat) {
|
|
898
|
+
processedFile = await convertVideoFormat(processedFile, String(config.outputFormat).toLowerCase());
|
|
906
899
|
}
|
|
907
|
-
|
|
908
900
|
return processedFile;
|
|
909
901
|
}
|
|
910
902
|
|
|
@@ -1072,47 +1064,45 @@ async function downloadSmartVideo(url, config) {
|
|
|
1072
1064
|
}
|
|
1073
1065
|
case "twitter": {
|
|
1074
1066
|
try {
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
data.result.media[0].videos[0].url) {
|
|
1084
|
-
videoUrl = data.result.media[0].videos[0].url;
|
|
1085
|
-
} else if (data.result.video && data.result.video[0] && data.result.video[0].url) {
|
|
1086
|
-
videoUrl = data.result.video[0].url;
|
|
1087
|
-
} else if (data.result.url) {
|
|
1088
|
-
videoUrl = data.result.url;
|
|
1089
|
-
} else if (data.result.media && data.result.media[0] && data.result.media[0].url) {
|
|
1090
|
-
videoUrl = data.result.media[0].url;
|
|
1091
|
-
} else {
|
|
1092
|
-
// Search for any video URL in the response
|
|
1093
|
-
const findVideoUrl = (obj) => {
|
|
1094
|
-
if (typeof obj === 'string' && obj.includes('http') &&
|
|
1095
|
-
(obj.includes('.mp4') || obj.includes('video') || obj.includes('media'))) {
|
|
1096
|
-
return obj;
|
|
1097
|
-
}
|
|
1098
|
-
if (typeof obj === 'object' && obj !== null) {
|
|
1099
|
-
for (const key in obj) {
|
|
1100
|
-
const result = findVideoUrl(obj[key]);
|
|
1101
|
-
if (result) return result;
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
return null;
|
|
1105
|
-
};
|
|
1106
|
-
|
|
1107
|
-
const foundUrl = findVideoUrl(data.result);
|
|
1108
|
-
if (foundUrl) {
|
|
1109
|
-
videoUrl = foundUrl;
|
|
1067
|
+
const data = await twitter(url);
|
|
1068
|
+
if (data && data.url) {
|
|
1069
|
+
// Se data.url for um array, procuramos por qualidade HD
|
|
1070
|
+
if (Array.isArray(data.url)) {
|
|
1071
|
+
// Tentar encontrar HD especificamente
|
|
1072
|
+
const hdVideo = data.url.find(v => v.hd);
|
|
1073
|
+
if (hdVideo) {
|
|
1074
|
+
videoUrl = hdVideo.hd;
|
|
1110
1075
|
} else {
|
|
1111
|
-
|
|
1076
|
+
// Tentar encontrar por label ou qualidade
|
|
1077
|
+
const highQuality = data.url.find(v =>
|
|
1078
|
+
(v.quality && typeof v.quality === 'string' && v.quality.toUpperCase().includes('HD')) ||
|
|
1079
|
+
(v.label && typeof v.label === 'string' && v.label.toUpperCase().includes('HD'))
|
|
1080
|
+
);
|
|
1081
|
+
|
|
1082
|
+
if (highQuality) {
|
|
1083
|
+
videoUrl = highQuality.url;
|
|
1084
|
+
} else {
|
|
1085
|
+
// Fallback: pega o primeiro que tiver url
|
|
1086
|
+
const anyVideo = data.url.find(v => v.url);
|
|
1087
|
+
videoUrl = anyVideo ? anyVideo.url : data.url[0];
|
|
1088
|
+
}
|
|
1112
1089
|
}
|
|
1090
|
+
} else if (typeof data.url === 'string') {
|
|
1091
|
+
videoUrl = data.url;
|
|
1113
1092
|
}
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
if (!videoUrl) {
|
|
1096
|
+
// Fallback para estrutura antiga ou diferente
|
|
1097
|
+
if (Array.isArray(data) && data[0] && data[0].url) {
|
|
1098
|
+
videoUrl = data[0].url;
|
|
1099
|
+
} else if (data && data.HD) {
|
|
1100
|
+
videoUrl = data.HD;
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
if (!videoUrl) {
|
|
1105
|
+
throw new Error("No video URL found in btch-downloader twitter response");
|
|
1116
1106
|
}
|
|
1117
1107
|
} catch (error) {
|
|
1118
1108
|
throw new Error(`Twitter download failed: ${error.message}`);
|
|
@@ -1127,7 +1117,7 @@ async function downloadSmartVideo(url, config) {
|
|
|
1127
1117
|
throw new Error("Returned video URL is invalid or unavailable.");
|
|
1128
1118
|
}
|
|
1129
1119
|
|
|
1130
|
-
// Download the video
|
|
1120
|
+
// Download the video with better error handling
|
|
1131
1121
|
const response = await axios({
|
|
1132
1122
|
url: videoUrl,
|
|
1133
1123
|
method: "GET",
|
|
@@ -1138,35 +1128,23 @@ async function downloadSmartVideo(url, config) {
|
|
|
1138
1128
|
}
|
|
1139
1129
|
});
|
|
1140
1130
|
|
|
1141
|
-
// Detect file type from content-type
|
|
1142
|
-
const contentType = response.headers['content-type'] || 'video/mp4';
|
|
1143
|
-
let ext = 'mp4'; // default
|
|
1144
|
-
|
|
1145
|
-
if (contentType.includes('image/jpeg')) ext = 'jpg';
|
|
1146
|
-
else if (contentType.includes('image/png')) ext = 'png';
|
|
1147
|
-
else if (contentType.includes('image/webp')) ext = 'webp';
|
|
1148
|
-
else if (contentType.includes('image/gif')) ext = 'gif';
|
|
1149
|
-
else if (contentType.includes('video/webm')) ext = 'webm';
|
|
1150
|
-
else if (contentType.includes('video/quicktime')) ext = 'mov';
|
|
1151
|
-
else if (contentType.includes('video/x-matroska')) ext = 'mkv';
|
|
1152
|
-
|
|
1153
1131
|
// Create minimal unique file name in output dir
|
|
1154
|
-
let fileName = path.join(OUTPUT_DIR, `v_${uuidv4().slice(0, 4)}
|
|
1132
|
+
let fileName = path.join(OUTPUT_DIR, `v_${uuidv4().slice(0, 4)}.mp4`);
|
|
1155
1133
|
|
|
1156
|
-
const
|
|
1157
|
-
response.data.pipe(
|
|
1134
|
+
const videoWriter = fs.createWriteStream(fileName);
|
|
1135
|
+
response.data.pipe(videoWriter);
|
|
1158
1136
|
|
|
1159
1137
|
return new Promise((resolve, reject) => {
|
|
1160
|
-
|
|
1138
|
+
videoWriter.on("finish", async () => {
|
|
1161
1139
|
try {
|
|
1162
1140
|
const finalFilePath = await processDownloadedFile(fileName, config, platform);
|
|
1163
1141
|
resolve(finalFilePath);
|
|
1164
1142
|
} catch (error) {
|
|
1165
|
-
reject(new Error(`Error processing downloaded
|
|
1143
|
+
reject(new Error(`Error processing downloaded video: ${error.message}`));
|
|
1166
1144
|
}
|
|
1167
1145
|
});
|
|
1168
|
-
|
|
1169
|
-
reject(new Error(`Error saving
|
|
1146
|
+
videoWriter.on("error", (error) => {
|
|
1147
|
+
reject(new Error(`Error saving video: ${error.message}`));
|
|
1170
1148
|
});
|
|
1171
1149
|
});
|
|
1172
1150
|
} catch (error) {
|
|
@@ -1187,35 +1165,23 @@ async function downloadDirectVideo(url, config) {
|
|
|
1187
1165
|
}
|
|
1188
1166
|
});
|
|
1189
1167
|
|
|
1190
|
-
// Detect file type from content-type
|
|
1191
|
-
const contentType = response.headers['content-type'] || 'video/mp4';
|
|
1192
|
-
let ext = 'mp4'; // default
|
|
1193
|
-
|
|
1194
|
-
if (contentType.includes('image/jpeg')) ext = 'jpg';
|
|
1195
|
-
else if (contentType.includes('image/png')) ext = 'png';
|
|
1196
|
-
else if (contentType.includes('image/webp')) ext = 'webp';
|
|
1197
|
-
else if (contentType.includes('image/gif')) ext = 'gif';
|
|
1198
|
-
else if (contentType.includes('video/webm')) ext = 'webm';
|
|
1199
|
-
else if (contentType.includes('video/quicktime')) ext = 'mov';
|
|
1200
|
-
else if (contentType.includes('video/x-matroska')) ext = 'mkv';
|
|
1201
|
-
|
|
1202
1168
|
// Create minimal unique file name in output dir
|
|
1203
|
-
let fileName = path.join(OUTPUT_DIR, `v_${uuidv4().slice(0, 4)}
|
|
1169
|
+
let fileName = path.join(OUTPUT_DIR, `v_${uuidv4().slice(0, 4)}.mp4`);
|
|
1204
1170
|
|
|
1205
|
-
const
|
|
1206
|
-
response.data.pipe(
|
|
1171
|
+
const videoWriter = fs.createWriteStream(fileName);
|
|
1172
|
+
response.data.pipe(videoWriter);
|
|
1207
1173
|
|
|
1208
1174
|
return new Promise((resolve, reject) => {
|
|
1209
|
-
|
|
1175
|
+
videoWriter.on("finish", async () => {
|
|
1210
1176
|
try {
|
|
1211
1177
|
const finalFilePath = await processDownloadedFile(fileName, config, "unknown");
|
|
1212
1178
|
resolve(finalFilePath);
|
|
1213
1179
|
} catch (error) {
|
|
1214
|
-
reject(new Error(`Error processing downloaded
|
|
1180
|
+
reject(new Error(`Error processing downloaded video: ${error.message}`));
|
|
1215
1181
|
}
|
|
1216
1182
|
});
|
|
1217
|
-
|
|
1218
|
-
reject(new Error(`Error saving
|
|
1183
|
+
videoWriter.on("error", (error) => {
|
|
1184
|
+
reject(new Error(`Error saving video: ${error.message}`));
|
|
1219
1185
|
});
|
|
1220
1186
|
});
|
|
1221
1187
|
} catch (error) {
|