Make it compile again
This commit is contained in:
parent
6e2a64bc77
commit
b09d32019e
|
@ -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 (
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue