Added video support

This commit is contained in:
Seednode 2023-05-08 20:05:10 -05:00
parent f92384f0ce
commit 3e1fb6be6a
4 changed files with 60 additions and 34 deletions

View File

@ -1,14 +1,14 @@
## About
Sometimes, you just need a way to randomly display images from your filesystem.
Sometimes, you just need a way to randomly display media from your filesystem.
Simply point this tool at one or more directories, and then open the specified port (default `8080`) in your browser.
A new image will be selected if you open `/` directly, or if you click on any displayed image.
A new file will be selected if you open `/` directly, or if you click on any displayed media.
Browser history is preserved, so you can always go back to any previously displayed image.
Browser history is preserved, so you can always go back to any previously displayed media.
Supported file types and extensions are `bmp`, `gif`, `jp[e]g`, `png`, and `webp`.
Supported file types and extensions are `bmp`, `gif`, `jp[e]g`, `png`, `webp`, `mp4`, `ogv`, and `webm`.
Feature requests, code criticism, bug reports, general chit-chat, and unrelated angst accepted at `roulette@seedno.de`.
@ -60,7 +60,7 @@ Note: These patterns require sequentially-numbered files matching the following
If a positive-value `refresh=<integer><unit>` query parameter is provided, the page will reload after that interval.
This can be used to generate a sort of slideshow of images.
This can be used to generate a sort of slideshow of files.
Supported units are `ns`, `us`/`µs`, `ms`, `s`, `m`, and `h`.

View File

@ -43,7 +43,7 @@ type Concurrency struct {
var (
ErrNoImagesFound = fmt.Errorf("no supported image formats found which match all criteria")
Extensions = [6]string{".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp"}
Extensions = [9]string{".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".mp4", ".ogv", ".webm"}
)
type Dimensions struct {
@ -168,12 +168,12 @@ func preparePath(path string) string {
func appendPath(directory, path string, files *Files, stats *ScanStats, shouldCache bool) error {
if shouldCache {
image, err := isImage(path)
image, video, err := isSupportedFileType(path)
if err != nil {
return err
}
if !image {
if !(image || video) {
return nil
}
}
@ -382,20 +382,27 @@ func pathIsValid(filePath string, paths []string) bool {
}
}
func isImage(path string) (bool, error) {
func isSupportedFileType(path string) (bool, bool, error) {
file, err := os.Open(path)
switch {
case errors.Is(err, os.ErrNotExist):
return false, nil
return false, false, nil
case err != nil:
return false, err
return false, false, err
}
defer file.Close()
head := make([]byte, 261)
file.Read(head)
return filetype.IsImage(head), nil
switch {
case filetype.IsImage(head):
return true, false, nil
case filetype.IsVideo(head):
return false, true, nil
default:
return false, false, nil
}
}
func pathHasSupportedFiles(path string) (bool, error) {
@ -410,12 +417,12 @@ func pathHasSupportedFiles(path string) (bool, error) {
case !recursive && info.IsDir() && p != path:
return filepath.SkipDir
case !info.IsDir():
image, err := isImage(p)
image, video, err := isSupportedFileType(p)
if err != nil {
return err
}
if image {
if image || video {
hasSupportedFiles <- true
return filepath.SkipAll
}
@ -609,12 +616,12 @@ func pickFile(args []string, filters *Filters, sort string, index *Index) (strin
filePath := fileList[r]
if !fromCache {
isImage, err := isImage(filePath)
image, video, err := isSupportedFileType(filePath)
if err != nil {
return "", err
}
if isImage {
if image || video {
return filePath, nil
}

View File

@ -10,7 +10,7 @@ import (
"github.com/spf13/cobra"
)
var Version = "0.44.0"
var Version = "0.45.0"
func init() {
rootCmd.AddCommand(versionCmd)

View File

@ -751,21 +751,26 @@ func serveImage(paths []string, Regexes *Regexes, index *Index) http.HandlerFunc
return
}
image, err := isImage(filePath)
image, video, err := isSupportedFileType(filePath)
if err != nil {
fmt.Println(err)
return
}
if !image {
if !(image || video) {
notFound(w, r, filePath)
return
}
dimensions, err := imageDimensions(filePath)
if err != nil {
fmt.Println(err)
return
var dimensions *Dimensions
if image {
dimensions, err = imageDimensions(filePath)
if err != nil {
fmt.Println(err)
return
}
}
fileName := filepath.Base(filePath)
@ -782,24 +787,38 @@ func serveImage(paths []string, Regexes *Regexes, index *Index) http.HandlerFunc
htmlBody.WriteString(`<!DOCTYPE html><html lang="en"><head>`)
htmlBody.WriteString(`<style>html,body{margin:0;padding:0;height:100%;}`)
htmlBody.WriteString(`a{display:block;height:100%;width:100%;text-decoration:none;}`)
htmlBody.WriteString(`img{margin:auto;display:block;max-width:97%;max-height:97%;object-fit:scale-down;`)
htmlBody.WriteString(`img,video{margin:auto;display:block;max-width:97%;max-height:97%;object-fit:scale-down;`)
htmlBody.WriteString(`position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);}</style>`)
htmlBody.WriteString(fmt.Sprintf(`<title>%s (%dx%d)</title>`,
fileName,
dimensions.width,
dimensions.height))
switch {
case image:
htmlBody.WriteString(fmt.Sprintf(`<title>%s (%dx%d)</title>`,
fileName,
dimensions.width,
dimensions.height))
case video:
htmlBody.WriteString(fmt.Sprintf(`<title>%s</title>`,
fileName))
}
htmlBody.WriteString(`</head><body>`)
if refreshInterval != "0ms" {
htmlBody.WriteString(fmt.Sprintf("<script>window.onload = function(){setInterval(function(){window.location.href = '/%s';}, %d);};</script>",
queryParams,
refreshTimer))
}
htmlBody.WriteString(fmt.Sprintf(`<a href="/%s"><img src="%s" width="%d" height="%d" alt="Roulette selected: %s"></a>`,
queryParams,
generateFilePath(filePath),
dimensions.width,
dimensions.height,
fileName))
switch {
case image:
htmlBody.WriteString(fmt.Sprintf(`<a href="/%s"><img src="%s" width="%d" height="%d" alt="Roulette selected: %s"></a>`,
queryParams,
generateFilePath(filePath),
dimensions.width,
dimensions.height,
fileName))
case video:
htmlBody.WriteString(fmt.Sprintf(`<a href="/%s"><video src="%s" alt="Roulette selected: %s" autoplay controls></a>`,
queryParams,
generateFilePath(filePath),
fileName))
}
htmlBody.WriteString(`</body></html>`)
_, err = io.WriteString(w, gohtml.Format(htmlBody.String()))