How can I restore file timestamps of video recordings using the embedded metadata?
Thanks to Warren for informing me about the mediainfo
command in his partial answer.
I managed to construct a command that achieved the restoration of timestamps. It loops over the applicable files, and for each file, mediainfo
reads the metadata, grep
and sed
select and format the timestamp, and touch
applies it.
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
The ‘select and format’ part could no doubt be a lot shorter/better; it looks cumbersome to me but I'm not fluent with regexs. Nevertheless, the command worked perfectly. I think I've quoted everything correctly, so it should work with any filename. It may not work if mediainfo
outputs a different format but it's easily adaptable.
For example, here is a regex that correctly matches both the format of output from my *.mp4
files such as UTC 2013-11-15 11:36:06
, and additionally the format of Warren's example of 2014-2-23T09:00:00Z
from 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/'
And apart from mediainfo
which I actually had to install manually due to it not being in my distro's repositories (though it looks like newer releases now package it), it should be fairly portable and useful to others if they encounter a similar problem.
Note: Remember to check timezones. According to the GNU info
pages, touch
, date
, and other GNU utilities use the TZ
environment variable if set and the ‘system default rules’ otherwise. To see the timezone offset that'll be used, issue:
date +%:::z
To change it, set the TZ
environment variable:
export TZ="UTC0"
If the video's timestamps are correct, and are correctly represented (i.e. the time value w.r.t. the timezone represents the correct point in time), then you should make sure that date +%:::z
outputs the matching offset for the timestamp's timezone before running touch -t
over those files (as above). Use stat
to check the files, as it shows the time offset (like date +%:::z
).
You can use MediaInfo for that:
$ mediainfo my.mov | grep 'Recorded date'
Recorded date : 2014-2-23T09:00:00Z
Getting from that date format to a touch
command should be a small matter of programming. Personally, I'd use Perl's Date::Manip
module for this. It can almost cope with the above format; it requires 2-digit months with zero padding to understand this particular date format. Fixing that only requires a trivial regexp, which is of course easy in Perl.
$ perl -M'Date::Manip' -e 'print ParseDate("2014-02-23T09:00:00Z")'
2014022302:00:00
The fact that it prints shows that it's parsing. If you drop the 0
, you'll see that it doesn't print anything, because ParseDate()
returns undef
.