Add video thumbnails

This commit is contained in:
Reimar 2024-02-11 00:02:33 +01:00
parent 9fb560fc9a
commit c3314c440a
Signed by: Reimar
GPG Key ID: 93549FA07F0AE268
5 changed files with 57 additions and 11 deletions

Binary file not shown.

View File

@ -172,24 +172,31 @@ app.post("/api/upload_video", authorized(), fileUpload({ limits: { fileSize: 2 *
const id = randomString(4); const id = randomString(4);
const tempPath = req.files.video.tempFilePath; const tempPath = req.files.video.tempFilePath;
const newPath = path.join(dirname(), "videos", `${id}.mp4`); const newPath = path.join(dirname(), "videos", `${id}.mp4`);
const thumbnailPath = path.join(dirname(), "videos", `${id}.png`);
console.log(newPath); console.log(newPath);
const exitCode = await new Promise((resolve, _reject) => { let exitCode = await new Promise(resolve => {
const process = childProcess.spawn("ffmpeg", ["-i", tempPath, "-b:v", "1M", "-b:a", "192k", newPath]); const process = childProcess.spawn("ffmpeg", ["-i", tempPath, "-b:v", "1M", "-b:a", "192k", newPath]);
process.stderr.on("data", (data) => { process.stderr.on("data", (data) => console.error(data.toString()));
console.error(data.toString()); process.on("close", resolve);
});
process.on("close", (code) => {
resolve(code);
})
}); });
if (exitCode !== 0) { if (exitCode !== 0) {
throw new Error("ffmpeg failed"); throw new Error("ffmpeg failed");
} }
await dbRun("INSERT INTO videos (id, user_id, title, path) VALUES (?, ?, ?, ?)", id, userId, title, newPath); exitCode = await new Promise(resolve => {
const process = childProcess.spawn("ffmpeg", ["-i", tempPath, "-ss", "00:00:01.000", "-vframes", "1", thumbnailPath]);
process.stderr.on("data", (data) => console.error(data.toString()));
process.on("close", resolve);
});
if (exitCode !== 0) {
throw new Error("thumbnail generation failed");
}
await dbRun("INSERT INTO videos (id, user_id, title) VALUES (?, ?, ?)", id, userId, title);
return res.status(200).json({ ok: true }); return res.status(200).json({ ok: true });
}) })

View File

@ -8,7 +8,6 @@ CREATE TABLE videos (
id TEXT PRIMARY KEY NOT NULL, id TEXT PRIMARY KEY NOT NULL,
user_id INTEGER, user_id INTEGER,
title TEXT NOT NULL, title TEXT NOT NULL,
path TEXT NOT NULL,
FOREIGN KEY(user_id) REFERENCES users(id) FOREIGN KEY(user_id) REFERENCES users(id)
); );

View File

@ -24,9 +24,20 @@ function displayResponse(response) {
+ videos + videos
.map(v => { .map(v => {
console.log(v); console.log(v);
return `<li><p><a href="/watch?id=${v.id}">${v.title}</a> - ${v.author}</p></li>` return `
<li>
<p class="video-item">
<img src="/videos/${v.id}.png" alt="">
<span class="video-info">
<a href="/watch?id=${v.id}">${v.title}</a>
<br>
by ${v.author}
</span>
</p>
</li>
`;
}) })
.join("") .join("")
+ "</ul>"; + "</ul>";
} }

View File

@ -62,12 +62,41 @@ body {
ul#video-list { ul#video-list {
padding: 0; padding: 0;
list-style: none; list-style: none;
width: 100%;
max-width: 800px;
margin: auto;
} }
#video-player { #video-player {
max-height: 80vh; max-height: 80vh;
} }
.video-item {
display: flex;
flex-direction: row;
align-items: flex-start;
gap: 2em;
text-align: left;
background-color: rgba(255, 255, 255, 0.3);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.video-item img {
width: 200px;
height: 100px;
object-fit: contain;
background-color: black;
}
.video-item .video-info {
padding-top: 0.5em;
}
.video-item a {
font-size: 1.4em;
font-weight: bold;
}
header { header {
display: flex; display: flex;
align-items: center; align-items: center;