Вопрос или проблема
Я ищу команду, которая будет считывать метаданные файла «*.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
Ответ или решение
Восстановление временных меток файлов видеозаписей при помощи встроенных метаданных может быть критически важно для организации медиаконтента. Ниже представлено подробное руководство, как достигнуть этой цели, сохраняя неизменным содержимое файлов.
Пошаговое руководство по восстановлению временных меток
-
Установка необходимых инструментов:
Прежде всего, убедитесь, что на вашем компьютере установлены такие инструменты, какmediainfo
,ffprobe
(часть пакетаffmpeg
), иexiftool
. Эти утилиты позволяют извлекать метаданные из видеофайлов. -
Извлечение временных меток с помощью
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. -
Работа с другими форматами файлов:
Для 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
. -
Использование
exiftool
:
Этот мощный инструмент позволяет изменить время последней модификации файла на дату создания, используя команду:exiftool "-CreateDate>FileModifyDate" FILES
Для определения нужных временнЫх тегов можно использовать:
exiftool -time:all -s FILE
-
Дополнительные настройки времени:
Обратите внимание на часовые пояса. Если временные метки в видеофайлах корректны, важно удостовериться, что ваши системные утилиты настроены на правильный часовой пояс. Для этого:date +%:::z
При необходимости измените настройку TZ:
export TZ="UTC0"
Заключение
Использование встроенных метаданных видеозаписей — это эффективный подход для восстановления временных меток, что позволяет поддерживать порядок и хронологию медиафайлов. Эти шаги обеспечивают сохранение целостности данных за счёт установки временных меток без изменения содержимого файлов. Следуя этим инструкциям, вы сможете эффективно организовать вашу медиабиблиотеку, восстановив корректные временные штампы файлов, даже после их переноса на другие носители данных.