Metadata: Support time zones in ExifTool JSON files #727
This commit is contained in:
parent
a16a5ee16a
commit
bc535b6248
4 changed files with 133 additions and 2 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,DateTimeDigitized,DateTime"`
|
||||
TakenAtLocal time.Time `meta:"DateTimeOriginal,CreateDate,MediaCreateDate,DateTimeDigitized,DateTime"`
|
||||
TakenAt time.Time `meta:"DateTimeOriginal,CreateDate,MediaCreateDate,ContentCreateDate,DateTimeDigitized,DateTime"`
|
||||
TakenAtLocal time.Time `meta:"DateTimeOriginal,CreateDate,MediaCreateDate,ContentCreateDate,DateTimeDigitized,DateTime"`
|
||||
TimeZone string `meta:"-"`
|
||||
Duration time.Duration `meta:"Duration,MediaDuration,TrackDuration"`
|
||||
Codec string `meta:"CompressorID,Compression,FileType"`
|
||||
|
|
|
@ -76,6 +76,8 @@ func (data *Data) Exiftool(jsonData []byte, originalName string) (err error) {
|
|||
|
||||
if tv, err := time.Parse("2006:01:02 15:04:05", s); err == nil {
|
||||
fieldValue.Set(reflect.ValueOf(tv.Round(time.Second).UTC()))
|
||||
} else if tv, err := time.Parse("2006:01:02 15:04:05-07:00", s); err == nil {
|
||||
fieldValue.Set(reflect.ValueOf(tv.Round(time.Second)))
|
||||
}
|
||||
case time.Duration:
|
||||
fieldValue.Set(reflect.ValueOf(StringToDuration(jsonValue.String())))
|
||||
|
@ -120,6 +122,10 @@ func (data *Data) Exiftool(jsonData []byte, originalName string) (err error) {
|
|||
if loc, err := time.LoadLocation(data.TimeZone); err != nil {
|
||||
log.Warnf("metadata: unknown time zone %s (exiftool)", data.TimeZone)
|
||||
} else if tl, err := time.ParseInLocation("2006:01:02 15:04:05", data.TakenAtLocal.Format("2006:01:02 15:04:05"), loc); err == nil {
|
||||
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 = tl.Round(time.Second).UTC()
|
||||
} else {
|
||||
log.Errorf("metadata: %s (exiftool)", err.Error()) // this should never happen
|
||||
|
|
|
@ -551,4 +551,28 @@ func TestJSON(t *testing.T) {
|
|||
assert.Equal(t, 0, data.FocalLength)
|
||||
assert.Equal(t, 1, int(data.Orientation))
|
||||
})
|
||||
|
||||
t.Run("date.mov.json", func(t *testing.T) {
|
||||
data, err := JSON("testdata/date.mov.json", "")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, CodecAvc1, data.Codec)
|
||||
assert.Equal(t, "6s", data.Duration.String())
|
||||
assert.Equal(t, "2015-06-10 14:06:09 +0000 UTC", data.TakenAtLocal.String())
|
||||
assert.Equal(t, "2015-06-10 11:06:09 +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, 1080, data.ActualWidth())
|
||||
assert.Equal(t, 1920, data.ActualHeight())
|
||||
assert.Equal(t, 6, data.Orientation)
|
||||
assert.Equal(t, float32(55.5636), data.Lat)
|
||||
assert.Equal(t, float32(37.9824), data.Lng)
|
||||
assert.Equal(t, "Apple", data.CameraMake)
|
||||
assert.Equal(t, "iPhone 6 Plus", data.CameraModel)
|
||||
assert.Equal(t, "", data.LensModel)
|
||||
})
|
||||
}
|
||||
|
|
101
internal/meta/testdata/date.mov.json
vendored
Normal file
101
internal/meta/testdata/date.mov.json
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
[{
|
||||
"SourceFile": "/photoprism/originals/2020/12/20201222_000924_663B50DC.mov",
|
||||
"ExifToolVersion": 11.88,
|
||||
"FileName": "20201222_000924_663B50DC.mov",
|
||||
"Directory": "/photoprism/originals/2020/12",
|
||||
"FileSize": "14 MB",
|
||||
"FileModifyDate": "2020:12:22 00:09:30+00:00",
|
||||
"FileAccessDate": "2020:12:22 00:09:30+00:00",
|
||||
"FileInodeChangeDate": "2020:12:22 00:09:30+00:00",
|
||||
"FilePermissions": "rwxr-xr-x",
|
||||
"FileType": "MOV",
|
||||
"FileTypeExtension": "mov",
|
||||
"MIMEType": "video/quicktime",
|
||||
"MajorBrand": "Apple QuickTime (.MOV/QT)",
|
||||
"MinorVersion": "0.0.0",
|
||||
"CompatibleBrands": ["qt "],
|
||||
"MediaDataSize": 14675292,
|
||||
"MediaDataOffset": 36,
|
||||
"MovieHeaderVersion": 0,
|
||||
"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": 3,
|
||||
"TrackHeaderVersion": 0,
|
||||
"TrackCreateDate": "2015:06:10 11:06:09",
|
||||
"TrackModifyDate": "2015:06:10 11:06:16",
|
||||
"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": "avc1",
|
||||
"SourceImageWidth": 1920,
|
||||
"SourceImageHeight": 1080,
|
||||
"XResolution": 72,
|
||||
"YResolution": 72,
|
||||
"CompressorName": "H.264",
|
||||
"BitDepth": 24,
|
||||
"VideoFrameRate": 30.007,
|
||||
"MatrixStructure": "1 0 0 0 1 0 0 0 1",
|
||||
"MediaHeaderVersion": 0,
|
||||
"MediaCreateDate": "2015:06:10 11:06:09",
|
||||
"MediaModifyDate": "2015:06:10 11:06:16",
|
||||
"MediaTimeScale": 44100,
|
||||
"MediaDuration": "6.90 s",
|
||||
"MediaLanguageCode": "und",
|
||||
"Balance": 0,
|
||||
"HandlerClass": "Data Handler",
|
||||
"HandlerVendorID": "Apple",
|
||||
"HandlerDescription": "Core Media Data Handler",
|
||||
"AudioFormat": "mp4a",
|
||||
"AudioBitsPerSample": 16,
|
||||
"AudioSampleRate": 44100,
|
||||
"LayoutFlags": "Mono",
|
||||
"AudioChannels": 1,
|
||||
"PurchaseFileFormat": "mp4a",
|
||||
"SoftwareVersion-rus": 8.3,
|
||||
"ContentCreateDate-rus": "2015:06:10 14:06:09+03:00",
|
||||
"GPSCoordinates-rus": "55 deg 33' 48.96\" N, 37 deg 58' 56.64\" E, 141.315 m Above Sea Level",
|
||||
"Model-rus": "iPhone 6 Plus",
|
||||
"Make-rus": "Apple",
|
||||
"XMPToolkit": "Image::ExifTool 11.16",
|
||||
"DateTimeOriginal": "2015:06:10 14:06:09+03:00",
|
||||
"CreateDate": "2015:06:10 14:06:09+03:00",
|
||||
"ModifyDate": "2015:06:10 14:06:09+03:00",
|
||||
"HandlerType": "Metadata Tags",
|
||||
"CreationDate-rus-RU": "2015:06:10 14:06:09+03:00",
|
||||
"Model-rus-RU": "iPhone 6 Plus",
|
||||
"Software-rus-RU": 8.3,
|
||||
"GPSCoordinates-rus-RU": "55 deg 33' 48.96\" N, 37 deg 58' 56.64\" E, 141.315 m Above Sea Level",
|
||||
"Make-rus-RU": "Apple",
|
||||
"SoftwareVersion": 8.3,
|
||||
"ContentCreateDate": "2015:06:10 14:06:09+03:00",
|
||||
"GPSCoordinates": "55 deg 33' 48.96\" N, 37 deg 58' 56.64\" E, 141.315 m Above Sea Level",
|
||||
"Model": "iPhone 6 Plus",
|
||||
"Make": "Apple",
|
||||
"CreationDate": "2015:06:10 14:06:09+03:00",
|
||||
"Software": 8.3,
|
||||
"ImageSize": "1920x1080",
|
||||
"Megapixels": 2.1,
|
||||
"AvgBitrate": "17.2 Mbps",
|
||||
"GPSAltitude": "141.315 m",
|
||||
"GPSAltitudeRef": "Above Sea Level",
|
||||
"GPSLatitude": "55 deg 33' 48.96\" N",
|
||||
"GPSLongitude": "37 deg 58' 56.64\" E",
|
||||
"Rotation": 90,
|
||||
"GPSPosition": "55 deg 33' 48.96\" N, 37 deg 58' 56.64\" E"
|
||||
}]
|
Loading…
Reference in a new issue