Skip to content

Commit be2ccbe

Browse files
committed
update non-challenge video thumbnails + automation script
1 parent 7ab1125 commit be2ccbe

File tree

273 files changed

+61
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

273 files changed

+61
-0
lines changed
123 KB
125 KB
104 KB
94.6 KB
96.5 KB
28.7 KB
84.7 KB
151 KB
111 KB
160 KB
94.8 KB
119 KB
104 KB
105 KB
138 KB
107 KB
119 KB

content/videos/js/const/index.jpg

96.1 KB
96.2 KB
91.7 KB
84.6 KB
97 KB
97.5 KB
79.8 KB
94.9 KB

content/videos/js/try-catch/index.jpg

127 KB
159 KB
68 KB
29.8 KB
26.6 KB
109 KB
127 KB
26 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
30.5 KB
32.9 KB
34.5 KB

content/videos/processing/index.jpg

156 KB
36.9 KB
27.4 KB
110 KB
158 KB
93.8 KB
96.9 KB
73.8 KB
41.1 KB
114 KB
118 KB
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { paths } from '../content-testing/content.js';
2+
import path from 'node:path';
3+
import fs from 'node:fs';
4+
5+
// Thumbnails for non-challenge videos can just use the YouTube thumbnail.
6+
// They are never displayed on the site directly, only when sharing links on social media.
7+
8+
function sleep(ms) {
9+
return new Promise((resolve) => setTimeout(resolve, ms));
10+
}
11+
12+
async function getImage(url) {
13+
const response = await fetch(url);
14+
15+
if (!response.ok) return;
16+
17+
const arrayBuffer = await response.arrayBuffer();
18+
return Buffer.from(arrayBuffer);
19+
}
20+
21+
console.log(`Downloading ${paths.videos.length} thumbnails`);
22+
23+
for (const jsonPath of paths.videos) {
24+
const baseDir = path.join(path.dirname(jsonPath));
25+
26+
// remove existing thumnails (co-located with index.json files if they exist)
27+
['index.jpg', 'index.png'].forEach((filename) => {
28+
fs.rmSync(path.join(baseDir, filename), { force: true });
29+
});
30+
31+
const { videoId } = JSON.parse(fs.readFileSync(jsonPath));
32+
33+
console.log(videoId);
34+
35+
// download thumbnail from YouTube CDN
36+
const thumbnailPaths = [
37+
`https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`, // highest resolution (might not be available for 720p videos)
38+
`https://img.youtube.com/vi/${videoId}/hqdefault.jpg` // fallback
39+
];
40+
41+
let buffer;
42+
for (const thumbnailPath of thumbnailPaths) {
43+
buffer = await getImage(thumbnailPath);
44+
if (buffer) break;
45+
46+
console.warn(`Failed to download ${thumbnailPath}`);
47+
}
48+
49+
if (!buffer) {
50+
console.error(
51+
`Failed to locate a thumbnail for ${videoId} - process aborted.`
52+
);
53+
process.exit(1);
54+
}
55+
56+
// write file to disk
57+
fs.writeFileSync(path.join(baseDir, 'index.jpg'), buffer);
58+
59+
// sleep for a bit to avoid spamming / getting blocked
60+
await sleep(100 + Math.random() * 500);
61+
}

0 commit comments

Comments
 (0)