diff --git a/Dockerfile b/Dockerfile index e0239c16..6eeae38f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -75,7 +75,9 @@ RUN export $(cat /env) \ && cp -a pkgconfig/* ${PKG_CONFIG_PATH} \ && cp -a lib/* /usr/local/lib/ \ && ldconfig \ - && apt-get install -y ./deb/jellyfin-ffmpeg.deb + && apt-get install -y ./deb/jellyfin-ffmpeg.deb \ + && ln -s /usr/lib/jellyfin-ffmpeg/ffmpeg /usr/local/bin/ \ + && ln -s /usr/lib/jellyfin-ffmpeg/ffprobe /usr/local/bin/ COPY api/go.mod api/go.sum /app/api/ # Split values in `/env` diff --git a/api/scanner/media_encoding/executable_worker/executable_worker_test.go b/api/scanner/media_encoding/executable_worker/executable_worker_test.go index 4450934d..51b45cb1 100644 --- a/api/scanner/media_encoding/executable_worker/executable_worker_test.go +++ b/api/scanner/media_encoding/executable_worker/executable_worker_test.go @@ -34,6 +34,8 @@ func SetPathWithCurrent(t *testing.T, paths ...string) { func TestInitFfprobePath(t *testing.T) { t.Run("PathFail", func(t *testing.T) { + SetPathWithCurrent(t, "non_exist_path") + err := SetFfprobePath() if err == nil { t.Fatalf("InitFfprobePath() returns nil, want an error") diff --git a/api/scanner/perf_test.go b/api/scanner/perf_test.go index 062f87c1..0c95098c 100644 --- a/api/scanner/perf_test.go +++ b/api/scanner/perf_test.go @@ -8,7 +8,6 @@ import ( "path/filepath" "testing" - "github.com/photoview/photoview/api/scanner/media_encoding/executable_worker" "gopkg.in/gographics/imagick.v3/imagick" ) @@ -44,21 +43,6 @@ func BenchmarkStdlib(b *testing.B) { } } -func BenchmarkMagickCLI(b *testing.B) { - dir := b.TempDir() - - for b.Loop() { - func() { - output := filepath.Join(dir, "test.jpg") - defer os.Remove(output) - - if err := executable_worker.Magick.EncodeJpeg("./test_media/real_media/png.png", output, 70); err != nil { - b.Fatal("encode jpeg error:", err) - } - }() - } -} - func BenchmarkMagickWand(b *testing.B) { dir := b.TempDir() diff --git a/api/scanner/scanner_test.go b/api/scanner/scanner_test.go index 10d98ee0..741d7ef2 100644 --- a/api/scanner/scanner_test.go +++ b/api/scanner/scanner_test.go @@ -36,38 +36,28 @@ func TestFullScan(t *testing.T) { Path: "./test_media", } - wantNoImages := []string{ - "avi.avi", - "mkv.mkv", - "mp4.mp4", - "mpeg.mpg", - "ogg.ogg", - "quicktime.mov", - "webm.webm", - "wmv.wmv", - } - wantThumbnailsImages := []string{ - "buttercup_close_summer_yellow.jpg", + wantWebPhotos := []string{ + "bmp.bmp", "gif.gif", - "lilac_lilac_bush_lilac.jpg", - "mount_merapi_volcano_indonesia.jpg", + "jpeg.jpg", + "png.png", + "webp.webp", + + "jpg_with_file.jpg", + "recoverable_bad_rst_marker.jpg", + "standalone_jpg.jpg", + "boy1.jpg", "boy2.jpg", + "buttercup_close_summer_yellow.jpg", "girl_black_hair2.jpg", "girl_blond1.jpg", "girl_blond2.jpg", "girl_blond3.jpg", - - "bmp.bmp", - "jpeg.jpg", - "jpg_with_file.jpg", - "webp.webp", - "png.png", - "standalone_jpg.jpg", - - "recoverable_bad_rst_marker.jpg", + "lilac_lilac_bush_lilac.jpg", + "mount_merapi_volcano_indonesia.jpg", } - wantHighresImages := []string{ + wantNonWebPhotos := []string{ "heif.heif", "jpg2000.jp2", "raw_with_file.tiff", @@ -75,6 +65,18 @@ func TestFullScan(t *testing.T) { "standalone_raw.tiff", "tiff.tiff", } + wantWebVideos := []string{ + "mp4.mp4", + "mpeg.mpg", + "ogg.ogg", + "webm.webm", + } + wantNonWebVideos := []string{ + "avi.avi", + "mkv.mkv", + "quicktime.mov", + "wmv.wmv", + } wantFaceGroups := [][]string{ {"boy1.jpg", "boy2.jpg"}, @@ -109,15 +111,19 @@ func TestFullScan(t *testing.T) { t.Fatal("get all media error:", err) } - var want []string - want = append(want, wantNoImages...) - want = append(want, wantThumbnailsImages...) - want = append(want, wantHighresImages...) + want := []string{} + want = append(want, wantWebPhotos...) + want = append(want, wantNonWebPhotos...) + want = append(want, wantWebVideos...) + want = append(want, wantNonWebVideos...) slices.Sort(want) got := make([]string, len(allMedia)) for i, media := range allMedia { got[i] = media.Title + if media.Blurhash == nil { + t.Errorf("media %q(%s) doesn't have Blurhash, while it should have", media.Title, media.Type) + } } slices.Sort(got) @@ -133,28 +139,27 @@ func TestFullScan(t *testing.T) { } var want []string - - wantThumbs := slices.Clone(wantThumbnailsImages) - want = append(want, wantThumbnailsImages...) - for _, file := range copyFilelistWithJpgExt(wantThumbs) { - want = append(want, "thumbnail_"+file) + want = append(want, wantWebPhotos...) + for _, name := range wantWebPhotos { + want = append(want, "thumbnail_"+strings.ReplaceAll(name, ".", "_")+".jpg") } - wantHighres := slices.Clone(wantHighresImages) - want = append(want, wantHighresImages...) - for _, file := range copyFilelistWithJpgExt(wantHighres) { - want = append(want, "highres_"+file) - want = append(want, "thumbnail_"+file) + want = append(want, wantNonWebPhotos...) + for _, name := range wantNonWebPhotos { + want = append(want, "thumbnail_"+strings.ReplaceAll(name, ".", "_")+".jpg") + want = append(want, "highres_"+strings.ReplaceAll(name, ".", "_")+".jpg") } - wantSet := make(map[string]struct{}) - for _, item := range want { - wantSet[item] = struct{}{} + want = append(want, wantWebVideos...) + for _, name := range wantWebVideos { + want = append(want, "video_thumb_"+strings.ReplaceAll(name, ".", "_")+".jpg") } - want = make([]string, 0, len(wantSet)) - for key := range wantSet { - want = append(want, key) + + for _, name := range wantNonWebVideos { + want = append(want, "video_thumb_"+strings.ReplaceAll(name, ".", "_")+".jpg") + want = append(want, "web_video_"+strings.ReplaceAll(name, ".", "_")+".mp4") } + slices.Sort(want) if got, want := len(allMediaURL), len(want); got != want { @@ -168,7 +173,7 @@ func TestFullScan(t *testing.T) { slices.Sort(got) if diff := cmp.Diff(got, want, cmp.Comparer(equalNameWithoutSuffix)); diff != "" { - t.Errorf("all media diff (-got, +want):\n%s", diff) + t.Errorf("all media url diff (-got, +want):\n%s", diff) } }) @@ -218,8 +223,8 @@ func equalNameWithoutSuffix(a, b string) bool { return false } - // a is not part of b and b is not part of a - if strings.Index(mainA, mainB) < 0 && strings.Index(mainB, mainA) < 0 { + // a is not prefix of b and b is not prefix of a + if strings.HasPrefix(mainA, mainB) && strings.HasPrefix(mainB, mainA) { return false } diff --git a/api/scanner/test_media/real_media/avi.avi b/api/scanner/test_media/real_media/avi.avi index 6db53dfa..850feab9 100644 Binary files a/api/scanner/test_media/real_media/avi.avi and b/api/scanner/test_media/real_media/avi.avi differ diff --git a/api/scanner/test_media/real_media/mp4.mp4 b/api/scanner/test_media/real_media/mp4.mp4 index 1431e98d..1fc47884 100644 Binary files a/api/scanner/test_media/real_media/mp4.mp4 and b/api/scanner/test_media/real_media/mp4.mp4 differ diff --git a/api/scanner/test_media/real_media/wmv.wmv b/api/scanner/test_media/real_media/wmv.wmv index d1094bda..b007f4c4 100644 Binary files a/api/scanner/test_media/real_media/wmv.wmv and b/api/scanner/test_media/real_media/wmv.wmv differ diff --git a/api/test_utils/scanner/scanner_helpers.go b/api/test_utils/scanner/scanner_helpers.go index ecd04312..70302c95 100644 --- a/api/test_utils/scanner/scanner_helpers.go +++ b/api/test_utils/scanner/scanner_helpers.go @@ -2,14 +2,22 @@ package scanner_utils import ( "testing" + "time" "github.com/photoview/photoview/api/graphql/models" + "github.com/photoview/photoview/api/scanner" "github.com/photoview/photoview/api/scanner/scanner_queue" "github.com/stretchr/testify/assert" "gorm.io/gorm" ) func RunScannerOnUser(t *testing.T, db *gorm.DB, user *models.User) { + start := time.Now() + defer func() { + dur := time.Now().Sub(start) + t.Logf("RunScannerOnUser(user(id:%d)) took %s.", user.ID, dur) + }() + if !assert.NoError(t, scanner_queue.InitializeScannerQueue(db)) { return } @@ -20,9 +28,19 @@ func RunScannerOnUser(t *testing.T, db *gorm.DB, user *models.User) { // wait for all jobs to finish scanner_queue.CloseScannerQueue() + + if err := scanner.GenerateBlurhashes(db); err != nil { + t.Fatalf("generate blurhashes error: %v", err) + } } func RunScannerAll(t *testing.T, db *gorm.DB) { + start := time.Now() + defer func() { + dur := time.Now().Sub(start) + t.Logf("RunScannerAll() took %s.", dur) + }() + if !assert.NoError(t, scanner_queue.InitializeScannerQueue(db)) { return } @@ -33,4 +51,8 @@ func RunScannerAll(t *testing.T, db *gorm.DB) { // wait for all jobs to finish scanner_queue.CloseScannerQueue() + + if err := scanner.GenerateBlurhashes(db); err != nil { + t.Fatalf("generate blurhashes error: %v", err) + } }