-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.js
More file actions
104 lines (86 loc) · 3.25 KB
/
main.js
File metadata and controls
104 lines (86 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
const express = require('express');
const path = require('path');
const { extractTikTokData } = require('./jsonExtractor');
const { VideoFetcher } = require('./utils/videoFetcher');
const app = express();
const port = 3500;
app.use(express.static(path.join(__dirname, 'public')));
app.get('/stream', async (req, res) => {
try {
const tiktokUrl = req.query.url;
if (!tiktokUrl) {
return res.status(400).send('No URL provided');
}
const { jsonData, cookieString } = await extractTikTokData(tiktokUrl);
const videoFetcher = new VideoFetcher(jsonData, cookieString);
const metadata = await videoFetcher.getVideoMetadata();
const range = req.headers.range;
let videoResponse;
if (range) {
const parts = range.replace(/bytes=/, '').split('-');
const start = parseInt(parts[0], 10);
const end = parts[1] ? parseInt(parts[1], 10) : metadata.contentLength - 1;
const chunkSize = end - start + 1;
videoResponse = await videoFetcher.streamVideo({ start, end });
res.writeHead(206, {
'Content-Range': `bytes ${start}-${end}/${metadata.contentLength}`,
'Accept-Ranges': 'bytes',
'Content-Length': chunkSize,
'Content-Type': metadata.contentType
});
} else {
videoResponse = await videoFetcher.streamVideo();
res.writeHead(200, {
'Content-Length': metadata.contentLength,
'Content-Type': metadata.contentType,
'Accept-Ranges': 'bytes'
});
}
const reader = videoResponse.body.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
res.write(value);
}
res.end();
} catch (error) {
console.error('Streaming error:', error);
if (!res.headersSent) {
res.status(500).send('Streaming error occurred');
}
} finally {
reader.releaseLock();
}
} catch (error) {
console.error('Error:', error);
if (!res.headersSent) {
res.status(500).send('Error processing video: ' + error.message);
}
}
});
app.get('/metadata', async (req, res) => {
try {
const tiktokUrl = req.query.url;
if (!tiktokUrl) {
return res.status(400).json({ error: 'No URL provided' });
}
const { jsonData } = await extractTikTokData(tiktokUrl);
const metadata = {
desc: jsonData.itemInfo.itemStruct.desc,
stats: jsonData.itemInfo.itemStruct.stats,
author: {
nickname: jsonData.itemInfo.itemStruct.author.nickname,
avatarThumb: jsonData.itemInfo.itemStruct.author.avatarThumb
},
music: jsonData.itemInfo.itemStruct.music
};
res.json(metadata);
} catch (error) {
console.error('Error:', error);
res.status(500).json({ error: error.message });
}
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});