Инструмент EXIF ​​и видеофайлы, которые сохраняются с метками времени UTC

Мне любопытно, кто-нибудь мог бы дать мне некоторое представление о текущей проблеме, которая у меня есть.

Для некоторого контекста у нас с женой есть телефон Android (Moto G5 Plus). Телефоны синхронизируют все элементы в папке DCIM с моим сервером Ubuntu через SFTP. Элементы хранятся в каталоге unsorted_pictures. Раз в ночь запускается задание cron, выполняющее скрипт, который автоматически копирует содержимое из unsorted_pictures в картинки / год / месяц. Позже (после максимального количества телефонов в космосе) я удалю каталог unsorted_pictures в качестве шага обслуживания.

Сценарий, во что бы то ни стало, выглядит следующим образом:

#!/bin/bash
exiftool -overwrite_original_in_place -P -if 'not $CreateDate' '-CreateDate<FileModifyDate' -r /mnt/vault/unsorted_pictures/staging
exiftool -o . '-Directory<CreateDate' -d /mnt/vault/pictures/%Y/%m -r /mnt/vault/unsorted_pictures/staging
exit

В общем, первая строка exiftool проверяет, существует ли CreateDate. Если это не так, он использует FileModifyDate для создания параметра CreateDate. Это действительно полезно только для изображений, сохраненных в чате Hangouts, так как Google, похоже, удаляет exif-данные. (?!) После этого вторая строка exiftool выполняет копирование + сортировку.

Этот процесс удивительный, и я очень доволен этим. Хотя есть один снэфу - видеофайлы, кажется, записываются в UTC, тогда как снимки, кажется, записываются по местному времени. Ниже приведен видеофайл, который был взят, немедленно передан на мой сервер, и exiftool был запущен для проверки всех отметок времени.

administrator@vault:/mnt/vault/unsorted_pictures$ exiftool -time:all -s VID_20171225_214456599.mp4
FileModifyDate      : 2017:12:25 21:47:02-05:00
FileAccessDate      : 2017:12:25 21:47:00-05:00
FileInodeChangeDate : 2017:12:25 21:47:02-05:00
CreateDate          : 2017:12:26 02:45:00
ModifyDate          : 2017:12:26 02:45:00
TrackCreateDate     : 2017:12:26 02:45:00
TrackModifyDate     : 2017:12:26 02:45:00
MediaCreateDate     : 2017:12:26 02:45:00
MediaModifyDate     : 2017:12:26 02:45:00

administrator@vault:/mnt/vault/unsorted_pictures$ date
Mon Dec 25 21:47:23 EST 2017

Как видите, CreateDate настроен, по-видимому, на будущее время. Ниже я выполнил команду date, чтобы вы могли увидеть текущее местное время, когда это произошло. В верхних строках вы можете видеть метки времени, заканчивающиеся на 05:00, и, насколько я понимаю, это разница во времени по UTC.

На мои актуальные вопросы:

1) Я попробовал несколько приложений камеры на моем Motorola, но все они дали одинаковое поведение. Это говорит о том, что это не специфичная для приложения настройка. Есть ли способ, чтобы мои видео не записывались в формате UTC? Картинки в порядке, это просто видео. Я нахожу это немного странным, но онлайн-поиск предполагает, что это распространено, но мне еще предстоит услышать и понять, почему.

2) Я уверен, что могу добавить некоторую логику в свой сценарий, чтобы просто сортировать изображения через CreateDate и сортировать типы видеофайлов через FileModifyDate, или даже добавить какой-то дополнительный параметр, чтобы систематически обновлять все видео обратно на 5 часов. Но мне стало интересно, есть ли способ, чтобы exiftool посмотрел на файл mp4 и подтвердил разницу во времени UTC? Я знаю, что видеофайлы - это другой зверь, и exiftool в основном сфокусирован на изображениях, но, тем не менее, учитывая, что exiftool отлично справляется с распознаванием метаданных даже на этих видео, я подумал, что может быть способ настроить его для просмотра не UTC время. Или, возможно, нет надежды, если телефон записывает в UTC время. / пожимание плечами

Возможно, это еще более веская причина для сортировки по году / месяцу, а не по году / месяцу / дню, поскольку я даже не скажу, что видео сдвигаются на 5 часов, поскольку все они будут в каталоге этого месяца. Но, тем не менее, я заинтригован этим и задаюсь вопросом... почему?

Любая помощь или понимание будет очень цениться!

2 ответа

По словам Фила Харви (создателя exiftool), метки времени Quicktime должны быть установлены на время UTC согласно стандарту. Но, похоже, что многие камеры этого не делают, поэтому exiftool не использует часовой пояс и принимает время как написано. Смотрите третий абзац под тегами Quicktime

Exiftool включает в себя возможность исправить это. Если вы используете exiftool версии 9.40 или более поздней, вы можете добавить -api QuickTimeUTC к команде, и он будет предполагать, что метки времени правильно записаны как UTC и преобразовать их в местное время.

Я предлагаю вам создать новый тег «CreateDateLocal», в котором вы будете хранить время создания как местное время.

Вы делаете это с помощью config.xml. В 'Image::ExifTool::XMP::xmp', вы добавляете:

      CreateDateLocal => { Groups => { 2 => 'Time' }, Shift => 'Time' },  # Stores the create date in local time (for videos)

Вероятно, после вставки это будет выглядеть так:

          # XMP tags may be added to existing namespaces:
    'Image::ExifTool::XMP::xmp' => {
        # Example 5.  XMP-xmp:NewXMPxmpTag
        NewXMPxmpTag => { Groups => { 2 => 'Author' } },

        # add more user-defined XMP-xmp tags here...
        CreateDateLocal => { Groups => { 2 => 'Time' } },  # Stores the create date in local time (for videos)
    },

Для видео с UTC выполните следующее:
exiftool -r -ext mp4 -api QuickTimeUTC "-CreateDateLocal<CreateDate" .

Для видео по местному времени выполните следующее:
exiftool -r -ext mp4 "-CreateDateLocal<CreateDate" .

Вы также можете запустить его на изображениях, а затем просто использовать «CreateDateLocal» вместо «CreateDate» для организации. Конец простого решения

Немного более продвинутое решение:

Вы можете создать новый составной тег, который возвращается к CreateDate, когда CreateDateLocal отсутствует. При этом вам нужно будет только пометить видео с отметкой времени UTC (то есть: это избавит вас от пометки всех изображений, а также избавит вас от пометки видео с локальной отметкой времени).

Вот как:

Ищи "'Image::ExifTool::Composite'"в конфиг. Внутри {} вставьте следующее:

      # TheDateTaken is best attempt to get the date the photo was taken - preferrably in local time
# First the custom tag "CreateDateLocal" is checked. This is expected to be set manually on all videos.
# - For videos with UTC, run this: `exiftool -ext mp4 -api QuickTimeUTC "-CreateDateLocal<CreateDate" .`
# - For videos in local time, run this: `exiftool -ext mp4 "-CreateDateLocal<CreateDate" .`
# If CreateDateLocal isn't set, we asume it is an image. Images are always set in local time.
# There are multiple tags used for storing creation time. We check them all (listed in Desire)

CreateDateLocalWithFallback => {
    Desire => {
        0 => 'CreateDateLocal',
        1 => 'DateTimeOriginal',
        2 => 'CreationDate',
        3 => 'CreateDate',
    },

    Groups => { 2 => 'Time' },
    ValueConv => sub {
        $val = shift;
        # Loop through dates
        foreach $date (@$val) {
            next if not defined $date;
            return $date if ($date =~ /^[12]\d\d\d/);    # if it doesn't start with four digits, skip, as it is not a valid date            
        }               
        return undef;               
    },            
    Shift => 'Time',
    Validate => 'ValidateExifDate($val)',
    PrintConv => '$self->ConvertDateTime($val)',
},

Расширьте решение, также проанализировав дату из имени файла

Samsung сохраняет дату создания в имени файла. Его можно использовать как запасной вариант. Этот составной тег может извлекать дату (чтобы использовать его в CreateDateLocalWithFallback, просто добавьте «DateFromFilename» в массив «Desire»)

      DateFromFilename => {
    Desire => {
        0 => 'OriginalFileName',
        1 => 'FileName',
    },

    Groups => { 2 => 'Time' },
    ValueConv => sub {
        $val = shift;

        foreach $filename (@$val) {
            # See if filename resembles date (it does on Samsung)
            # Samsung naming: "20150827_165859.jpg"
            if ($filename =~ /^\d{8}_\d{6}/) {
                $year = substr($filename, 0, 4);
                $month = substr($filename, 4, 2);
                $day = substr($filename, 6, 2);
                $hour = substr($filename, 9, 2);
                $minute = substr($filename, 11, 2);
                $second = substr($filename, 13, 2);
                $y = int($year);
                $mo = int($month);
                $d = int($day);
                $h = int($hour);
                $mi = int($minute);
                $s = int($second);
            
                #return '2015:08:27 16:58:59';
                #return @$val[0];
                if (
                    (($y > 1900) && ($y < 2400)) &&
                    (($mo >= 1) && ($mo <= 12)) &&
                    (($d >= 1) && ($d <= 31)) &&
                    (($h >= 0) && ($h <= 24)) &&
                    (($mi >= 0) && ($mi <= 60)) &&
                    (($s >= 0) && ($s <= 60))
                ) {
                    # '2015:08:27 16:58:59';
                    return $year . ':' . $month . ':' . $day . ' ' . $hour . ':' . $minute . ':' . $second; 
                }
            }               
        }
        return undef;               
    },            
    Shift => 'Time',
    Validate => 'ValidateExifDate($val)',
    PrintConv => '$self->ConvertDateTime($val)',
    #PrintConvInv => '$self->InverseDateTime($val,0)',
},
Другие вопросы по тегам