Live Photos: Refactor Support for Samsung Motion Photos #439 #3588

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer 2023-08-22 10:48:37 +02:00
parent 44759d6673
commit fd55b9046c
4 changed files with 32 additions and 41 deletions

View file

@ -65,7 +65,7 @@ type Data struct {
Rotation int `meta:"Rotation"`
Views int `meta:"-"`
Albums []string `meta:"-"`
EmbeddedVideo string `meta:"EmbeddedVideo"`
EmbeddedVideo string `meta:"-"`
Error error `meta:"-"`
json map[string]string
exif map[string]string

View file

@ -365,10 +365,10 @@ func (data *Data) Exiftool(jsonData []byte, originalName string) (err error) {
data.Subject = SanitizeMeta(data.Subject)
data.Artist = SanitizeMeta(data.Artist)
// set the embedded video file name, if it exists
// Set the name of the embedded video data field, if any.
if embeddedVideo, ok := data.json["EmbeddedVideoFile"]; ok && embeddedVideo != "" {
data.EmbeddedVideo = "EmbeddedVideoFile"
} else if embeddedVideo, ok := data.json["MotionPhotoVideo"]; ok && embeddedVideo != "" {
} else if embeddedVideo, ok = data.json["MotionPhotoVideo"]; ok && embeddedVideo != "" {
data.EmbeddedVideo = "MotionPhotoVideo"
}

View file

@ -317,42 +317,37 @@ func (m *MediaFile) EditedName() string {
return ""
}
// ExtractEmbeddedVideo extracts an embedded video file and returns its filename, if any.
func (m *MediaFile) ExtractEmbeddedVideo() (string, error) {
if m == nil {
return "", fmt.Errorf(
"mediafile: file is nil - you may have found a" +
" bug",
)
return "", fmt.Errorf("mediafile: file is nil - you may have found a bug")
}
// Abort if the source media file does not exist.
if !m.Exists() {
return "", fmt.Errorf(
"mediafile: %s not found", clean.Log(m.RootRelName()),
)
return "", fmt.Errorf("mediafile: %s not found", clean.Log(m.RootRelName()))
} else if m.Empty() {
return "", fmt.Errorf(
"mediafile: %s is empty", clean.Log(m.RootRelName()),
)
return "", fmt.Errorf("mediafile: %s is empty", clean.Log(m.RootRelName()))
}
// get the embedded video field name from the file metadata
if metaData := m.MetaData(); metaData.Error == nil && metaData.
EmbeddedVideo != "" {
// Get the embedded video field name from the file metadata.
if metaData := m.MetaData(); metaData.Error == nil && metaData.EmbeddedVideo != "" {
outputPath := filepath.Join(Config().TempPath(), m.RootRelPath(), "%f")
cmd := exec.Command(
Config().ExifToolBin(), fmt.Sprintf("-%s", metaData.EmbeddedVideo),
cmd := exec.Command(Config().ExifToolBin(),
fmt.Sprintf("-%s", metaData.EmbeddedVideo), // TODO: Is this safe?
"-b", "-w",
outputPath, m.FileName(),
)
outputPath, m.FileName())
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
cmd.Env = []string{fmt.Sprintf("HOME=%s", Config().TempPath())}
if err := cmd.Run(); err != nil {
log.Debugf("Error running exiftool on video file: ", err)
if stderr.String() != "" {
return "", errors.New(stderr.String())
} else {
@ -360,32 +355,27 @@ func (m *MediaFile) ExtractEmbeddedVideo() (string, error) {
}
}
// find the extracted video path
// Find the extracted video file.
outputPath = strings.Replace(outputPath, "%f", m.BasePrefix(false), 1)
// detect mime type of the extracted video
// Detect mime type of the extracted video file.
mimeType := fs.MimeType(outputPath)
if len := len(strings.Split(mimeType, "/")); len <= 1 {
log.Debugf(
"Error detecting the mime type of video file at %s",
outputPath,
)
if l := len(strings.Split(mimeType, "/")); l <= 1 {
log.Debugf("Error detecting the mime type of video file at %s", outputPath)
return "", nil
} else if extension := strings.Split(
mimeType, "/",
)[len-1]; extension != "" {
// rename the extracted video file with the correct extension and
// move it to the sidecar path
} else if extension := strings.Split(mimeType, "/")[l-1]; extension != "" {
// Rename the extracted video file with the correct extension and move it to the sidecar path.
_, file := filepath.Split(outputPath)
newFileName := fmt.Sprintf("%s.%s", file, extension)
dstPath := filepath.Join(
Config().SidecarPath(), m.RootRelPath(), newFileName,
)
dstPath := filepath.Join(Config().SidecarPath(), m.RootRelPath(), newFileName)
if err := fs.Move(outputPath, dstPath); err != nil {
log.Debugf("Error moving the video file at %s", outputPath)
log.Debugf("failed to move extracted video file to %s", outputPath)
return "", err
}
return dstPath, nil
}
}

View file

@ -51,15 +51,16 @@ func (m *MediaFile) RelatedFiles(stripSequence bool) (result RelatedFiles, err e
return result, err
}
// Search for related edited image file name (as used by Apple) and add it to the list of files, if found.
if name := m.EditedName(); name != "" {
matches = append(matches, name)
}
// check for an embedded video in the media file
if embeddedVideoName, err := m.ExtractEmbeddedVideo(); err != nil {
return result, err
} else if embeddedVideoName != "" {
matches = append(matches, embeddedVideoName)
// Extract an embedded video file and add it to the list of files, if successful.
if videoName, videoErr := m.ExtractEmbeddedVideo(); videoErr != nil {
log.Warnf("media: %s om %s (extract embedded video)", clean.Error(videoErr), clean.Log(m.RootRelName()))
} else if videoName != "" {
matches = append(matches, videoName)
}
isHEIC := false