Metadata: Add support for CreationDate in ExifTool JSON files #727
This commit is contained in:
parent
48fba799a2
commit
2ed6880270
5 changed files with 243 additions and 4 deletions
|
@ -13,8 +13,8 @@ import (
|
|||
type Data struct {
|
||||
DocumentID string `meta:"ImageUniqueID,OriginalDocumentID,DocumentID"`
|
||||
InstanceID string `meta:"InstanceID,DocumentID"`
|
||||
TakenAt time.Time `meta:"DateTimeOriginal,CreateDate,MediaCreateDate,ContentCreateDate,DateTimeDigitized,DateTime"`
|
||||
TakenAtLocal time.Time `meta:"DateTimeOriginal,CreateDate,MediaCreateDate,ContentCreateDate,DateTimeDigitized,DateTime"`
|
||||
TakenAt time.Time `meta:"DateTimeOriginal,CreationDate,CreateDate,MediaCreateDate,ContentCreateDate,DateTimeDigitized,DateTime"`
|
||||
TakenAtLocal time.Time `meta:"DateTimeOriginal,CreationDate,CreateDate,MediaCreateDate,ContentCreateDate,DateTimeDigitized,DateTime"`
|
||||
TimeZone string `meta:"-"`
|
||||
Duration time.Duration `meta:"Duration,MediaDuration,TrackDuration"`
|
||||
Codec string `meta:"CompressorID,Compression,FileType"`
|
||||
|
|
|
@ -131,6 +131,12 @@ func (data *Data) Exiftool(jsonData []byte, originalName string) (err error) {
|
|||
log.Errorf("metadata: %s (exiftool)", err.Error()) // this should never happen
|
||||
}
|
||||
}
|
||||
} else if _, offset := data.TakenAtLocal.Zone(); offset != 0 && !data.TakenAtLocal.IsZero() {
|
||||
if localUtc, err := time.ParseInLocation("2006:01:02 15:04:05", data.TakenAtLocal.Format("2006:01:02 15:04:05"), time.UTC); err == nil {
|
||||
data.TakenAtLocal = localUtc
|
||||
}
|
||||
|
||||
data.TakenAt = data.TakenAt.Round(time.Second).UTC()
|
||||
}
|
||||
|
||||
if orientation, ok := jsonStrings["Orientation"]; ok && orientation != "" {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package meta
|
||||
|
||||
import (
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -18,8 +19,8 @@ func TestJSON(t *testing.T) {
|
|||
|
||||
assert.Equal(t, CodecAvc1, data.Codec)
|
||||
assert.Equal(t, "3s", data.Duration.String())
|
||||
assert.Equal(t, "2018-09-08 17:20:14 +0000 UTC", data.TakenAtLocal.String())
|
||||
assert.Equal(t, "2018-09-08 15:20:14 +0000 UTC", data.TakenAt.String())
|
||||
assert.Equal(t, "2018-09-08 19:20:14 +0000 UTC", data.TakenAtLocal.String())
|
||||
assert.Equal(t, "2018-09-08 17:20:14 +0000 UTC", data.TakenAt.String())
|
||||
assert.Equal(t, "Europe/Berlin", data.TimeZone)
|
||||
assert.Equal(t, 1920, data.Width)
|
||||
assert.Equal(t, 1080, data.Height)
|
||||
|
@ -575,4 +576,52 @@ func TestJSON(t *testing.T) {
|
|||
assert.Equal(t, "iPhone 6 Plus", data.CameraModel)
|
||||
assert.Equal(t, "", data.LensModel)
|
||||
})
|
||||
|
||||
t.Run("date-creation.mov.json", func(t *testing.T) {
|
||||
data, err := JSON("testdata/date-creation.mov.json", "")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, string(fs.CodecAvc), data.Codec)
|
||||
assert.Equal(t, "10s", data.Duration.String())
|
||||
assert.Equal(t, "2015-12-06 18:22:29 +0000 UTC", data.TakenAtLocal.String())
|
||||
assert.Equal(t, "2015-12-06 15:22:29 +0000 UTC", data.TakenAt.String())
|
||||
assert.Equal(t, "Europe/Moscow", data.TimeZone)
|
||||
assert.Equal(t, 1920, data.Width)
|
||||
assert.Equal(t, 1080, data.Height)
|
||||
assert.Equal(t, 1920, data.ActualWidth())
|
||||
assert.Equal(t, 1080, data.ActualHeight())
|
||||
assert.Equal(t, 1, data.Orientation)
|
||||
assert.Equal(t, float32(55.7579), data.Lat)
|
||||
assert.Equal(t, float32(37.6197), data.Lng)
|
||||
assert.Equal(t, "Apple", data.CameraMake)
|
||||
assert.Equal(t, "iPhone 6 Plus", data.CameraModel)
|
||||
assert.Equal(t, "", data.LensModel)
|
||||
})
|
||||
|
||||
t.Run("date-iphone8.mov.json", func(t *testing.T) {
|
||||
data, err := JSON("testdata/date-iphone8.mov.json", "")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, string(fs.CodecHvc), data.Codec)
|
||||
assert.Equal(t, "6s", data.Duration.String())
|
||||
assert.Equal(t, "2020-12-22 02:45:43 +0000 UTC", data.TakenAtLocal.String())
|
||||
assert.Equal(t, "2020-12-22 01:45:43 +0000 UTC", data.TakenAt.String())
|
||||
assert.Equal(t, "", data.TimeZone)
|
||||
assert.Equal(t, 1920, data.Width)
|
||||
assert.Equal(t, 1080, data.Height)
|
||||
assert.Equal(t, 1080, data.ActualWidth())
|
||||
assert.Equal(t, 1920, data.ActualHeight())
|
||||
assert.Equal(t, 6, data.Orientation)
|
||||
assert.Equal(t, float32(0), data.Lat)
|
||||
assert.Equal(t, float32(0), data.Lng)
|
||||
assert.Equal(t, "Apple", data.CameraMake)
|
||||
assert.Equal(t, "iPhone 8", data.CameraModel)
|
||||
assert.Equal(t, "", data.LensModel)
|
||||
})
|
||||
}
|
||||
|
|
95
internal/meta/testdata/date-creation.mov.json
vendored
Normal file
95
internal/meta/testdata/date-creation.mov.json
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
[{
|
||||
"SourceFile": "IMG_4561.MOV",
|
||||
"ExifToolVersion": 12.00,
|
||||
"FileName": "IMG_4561.MOV",
|
||||
"Directory": ".",
|
||||
"FileSize": "22 MB",
|
||||
"FileModifyDate": "2020:07:16 19:06:26+02:00",
|
||||
"FileAccessDate": "2020:12:22 02:37:08+01:00",
|
||||
"FileInodeChangeDate": "2020:12:22 02:07:04+01:00",
|
||||
"FilePermissions": "rw-------",
|
||||
"FileType": "MOV",
|
||||
"FileTypeExtension": "mov",
|
||||
"MIMEType": "video/quicktime",
|
||||
"MajorBrand": "Apple QuickTime (.MOV/QT)",
|
||||
"MinorVersion": "0.0.0",
|
||||
"CompatibleBrands": ["qt "],
|
||||
"MediaDataSize": 23138648,
|
||||
"MediaDataOffset": 36,
|
||||
"MovieHeaderVersion": 0,
|
||||
"CreateDate": "2015:12:06 15:22:29",
|
||||
"ModifyDate": "2015:12:06 15:22:40",
|
||||
"TimeScale": 600,
|
||||
"Duration": "10.67 s",
|
||||
"PreferredRate": 1,
|
||||
"PreferredVolume": "100.00%",
|
||||
"PreviewTime": "0 s",
|
||||
"PreviewDuration": "0 s",
|
||||
"PosterTime": "0 s",
|
||||
"SelectionTime": "0 s",
|
||||
"SelectionDuration": "0 s",
|
||||
"CurrentTime": "0 s",
|
||||
"NextTrackID": 5,
|
||||
"TrackHeaderVersion": 0,
|
||||
"TrackCreateDate": "2015:12:06 15:22:29",
|
||||
"TrackModifyDate": "2015:12:06 15:22:40",
|
||||
"TrackID": 1,
|
||||
"TrackDuration": "10.67 s",
|
||||
"TrackLayer": 0,
|
||||
"TrackVolume": "100.00%",
|
||||
"ImageWidth": 1920,
|
||||
"ImageHeight": 1080,
|
||||
"CleanApertureDimensions": "1920x1080",
|
||||
"ProductionApertureDimensions": "1920x1080",
|
||||
"EncodedPixelsDimensions": "1920x1080",
|
||||
"GraphicsMode": "ditherCopy",
|
||||
"OpColor": "32768 32768 32768",
|
||||
"CompressorID": "avc1",
|
||||
"SourceImageWidth": 1920,
|
||||
"SourceImageHeight": 1080,
|
||||
"XResolution": 72,
|
||||
"YResolution": 72,
|
||||
"CompressorName": "H.264",
|
||||
"BitDepth": 24,
|
||||
"VideoFrameRate": 29.981,
|
||||
"Balance": 0,
|
||||
"AudioFormat": "mp4a",
|
||||
"AudioBitsPerSample": 16,
|
||||
"AudioSampleRate": 44100,
|
||||
"LayoutFlags": "Mono",
|
||||
"AudioChannels": 1,
|
||||
"PurchaseFileFormat": "mp4a",
|
||||
"Warning": "[minor] The ExtractEmbedded option may find more tags in the media data",
|
||||
"MatrixStructure": "1 0 0 0 1 0 0 0 1",
|
||||
"ContentDescribes": "Track 1",
|
||||
"MediaHeaderVersion": 0,
|
||||
"MediaCreateDate": "2015:12:06 15:22:29",
|
||||
"MediaModifyDate": "2015:12:06 15:22:40",
|
||||
"MediaTimeScale": 600,
|
||||
"MediaDuration": "10.67 s",
|
||||
"MediaLanguageCode": "und",
|
||||
"GenMediaVersion": 0,
|
||||
"GenFlags": "0 0 0",
|
||||
"GenGraphicsMode": "ditherCopy",
|
||||
"GenOpColor": "32768 32768 32768",
|
||||
"GenBalance": 0,
|
||||
"HandlerClass": "Data Handler",
|
||||
"HandlerVendorID": "Apple",
|
||||
"HandlerDescription": "Core Media Data Handler",
|
||||
"MetaFormat": "mebx",
|
||||
"HandlerType": "Metadata Tags",
|
||||
"GPSCoordinates": "55 deg 45' 28.44\" N, 37 deg 37' 10.92\" E, 135.89 m Above Sea Level",
|
||||
"Make": "Apple",
|
||||
"Model": "iPhone 6 Plus",
|
||||
"Software": 9.1,
|
||||
"CreationDate": "2015:12:06 18:22:29+03:00",
|
||||
"ImageSize": "1920x1080",
|
||||
"Megapixels": 2.1,
|
||||
"AvgBitrate": "17.3 Mbps",
|
||||
"GPSAltitude": "135.89 m",
|
||||
"GPSAltitudeRef": "Above Sea Level",
|
||||
"GPSLatitude": "55 deg 45' 28.44\" N",
|
||||
"GPSLongitude": "37 deg 37' 10.92\" E",
|
||||
"Rotation": 0,
|
||||
"GPSPosition": "55 deg 45' 28.44\" N, 37 deg 37' 10.92\" E"
|
||||
}]
|
89
internal/meta/testdata/date-iphone8.mov.json
vendored
Normal file
89
internal/meta/testdata/date-iphone8.mov.json
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
[{
|
||||
"SourceFile": "IMG_6884.MOV",
|
||||
"ExifToolVersion": 12.00,
|
||||
"FileName": "IMG_6884.MOV",
|
||||
"Directory": ".",
|
||||
"FileSize": "9.6 MB",
|
||||
"FileModifyDate": "2020:12:22 02:46:08+01:00",
|
||||
"FileAccessDate": "2020:12:22 02:48:31+01:00",
|
||||
"FileInodeChangeDate": "2020:12:22 02:46:24+01:00",
|
||||
"FilePermissions": "rw-r--r--",
|
||||
"FileType": "MOV",
|
||||
"FileTypeExtension": "mov",
|
||||
"MIMEType": "video/quicktime",
|
||||
"MajorBrand": "Apple QuickTime (.MOV/QT)",
|
||||
"MinorVersion": "0.0.0",
|
||||
"CompatibleBrands": ["qt "],
|
||||
"MediaDataSize": 10091927,
|
||||
"MediaDataOffset": 36,
|
||||
"MovieHeaderVersion": 0,
|
||||
"CreateDate": "2020:12:22 01:46:08",
|
||||
"ModifyDate": "2020:12:22 01:46:08",
|
||||
"TimeScale": 600,
|
||||
"Duration": "6.83 s",
|
||||
"PreferredRate": 1,
|
||||
"PreferredVolume": "100.00%",
|
||||
"PreviewTime": "0 s",
|
||||
"PreviewDuration": "0 s",
|
||||
"PosterTime": "0 s",
|
||||
"SelectionTime": "0 s",
|
||||
"SelectionDuration": "0 s",
|
||||
"CurrentTime": "0 s",
|
||||
"NextTrackID": 5,
|
||||
"TrackHeaderVersion": 0,
|
||||
"TrackCreateDate": "2020:12:22 01:46:08",
|
||||
"TrackModifyDate": "2020:12:22 01:46:08",
|
||||
"TrackID": 1,
|
||||
"TrackDuration": "6.83 s",
|
||||
"TrackLayer": 0,
|
||||
"TrackVolume": "0.00%",
|
||||
"ImageWidth": 1920,
|
||||
"ImageHeight": 1080,
|
||||
"CleanApertureDimensions": "1920x1080",
|
||||
"ProductionApertureDimensions": "1920x1080",
|
||||
"EncodedPixelsDimensions": "1920x1080",
|
||||
"GraphicsMode": "ditherCopy",
|
||||
"OpColor": "32768 32768 32768",
|
||||
"CompressorID": "hvc1",
|
||||
"SourceImageWidth": 1920,
|
||||
"SourceImageHeight": 1080,
|
||||
"XResolution": 72,
|
||||
"YResolution": 72,
|
||||
"CompressorName": "HEVC",
|
||||
"BitDepth": 24,
|
||||
"VideoFrameRate": 60,
|
||||
"Balance": 0,
|
||||
"AudioFormat": "mp4a",
|
||||
"AudioChannels": 1,
|
||||
"AudioBitsPerSample": 16,
|
||||
"AudioSampleRate": 44100,
|
||||
"PurchaseFileFormat": "mp4a",
|
||||
"Warning": "[minor] The ExtractEmbedded option may find more tags in the media data",
|
||||
"MatrixStructure": "1 0 0 0 1 0 0 0 1",
|
||||
"ContentDescribes": "Track 1",
|
||||
"MediaHeaderVersion": 0,
|
||||
"MediaCreateDate": "2020:12:22 01:46:08",
|
||||
"MediaModifyDate": "2020:12:22 01:46:08",
|
||||
"MediaTimeScale": 600,
|
||||
"MediaDuration": "6.83 s",
|
||||
"MediaLanguageCode": "und",
|
||||
"GenMediaVersion": 0,
|
||||
"GenFlags": "0 0 0",
|
||||
"GenGraphicsMode": "ditherCopy",
|
||||
"GenOpColor": "32768 32768 32768",
|
||||
"GenBalance": 0,
|
||||
"HandlerClass": "Data Handler",
|
||||
"HandlerVendorID": "Apple",
|
||||
"HandlerDescription": "Core Media Data Handler",
|
||||
"MetaFormat": "mebx",
|
||||
"HandlerType": "Metadata Tags",
|
||||
"LocationAccuracyHorizontal": 65.000000,
|
||||
"Make": "Apple",
|
||||
"Model": "iPhone 8",
|
||||
"Software": 14.3,
|
||||
"CreationDate": "2020:12:22 02:45:43+01:00",
|
||||
"ImageSize": "1920x1080",
|
||||
"Megapixels": 2.1,
|
||||
"AvgBitrate": "11.8 Mbps",
|
||||
"Rotation": 90
|
||||
}]
|
Loading…
Reference in a new issue