Как восстановить временные метки файлов видеозаписей с помощью встроенных метаданных?

Вопрос или проблема

Я ищу команду, которая будет считывать метаданные файла «*.mp4» и изменять временную метку файла на время создания видео. Команда должна быть доступной только для чтения по отношению к содержимому файла, т. е. хеширование файла до и после должно давать одинаковый результат.

Ситуация: Я допустил ошибку, переместив фотографии и видео с внутренней памяти своего телефона на SD-карту, используя стандартный инструмент Android для этого («Настройки» → «Хранилище» → «Перенести данные на SD-карту»). К несчастью, это сбило временные метки всех файлов и также изменило порядок в директориях, отличных от DCIM/ (фотографии и видео также были перемещены из директорий Download/, image/, Pictures/ и video/). В ретроспективе, кажется глупым использовать такой инструмент (обычно я использую Ghost Commander), но он появился в уведомлении, когда места стало мало, и это казалось таким простым. Сейчас я пытаюсь воссоздать временные метки различных фотографий и видео.

Я фактически ищу аналог для видео следующей команды, которую я использовал, чтобы разобраться с изображениями в DCIM/100ANDRO/:

exiv2 -T mv *.JPG

Я просмотрел некоторые документы FFmpeg, но не вижу упоминания команд, доступных только для чтения, или печати временных меток.

(К сожалению, для моей ситуации такой подход не предлагает решения для файлов, которые я не создавал, таких как файлы в Download/, которые я хочу видеть в медиа-коллекции в хронологическом порядке их получения.)

Спасибо Уоррену за информацию о команде mediainfo в его частичном ответе.

Мне удалось построить команду, которая восстановила временные метки. Она проходит по подходящим файлам, и для каждого файла mediainfo считывает метаданные, grep и sed выбирают и форматируют временную метку, и touch применяет её.

for file in *.mp4; do touch -t "$(mediainfo "$file" | grep -m 1 'Tagged date' | sed -r 's/.*([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2}).*/\1\2\3\4\5.\6/')" "$file"; done

Часть «выбора и форматирования» наверняка могла бы быть короче/лучше; она выглядит громоздкой для меня, но я не владею regex. Тем не менее команда работала безупречно. Думаю, я правильно всё процитировал, поэтому она должна работать с любым именем файла. Может не сработать, если mediainfo выдаёт другой формат, но это легко адаптируется.

Например, вот регулярное выражение, которое правильно соответствует как формату вывода из моих файлов *.mp4, как UTC 2013-11-15 11:36:06, и дополнительно формату примера Уоррена 2014-2-23T09:00:00Z из my.mov:

's/-/-0/g; s/.*([0-9]{4})-0?([0-9]{2})-0?([0-9]{2})[T ]([0-9]{2}):([0-9]{2}):([0-9]{2}).*/\1\2\3\4\5.\6/'

И кроме mediainfo, который мне пришлось устанавливать вручную из-за его отсутствия в репозиториях моей дистрибуции (хотя, похоже, более новые релизы уже включают его), она должна быть достаточно переносимой и полезной другим, если они столкнутся с похожей проблемой.

Примечание: не забудьте проверить часовые пояса. Согласно страницам справки GNU, touch, date и другие утилиты GNU используют переменную окружения TZ, если она установлена, и «системные стандартные правила» в противном случае. Чтобы увидеть используемое смещение часового пояса, введите:

date +%:::z

Чтобы изменить его, задайте переменную окружения TZ:

export TZ="UTC0"

Если временные метки видео верны и правильно представлены (т.е. значение времени относительно часового пояса соответствует правильному моменту времени), тогда перед запуском touch -t на этих файлах (как выше) убедитесь, что date +%:::z выводит соответствующее смещение для часового пояса временной метки. Используйте stat для проверки файлов, так как он показывает смещение времени (как date +%:::z).

Вы можете использовать MediaInfo для этого:

$ mediainfo my.mov | grep 'Recorded date'
Recorded date                            : 2014-2-23T09:00:00Z

Перевести этот формат даты в команду touch должно быть простой задачей программирования. Лично я бы использовал модуль Perl Date::Manip для этого. Он может почти справиться с приведенным выше форматом; для понимания этого конкретного формата даты он требует 2-значные месяцы с нулевым началом. Исправить это можно с помощью простого регулярного выражения, что, конечно, легко в Perl.

$ perl -M'Date::Manip' -e 'print ParseDate("2014-02-23T09:00:00Z")'
2014022302:00:00

Тот факт, что он выводит, показывает, что он парсит. Если вы уберёте 0, вы увидите, что ничего не выводится, потому что ParseDate() возвращает undef.

Следуйте совету Джеймса выше для MP4 и большинства файлов QuickTime. Для файлов AVI mediainfo выдаст Mastered date, но формат в основном не поддаётся разбору. Установите ffmpeg для получения ffprobe (также известного как avprobe), затем используйте:

for file in *.avi; do touch -t "$(ffprobe "$file" 2>&1 | grep -m 1 'creation_time' | sed -r 's/.*([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2}).*/\1\2\3\4\5.\6/')" "$file"; done

Обратите внимание на модификацию перед передачей в grep. Это связано с тем, что ffprobe использует stderr, а не stdout.

exiftool:

exiftool "-CreateDate>FileModifyDate" FILES или ПАПКИ

Название значения, которое вы хотите, может отличаться в зависимости от формата файла и других факторов. Используйте ниже для их отображения:

exiftool -time:all -s FILE

Есть гораздо более простой способ.

for filename in *.avi; do 
ffmpeg -fflags +genpts -i $filename -c:v copy -c:a copy ${filename%.*}.mkv && rm $filename
done

Ответ или решение

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

Пошаговое руководство по восстановлению временных меток

  1. Установка необходимых инструментов:
    Прежде всего, убедитесь, что на вашем компьютере установлены такие инструменты, как mediainfo, ffprobe (часть пакета ffmpeg), и exiftool. Эти утилиты позволяют извлекать метаданные из видеофайлов.

  2. Извлечение временных меток с помощью mediainfo:
    Для MP4 файлов можно использовать следующую команду для извлечения даты из метаданных и последующего обновления временной метки файла:

    for file in *.mp4; do 
       touch -t "$(mediainfo "$file" | grep -m 1 'Tagged date' | sed -r 's/.*([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2}).*/\1\2\3\4\5.\6/')" "$file"
    done

    Этот скрипт методично перебирает все файлы .mp4 в текущем каталоге, извлекая "Tagged date" из метаданных и устанавливая соответствующую временную метку OS.

  3. Работа с другими форматами файлов:
    Для AVI файлов, использование ffprobe оказывается полезным:

    for file in *.avi; do 
       touch -t "$(ffprobe "$file" 2>&1 | grep -m 1 'creation_time' | sed -r 's/.*([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2}).*/\1\2\3\4\5.\6/')" "$file"
    done

    Важно отметить использование 2>&1, так как ffprobe выводит данные в stderr.

  4. Использование exiftool:
    Этот мощный инструмент позволяет изменить время последней модификации файла на дату создания, используя команду:

    exiftool "-CreateDate>FileModifyDate" FILES

    Для определения нужных временнЫх тегов можно использовать:

    exiftool -time:all -s FILE
  5. Дополнительные настройки времени:
    Обратите внимание на часовые пояса. Если временные метки в видеофайлах корректны, важно удостовериться, что ваши системные утилиты настроены на правильный часовой пояс. Для этого:

    date +%:::z

    При необходимости измените настройку TZ:

    export TZ="UTC0"

Заключение

Использование встроенных метаданных видеозаписей — это эффективный подход для восстановления временных меток, что позволяет поддерживать порядок и хронологию медиафайлов. Эти шаги обеспечивают сохранение целостности данных за счёт установки временных меток без изменения содержимого файлов. Следуя этим инструкциям, вы сможете эффективно организовать вашу медиабиблиотеку, восстановив корректные временные штампы файлов, даже после их переноса на другие носители данных.

Оцените материал
Добавить комментарий

Капча загружается...