-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
151 lines (126 loc) · 4.7 KB
/
server.js
File metadata and controls
151 lines (126 loc) · 4.7 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
require("dotenv").config();
const express = require("express");
const axios = require("axios");
const path = require("path");
const app = express();
const PORT =process.env.PORT || 5000;
const cors = require("cors");
app.use(cors());
app.set("view engine", "ejs");
app.use(express.static(path.join(__dirname, "public")));
const YOUTUBE_API_KEY = process.env.YOUTUBE_API_KEY;
// Convert YouTube duration format (ISO 8601) to seconds
const convertDurationToSeconds = (duration) => {
let hours = 0, minutes = 0, seconds = 0;
duration = duration.replace("PT", "");
if (duration.includes("H")) {
[hours, duration] = duration.split("H");
hours = parseInt(hours);
}
if (duration.includes("M")) {
[minutes, duration] = duration.split("M");
minutes = parseInt(minutes);
}
if (duration.includes("S")) {
[seconds] = duration.split("S");
seconds = parseInt(seconds);
}
return hours * 3600 + minutes * 60 + seconds;
};
// Convert seconds to HH:MM:SS format
const formatTime = (totalSeconds) => {
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
return `${hours}h ${minutes}m ${seconds}s`;
};
// Calculate duration at different speeds
const calculatePlaybackTime = (totalSeconds, speed) => {
return formatTime(Math.ceil(totalSeconds / speed));
};
function extractPlaylistId(url) {
const urlParams = new URLSearchParams(new URL(url).search);
return urlParams.get('list');
}
// Home Route
app.get("/", (req, res) => {
res.render("index", { result: null });
});
// Playlist API Route
app.get("/playlist", async (req, res) => {
try {
let { playlistId } = req.query;
playlistId = extractPlaylistId(playlistId);
if (!playlistId) {
return res.status(400).json({ error: "Playlist ID is required" });
}
let videoIds = [];
let nextPageToken = "";
let videoDetails = [];
// Fetch all video IDs from the playlist
do {
const playlistResponse = await axios.get(
`https://www.googleapis.com/youtube/v3/playlistItems`, {
params: {
part: "contentDetails",
maxResults: 50,
playlistId,
key: YOUTUBE_API_KEY,
pageToken: nextPageToken
}
}
);
playlistResponse.data.items.forEach(item => {
videoIds.push(item.contentDetails.videoId);
});
nextPageToken = playlistResponse.data.nextPageToken;
} while (nextPageToken);
if (videoIds.length === 0) {
return res.json({ message: "No videos found in the playlist" });
}
let totalDurationSeconds = 0;
// Fetch video details
for (let i = 0; i < videoIds.length; i += 50) {
const videoResponse = await axios.get(
`https://www.googleapis.com/youtube/v3/videos`, {
params: {
part: "contentDetails,snippet",
id: videoIds.slice(i, i + 50).join(","),
key: YOUTUBE_API_KEY
}
}
);
videoResponse.data.items.forEach(video => {
const duration = convertDurationToSeconds(video.contentDetails.duration);
totalDurationSeconds += duration;
videoDetails.push({
videoId: video.id, // ✅ Ensure videoId is included
title: video.snippet.title,
duration: formatTime(duration),
});
});
}
// Calculate analytics
const avgSpeed = calculatePlaybackTime(totalDurationSeconds, 1.25);
const avgSpeed150 = calculatePlaybackTime(totalDurationSeconds, 1.50);
const avgSpeed175 = calculatePlaybackTime(totalDurationSeconds, 1.75);
const doubleSpeed = calculatePlaybackTime(totalDurationSeconds, 2.0);
res.render("index", {
result: {
totalVideos: videoDetails.length,
totalDuration: formatTime(totalDurationSeconds),
avgSpeed,
doubleSpeed,
avgSpeed150,
avgSpeed175,
videos: videoDetails // ✅ Pass video details to frontend
}
});
} catch (error) {
console.error("Error fetching playlist:", error);
res.status(500).send("Failed to fetch playlist details");
}
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});