@media-downloaders/v2 2.0.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/.old/index.js ADDED
@@ -0,0 +1,277 @@
1
+ const axios = require('axios');
2
+ const fs = require('fs');
3
+ const ytdl = require('@distube/ytdl-core');
4
+ const Tiktok = require("@tobyg74/tiktok-api-dl");
5
+ const instagramDl = require("@sasmeee/igdl");
6
+ const { TwitterDL } = require("twitter-downloader");
7
+
8
+ const defaultConfig = {
9
+ autocrop: false, // Paramètre par défaut
10
+ };
11
+
12
+ const MediaDownloader = async (url, options = {}) => {
13
+ const config = { ...defaultConfig, ...options };
14
+
15
+ if (!url || !url.includes("http")) {
16
+ throw new Error("Please specify a video URL...");
17
+ }
18
+ url = extractUrlFromString(url);
19
+ await deleteTempVideos();
20
+
21
+ if (url.includes("instagram.com/")) {
22
+ try {
23
+ const dataList = await instagramDl(url);
24
+ if (!dataList || !dataList[0]) {
25
+ throw new Error("Error: Invalid video URL...");
26
+ }
27
+ const videoURL = dataList[0].download_link;
28
+ const videofile = await downloadDirectVideo(videoURL, config);
29
+
30
+ return videofile;
31
+
32
+ } catch (error) {
33
+ throw new Error("Error downloading or sending Instagram video: " + error.message);
34
+ }
35
+
36
+ } else if (url.includes('tiktok.com/')) {
37
+ try {
38
+ const result = await Tiktok.Downloader(url, {
39
+ version: "v2" // version: "v1" | "v2" | "v3"
40
+ });
41
+
42
+ const videoLink = result.result.video;
43
+ const videofile = await downloadDirectVideo(videoLink, config);
44
+
45
+ return videofile;
46
+ } catch (error) {
47
+ throw new Error("Error downloading TikTok video: " + error.message);
48
+ }
49
+
50
+ } else if (url.includes("youtu.be/") || url.includes("youtube.com/")) {
51
+ try {
52
+ const videoLink = await downloadYoutubeVideo(url, config);
53
+ return videoLink;
54
+ } catch (error) {
55
+ throw new Error("Error downloading YouTube video: " + error.message);
56
+ }
57
+
58
+ } else if (url.includes("twitter.com") || url.includes("x.com/")) {
59
+ try {
60
+ const result = await TwitterDL(url);
61
+ const videoLink = result.result.media[0].videos[result.result.media[0].videos.length - 1].url;
62
+ const videofile = await downloadDirectVideo(videoLink, config);
63
+
64
+ return videofile;
65
+ } catch (error) {
66
+ throw new Error("Error downloading Twitter video: " + error.message);
67
+ }
68
+
69
+ } else if (url.includes("http")) {
70
+ const videofile = await downloadDirectVideo(url, config);
71
+
72
+ return videofile;
73
+ } else {
74
+ throw new Error("Please specify a video URL from Instagram, YouTube, or TikTok...");
75
+ }
76
+ };
77
+
78
+ async function downloadDirectVideo(url, config) {
79
+ try {
80
+ const response = await axios({
81
+ url: url,
82
+ method: 'GET',
83
+ responseType: 'stream'
84
+ });
85
+
86
+ // Check if the downloaded content is a MP4 video
87
+ const contentType = response.headers['content-type'];
88
+
89
+ // Generate a unique file name
90
+ let fileName = 'temp_video.mp4';
91
+ let count = 1;
92
+ while (fs.existsSync(fileName)) {
93
+ fileName = `temp_video_${count}.mp4`;
94
+ count++;
95
+ }
96
+
97
+ // Create a write stream to save the video
98
+ const videoWriter = fs.createWriteStream(fileName);
99
+ response.data.pipe(videoWriter);
100
+
101
+ // Return a promise that resolves when the download is finished
102
+ return new Promise((resolve, reject) => {
103
+ videoWriter.on('finish', async () => {
104
+ if (config.autocrop) {
105
+ try {
106
+ const croppedFileName = await autoCrop(fileName);
107
+ resolve(croppedFileName);
108
+ } catch (error) {
109
+ reject(error);
110
+ }
111
+ } else {
112
+ resolve(fileName);
113
+ }
114
+ });
115
+ videoWriter.on('error', (error) => reject(error));
116
+ });
117
+ } catch (error) {
118
+ throw new Error(`An error occurred while downloading video: ${error.message}`);
119
+ }
120
+ }
121
+
122
+ async function downloadYoutubeVideo(url, config) {
123
+ try {
124
+ const info = await ytdl.getInfo(url);
125
+ const formats = ytdl.filterFormats(info.formats, 'videoandaudio');
126
+
127
+ // Choose the format with the highest quality up to 25MB
128
+ let format;
129
+ for (let i = 0; i < formats.length; i++) {
130
+ const currentFormat = formats[i];
131
+ let contentLength = currentFormat?.contentLength;
132
+ if (!contentLength) {
133
+ contentLength = await getContentLength(currentFormat.url);
134
+ currentFormat.contentLength = contentLength;
135
+ }
136
+
137
+ if (contentLength && contentLength <= 25 * 1024 * 1024) {
138
+ format = currentFormat;
139
+ break;
140
+ }
141
+ }
142
+
143
+ if (!format) {
144
+ throw new Error('No suitable format found within 25 MB.');
145
+ }
146
+
147
+ // Ensure unique file name
148
+ let count = 0;
149
+ let fileName = `temp_video.mp4`;
150
+ while (fs.existsSync(fileName)) {
151
+ count++;
152
+ fileName = `temp_video_${count}.mp4`;
153
+ }
154
+
155
+ const videoStream = ytdl.downloadFromInfo(info, {
156
+ format: format,
157
+ filter: 'videoandaudio',
158
+ });
159
+
160
+ const writeStream = fs.createWriteStream(fileName);
161
+
162
+ // Pipe video stream to file
163
+ videoStream.pipe(writeStream);
164
+
165
+ // Promisify the writeStream finish event
166
+ return new Promise((resolve, reject) => {
167
+ writeStream.on('finish', async () => {
168
+ if (config.autocrop) {
169
+ try {
170
+ const croppedFileName = await autoCrop(fileName);
171
+ resolve(croppedFileName);
172
+ } catch (error) {
173
+ reject(error);
174
+ }
175
+ } else {
176
+ resolve(fileName);
177
+ }
178
+ });
179
+ writeStream.on('error', reject);
180
+ });
181
+ } catch (error) {
182
+ console.log(error);
183
+ throw error;
184
+ }
185
+ }
186
+
187
+ // Helper function to get content length
188
+ async function getContentLength(url) {
189
+ try {
190
+ const response = await axios.head(url);
191
+ const contentLength = response.headers['content-length'];
192
+ console.log(`Content-Length: ${contentLength} bytes`);
193
+ return contentLength;
194
+ } catch (error) {
195
+ console.error(`Error fetching content length: ${error.message}`);
196
+ }
197
+ }
198
+
199
+ function extractUrlFromString(text) {
200
+ const urlRegex = /(https?:\/\/[^\s]+)/;
201
+ const match = text.match(urlRegex);
202
+ if (match) {
203
+ return match[0];
204
+ } else {
205
+ return null;
206
+ }
207
+ }
208
+
209
+ async function deleteTempVideos() {
210
+ try {
211
+ const files = fs.readdirSync("./");
212
+ const tempVideoFiles = files.filter(file => file.startsWith('temp_video'));
213
+
214
+ for (const file of tempVideoFiles) {
215
+ fs.unlinkSync("./" + file);
216
+ }
217
+ } catch (error) {
218
+ throw new Error(`Error deleting temp_video files: ${error.message}`);
219
+ }
220
+ }
221
+
222
+ async function autoCrop(fileName) {
223
+ const pathToFfmpeg = require('ffmpeg-ffprobe-static');
224
+ const ffmpeg = require('fluent-ffmpeg');
225
+ ffmpeg.setFfmpegPath(pathToFfmpeg.ffmpegPath);
226
+
227
+ const inputPath = fileName;
228
+ const outputPath = fileName.split('.')[0] + "_cropped.mp4";
229
+
230
+ return new Promise((resolve, reject) => {
231
+ ffmpeg(inputPath)
232
+ .videoFilters('cropdetect')
233
+ .output(outputPath)
234
+ .on('end', function(stdout, stderr) {
235
+ const crop = parseCrop(stderr);
236
+ if (!crop) {
237
+ reject(new Error('Erreur: Impossible de détecter les valeurs de crop.'));
238
+ return;
239
+ }
240
+
241
+ console.log('Valeurs de crop détectées:', crop);
242
+
243
+ // CROP
244
+ ffmpeg(inputPath)
245
+ .videoFilters(`crop=${crop.width}:${crop.height}:${crop.x}:${crop.y}`)
246
+ .on('end', () => {
247
+ console.log('Rogner terminé avec succès.');
248
+ resolve(outputPath);
249
+ })
250
+ .on('error', (err) => {
251
+ reject(new Error('Erreur lors du rognage: ' + err.message));
252
+ })
253
+ .save(outputPath);
254
+ })
255
+ .on('error', (err) => {
256
+ reject(new Error('Erreur lors de la détection du crop: ' + err.message));
257
+ })
258
+ .run();
259
+ });
260
+
261
+ function parseCrop(stderr) {
262
+ const cropRegex = /crop=([0-9]+):([0-9]+):([0-9]+):([0-9]+)/;
263
+ const match = stderr.match(cropRegex);
264
+ if (match) {
265
+ return {
266
+ width: match[1],
267
+ height: match[2],
268
+ x: match[3],
269
+ y: match[4],
270
+ };
271
+ } else {
272
+ return null;
273
+ }
274
+ }
275
+ }
276
+
277
+ module.exports = MediaDownloader;