无法使用 Python 从视频文件中获取正确的 Exif 数据

Unable to get correct Exif data from video file using Python

我找不到使用 Python.

从视频文件中获取 Exif 属性“DateEncoded”的方法

我试过几个exif工具,但this specific mp4 file(使用Android应用程序FilmicPro记录)似乎是一个特例。

Windows 资源管理器在 "Create Date" 属性 下显示正确的日期(见图),这实际上是 QuickTime exif 键“Media_DateEncoded ”。

Correct Date on Windows Explorer

Adobe Media Encoder 似乎也检索到正确的日期:

MediaEncoder Metadata panel

但是,我尝试的五种方法中的 none 可以通过编程方式检索正确的日期:2019 年 1 月 6 日。它总是 returns 1 月 7 日!

有没有人能解释一下why/how?

代码如下:

import os
import re
import struct
import subprocess as sub
from datetime import datetime
from hachoir.parser import createParser
from hachoir.metadata import extractMetadata
from win32com.propsys import propsys, pscon

# Download ExifTool from https://exiftool.org/
EXIF_TOOL = "exiftool.exe"

def method_1(fpath):
    # On Windows ctime means "Creation time", on Linux "Changed time"
    ctime = os.path.getctime(fpath)
    dtime = datetime.fromtimestamp(ctime)
    return dtime.strftime("%Y:%m:%d %H:%M:%S")

def method_2(fpath):
    '''
    This requires Hachoir installed. For Python3 run:
        >> pip3 install hachoir==3.1.1
        >> pip3 install hachoir-parser
    The property key 'Creation date' is a filesystem metadata, but
    it was the only one returned by Hachoir. What I really need is
    the Quicktime key 'Media_DateEncoded', which Windows Explorer
    calls "Media Created"
    '''
    parser = createParser(fpath)
    with parser:
        metadata = extractMetadata(parser)
    exif_dict = metadata.exportDictionary()['Metadata']
    return exif_dict['Creation date']

def method_3(fpath):
    '''
    This executes this shell comand:
        >> exiftool.exe -h VID_20190106_162804.mp4
    ...which returns an HTML like string from stdout.
    So using regular expression, we look for this section:
        "Media Create Date</td><td>2019:01:07 00:28:08</td></tr>"
    '''
    p = sub.Popen(
        [EXIF_TOOL, '-h',fpath],
        stdout=sub.PIPE,
        encoding='utf8')
    res, err = p.communicate()
    pattern = re.compile(
        r'Media Create Date\</td\>\<td\>(\d{4}:\d{2}:\d{2}\s\d{2}:\d{2}:\d{2})'
    )
    match = re.findall(pattern, res)
    if match:
        return match[0]

def method_4(fpath):
    '''
    Here we look for the Quicktime property key: Media_DateEncoded, which
    Windows Explorer calls "Media Created"
    '''
    fpath = fpath.replace('/', '\') # Windows api does not work with posix paths
    properties = propsys.SHGetPropertyStoreFromParsingName(fpath)
    dtime = properties.GetValue(pscon.PKEY_Media_DateEncoded).GetValue()
    return dtime.strftime("%Y:%m:%d %H:%M:%S")

def method_5(fpath):
    ATOM_HEADER_SIZE = 8

    # Difference between Unix epoch and QuickTime epoch, in seconds
    EPOCH_ADJUSTER = 2082844800

    # open file and search for moov item
    f = open(fpath, "rb")
    while 1:
        atom_header = f.read(ATOM_HEADER_SIZE)
        if atom_header[4:8] == b'moov':
            break
        atom_size = struct.unpack(">I", atom_header[0:4])[0]
        f.seek(atom_size - 8, 1)

    # found 'moov', look for 'mvhd' and timestamps
    atom_header = f.read(ATOM_HEADER_SIZE)
    if atom_header[4:8] == b'cmov':
        raise Exception("moov atom is compressed")
    elif atom_header[4:8] != b'mvhd':
        raise Exception("expected to find 'mvhd' header")
    else:
        f.seek(4, 1)
        creation_date = struct.unpack(">I", f.read(4))[0]
        dtime = datetime.utcfromtimestamp(creation_date - EPOCH_ADJUSTER)
        return dtime.strftime("%Y:%m:%d %H:%M:%S")

Python 3.7.3 (v3.7.3:ef4ec6ed12) [MSC v.1916 64 位 (AMD64)] on win32

OS:Windows 10 版本 10.0.18362 内部版本 18362

您没有考虑到的事实是 Quicktime 元数据时间戳保存为 UTC,而不是本地时间。您需要根据您的时区调整存储的时间。 Windows 理解这一点并相应地显示更正时间,但并非所有程序都这样做。

用exiftool提取时间戳时,可以加上-api QuickTimeUTC option,exiftool会自动调整到电脑当前时区。