1
Fork 0

Make it compile again

This commit is contained in:
viktorstrate 2022-03-02 17:26:06 +01:00
parent 6e2a64bc77
commit b09d32019e
No known key found for this signature in database
GPG Key ID: 3F855605109C1E8A
13 changed files with 151 additions and 78 deletions

View File

@ -77,6 +77,10 @@ func (m *Media) GetHighRes() (*MediaURL, error) {
return nil, nil return nil, nil
} }
func (m *Media) CachePath() (string, error) {
return utils.CachePathForMedia(m.AlbumID, m.ID)
}
type MediaType string type MediaType string
const ( const (

View File

@ -46,7 +46,7 @@ func RegisterPhotoRoutes(db *gorm.DB, router *mux.Router) {
if _, err := os.Stat(cachedPath); os.IsNotExist((err)) { if _, err := os.Stat(cachedPath); os.IsNotExist((err)) {
err := db.Transaction(func(tx *gorm.DB) error { err := db.Transaction(func(tx *gorm.DB) error {
if _, err = scanner.ProcessMedia(tx, media); err != nil { if err = scanner.ProcessSingleMedia(tx, media); err != nil {
log.Printf("ERROR: processing image not found in cache (%s): %s\n", cachedPath, err) log.Printf("ERROR: processing image not found in cache (%s): %s\n", cachedPath, err)
return err return err
} }

View File

@ -52,7 +52,7 @@ func RegisterVideoRoutes(db *gorm.DB, router *mux.Router) {
if _, err := os.Stat(cachedPath); err != nil { if _, err := os.Stat(cachedPath); err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
err := db.Transaction(func(tx *gorm.DB) error { err := db.Transaction(func(tx *gorm.DB) error {
if _, err := scanner.ProcessMedia(tx, media); err != nil { if err := scanner.ProcessSingleMedia(tx, media); err != nil {
log.Printf("ERROR: processing video not found in cache: %s\n", err) log.Printf("ERROR: processing video not found in cache: %s\n", err)
return err return err
} }

View File

@ -61,6 +61,12 @@ type EncodeMediaData struct {
_videoMetadata *ffprobe.ProbeData _videoMetadata *ffprobe.ProbeData
} }
func NewEncodeMediaData(media *models.Media) EncodeMediaData {
return EncodeMediaData{
Media: media,
}
}
// ContentType reads the image to determine its content type // ContentType reads the image to determine its content type
func (img *EncodeMediaData) ContentType() (*media_type.MediaType, error) { func (img *EncodeMediaData) ContentType() (*media_type.MediaType, error) {
if img._contentType != nil { if img._contentType != nil {

View File

@ -6,7 +6,6 @@ import (
"log" "log"
"os" "os"
"path" "path"
"strconv"
"github.com/photoview/photoview/api/graphql/models" "github.com/photoview/photoview/api/graphql/models"
"github.com/photoview/photoview/api/scanner/media_encoding" "github.com/photoview/photoview/api/scanner/media_encoding"
@ -104,9 +103,7 @@ func ScanAlbum(ctx scanner_task.TaskContext) error {
for i, media := range albumMedia { for i, media := range albumMedia {
updatedURLs := []*models.MediaURL{} updatedURLs := []*models.MediaURL{}
mediaData := media_encoding.EncodeMediaData{ mediaData := media_encoding.NewEncodeMediaData(media)
Media: media,
}
// define new ctx for scope of for-loop // define new ctx for scope of for-loop
ctx, err := scanner_tasks.Tasks.BeforeProcessMedia(ctx, &mediaData) ctx, err := scanner_tasks.Tasks.BeforeProcessMedia(ctx, &mediaData)
@ -200,44 +197,11 @@ func findMediaForAlbum(ctx scanner_task.TaskContext) ([]*models.Media, error) {
func processMedia(ctx scanner_task.TaskContext, mediaData *media_encoding.EncodeMediaData) ([]*models.MediaURL, error) { func processMedia(ctx scanner_task.TaskContext, mediaData *media_encoding.EncodeMediaData) ([]*models.MediaURL, error) {
_, err := mediaData.ContentType()
if err != nil {
return []*models.MediaURL{}, errors.Wrapf(err, "get content-type of media (%s)", mediaData.Media.Path)
}
// Make sure media cache directory exists // Make sure media cache directory exists
mediaCachePath, err := makeMediaCacheDir(mediaData.Media) mediaCachePath, err := mediaData.Media.CachePath()
if err != nil { if err != nil {
return []*models.MediaURL{}, errors.Wrap(err, "cache directory error") return []*models.MediaURL{}, errors.Wrap(err, "cache directory error")
} }
return scanner_tasks.Tasks.ProcessMedia(ctx, mediaData, *mediaCachePath) return scanner_tasks.Tasks.ProcessMedia(ctx, mediaData, mediaCachePath)
}
func makeMediaCacheDir(media *models.Media) (*string, error) {
// Make root cache dir if not exists
if _, err := os.Stat(utils.MediaCachePath()); os.IsNotExist(err) {
if err := os.Mkdir(utils.MediaCachePath(), os.ModePerm); err != nil {
return nil, errors.Wrap(err, "could not make root image cache directory")
}
}
// Make album cache dir if not exists
albumCachePath := path.Join(utils.MediaCachePath(), strconv.Itoa(int(media.AlbumID)))
if _, err := os.Stat(albumCachePath); os.IsNotExist(err) {
if err := os.Mkdir(albumCachePath, os.ModePerm); err != nil {
return nil, errors.Wrap(err, "could not make album image cache directory")
}
}
// Make photo cache dir if not exists
photoCachePath := path.Join(albumCachePath, strconv.Itoa(int(media.ID)))
if _, err := os.Stat(photoCachePath); os.IsNotExist(err) {
if err := os.Mkdir(photoCachePath, os.ModePerm); err != nil {
return nil, errors.Wrap(err, "could not make photo image cache directory")
}
}
return &photoCachePath, nil
} }

View File

@ -1,12 +1,16 @@
package scanner package scanner
import ( import (
"context"
"log" "log"
"os" "os"
"path" "path"
"github.com/photoview/photoview/api/graphql/models" "github.com/photoview/photoview/api/graphql/models"
"github.com/photoview/photoview/api/scanner/media_encoding"
"github.com/photoview/photoview/api/scanner/scanner_cache" "github.com/photoview/photoview/api/scanner/scanner_cache"
"github.com/photoview/photoview/api/scanner/scanner_task"
"github.com/photoview/photoview/api/scanner/scanner_tasks"
"github.com/pkg/errors" "github.com/pkg/errors"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -62,11 +66,41 @@ func ScanMedia(tx *gorm.DB, mediaPath string, albumId int, cache *scanner_cache.
return nil, false, errors.Wrap(err, "could not insert media into database") return nil, false, errors.Wrap(err, "could not insert media into database")
} }
if media.Type == models.MediaTypeVideo {
if err = ScanVideoMetadata(tx, &media); err != nil {
log.Printf("WARN: ScanVideoMetadata for %s failed: %s\n", mediaName, err)
}
}
return &media, true, nil return &media, true, nil
} }
// ProcessSingleMedia processes a single media, might be used to reprocess media with corrupted cache
// Function waits for processing to finish before returning.
func ProcessSingleMedia(db *gorm.DB, media *models.Media) error {
album_cache := scanner_cache.MakeAlbumCache()
var album models.Album
if err := db.Model(media).Association("Album").Find(&album); err != nil {
return err
}
media_data := media_encoding.NewEncodeMediaData(media)
task_context := scanner_task.NewTaskContext(context.Background(), db, &album, album_cache)
new_ctx, err := scanner_tasks.Tasks.BeforeProcessMedia(task_context, &media_data)
if err != nil {
return err
}
mediaCachePath, err := media.CachePath()
if err != nil {
return err
}
updated_urls, err := scanner_tasks.Tasks.ProcessMedia(new_ctx, &media_data, mediaCachePath)
if err != nil {
return err
}
err = scanner_tasks.Tasks.AfterProcessMedia(new_ctx, &media_data, updated_urls, 0, 1)
if err != nil {
return err
}
return nil
}

View File

@ -217,6 +217,8 @@ func AddAllToQueue() error {
return nil return nil
} }
// AddUserToQueue finds all root albums owned by the given user and adds them to the scanner queue.
// Function does not block.
func AddUserToQueue(user *models.User) error { func AddUserToQueue(user *models.User) error {
album_cache := scanner_cache.MakeAlbumCache() album_cache := scanner_cache.MakeAlbumCache()
albums, album_errors := scanner.FindAlbumsForUser(global_scanner_queue.db, user, album_cache) albums, album_errors := scanner.FindAlbumsForUser(global_scanner_queue.db, user, album_cache)

View File

@ -5,7 +5,6 @@ import (
"github.com/photoview/photoview/api/graphql/models" "github.com/photoview/photoview/api/graphql/models"
"github.com/photoview/photoview/api/scanner/exif" "github.com/photoview/photoview/api/scanner/exif"
"github.com/photoview/photoview/api/scanner/media_encoding"
"github.com/photoview/photoview/api/scanner/scanner_task" "github.com/photoview/photoview/api/scanner/scanner_task"
) )
@ -13,11 +12,15 @@ type ExifTask struct {
scanner_task.ScannerTaskBase scanner_task.ScannerTaskBase
} }
func (t ExifTask) AfterProcessMedia(ctx scanner_task.TaskContext, mediaData *media_encoding.EncodeMediaData, updatedURLs []*models.MediaURL, mediaIndex int, mediaTotal int) error { func (t ExifTask) AfterMediaFound(ctx scanner_task.TaskContext, media *models.Media, newMedia bool) error {
_, err := exif.SaveEXIF(ctx.GetDB(), mediaData.Media) if !newMedia {
return nil
}
_, err := exif.SaveEXIF(ctx.GetDB(), media)
if err != nil { if err != nil {
log.Printf("WARN: SaveEXIF for %s failed: %s\n", mediaData.Media.Title, err) log.Printf("WARN: SaveEXIF for %s failed: %s\n", media.Title, err)
} }
return nil return nil

View File

@ -59,7 +59,7 @@ func (t ProcessVideoTask) ProcessMedia(ctx scanner_task.TaskContext, mediaData *
origVideoPath := video.Path origVideoPath := video.Path
videoMediaName := generateUniqueMediaName(video.Path) videoMediaName := generateUniqueMediaName(video.Path)
webMetadata, err := readVideoStreamMetadata(origVideoPath) webMetadata, err := ReadVideoStreamMetadata(origVideoPath)
if err != nil { if err != nil {
return []*models.MediaURL{}, errors.Wrapf(err, "failed to read metadata for original video (%s)", video.Title) return []*models.MediaURL{}, errors.Wrapf(err, "failed to read metadata for original video (%s)", video.Title)
} }
@ -99,7 +99,7 @@ func (t ProcessVideoTask) ProcessMedia(ctx scanner_task.TaskContext, mediaData *
return []*models.MediaURL{}, errors.Wrapf(err, "could not encode mp4 video (%s)", video.Path) return []*models.MediaURL{}, errors.Wrapf(err, "could not encode mp4 video (%s)", video.Path)
} }
webMetadata, err := readVideoStreamMetadata(webVideoPath) webMetadata, err := ReadVideoStreamMetadata(webVideoPath)
if err != nil { if err != nil {
return []*models.MediaURL{}, errors.Wrapf(err, "failed to read metadata for encoded web-video (%s)", video.Title) return []*models.MediaURL{}, errors.Wrapf(err, "failed to read metadata for encoded web-video (%s)", video.Title)
} }
@ -205,7 +205,7 @@ func (t ProcessVideoTask) ProcessMedia(ctx scanner_task.TaskContext, mediaData *
return updatedURLs, nil return updatedURLs, nil
} }
func readVideoMetadata(videoPath string) (*ffprobe.ProbeData, error) { func ReadVideoMetadata(videoPath string) (*ffprobe.ProbeData, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second) ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
defer cancelFn() defer cancelFn()
@ -217,8 +217,8 @@ func readVideoMetadata(videoPath string) (*ffprobe.ProbeData, error) {
return data, nil return data, nil
} }
func readVideoStreamMetadata(videoPath string) (*ffprobe.Stream, error) { func ReadVideoStreamMetadata(videoPath string) (*ffprobe.Stream, error) {
data, err := readVideoMetadata(videoPath) data, err := ReadVideoMetadata(videoPath)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "read video stream metadata") return nil, errors.Wrap(err, "read video stream metadata")
} }

View File

@ -19,6 +19,7 @@ var allTasks []scanner_task.ScannerTask = []scanner_task.ScannerTask{
processing_tasks.ProcessVideoTask{}, processing_tasks.ProcessVideoTask{},
FaceDetectionTask{}, FaceDetectionTask{},
ExifTask{}, ExifTask{},
VideoMetadataTask{},
cleanup_tasks.MediaCleanupTask{}, cleanup_tasks.MediaCleanupTask{},
} }

View File

@ -1,18 +1,39 @@
package scanner package scanner_tasks
import ( import (
"fmt" "fmt"
"log"
"strconv" "strconv"
"strings" "strings"
"github.com/photoview/photoview/api/graphql/models" "github.com/photoview/photoview/api/graphql/models"
"github.com/photoview/photoview/api/scanner/scanner_task"
"github.com/photoview/photoview/api/scanner/scanner_tasks/processing_tasks"
"github.com/pkg/errors" "github.com/pkg/errors"
"gorm.io/gorm" "gorm.io/gorm"
) )
type VideoMetadataTask struct {
scanner_task.ScannerTaskBase
}
func (t VideoMetadataTask) AfterMediaFound(ctx scanner_task.TaskContext, media *models.Media, newMedia bool) error {
if !newMedia || media.Type != models.MediaTypeVideo {
return nil
}
err := ScanVideoMetadata(ctx.GetDB(), media)
if err != nil {
log.Printf("WARN: ScanVideoMetadata for %s failed: %s\n", media.Title, err)
}
return nil
}
func ScanVideoMetadata(tx *gorm.DB, video *models.Media) error { func ScanVideoMetadata(tx *gorm.DB, video *models.Media) error {
data, err := readVideoMetadata(video.Path) data, err := processing_tasks.ReadVideoMetadata(video.Path)
if err != nil { if err != nil {
return errors.Wrapf(err, "scan video metadata failed (%s)", video.Title) return errors.Wrapf(err, "scan video metadata failed (%s)", video.Title)
} }

58
api/utils/media_cache.go Normal file
View File

@ -0,0 +1,58 @@
package utils
import (
"os"
"path"
"strconv"
"github.com/pkg/errors"
)
// CachePathForMedia is a low-level implementation for Media.CachePath()
func CachePathForMedia(albumID int, mediaID int) (string, error) {
// Make root cache dir if not exists
if _, err := os.Stat(MediaCachePath()); os.IsNotExist(err) {
if err := os.Mkdir(MediaCachePath(), os.ModePerm); err != nil {
return "", errors.Wrap(err, "could not make root image cache directory")
}
}
// Make album cache dir if not exists
albumCachePath := path.Join(MediaCachePath(), strconv.Itoa(int(albumID)))
if _, err := os.Stat(albumCachePath); os.IsNotExist(err) {
if err := os.Mkdir(albumCachePath, os.ModePerm); err != nil {
return "", errors.Wrap(err, "could not make album image cache directory")
}
}
// Make photo cache dir if not exists
photoCachePath := path.Join(albumCachePath, strconv.Itoa(int(mediaID)))
if _, err := os.Stat(photoCachePath); os.IsNotExist(err) {
if err := os.Mkdir(photoCachePath, os.ModePerm); err != nil {
return "", errors.Wrap(err, "could not make photo image cache directory")
}
}
return photoCachePath, nil
}
var test_cache_path string = ""
func ConfigureTestCache(tmp_dir string) {
test_cache_path = tmp_dir
}
// MediaCachePath returns the path for where the media cache is located on the file system
func MediaCachePath() string {
if test_cache_path != "" {
return test_cache_path
}
photoCache := EnvMediaCachePath.GetValue()
if photoCache == "" {
photoCache = "./media_cache"
}
return photoCache
}

View File

@ -47,26 +47,6 @@ func HandleError(message string, err error) PhotoviewError {
} }
} }
var test_cache_path string = ""
func ConfigureTestCache(tmp_dir string) {
test_cache_path = tmp_dir
}
// MediaCachePath returns the path for where the media cache is located on the file system
func MediaCachePath() string {
if test_cache_path != "" {
return test_cache_path
}
photoCache := EnvMediaCachePath.GetValue()
if photoCache == "" {
photoCache = "./media_cache"
}
return photoCache
}
var test_face_recognition_models_path string = "" var test_face_recognition_models_path string = ""
func ConfigureTestFaceRecognitionModelsPath(path string) { func ConfigureTestFaceRecognitionModelsPath(path string) {