Compare commits

...

7 Commits

Author SHA1 Message Date
Bel LaPointe
3e36e53805 no catch sigint 2024-11-18 06:51:17 -07:00
Bel LaPointe
9de277a879 i messed up 2024-11-17 23:13:27 -07:00
bel
eb12586a40 DONT FAIL FOREVER ON 1 BLACKOUT FILE loser 2024-11-16 07:30:25 -07:00
Bel LaPointe
03565e4fbc cache media 2024-09-19 13:54:02 -04:00
Bel LaPointe
9bda977a29 prune also stashes the first jpg with movement as movement/cam/series.jpg 2024-09-19 12:36:26 -04:00
Bel LaPointe
6a8445fbd0 draw even if no thumbnail avail 2024-09-19 12:31:13 -04:00
Bel LaPointe
0e4da7e436 sort by href 2024-09-19 12:30:01 -04:00
7 changed files with 110 additions and 46 deletions

View File

@@ -68,7 +68,17 @@ func Run(ctx context.Context, args []string) error {
} }
if seriesHasMovement, err := seriesHasMovement(ctx, seriesFiles, movementInterval); err != nil { if seriesHasMovement, err := seriesHasMovement(ctx, seriesFiles, movementInterval); err != nil {
return err return err
} else if seriesHasMovement { } else if seriesHasMovement > -1 {
outd := strings.ReplaceAll(cam, "record", "movement")
os.MkdirAll(outd, os.ModePerm)
fileWithMovement := seriesFiles[seriesHasMovement]
if b, err := os.ReadFile(fileWithMovement); err != nil {
return err
} else if err := os.WriteFile(path.Join(outd, series+path.Ext(fileWithMovement)), b, os.ModePerm); err != nil {
return err
}
firstFileInfo, err := os.Stat(seriesFiles[0]) firstFileInfo, err := os.Stat(seriesFiles[0])
if err != nil { if err != nil {
return err return err
@@ -83,8 +93,6 @@ func Run(ctx context.Context, args []string) error {
log.Println("found movement in", series, "over", durationSeconds, "seconds at", fps, "fps") log.Println("found movement in", series, "over", durationSeconds, "seconds at", fps, "fps")
outd := strings.ReplaceAll(cam, "record", "movement")
os.MkdirAll(outd, os.ModePerm)
cmd := exec.CommandContext(ctx, cmd := exec.CommandContext(ctx,
"ffmpeg", "ffmpeg",
"-y", "-y",
@@ -107,12 +115,13 @@ func Run(ctx context.Context, args []string) error {
} }
return nil return nil
}(); err != nil { }(); err != nil {
return err log.Println("failed series", series, ":", err)
} }
} }
} }
for _, cam := range cams { for _, cam := range cams {
if err := func() error {
camMovementD := strings.ReplaceAll(cam, "record", "movement") camMovementD := strings.ReplaceAll(cam, "record", "movement")
movementFiles, err := lsf(camMovementD) movementFiles, err := lsf(camMovementD)
@@ -149,20 +158,24 @@ func Run(ctx context.Context, args []string) error {
sizeOfCamDMiB -= oldestFileSizeMiB sizeOfCamDMiB -= oldestFileSizeMiB
movementFiles = movementFiles[1:] movementFiles = movementFiles[1:]
} }
return nil
}(); err != nil {
log.Println("failed to cap size of cam", cam, " dir:", err)
}
} }
return nil return nil
} }
func seriesHasMovement(ctx context.Context, files []string, movementInterval time.Duration) (bool, error) { func seriesHasMovement(ctx context.Context, files []string, movementInterval time.Duration) (int, error) {
if len(files) < 1 { if len(files) < 1 {
return false, nil return -1, nil
} }
f := files[0] f := files[0]
fStat, err := os.Stat(f) fStat, err := os.Stat(f)
if err != nil { if err != nil {
return false, err return -1, err
} }
fTime := fStat.ModTime() fTime := fStat.ModTime()
@@ -170,7 +183,7 @@ func seriesHasMovement(ctx context.Context, files []string, movementInterval tim
g := files[i] g := files[i]
gStat, err := os.Stat(g) gStat, err := os.Stat(g)
if err != nil { if err != nil {
return false, err return -1, err
} }
gTime := gStat.ModTime() gTime := gStat.ModTime()
@@ -179,15 +192,15 @@ func seriesHasMovement(ctx context.Context, files []string, movementInterval tim
} }
if hasMovement, err := hasMovement(ctx, f, g); err != nil { if hasMovement, err := hasMovement(ctx, f, g); err != nil {
return false, fmt.Errorf("failed to check for movement between %s and %s: %w", f, g, err) return -1, fmt.Errorf("failed to check for movement between %s and %s: %w", f, g, err)
} else if hasMovement { } else if hasMovement {
return true, nil return i, nil
} }
f = g f = g
fTime = gTime fTime = gTime
} }
return false, nil return -1, nil
} }
func hasMovement(ctx context.Context, a, b string) (bool, error) { func hasMovement(ctx context.Context, a, b string) (bool, error) {

View File

@@ -57,9 +57,11 @@ func TestRun(t *testing.T) {
if results, err := lsf(path.Join(path.Dir(d), "movement")); err != nil { if results, err := lsf(path.Join(path.Dir(d), "movement")); err != nil {
t.Fatal("failed to lsf for results:", err) t.Fatal("failed to lsf for results:", err)
} else if len(results) != 1 { } else if len(results) != 2 {
t.Fatal(results) t.Fatal(results)
} else if path.Base(results[0]) != seriesA+".mp4" { } else if path.Base(results[0]) != seriesA+".jpg" {
t.Fatal(results)
} else if path.Base(results[1]) != seriesA+".mp4" {
t.Fatal(results) t.Fatal(results)
} }

49
cmd/rmdir/main.go Normal file
View File

@@ -0,0 +1,49 @@
package main
import (
"context"
"fmt"
"log"
"os"
"ffmpeg.d/pkg/fs"
)
func main() {
if err := Run(context.Background(), os.Args[1:]); err != nil {
panic(err)
}
}
func Run(ctx context.Context, args []string) error {
cams, err := lsd(args[0])
if err != nil {
return fmt.Errorf("failed to lsd %s: %w", args[0], err)
}
for _, cam := range cams {
files, err := lsf(cam)
if err != nil {
return fmt.Errorf("failed to lsf %s: %w", cam, err)
} else if len(files) < 1 {
continue
}
for _, file := range files {
log.Println("rm", file)
if os.Getenv("DRY_RUN") == "false" {
os.Remove(file)
}
}
}
return nil
}
func lsd(d string) ([]string, error) {
return fs.LsD(d)
}
func lsf(d string) ([]string, error) {
return fs.LsF(d)
}

View File

@@ -6,9 +6,9 @@
<body> <body>
<div> <div>
{{ range .Series }} {{ range .Series }}
<div style="display: inline-block; max-width: 12em; max-height: 9em; margin-bottom: .7em;"> <div style="display: inline-block; width: 12em; height: 9em; margin-bottom: .7em;">
<a href="/media/{{ .HREF }}"> <a href="/media/{{ .HREF }}">
<img src="/media/{{ .Thumbnail }}" alt="{{ .Thumbnail }}"/> <img src="/media/{{ .Thumbnail }}" alt="{{ .HREF }}"/>
<span>{{ .Thumbnail }}</span> <span>{{ .Thumbnail }}</span>
<br> <br>
</a> </a>

View File

@@ -50,6 +50,8 @@ func Run(ctx context.Context, args []string) error {
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, "/media/") { if strings.HasPrefix(r.URL.Path, "/media/") {
http.StripPrefix("/media/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.StripPrefix("/media/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "private, max-age=31536000")
w.Header().Add("Cache-Control", "immutable")
http.FileServer(http.Dir(*d)).ServeHTTP(w, r) http.FileServer(http.Dir(*d)).ServeHTTP(w, r)
})).ServeHTTP(w, r) })).ServeHTTP(w, r)
return return
@@ -89,7 +91,7 @@ func Run(ctx context.Context, args []string) error {
series = append(series, v) series = append(series, v)
} }
slices.SortFunc(series, func(a, b Series) int { slices.SortFunc(series, func(a, b Series) int {
return -1 * strings.Compare(path.Base(a.Thumbnail), path.Base(b.Thumbnail)) return -1 * strings.Compare(path.Base(a.HREF), path.Base(b.HREF))
}) })
if err := tmpl.Execute(w, map[string]any{ if err := tmpl.Execute(w, map[string]any{

View File

@@ -1 +0,0 @@
LAdN7KVw-Ig.mp4

View File

@@ -1 +0,0 @@
LAdN7KVw-Ig.jpg