commit 116eaaae012aa23b30195d75c8400c7cf1b842c6
parent 40b4f8827bd690fe08b0c08ebc6f25de26e3df84
Author: breadcat <breadcat@users.noreply.github.com>
Date: Sat, 27 Sep 2025 00:36:04 +0100
Generate thumbnails on video upload
And use in gallery pages
Diffstat:
3 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/main.go b/main.go
@@ -1257,6 +1257,13 @@ func processVideoFile(tempPath, finalPath string) (string, string, error) {
return "", "", fmt.Errorf("failed to move file: %v", err)
}
+ ext := strings.ToLower(filepath.Ext(finalPath))
+ if ext == ".mp4" || ext == ".mov" || ext == ".avi" || ext == ".mkv" || ext == ".webm" {
+ if err := generateThumbnail(finalPath, config.UploadDir, filepath.Base(finalPath)); err != nil {
+ log.Printf("Warning: could not generate thumbnail: %v", err)
+ }
+ }
+
return finalPath, "", nil
}
@@ -1334,4 +1341,41 @@ func orphansHandler(w http.ResponseWriter, r *http.Request) {
pageData := buildPageData("Orphaned Files", orphans)
renderTemplate(w, "orphans.html", pageData)
+}
+func generateThumbnail(videoPath, uploadDir, filename string) error {
+ thumbDir := filepath.Join(uploadDir, "thumbnails")
+ if err := os.MkdirAll(thumbDir, 0755); err != nil {
+ return fmt.Errorf("failed to create thumbnails directory: %v", err)
+ }
+
+ thumbPath := filepath.Join(thumbDir, filename+".jpg")
+
+ // Use ffmpeg to grab a frame in the first 5s, resize width to 400px
+ cmd := exec.Command("ffmpeg", "-y",
+ "-ss", "00:00:05", // seek to 5s
+ "-i", videoPath,
+ "-vframes", "1",
+ "-vf", "scale=400:-1",
+ thumbPath,
+ )
+
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+
+ if err := cmd.Run(); err != nil {
+ // fallback: try frame 0 if grabbing at 5s fails
+ cmd := exec.Command("ffmpeg", "-y",
+ "-i", videoPath,
+ "-vframes", "1",
+ "-vf", "scale=400:-1",
+ thumbPath,
+ )
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err2 := cmd.Run(); err2 != nil {
+ return fmt.Errorf("failed to generate thumbnail: %v", err2)
+ }
+ }
+
+ return nil
}
\ No newline at end of file
diff --git a/static/style.css b/static/style.css
@@ -29,6 +29,8 @@ span#searchToggle{cursor:pointer;color:#add8e6;padding:8px}
div.gallery-item a{overflow:hidden;text-overflow:ellipsis}
div.gallery-item,div.gallery-item a,nav ul li,nav>ul>li{display:inline-block}
div.gallery-item,div.gallery-item a{width:250px;display:inline-block}
+div.play-button {position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 0; height: 0; border-left: 15px solid white; border-top: 10px solid transparent; border-bottom: 10px solid transparent; opacity: 0.8;}
+div.gallery-video {position: relative; display: inline-block; width: 150px; max-width: 100%;}
/* descriptions */
div.description-section {margin: 20px 0; padding: 15px;}
diff --git a/templates/_gallery.html b/templates/_gallery.html
@@ -1,9 +1,9 @@
{{define "_gallery"}}
<div class="gallery-item">
<a href="/file/{{.ID}}" title="{{.Filename}}">
- {{if hasAnySuffix .Filename ".jpg" ".jpeg" ".png" ".gif" ".webp"}}<img src="/uploads/{{.EscapedFilename}}" style="max-width:150px"><br />
- {{else if hasAnySuffix .Filename ".mp4" ".webm" ".mov"}}<video width="150" controls><source src="/uploads/{{.EscapedFilename}}"></video><br />
+ {{if hasAnySuffix .Filename ".jpg" ".jpeg" ".png" ".gif" ".webp"}}<img src="/uploads/{{.EscapedFilename}}" style="max-width:150px">
+ {{else if hasAnySuffix .Filename ".mp4" ".webm" ".mov"}}<div class="gallery-video"><img src="/uploads/thumbnails/{{.EscapedFilename}}.jpg" style="width: 100%; display: block;" /><div class="play-button"></div></div>
{{end}}
- {{.Filename}}</a>
+ <br>{{.Filename}}</a>
</div>
{{end}}
\ No newline at end of file