From d21c06c4651e2ac6eebca25d94ff2855618a94d8 Mon Sep 17 00:00:00 2001 From: James Mills Date: Sat, 28 Mar 2020 15:59:16 +1000 Subject: [PATCH] Add backend support for serving lower quality videos (if available) --- app/app.go | 48 +++++++++++++++++++++++++++++++++++++++++++- app/rice-box.go | 8 ++++---- app/watcher.go | 3 ++- media/library.go | 4 ++++ templates/index.html | 4 +++- 5 files changed, 60 insertions(+), 7 deletions(-) diff --git a/app/app.go b/app/app.go index 3f99998..8899de1 100644 --- a/app/app.go +++ b/app/app.go @@ -178,12 +178,15 @@ func (a *App) indexHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, fmt.Sprintf("/v/%s?%s", pl[0].ID, r.URL.RawQuery), 302) } else { sort := strings.ToLower(r.URL.Query().Get("sort")) + quality := strings.ToLower(r.URL.Query().Get("quality")) ctx := &struct { Sort string + Quality string Playing *media.Video Playlist media.Playlist }{ Sort: sort, + Quality: quality, Playing: &media.Video{ID: ""}, Playlist: a.Library.Playlist(), } @@ -449,10 +452,16 @@ func (a *App) pageHandler(w http.ResponseWriter, r *http.Request) { log.Printf("/v/%s", id) playing, ok := a.Library.Videos[id] if !ok { + sort := strings.ToLower(r.URL.Query().Get("sort")) + quality := strings.ToLower(r.URL.Query().Get("quality")) ctx := &struct { + Sort string + Quality string Playing *media.Video Playlist media.Playlist }{ + Sort: sort, + Quality: quality, Playing: &media.Video{ID: ""}, Playlist: a.Library.Playlist(), } @@ -491,13 +500,23 @@ func (a *App) pageHandler(w http.ResponseWriter, r *http.Request) { log.Warnf("invalid sort critiera: %s", sort) } + quality := strings.ToLower(r.URL.Query().Get("quality")) + switch quality { + case "", "720p", "480p", "360p", "240p": + default: + log.WithField("quality", quality).Warn("invalid quality") + quality = "" + } + w.Header().Set("Content-Type", "text/html; charset=utf-8") ctx := &struct { Sort string + Quality string Playing *media.Video Playlist media.Playlist }{ Sort: sort, + Quality: quality, Playing: playing, Playlist: playlist, } @@ -508,16 +527,43 @@ func (a *App) pageHandler(w http.ResponseWriter, r *http.Request) { func (a *App) videoHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id := vars["id"] + prefix, ok := vars["prefix"] if ok { id = path.Join(prefix, id) } + log.Printf("/v/%s", id) + m, ok := a.Library.Videos[id] if !ok { return } + var videoPath string + + quality := strings.ToLower(r.URL.Query().Get("quality")) + switch quality { + case "720p", "480p", "360p", "240p": + videoPath = fmt.Sprintf( + "%s#%s.mp4", + strings.TrimSuffix(m.Path, filepath.Ext(m.Path)), + quality, + ) + if !utils.FileExists(videoPath) { + log. + WithField("quality", quality). + WithField("videoPath", videoPath). + Warn("video with specified quality does not exist (defaulting to default quality)") + videoPath = m.Path + } + case "": + videoPath = m.Path + default: + log.WithField("quality", quality).Warn("invalid quality") + videoPath = m.Path + } + if err := a.Store.Migrate(prefix, id); err != nil { err := fmt.Errorf("error migrating store data: %w", err) log.Warn(err) @@ -532,7 +578,7 @@ func (a *App) videoHandler(w http.ResponseWriter, r *http.Request) { disposition := "attachment; filename=\"" + title + ".mp4\"" w.Header().Set("Content-Disposition", disposition) w.Header().Set("Content-Type", "video/mp4") - http.ServeFile(w, r, m.Path) + http.ServeFile(w, r, videoPath) } // HTTP handler for /t/id diff --git a/app/rice-box.go b/app/rice-box.go index a603db4..83bc264 100644 --- a/app/rice-box.go +++ b/app/rice-box.go @@ -23,9 +23,9 @@ func init() { } file4 := &embedded.EmbeddedFile{ Filename: "index.html", - FileModTime: time.Unix(1585371597, 0), + FileModTime: time.Unix(1585374250, 0), - Content: string("{{ define \"content\" }}\r\n{{ $playing := .Playing }}\r\n
\r\n {{ if $playing.ID }}\r\n \r\n

{{ $playing.Title }}

\r\n

{{ $playing.Views }} views • {{ $playing.Modified }}
{{ $playing.Size | bytes }}

\r\n

{{ $playing.Description }}

\r\n {{ else }}\r\n \r\n {{ end }}\r\n
\r\n
\r\n
\r\n \r\n
\r\n {{ range $m := .Playlist }}\r\n {{ if eq $m.ID $playing.ID }}\r\n \r\n {{ else }}\r\n \r\n {{ end }}\r\n \r\n
\r\n

{{ $m.Title }}

\r\n

{{ $m.Views }} views • {{ $m.Modified }}
{{ $m.Size | bytes }}

\r\n
\r\n
\r\n {{ end }}\r\n
\r\n{{end}}\r\n"), + Content: string("{{ define \"content\" }}\r\n{{ $playing := .Playing }}\r\n
\r\n {{ if $playing.ID }}\r\n \r\n

{{ $playing.Title }}

\r\n

{{ $playing.Views }} views • {{ $playing.Modified }}
{{ $playing.Size | bytes }}

\r\n

{{ $playing.Description }}

\r\n {{ else }}\r\n \r\n {{ end }}\r\n
\r\n
\r\n
\r\n \r\n
\r\n {{ range $m := .Playlist }}\r\n {{ if eq $m.ID $playing.ID }}\r\n \r\n {{ else }}\r\n \r\n {{ end }}\r\n \r\n
\r\n

{{ $m.Title }}

\r\n

{{ $m.Views }} views • {{ $m.Modified }}
{{ $m.Size | bytes }}

\r\n
\r\n
\r\n {{ end }}\r\n
\r\n{{end}}\r\n"), } file5 := &embedded.EmbeddedFile{ Filename: "upload.html", @@ -37,7 +37,7 @@ func init() { // define dirs dir1 := &embedded.EmbeddedDir{ Filename: "", - DirModTime: time.Unix(1585371597, 0), + DirModTime: time.Unix(1585374250, 0), ChildFiles: []*embedded.EmbeddedFile{ file2, // "base.html" file3, // "import.html" @@ -53,7 +53,7 @@ func init() { // register embeddedBox embedded.RegisterEmbeddedBox(`../templates`, &embedded.EmbeddedBox{ Name: `../templates`, - Time: time.Unix(1585371597, 0), + Time: time.Unix(1585374250, 0), Dirs: map[string]*embedded.EmbeddedDir{ "": dir1, }, diff --git a/app/watcher.go b/app/watcher.go index 000df02..e08dff5 100644 --- a/app/watcher.go +++ b/app/watcher.go @@ -2,6 +2,7 @@ package app import ( "path/filepath" + "strings" "time" fs "github.com/fsnotify/fsnotify" @@ -29,7 +30,7 @@ func startWatcher(a *App) { for { select { case e := <-a.Watcher.Events: - if filepath.Ext(e.Name) != ".mp4" { + if strings.ContainsAny(e.Name, "#") || filepath.Ext(e.Name) != ".mp4" { continue } log.Debugf("fsnotify event: %s", e) diff --git a/media/library.go b/media/library.go index 0a0b522..5ea20e3 100644 --- a/media/library.go +++ b/media/library.go @@ -50,6 +50,10 @@ func (lib *Library) Import(p *Path) error { return err } for _, info := range files { + if strings.ContainsAny(info.Name(), "#") { + // ignore resized videos e.g: #240p.mp4 + continue + } err = lib.Add(path.Join(p.Path, info.Name())) if err != nil { // Ignore files that can't be parsed diff --git a/templates/index.html b/templates/index.html index aea20cb..5d8cd18 100644 --- a/templates/index.html +++ b/templates/index.html @@ -2,7 +2,9 @@ {{ $playing := .Playing }}
{{ if $playing.ID }} - +

{{ $playing.Title }}

{{ $playing.Views }} views • {{ $playing.Modified }}
{{ $playing.Size | bytes }}

{{ $playing.Description }}