Compare commits
7 Commits
5b67d5c5f0
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e36e53805 | ||
|
|
9de277a879 | ||
|
|
eb12586a40 | ||
|
|
03565e4fbc | ||
|
|
9bda977a29 | ||
|
|
6a8445fbd0 | ||
|
|
0e4da7e436 |
@@ -68,7 +68,17 @@ func Run(ctx context.Context, args []string) error {
|
||||
}
|
||||
if seriesHasMovement, err := seriesHasMovement(ctx, seriesFiles, movementInterval); err != nil {
|
||||
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])
|
||||
if err != nil {
|
||||
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")
|
||||
|
||||
outd := strings.ReplaceAll(cam, "record", "movement")
|
||||
os.MkdirAll(outd, os.ModePerm)
|
||||
cmd := exec.CommandContext(ctx,
|
||||
"ffmpeg",
|
||||
"-y",
|
||||
@@ -107,62 +115,67 @@ func Run(ctx context.Context, args []string) error {
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return err
|
||||
log.Println("failed series", series, ":", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, cam := range cams {
|
||||
camMovementD := strings.ReplaceAll(cam, "record", "movement")
|
||||
if err := func() error {
|
||||
camMovementD := strings.ReplaceAll(cam, "record", "movement")
|
||||
|
||||
movementFiles, err := lsf(camMovementD)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.Strings(movementFiles)
|
||||
|
||||
var sizeOfCamDMiB int64
|
||||
for _, movementFile := range movementFiles {
|
||||
stat, err := os.Stat(movementFile)
|
||||
movementFiles, err := lsf(camMovementD)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileSizeMiB := stat.Size() / 1024 / 1024
|
||||
sizeOfCamDMiB += fileSizeMiB
|
||||
}
|
||||
sort.Strings(movementFiles)
|
||||
|
||||
GiB100 := int64(100 * 1024)
|
||||
for sizeOfCamDMiB > GiB100 && len(movementFiles) > 0 {
|
||||
oldestFile := movementFiles[0]
|
||||
|
||||
oldestFileStat, err := os.Stat(oldestFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldestFileSizeMiB := oldestFileStat.Size() / 1024 / 1024
|
||||
|
||||
log.Println("deleting old file", oldestFile)
|
||||
if err := os.Remove(oldestFile); err != nil {
|
||||
return err
|
||||
var sizeOfCamDMiB int64
|
||||
for _, movementFile := range movementFiles {
|
||||
stat, err := os.Stat(movementFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileSizeMiB := stat.Size() / 1024 / 1024
|
||||
sizeOfCamDMiB += fileSizeMiB
|
||||
}
|
||||
|
||||
sizeOfCamDMiB -= oldestFileSizeMiB
|
||||
movementFiles = movementFiles[1:]
|
||||
GiB100 := int64(100 * 1024)
|
||||
for sizeOfCamDMiB > GiB100 && len(movementFiles) > 0 {
|
||||
oldestFile := movementFiles[0]
|
||||
|
||||
oldestFileStat, err := os.Stat(oldestFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldestFileSizeMiB := oldestFileStat.Size() / 1024 / 1024
|
||||
|
||||
log.Println("deleting old file", oldestFile)
|
||||
if err := os.Remove(oldestFile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sizeOfCamDMiB -= oldestFileSizeMiB
|
||||
movementFiles = movementFiles[1:]
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
log.Println("failed to cap size of cam", cam, " dir:", err)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
return false, nil
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
f := files[0]
|
||||
fStat, err := os.Stat(f)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return -1, err
|
||||
}
|
||||
fTime := fStat.ModTime()
|
||||
|
||||
@@ -170,7 +183,7 @@ func seriesHasMovement(ctx context.Context, files []string, movementInterval tim
|
||||
g := files[i]
|
||||
gStat, err := os.Stat(g)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return -1, err
|
||||
}
|
||||
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 {
|
||||
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 {
|
||||
return true, nil
|
||||
return i, nil
|
||||
}
|
||||
|
||||
f = g
|
||||
fTime = gTime
|
||||
}
|
||||
return false, nil
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func hasMovement(ctx context.Context, a, b string) (bool, error) {
|
||||
|
||||
@@ -57,9 +57,11 @@ func TestRun(t *testing.T) {
|
||||
|
||||
if results, err := lsf(path.Join(path.Dir(d), "movement")); err != nil {
|
||||
t.Fatal("failed to lsf for results:", err)
|
||||
} else if len(results) != 1 {
|
||||
} else if len(results) != 2 {
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
49
cmd/rmdir/main.go
Normal file
49
cmd/rmdir/main.go
Normal 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)
|
||||
}
|
||||
@@ -6,9 +6,9 @@
|
||||
<body>
|
||||
<div>
|
||||
{{ 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 }}">
|
||||
<img src="/media/{{ .Thumbnail }}" alt="{{ .Thumbnail }}"/>
|
||||
<img src="/media/{{ .Thumbnail }}" alt="{{ .HREF }}"/>
|
||||
<span>{{ .Thumbnail }}</span>
|
||||
<br>
|
||||
</a>
|
||||
|
||||
@@ -50,6 +50,8 @@ func Run(ctx context.Context, args []string) error {
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasPrefix(r.URL.Path, "/media/") {
|
||||
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)
|
||||
})).ServeHTTP(w, r)
|
||||
return
|
||||
@@ -89,7 +91,7 @@ func Run(ctx context.Context, args []string) error {
|
||||
series = append(series, v)
|
||||
}
|
||||
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{
|
||||
|
||||
1
cmd/ui/testdata/cam/4.mp4
vendored
1
cmd/ui/testdata/cam/4.mp4
vendored
@@ -1 +0,0 @@
|
||||
LAdN7KVw-Ig.mp4
|
||||
1
cmd/ui/testdata/cam/5.jpg
vendored
1
cmd/ui/testdata/cam/5.jpg
vendored
@@ -1 +0,0 @@
|
||||
LAdN7KVw-Ig.jpg
|
||||
Reference in New Issue
Block a user