corrected GoPro mp4 with exiftool
This commit is contained in:
73
correct_date_gopro.py
Normal file
73
correct_date_gopro.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#!python
|
||||||
|
|
||||||
|
# https://github.com/hMatoba/Piexif
|
||||||
|
# http://ce3wiki.theturninggate.net/doku.php?id=file_name_convention
|
||||||
|
# destination: <BASE>/<year>/<YYYYMMDD> <Event>/ab-<YYYYMMDD>-<Event>-<nnnn>.jpg
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
from pathlib import Path
|
||||||
|
import datetime as dt
|
||||||
|
import piexif
|
||||||
|
from collections import defaultdict
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
|
||||||
|
SRC = r'E:\RawTriage\GoPro Hero\20230819'
|
||||||
|
DRY_RUN = True
|
||||||
|
|
||||||
|
# def constant_factory(value):
|
||||||
|
# return lambda: value
|
||||||
|
# fileidx = defaultdict(constant_factory(0))
|
||||||
|
|
||||||
|
fileidx = defaultdict(int)
|
||||||
|
|
||||||
|
real_dt = dt.datetime(2023,7,28,15,0,0)
|
||||||
|
gopro_dt = dt.datetime(2015,1,3,19,23,25)
|
||||||
|
dt_diff = real_dt - gopro_dt
|
||||||
|
|
||||||
|
# print(dt_diff)
|
||||||
|
# print(gopro_dt + dt_diff)
|
||||||
|
|
||||||
|
for raw in Path(SRC).iterdir():
|
||||||
|
fn = raw.name
|
||||||
|
# print(fn)
|
||||||
|
if not raw.is_file():
|
||||||
|
print(f"skipped {fn}")
|
||||||
|
continue
|
||||||
|
if raw.suffix == ".MP4":
|
||||||
|
atime = raw.stat().st_atime
|
||||||
|
mtime = raw.stat().st_mtime
|
||||||
|
if dt.datetime.fromtimestamp(mtime) < dt.datetime(2020,1,1,0,0,0):
|
||||||
|
ctime = mtime + dt_diff.total_seconds()
|
||||||
|
print(f"{raw.name}: cur {dt.datetime.fromtimestamp(mtime)}, new {dt.datetime.fromtimestamp(ctime)}")
|
||||||
|
os.utime(raw, (atime, ctime))
|
||||||
|
else:
|
||||||
|
orig = raw.with_suffix(".MP4_original")
|
||||||
|
atime = orig.stat().st_atime
|
||||||
|
mtime = orig.stat().st_mtime
|
||||||
|
os.utime(raw, (atime, mtime))
|
||||||
|
# use exiftool for MP4 metadata timestamps 3127 days, 19:36:35
|
||||||
|
# exiftool "-AllDates+=3127 19:36:35" "E:\RawTriage\GoPro Hero\20230819"
|
||||||
|
if raw.suffix == ".JPG":
|
||||||
|
atime = raw.stat().st_atime
|
||||||
|
mtime = raw.stat().st_mtime
|
||||||
|
ctime = mtime + dt_diff.total_seconds()
|
||||||
|
print(f"{raw.name}: cur {dt.datetime.fromtimestamp(mtime)}, new {dt.datetime.fromtimestamp(ctime)}")
|
||||||
|
if not DRY_RUN:
|
||||||
|
os.utime(raw, (atime, ctime))
|
||||||
|
# EXIF update
|
||||||
|
im = Image.open(raw)
|
||||||
|
exif_dict = piexif.load(im.info["exif"])
|
||||||
|
try:
|
||||||
|
model = exif_dict["0th"][piexif.ImageIFD.Model].decode("ascii")
|
||||||
|
idto = exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal].decode("ascii")
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
rawdt = dt.datetime.strptime(idto,"%Y:%m:%d %H:%M:%S")
|
||||||
|
print(model, rawdt)
|
||||||
|
crawstr = dt.datetime.fromtimestamp(ctime).strftime("%Y:%m:%d %H:%M:%S")
|
||||||
|
exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal] = crawstr.encode("ascii")
|
||||||
|
exif_bytes = piexif.dump(exif_dict)
|
||||||
|
fn2 = raw.with_name(raw.stem + "_corrected" + raw.suffix)
|
||||||
|
im.save(fn2, "jpeg", exif=exif_bytes, quality=95)
|
||||||
|
os.utime(fn2, (atime, ctime))
|
||||||
15
exiftool_scratchpad.cmd
Normal file
15
exiftool_scratchpad.cmd
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
exiftool -G -args "ab-20230726-183944-DJI Mini 2.MP4" | findstr Date
|
||||||
|
|
||||||
|
for %F in ("*DJI Mini 2.mp4") DO exiftool -P -tagsFromFile "E:\RawTriage\DJI Mini 2\20230819 Videos\%F" -DateTimeOriginal^<CreateDate -CreateDate^<CreateDate -ModifyDate^<ModifyDate -TrackCreateDate^<TrackCreateDate -TrackModifyDate^<TrackModifyDate -MediaCreateDate^<MediaCreateDate -MediaModifyDate^<MediaModifyDate "%F"
|
||||||
|
|
||||||
|
exiftool -G -args "ab-20230731-115059-GoPro Hero.MP4" | findstr Date
|
||||||
|
|
||||||
|
rem original GoPro files (copy within same file @)
|
||||||
|
for %F in ("*GoPro Hero.mp4") DO exiftool -P -tagsFromFile @ -QuickTime:CreateDate^<FileModifyDate -QuickTime:ModifyDate^<FileModifyDate -TrackCreateDate^<FileModifyDate -TrackModifyDate^<FileModifyDate -MediaCreateDate^<FileModifyDate -MediaModifyDate^<FileModifyDate "%F"
|
||||||
|
|
||||||
|
rem Handbrake transcoded
|
||||||
|
for %F in ("*GoPro Hero.mp4") DO exiftool -P -tagsFromFile "E:\RawTriage\GoPro Hero\20230819 Videos\%F" -DateTimeOriginal^<FileModifyDate -CreateDate^<FileModifyDate -ModifyDate^<FileModifyDate -TrackCreateDate^<FileModifyDate -TrackModifyDate^<FileModifyDate -MediaCreateDate^<FileModifyDate -MediaModifyDate^<FileModifyDate "%F"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
exiftool -G -args "ab-20230731-115059-GoPro Hero.MP4"
|
||||||
@@ -19,7 +19,7 @@ DRY_RUN = False
|
|||||||
|
|
||||||
fileidx = defaultdict(int)
|
fileidx = defaultdict(int)
|
||||||
|
|
||||||
CAMERAS = ("GoPro Hero3+", "Ricoh Theta V", "Ricoh Theta S", "Sony a5100", "Sony a65", "Sony a68", "Sony TRV-25E", "Fuji Finepix Real 3D W3", "DJI Mini 2", "Samsung Galaxy A40", "Samsung Galaxy A41")
|
CAMERAS = ("GoPro Hero", "DJI Mini 2", "Ricoh Theta V", "Ricoh Theta S", "Sony a5100", "Sony a65", "Sony a68", "Sony TRV-25E", "Fuji Finepix Real 3D W3", "DJI Mini 2", "Samsung Galaxy A40", "Samsung Galaxy A41")
|
||||||
|
|
||||||
|
|
||||||
def recurse(dir, md, camera=None):
|
def recurse(dir, md, camera=None):
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from pathlib import Path
|
|||||||
import datetime as dt
|
import datetime as dt
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
DRY_RUN = False
|
DRY_RUN = False
|
||||||
|
|
||||||
@@ -22,10 +23,10 @@ def rename(old, new):
|
|||||||
print(f"skipped {old.name}, {new.name}, already exists")
|
print(f"skipped {old.name}, {new.name}, already exists")
|
||||||
|
|
||||||
# src = Path(r'D:\Videos')
|
# src = Path(r'D:\Videos')
|
||||||
src = Path(r"D:\MediaLibrary\Pictures\2022\20220831 Urlaub Cote d'Azur")
|
src = Path(r"D:\MediaLibrary\Pictures\2023\20230819 Urlaub Nordkapp")
|
||||||
|
|
||||||
for raw in src.glob("*pano.jpg"):
|
for raw in src.glob("*.mp4"):
|
||||||
mo = re.match("(?P<author>[^-]*)-(?P<dt>\S*)-(?P<model>[^-]*)(-\S+)?.jpg", raw.name)
|
mo = re.match("(?P<author>[^-]*)-(?P<dt>\S{8}-\S{6})-(?P<model>[^-]*)(-\S+)?.mp4", raw.name)
|
||||||
if mo is None:
|
if mo is None:
|
||||||
print(f"skipped {raw.name}, no match")
|
print(f"skipped {raw.name}, no match")
|
||||||
continue
|
continue
|
||||||
@@ -34,7 +35,12 @@ for raw in src.glob("*pano.jpg"):
|
|||||||
mtime = rawdt.timestamp()
|
mtime = rawdt.timestamp()
|
||||||
atime = raw.stat().st_atime
|
atime = raw.stat().st_atime
|
||||||
print(f"setting {raw.name} to {rawdt}")
|
print(f"setting {raw.name} to {rawdt}")
|
||||||
|
exifdt = (rawdt+dt.timedelta(hours=2)).strftime('%Y:%m:%d %H:%M:%S')
|
||||||
|
print(f'exiftool "-AllDates={exifdt}" "{raw}"')
|
||||||
|
subprocess.run(["exiftool", f"-AllDates={exifdt}", f"{raw}"])
|
||||||
if not DRY_RUN:
|
if not DRY_RUN:
|
||||||
os.utime(raw, (atime, mtime))
|
os.utime(raw, (atime, mtime))
|
||||||
# fn = f"{md['author'].lower()}-{md['dt']}-{md['model']}{raw.suffix}"
|
# fn = f"{md['author'].lower()}-{md['dt']}-{md['model']}{raw.suffix}"
|
||||||
# rename(raw, raw.parent / fn)
|
# rename(raw, raw.parent / fn)
|
||||||
|
# use exiftool for MP4 metadata timestamps 3127 days, 19:36:35
|
||||||
|
# exiftool "-AllDates+=3127 19:36:35" "E:\RawTriage\GoPro Hero\20230819"
|
||||||
|
|||||||
Reference in New Issue
Block a user