diff --git a/frontend/src/components/files/ListingItem.vue b/frontend/src/components/files/ListingItem.vue index 75326f4c..6417f97c 100644 --- a/frontend/src/components/files/ListingItem.vue +++ b/frontend/src/components/files/ListingItem.vue @@ -16,7 +16,7 @@ >
diff --git a/http/preview.go b/http/preview.go index 1abc6019..e5ad09e5 100644 --- a/http/preview.go +++ b/http/preview.go @@ -8,9 +8,9 @@ import ( "fmt" "io" "net/http" - + "github.com/spf13/afero" "github.com/gorilla/mux" - + "os/exec" "github.com/filebrowser/filebrowser/v2/files" "github.com/filebrowser/filebrowser/v2/img" ) @@ -63,12 +63,59 @@ func previewHandler(imgSvc ImgService, fileCache FileCache, enableThumbnails, re switch file.Type { case "image": return handleImagePreview(w, r, imgSvc, fileCache, file, previewSize, enableThumbnails, resizePreview) + case "video": + return handleVideoPreview(w, r, imgSvc, fileCache, file, previewSize, enableThumbnails, resizePreview) default: return http.StatusNotImplemented, fmt.Errorf("can't create preview for %s type", file.Type) } }) } +var sem = make(chan int, 3) + +func handleVideoPreview( + w http.ResponseWriter, + r *http.Request, + imgSvc ImgService, + fileCache FileCache, + file *files.FileInfo, + previewSize PreviewSize, + enableThumbnails, resizePreview bool, +) (int, error) { + path := afero.FullBaseFsPath(file.Fs.(*afero.BasePathFs), file.Path) + + cacheKey := previewCacheKey(file, previewSize) + resizedImage, ok, err := fileCache.Load(r.Context(), cacheKey) + if err != nil { + return errToStatus(err), err + } + if !ok { + sem <- 1 + //cmd := exec.Command("ffmpeg", "-y", "-i", path, "-vf", "thumbnail,crop=w='min(iw\\,ih)':h='min(iw\\,ih)',scale=128:128", "-qscale:v", "25", "-frames:v", "1", tmp.Name()) + stdout, err := exec.Command("ffmpeg", "-y", "-i", path, "-vf", "thumbnail,crop=w='min(iw\\,ih)':h='min(iw\\,ih)',scale=128:128", "-quality", "40", "-frames:v", "1", "-c:v", "webp", "-f", "image2pipe", "-").Output() + <- sem + if err != nil { + return errToStatus(err), err + } + + resizedImage = stdout + + go func() { + cacheKey := previewCacheKey(file, previewSize) + if err := fileCache.Store(context.Background(), cacheKey, resizedImage); err != nil { + fmt.Printf("failed to cache resized image: %v", err) + } + }() + + } + + w.Header().Set("Cache-Control", "private") + //w.Header().Set("Content-Type", "image/jpeg") + w.Header().Set("Content-Type", "image/webp") + http.ServeContent(w, r, "", file.ModTime, bytes.NewReader(resizedImage)) + return 0, nil +} + func handleImagePreview( w http.ResponseWriter, r *http.Request,